diff --git a/bsp/ESP32_C3/.config b/bsp/ESP32_C3/.config index 0fbb456ad9..fd79b650f0 100644 --- a/bsp/ESP32_C3/.config +++ b/bsp/ESP32_C3/.config @@ -657,37 +657,77 @@ CONFIG_PKG_ESP_IDF_VER="latest" # CONFIG_PKG_USING_RTDUINO is not set # -# Sensor libraries +# Projects +# +# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set +# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set + +# +# Sensors # # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SENSOR is not set -# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BUSIO is not set # CONFIG_PKG_USING_ARDUINO_ADAFRUIT_AHTX0 is not set -# CONFIG_PKG_USING_ARDUINO_DHT_SENSOR is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BMP280 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_INA219 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DHT is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_MAX1704X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ICM20X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_DPS310 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT4X is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_SHT31 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_ADXL343 is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BME280 is not set # CONFIG_PKG_USING_ARDUINO_SEEED_BMP280 is not set # CONFIG_PKG_USING_ARDUINO_SEEED_LIS3DHTR is not set # CONFIG_PKG_USING_ARDUINO_CAPACITIVESENSOR is not set # -# Display libraries +# Display # # CONFIG_PKG_USING_ARDUINO_U8G2 is not set # -# Timing libraries +# Timing # # CONFIG_PKG_USING_ARDUINO_MSTIMER2 is not set # -# Project libraries +# Data Processing +# +# CONFIG_PKG_USING_ARDUINO_KALMANFILTER is not set + +# +# Data Storage +# + +# +# Communication +# + +# +# Device Control +# + +# +# Other +# + +# +# Signal IO +# +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_BUSIO is not set +# CONFIG_PKG_USING_ARDUINO_ADAFRUIT_TCA8418 is not set + +# +# Uncategorized # -# CONFIG_PKG_USING_ARDUINO_ULTRASOUND_RADAR is not set -# CONFIG_PKG_USING_ARDUINO_SENSOR_KIT is not set CONFIG_SOC_ESPRESSIF=y CONFIG_SOC_ESP32_C3=y # # Hardware Drivers Config # +# CONFIG_BSP_USING_LOCAL_ESP_IDF is not set CONFIG_BSP_BOARD_LUATOS_ESP32C3=y # CONFIG_BSP_BOARD_HX_EXP32C3 is not set diff --git a/bsp/ESP32_C3/CMakeLists.txt b/bsp/ESP32_C3/CMakeLists.txt index 8c321af8d4..8e74c5b76a 100644 --- a/bsp/ESP32_C3/CMakeLists.txt +++ b/bsp/ESP32_C3/CMakeLists.txt @@ -1,6 +1,5 @@ -# The following lines of boilerplate have to be in your project's -# CMakeLists in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.16) set(COMPONENTS esptool_py main) include($ENV{IDF_PATH}/tools/cmake/project.cmake) +set(freertos_root /Users/tangyi/rt-thread/bsp/ESP32_C3/packages/FreeRTOS_Wrapper-latest/FreeRTOS) project(rtthread) diff --git a/bsp/ESP32_C3/README.md b/bsp/ESP32_C3/README.md index 1fb7a5c787..2af3935bf6 100644 --- a/bsp/ESP32_C3/README.md +++ b/bsp/ESP32_C3/README.md @@ -43,33 +43,55 @@ Each peripheral supporting condition for this BSP is as follows: | UART | Support | Using LUATOS_ESP32C3 development board requires connecting serial port to USB chip UART0_TX and UART0_RX (such as CP2102) | | JTAG debug | Support | ESP32C3 usb-linked development boards can be debugged | -## Quick Start Guide - -1. Download ESP-IDF package +## Install ESP-IDF +ESP-IDF can be installed in two ways +1. Use Env tool +- Download the package ``` pkgs --update ``` -2. Go to ESP-IDF package directory and install IDF tools. This command only needs to be run once after the package is downloaded for the first time. +- Go to ESP-IDF package directory and install IDF tools. This command only needs to be run once after the package is downloaded for the first time. ``` cd packages/ESP-IDF-latest ./install.sh # Use install.bat in Windows environment ``` -3. Under the ESP-IDF package directory, export IDF environment variables. This commands need to be run every time when the BSP is built in a new terminal. +- Under the ESP-IDF package directory, export IDF environment variables. This commands need to be run every time when the BSP is built in a new terminal. ``` . export.sh # Use export.bat in Windows environment ``` -4. Configure RT-Thread under the BSP directory +2. Apply patch to a local installation of ESP-IDF +- Select the below option with `SCons --menuconfig` +``` +Hardware Drivers Config + [*] Use local ESP-IDF installation +``` +And deselect ESP-IDF package +``` +RT-Thread online packages + peripheral libraries and drivers + [ ] ESP-IDF: Espressif IoT Development Framework +``` +- Any convenient method to install ESP-IDF can be used, such as [VSCode plugin](https://github.com/espressif/vscode-esp-idf-extension/blob/master/docs/tutorial/install.md). Make sure to install the master version of ESP-IDF. +- Enter the local ESP-IDF directory and run the following commands +``` +git checkout 5c1044d84d625219eafa18c24758d9f0e4006b2c +# Replace rtt.patch with the actual directory of rtt.patch under the BSP directory +git am rtt.patch +``` +- After applying the patch, ESP-IDF FreeRTOS projects can be compiled as usual +## Compile and Upload +- Configure RT-Thread under the BSP directory ``` scons --menuconfig ``` -5. Whenever RT-Thread configuration is changed with `scons --menuconfig`, a new `CMakeLists.txt` needs to be generated with the command below +- Whenever RT-Thread configuration is changed with `scons --menuconfig`, a new `CMakeLists.txt` needs to be generated with the command below ``` scons --target=esp-idf ``` -6. Use `idf.py` to compile and upload the program. Refer to [Espressif official documents](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html#build-your-first-project) for reference. -7. Once the project is successfully downloaded, the system runs automatically, the red LED will blink in 1s on cycles. +- If ESP-IDf is installed using Env, use `idf.py` to compile and upload the program. Refer to [Espressif official documents](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html#build-your-first-project) for reference. Otherwise follow the appropriate steps depending on how ESP-IDF was installed, such as using [VSCode plugin](https://github.com/espressif/vscode-esp-idf-extension/blob/master/docs/tutorial/install.md). +- Once the project is successfully downloaded, the system runs automatically, the red LED will blink in 1s on cycles. ## Notes diff --git a/bsp/ESP32_C3/README_ZH.md b/bsp/ESP32_C3/README_ZH.md index 6502a01260..d4595a6e4e 100644 --- a/bsp/ESP32_C3/README_ZH.md +++ b/bsp/ESP32_C3/README_ZH.md @@ -50,33 +50,56 @@ | UART | 支持 | 使用LUATOS_ESP32C3开发板需要在UART0_TX和UART0_RX连接串口转USB芯片(如CP2102)| | JTAG调试 | 支持 | ESP32C3采用USB方式和PC链接的开发板可以调试 | -## 使用说明 - -1. 下载ESP-IDF软件包 +## 安装ESP-IDF +可以使用两种方法安装ESP-IDF +1. 使用Env工具安装 +- 下载软件包 ``` pkgs --update ``` -2. 进入到ESP-IDF软件包路径,安装IDf工具链。此命令只需要在下载完软件包后执行一次。 +- 进入到ESP-IDF软件包路径,安装IDf工具链。此命令只需要在下载完软件包后执行一次。 ``` cd packages/ESP-IDF-latest ./install.sh # Windows环境下使用install.bat ``` -3. 在软件包路径下设置IDF路径。每当在新的命令行编译BSP时需要执行此命令。 +- 在软件包路径下设置IDF路径。每当在新的命令行编译BSP时需要执行此命令。 ``` . export.sh # Windows环境下使用export.bat ``` -4. 在BSP路径下配置RT-Thread +2. 在本地ESP-IDF加载patch +- 通过`SCons --menuconfig`选择 +``` +Hardware Drivers Config + [*] Use local ESP-IDF installation +``` +并取消勾选ESP-IDF软件包 +``` +RT-Thread online packages + peripheral libraries and drivers + [ ] ESP-IDF: Espressif IoT Development Framework +``` +- 可以选择其他方式在本地安装ESP-IDF,如[VSCode插件](https://github.com/espressif/vscode-esp-idf-extension/blob/master/docs/tutorial/install.md)。确保安装的ESP-IDF是master版本。 +- 进入本地ESP-IDF目录执行以下命令 +``` +git checkout 5c1044d84d625219eafa18c24758d9f0e4006b2c +# 把rtt.patch换成BSP目录下rtt.patch的正确路径 +git am rtt.patch +``` +- 加载patch后不会影响使用ESP-IDF编译基于FreeRTOS的工程 + +## 编译和烧录 +1. 在BSP路径下配置RT-Thread ``` scons --menuconfig ``` -5. 每当使用`scons --menuconfig`更改RT-Thread配置后需要重新生成`CMakeLists.txt`。 +2. 每当使用`scons --menuconfig`更改RT-Thread配置后需要重新生成`CMakeLists.txt`。 ``` scons --target=esp-idf ``` -6. 使用`idf.py`命令编译,烧录。具体参考[乐鑫官网](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html#build-your-first-project) -7. 下载程序成功之后,系统会运行,红色的 LED灯以 1S 周期闪烁。 +3. 如果使用Env安装了ESP-IDF,使用`idf.py`命令编译,烧录。具体参考[乐鑫官网](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html#build-your-first-project)。如果使用了在本地ESP-IDF加载patch的方式,可使用其他相应的编译和烧录方法,如[VSCode插件](https://github.com/espressif/vscode-esp-idf-extension/blob/master/docs/tutorial/install.md)。 +4. 下载程序成功之后,系统会运行,红色的 LED灯以 1S 周期闪烁。 ## 注意事项 diff --git a/bsp/ESP32_C3/drivers/Kconfig b/bsp/ESP32_C3/drivers/Kconfig index fe413502f2..2d4afd0f30 100644 --- a/bsp/ESP32_C3/drivers/Kconfig +++ b/bsp/ESP32_C3/drivers/Kconfig @@ -7,11 +7,15 @@ config SOC_ESP32_C3 select SOC_ESPRESSIF select RT_USING_COMPONENTS_INIT select RT_USING_USER_MAIN - select PKG_USING_ESP_IDF + select PKG_USING_ESP_IDF if BSP_USING_LOCAL_ESP_IDF = n default y menu "Hardware Drivers Config" +config BSP_USING_LOCAL_ESP_IDF + bool "Use local ESP-IDF installation" + default n + choice prompt "Select BSP board " default BSP_BOARD_LUATOS_ESP32C3 diff --git a/bsp/ESP32_C3/rtconfig.h b/bsp/ESP32_C3/rtconfig.h index fea81a32b3..b04847a6d1 100644 --- a/bsp/ESP32_C3/rtconfig.h +++ b/bsp/ESP32_C3/rtconfig.h @@ -176,16 +176,33 @@ /* Arduino libraries */ -/* Sensor libraries */ +/* Projects */ -/* Display libraries */ +/* Sensors */ -/* Timing libraries */ +/* Display */ -/* Project libraries */ +/* Timing */ + + +/* Data Processing */ + + +/* Data Storage */ + +/* Communication */ + +/* Device Control */ + +/* Other */ + +/* Signal IO */ + + +/* Uncategorized */ #define SOC_ESPRESSIF #define SOC_ESP32_C3 diff --git a/bsp/ESP32_C3/rtt.patch b/bsp/ESP32_C3/rtt.patch index e4f3d431f9..37c41b76b0 100644 --- a/bsp/ESP32_C3/rtt.patch +++ b/bsp/ESP32_C3/rtt.patch @@ -1,22 +1,28 @@ -From 3d7fabf23eeae26b7d739fbb649090aa590dcf3b Mon Sep 17 00:00:00 2001 -From: supperthomas <78900636@qq.com> -Date: Fri, 6 May 2022 23:06:28 +0800 -Subject: [PATCH 1/4] add the config of RTTHREAD +From 92402217b821c8da7e2a188352f095caaf0818d1 Mon Sep 17 00:00:00 2001 +From: tangzz98 +Date: Tue, 13 Sep 2022 18:05:44 -0400 +Subject: [PATCH 1/2] Add config for RT-Thread -add the init link file --- Kconfig | 4 + - .../esp_system/ld/esp32c3/sections.ld.in | 26 +++ - components/freertos/port/port_common.c | 5 + - components/freertos/port/port_systick.c | 3 + - components/riscv/vectors.S | 220 ++++++++++++++++-- - 5 files changed, 239 insertions(+), 19 deletions(-) + components/driver/deprecated/i2s_legacy.c | 4 + + components/driver/uart.c | 4 + + components/esp_system/crosscore_int.c | 5 +- + .../esp_system/ld/esp32c3/sections.ld.in | 37 ++++ + .../port/arch/riscv/expression_with_stack.c | 8 + + components/esp_system/startup.c | 9 + + components/esp_system/task_wdt.c | 4 + + components/esp_timer/src/esp_timer.c | 2 + + components/freertos/CMakeLists.txt | 50 ++++- + .../freertos_tasks_c_additions.h | 6 +- + components/riscv/vectors.S | 179 ++++++++++++++++++ + 12 files changed, 309 insertions(+), 3 deletions(-) diff --git a/Kconfig b/Kconfig -index 928d274106..d368adaa37 100644 +index c86ebeaaef..56d062b2db 100644 --- a/Kconfig +++ b/Kconfig -@@ -61,6 +61,10 @@ mainmenu "Espressif IoT Development Framework Configuration" +@@ -101,6 +101,10 @@ mainmenu "Espressif IoT Development Framework Configuration" bool default "y" if IDF_TARGET="linux" @@ -27,18 +33,80 @@ index 928d274106..d368adaa37 100644 config IDF_FIRMWARE_CHIP_ID hex default 0x0000 if IDF_TARGET_ESP32 +diff --git a/components/driver/deprecated/i2s_legacy.c b/components/driver/deprecated/i2s_legacy.c +index 2e36ab2608..92edf9d2bb 100644 +--- a/components/driver/deprecated/i2s_legacy.c ++++ b/components/driver/deprecated/i2s_legacy.c +@@ -1600,7 +1600,11 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config, + i2s_obj->i2s_queue = xQueueCreate(queue_size, sizeof(i2s_event_t)); + ESP_GOTO_ON_FALSE(i2s_obj->i2s_queue, ESP_ERR_NO_MEM, err, TAG, "I2S queue create failed"); + *((QueueHandle_t *) i2s_queue) = i2s_obj->i2s_queue; ++#if !defined CONFIG_IDF_RTOS_RTTHREAD + ESP_LOGD(TAG, "queue free spaces: %d", uxQueueSpacesAvailable(i2s_obj->i2s_queue)); ++#else ++ ESP_LOGD(TAG, "queue free spaces: %lu", uxQueueSpacesAvailable(i2s_obj->i2s_queue)); ++#endif + } else { + i2s_obj->i2s_queue = NULL; + } +diff --git a/components/driver/uart.c b/components/driver/uart.c +index b68b2900e1..63c9841380 100644 +--- a/components/driver/uart.c ++++ b/components/driver/uart.c +@@ -1603,7 +1603,11 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b + uart_pattern_queue_reset(uart_num, UART_PATTERN_DET_QLEN_DEFAULT); + if (uart_queue) { + *uart_queue = p_uart_obj[uart_num]->event_queue; ++#if !defined CONFIG_IDF_RTOS_RTTHREAD + ESP_LOGI(UART_TAG, "queue free spaces: %d", uxQueueSpacesAvailable(p_uart_obj[uart_num]->event_queue)); ++#else ++ ESP_LOGI(UART_TAG, "queue free spaces: %lu", uxQueueSpacesAvailable(p_uart_obj[uart_num]->event_queue)); ++#endif + } + } else { + ESP_LOGE(UART_TAG, "UART driver already installed"); +diff --git a/components/esp_system/crosscore_int.c b/components/esp_system/crosscore_int.c +index 4aae2a2540..8a9079de64 100644 +--- a/components/esp_system/crosscore_int.c ++++ b/components/esp_system/crosscore_int.c +@@ -95,13 +95,14 @@ static void IRAM_ATTR esp_crosscore_isr(void *arg) { + if (my_reason_val & REASON_PRINT_BACKTRACE) { + esp_backtrace_print(100); + } +- ++#ifdef CONFIG_ESP_TASK_WDT + if (my_reason_val & REASON_TWDT_ABORT) { + extern void task_wdt_timeout_abort_xtensa(bool); + /* Called from a crosscore interrupt, thus, we are not the core that received + * the TWDT interrupt, call the function with `false` as a parameter. */ + task_wdt_timeout_abort_xtensa(false); + } ++#endif + #endif // CONFIG_IDF_TARGET_ARCH_XTENSA + } + +@@ -171,7 +172,9 @@ void IRAM_ATTR esp_crosscore_int_send_print_backtrace(int core_id) + esp_crosscore_int_send(core_id, REASON_PRINT_BACKTRACE); + } + ++#ifdef CONFIG_ESP_TASK_WDT + void IRAM_ATTR esp_crosscore_int_send_twdt_abort(int core_id) { + esp_crosscore_int_send(core_id, REASON_TWDT_ABORT); + } + #endif ++#endif diff --git a/components/esp_system/ld/esp32c3/sections.ld.in b/components/esp_system/ld/esp32c3/sections.ld.in -index 0ebeda06c1..8215237fff 100644 +index d6670bf759..1d51ffeea0 100644 --- a/components/esp_system/ld/esp32c3/sections.ld.in +++ b/components/esp_system/ld/esp32c3/sections.ld.in -@@ -183,6 +183,32 @@ SECTIONS +@@ -178,6 +178,26 @@ SECTIONS _noinit_end = ABSOLUTE(.); } > dram0_0_seg -+ .stack_dummy (COPY): ++ .stack : + { + . = ALIGN(8); -+ __STACKSIZE__ = 40960; ++ __STACKSIZE__ = 40960; + __stack_start__ = .; + *(.stack*) + . += __STACKSIZE__; @@ -46,71 +114,263 @@ index 0ebeda06c1..8215237fff 100644 + __stack_end__ = .; + } > dram0_0_seg + -+ .stack_dummy (COPY): ++ .heap : + { + . = ALIGN(8); -+ __HEAPSIZE__ = 40960; ++ __HEAPSIZE__ = 40960; + __heap_start__ = .; -+ . += __STACKSIZE__; ++ . += __HEAPSIZE__; + __heap_end__ = .; -+ /* section information for initial. */ -+ . = ALIGN(4); -+ __rt_init_start = .; -+ KEEP(*(SORT(.rti_fn*))) -+ __rt_init_end = .; -+ -+ . = ALIGN(4); + } > dram0_0_seg ++ /* Shared RAM */ .dram0.bss (NOLOAD) : { -diff --git a/components/freertos/port/port_common.c b/components/freertos/port/port_common.c -index ffca3d5429..9d8159f588 100644 ---- a/components/freertos/port/port_common.c -+++ b/components/freertos/port/port_common.c -@@ -74,11 +74,16 @@ void esp_startup_start_app_common(void) - esp_gdbstub_init(); - #endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME +@@ -218,6 +238,17 @@ SECTIONS + *(.fini) + *(.gnu.version) + ++ /* section information for finsh shell */ ++ . = ALIGN(8); ++ __fsymtab_start = .; ++ KEEP(*(FSymTab)) ++ __fsymtab_end = .; ++ . = ALIGN(8); ++ __vsymtab_start = .; ++ KEEP(*(VSymTab)) ++ __vsymtab_end = .; ++ . = ALIGN(8); ++ + /** CPU will try to prefetch up to 16 bytes of + * of instructions. This means that any configuration (e.g. MMU, PMS) must allow + * safe access to up to 16 bytes after the last real instruction, add +@@ -318,6 +349,12 @@ SECTIONS + _esp_system_init_fn_array_start = ABSOLUTE(.); + KEEP (*(SORT_BY_INIT_PRIORITY(.esp_system_init_fn.*))) + _esp_system_init_fn_array_end = ABSOLUTE(.); ++ /* section information for initial. */ ++ . = ALIGN(4); ++ __rt_init_start = .; ++ KEEP(*(SORT(.rti_fn*))) ++ __rt_init_end = .; ++ . = ALIGN(4); + _rodata_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); +diff --git a/components/esp_system/port/arch/riscv/expression_with_stack.c b/components/esp_system/port/arch/riscv/expression_with_stack.c +index 07d22bf3aa..5eac5a88f8 100644 +--- a/components/esp_system/port/arch/riscv/expression_with_stack.c ++++ b/components/esp_system/port/arch/riscv/expression_with_stack.c +@@ -18,6 +18,8 @@ + #include "freertos/FreeRTOS.h" + #include "freertos/portmacro.h" + ++#if !defined CONFIG_IDF_RTOS_RTTHREAD ++ + static portMUX_TYPE shared_stack_spinlock = portMUX_INITIALIZER_UNLOCKED; + static void *current_task_stack = NULL; + +@@ -46,9 +48,12 @@ static StackType_t *esp_switch_stack_setup(StackType_t *stack, size_t stack_size + return ((StackType_t *)adjusted_top_of_stack); + } -+#ifdef CONFIG_IDF_RTOS_RTTHREAD -+ app_main(); -+#else - portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main", - ESP_TASK_MAIN_STACK, NULL, - ESP_TASK_MAIN_PRIO, NULL, ESP_TASK_MAIN_CORE); - assert(res == pdTRUE); - (void)res; +#endif + - } - static void main_task(void* args) -diff --git a/components/freertos/port/port_systick.c b/components/freertos/port/port_systick.c -index 0c14a155a1..0fa203574b 100644 ---- a/components/freertos/port/port_systick.c -+++ b/components/freertos/port/port_systick.c -@@ -116,6 +116,8 @@ void vPortSetupTimer(void) - */ - IRAM_ATTR void SysTickIsrHandler(void *arg) + void esp_execute_shared_stack_function(SemaphoreHandle_t lock, void *stack, size_t stack_size, shared_stack_function function) { -+#ifdef CONFIG_IDF_RTOS_RTTHREAD ++#if !defined CONFIG_IDF_RTOS_RTTHREAD + assert(lock); + assert(stack); + assert(stack_size > 0 && stack_size >= CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE); +@@ -70,4 +75,7 @@ void esp_execute_shared_stack_function(SemaphoreHandle_t lock, void *stack, size + portEXIT_CRITICAL(&shared_stack_spinlock); + + xSemaphoreGive(lock); +#else - uint32_t cpuid = xPortGetCoreID(); - systimer_hal_context_t *systimer_hal = (systimer_hal_context_t *)arg; - #ifdef CONFIG_PM_TRACE -@@ -144,6 +146,7 @@ IRAM_ATTR void SysTickIsrHandler(void *arg) - #ifdef CONFIG_PM_TRACE - ESP_PM_TRACE_EXIT(TICK, cpuid); - #endif ++ function(); +#endif } +diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c +index 0feda4e9f5..b1752d91a0 100644 +--- a/components/esp_system/startup.c ++++ b/components/esp_system/startup.c +@@ -72,6 +72,10 @@ + #include "esp_psram.h" + #include "esp_private/esp_psram_extram.h" + #endif ++ ++#if CONFIG_IDF_RTOS_RTTHREAD ++#include "rtthread.h" ++#endif + /***********************************************/ - #endif // CONFIG_FREERTOS_SYSTICK_USES_CCOUNT + #include "esp_private/startup_internal.h" +@@ -266,6 +270,11 @@ static void do_core_init(void) + app CPU, and when that is not up yet, the memory will be inaccessible and heap_caps_init may + fail initializing it properly. */ + heap_caps_init(); ++#if CONFIG_IDF_RTOS_RTTHREAD && defined RT_USING_HEAP ++ extern int __heap_start__; ++ extern int __heap_end__; ++ rt_system_heap_init((void *)&__heap_start__, (void *)&__heap_end__); ++#endif + + // When apptrace module is enabled, there will be SEGGER_SYSVIEW calls in the newlib init. + // SEGGER_SYSVIEW relies on apptrace module +diff --git a/components/esp_system/task_wdt.c b/components/esp_system/task_wdt.c +index 58d1247bf0..60330edf8a 100644 +--- a/components/esp_system/task_wdt.c ++++ b/components/esp_system/task_wdt.c +@@ -29,6 +29,8 @@ + #include "esp_private/eh_frame_parser.h" + #endif // CONFIG_ESP_SYSTEM_USE_EH_FRAME + ++#if CONFIG_ESP_TASK_WDT ++ + #if CONFIG_IDF_TARGET_ARCH_RISCV && !CONFIG_ESP_SYSTEM_USE_EH_FRAME + /* Function used to print all the registers pointed by the given frame .*/ + extern void panic_print_registers(const void *frame, int core); +@@ -784,3 +786,5 @@ esp_err_t esp_task_wdt_status(TaskHandle_t task_handle) + + return ret; + } ++ ++#endif +diff --git a/components/esp_timer/src/esp_timer.c b/components/esp_timer/src/esp_timer.c +index 3ca19f642f..78779a08b3 100644 +--- a/components/esp_timer/src/esp_timer.c ++++ b/components/esp_timer/src/esp_timer.c +@@ -460,10 +460,12 @@ out: + return ESP_ERR_NO_MEM; + } + ++#if !defined CONFIG_IDF_RTOS_RTTHREAD + ESP_SYSTEM_INIT_FN(esp_timer_startup_init, BIT(0), 100) + { + return esp_timer_init(); + } ++#endif + + esp_err_t esp_timer_deinit(void) + { +diff --git a/components/freertos/CMakeLists.txt b/components/freertos/CMakeLists.txt +index 78a8e4ae4e..5cd54494f6 100644 +--- a/components/freertos/CMakeLists.txt ++++ b/components/freertos/CMakeLists.txt +@@ -6,7 +6,36 @@ endif() + + idf_build_get_property(target IDF_TARGET) + +-if(CONFIG_FREERTOS_SMP) ++if(CONFIG_IDF_RTOS_RTTHREAD) ++ set(freertos_root "../../../FreeRTOS_Wrapper-latest/FreeRTOS") ++ set(srcs ++ "${freertos_root}/portable/esp-idf/riscv/port.c") ++ ++ set(include_dirs ++ "${freertos_root}/include" ++ esp_additions/include ++ esp_additions/include/freertos ++ "${freertos_root}/portable/esp-idf/riscv/include") ++ ++ set(private_include_dirs ++ "${freertos_root}/portable/esp-idf/riscv/include/freertos") ++ ++ list(APPEND srcs ++ "${freertos_root}/portable/esp-idf/port_common.c" ++ "${freertos_root}/portable/esp-idf/port_rt.c" ++ "${freertos_root}/event_groups.c" ++ "${freertos_root}/queue.c" ++ "${freertos_root}/tasks.c" ++ "${freertos_root}/timers.c" ++ "${freertos_root}/list.c" ++ "FreeRTOS-openocd.c" ++ "esp_additions/freertos_v8_compat.c") ++ ++ list(APPEND private_include_dirs ++ "${freertos_root}/include/freertos" ++ "esp_additions/private_include") ++ ++elseif(CONFIG_FREERTOS_SMP) + set(ldfragments linker_smp.lf) + if(CONFIG_IDF_TARGET_ARCH_XTENSA) + set(srcs +@@ -133,11 +162,19 @@ else() + endif() + endif() + ++if(CONFIG_IDF_RTOS_RTTHREAD) ++idf_component_register(SRCS "${srcs}" ++ INCLUDE_DIRS ${include_dirs} ++ PRIV_INCLUDE_DIRS ${private_include_dirs} ++ PRIV_REQUIRES soc esp_pm) ++else() + idf_component_register(SRCS "${srcs}" + INCLUDE_DIRS ${include_dirs} + PRIV_INCLUDE_DIRS ${private_include_dirs} + LDFRAGMENTS "${ldfragments}" ++ REQUIRES main + PRIV_REQUIRES soc esp_pm) ++endif() + + idf_component_get_property(COMPONENT_DIR freertos COMPONENT_DIR) + +@@ -153,6 +190,16 @@ if(CONFIG_FREERTOS_DEBUG_OCDAWARE) + idf_build_set_property(COMPILE_OPTIONS "-DconfigENABLE_FREERTOS_DEBUG_OCDAWARE=1" APPEND) + endif() + ++if(CONFIG_IDF_RTOS_RTTHREAD) ++set_source_files_properties( ++ tasks.c ++ event_groups.c ++ timers.c ++ queue.c ++ PROPERTIES COMPILE_DEFINITIONS ++ _ESP_FREERTOS_INTERNAL ++ ) ++else() + set_source_files_properties( + tasks.c + event_groups.c +@@ -162,6 +209,7 @@ set_source_files_properties( + PROPERTIES COMPILE_DEFINITIONS + _ESP_FREERTOS_INTERNAL + ) ++endif() + + # The freertos component provides the `start_app` and `start_app_other_cores` + # if it is included in the build. It then calls `app_main` +diff --git a/components/freertos/esp_additions/private_include/freertos_tasks_c_additions.h b/components/freertos/esp_additions/private_include/freertos_tasks_c_additions.h +index f5ecdbb5a9..96fc4f73ce 100644 +--- a/components/freertos/esp_additions/private_include/freertos_tasks_c_additions.h ++++ b/components/freertos/esp_additions/private_include/freertos_tasks_c_additions.h +@@ -34,8 +34,9 @@ + struct _reent *__getreent(void) + { + // No lock needed because if this changes, we won't be running anymore. +- TCB_t *pxCurTask = xTaskGetCurrentTaskHandle(); + struct _reent *ret; ++#if !defined CONFIG_IDF_RTOS_RTTHREAD ++ TCB_t *pxCurTask = xTaskGetCurrentTaskHandle(); + if (pxCurTask == NULL) { + // No task running. Return global struct. + ret = _GLOBAL_REENT; +@@ -43,6 +44,9 @@ struct _reent *__getreent(void) + // We have a task; return its reentrant struct. + ret = &pxCurTask->xNewLib_reent; + } ++#else ++ ret = _GLOBAL_REENT; ++#endif + return ret; + } + #endif // configUSE_NEWLIB_REENTRANT == 1 diff --git a/components/riscv/vectors.S b/components/riscv/vectors.S -index 1006d5bea5..963494fcb3 100644 +index 9b868280db..23236f3d8d 100644 --- a/components/riscv/vectors.S +++ b/components/riscv/vectors.S -@@ -17,6 +17,9 @@ +@@ -10,6 +10,9 @@ #include "soc/soc_caps.h" #include "sdkconfig.h" @@ -118,102 +378,21 @@ index 1006d5bea5..963494fcb3 100644 +#define LOAD lw +#define REGBYTES 4 - .equ SAVE_REGS, 32 - .equ CONTEXT_SIZE, (SAVE_REGS * 4) -@@ -218,25 +221,27 @@ _call_panic_handler: - */ - .global _interrupt_handler - .type _interrupt_handler, @function + .equ SAVE_REGS, 32 + .equ CONTEXT_SIZE, (SAVE_REGS * 4) +@@ -210,6 +213,8 @@ _return_from_exception: + */ + .global _interrupt_handler + .type _interrupt_handler, @function +#ifndef CONFIG_IDF_RTOS_RTTHREAD + _interrupt_handler: - /* entry */ -- save_regs -- save_mepc -+ save_regs /* 保存寄存器 */ -+ save_mepc /* 保存MEPC */ - - /* Before doing anythig preserve the stack pointer */ - /* It will be saved in current TCB, if needed */ -- mv a0, sp -+ mv a0, sp /* 保存SP a0 = sp */ - call rtos_int_enter - - /* Before dispatch c handler, restore interrupt to enable nested intr */ -- csrr s1, mcause -- csrr s2, mstatus -+ csrr s1, mcause /* 保存mcause s1 = mcause */ -+ csrr s2, mstatus /* 保存mstatus s2 = mstatus */ - -- /* Save the interrupt threshold level */ -- la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG -- lw s3, 0(t0) -+ /* Save the interrupt threshold level 保存中断嵌套层数? */ -+ la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG /* 保存mstatus t0 = &INTERRUPT_CORE0_CPU_INT_THRESH_REG */ -+ lw s3, 0(t0) /* s3 = mstatus */ - -- /* Increase interrupt threshold level */ -+ /* Increase interrupt threshold level 增加中断嵌套层数*/ - li t2, 0x7fffffff - and t1, s1, t2 /* t1 = mcause & mask */ - slli t1, t1, 2 /* t1 = mcause * 4 */ -@@ -247,8 +252,8 @@ _interrupt_handler: - sw t2, 0(t0) /* INTERRUPT_CORE0_CPU_INT_THRESH_REG = t2 */ - fence - -- li t0, 0x8 -- csrrs t0, mstatus, t0 -+ li t0, 0x8 /* t0 = 8 */ -+ csrrs t0, mstatus, t0 /*设置状态MIE寄存器,开总中断*/ - - #ifdef CONFIG_PM_TRACE - li a0, 0 /* = ESP_PM_TRACE_IDLE */ -@@ -269,34 +274,211 @@ _interrupt_handler: - /* call the C dispatcher */ - mv a0, sp /* argument 1, stack pointer */ - mv a1, s1 /* argument 2, interrupt number (mcause) */ -- /* mask off the interrupt flag of mcause */ -+ /* mask off the interrupt flag of mcause 屏幕异常中断*/ - li t0, 0x7fffffff - and a1, a1, t0 - jal _global_interrupt_handler - -- /* After dispatch c handler, disable interrupt to make freertos make context switch */ -+ /* After dispatch c handler, disable interrupt to make freertos make context switch -+ 在调用c函数之后,disable 中断让freertos能够做内容切换 -+ */ - - li t0, 0x8 -- csrrc t0, mstatus, t0 -+ csrrc t0, mstatus, t0 /*清状态MIE寄存器 关总中断*/ - -- /* restore the interrupt threshold level */ -+ -+ /* restore the interrupt threshold level 中断嵌套 */ - la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG - sw s3, 0(t0) - fence - - /* Yield to the next task is needed: */ -- mv a0, sp -+ mv a0, sp /* a0 = sp*/ - call rtos_int_exit - - /* The next (or current) stack pointer is returned in a0 */ -- mv sp, a0 -+ mv sp, a0 /* sp = a0*/ - - /* restore the rest of the registers */ -- csrw mcause, s1 -- csrw mstatus, s2 -+ csrw mcause, s1 /* mcause = s1 */ -+ csrw mstatus, s2 /* mstatus = s2 */ - restore_mepc - restore_regs - - /* exit, this will also re-enable the interrupts */ - mret - .size _interrupt_handler, .-_interrupt_handler + /* Start by saving the general purpose registers and the PC value before + * the interrupt happened. */ +@@ -308,3 +313,177 @@ _interrupt_handler: + /* exit, this will also re-enable the interrupts */ + mret + .size _interrupt_handler, .-_interrupt_handler +#else +_interrupt_handler: + /* 此时CPU的sp = from_thread->sp */ @@ -320,7 +499,7 @@ index 1006d5bea5..963494fcb3 100644 + beqz s2, spurious_interrupt /* if (s2 == 0) goto spurious_interrupt; else 执行下一条语句*/ + + /* 需要上下文切换: 主要目的是将CPU的sp指针,赋值为to_thread的sp */ -+ ++ + /* 将 s0 所执向的地址的内容设置为0, 也就是,将变量 rt_thread_switch_interrupt_flag 赋值为了 0 */ + /* s0存放的值是 rt_thread_switch_interrupt_flag 变量的地址*/ + sw zero, 0(s0) /* *s0 = 0; 也就是 rt_thread_switch_interrupt_flag = 0 */ @@ -335,7 +514,7 @@ index 1006d5bea5..963494fcb3 100644 + la s0, rt_interrupt_from_thread /* s0 = &rt_interrupt_from_thread 注意: rt_interrupt_from_thread = &(from_thread->sp) */ + LOAD s1, 0(s0) /* s1 = rt_interrupt_from_thread,也就是s1 = &(from_thread->sp) */ + STORE sp, 0(s1) /* from_thread->sp = sp*/ -+ ++ + /* 接下来,需要开始恢复CPU的sp为to_thread的sp了 */ + la s0, rt_interrupt_to_thread /* s0 = &rt_interrupt_to_thread 注意: rt_interrupt_to_thread = &(to_thred->sp)*/ + LOAD s1, 0(s0) /* s1 = rt_interrupt_to_thread, 也就是s1 = &(to_thred->sp) */ @@ -388,14986 +567,33 @@ index 1006d5bea5..963494fcb3 100644 + mret + .size _interrupt_handler, .-_interrupt_handler +#endif +\ No newline at end of file -- 2.32.0 (Apple Git-132) -From d0d1f625543282df462af56cc18abaa5a47d4f40 Mon Sep 17 00:00:00 2001 -From: supperthomas <78900636@qq.com> -Date: Sat, 9 Jul 2022 21:37:53 +0800 -Subject: [PATCH 2/4] remove submodule - -remove submodule ---- - .gitmodules | 111 ---------------------------------------------------- - 1 file changed, 111 deletions(-) - -diff --git a/.gitmodules b/.gitmodules -index 49edc68e10..8b13789179 100644 ---- a/.gitmodules -+++ b/.gitmodules -@@ -1,112 +1 @@ --# --# All the relative URL paths are intended to be GitHub ones --# For Espressif's public projects please use '../../espressif/proj', not a '../proj' --# - --[submodule "components/esptool_py/esptool"] -- path = components/esptool_py/esptool -- url = ../../espressif/esptool.git -- --[submodule "components/bt/controller/lib_esp32"] -- path = components/bt/controller/lib_esp32 -- url = ../../espressif/esp32-bt-lib.git -- --[submodule "components/bootloader/subproject/components/micro-ecc/micro-ecc"] -- path = components/bootloader/subproject/components/micro-ecc/micro-ecc -- url = ../../kmackay/micro-ecc.git -- --[submodule "components/coap/libcoap"] -- path = components/coap/libcoap -- url = ../../obgm/libcoap.git -- --[submodule "components/nghttp/nghttp2"] -- path = components/nghttp/nghttp2 -- url = ../../nghttp2/nghttp2.git -- --[submodule "components/libsodium/libsodium"] -- path = components/libsodium/libsodium -- url = ../../jedisct1/libsodium.git -- --[submodule "components/spiffs/spiffs"] -- path = components/spiffs/spiffs -- url = ../../pellepl/spiffs.git -- --[submodule "components/json/cJSON"] -- path = components/json/cJSON -- url = ../../DaveGamble/cJSON.git -- --[submodule "components/mbedtls/mbedtls"] -- path = components/mbedtls/mbedtls -- url = ../../espressif/mbedtls.git -- --[submodule "components/asio/asio"] -- path = components/asio/asio -- url = ../../espressif/asio.git -- --[submodule "components/expat/expat"] -- path = components/expat/expat -- url = ../../libexpat/libexpat.git -- --[submodule "components/lwip/lwip"] -- path = components/lwip/lwip -- url = ../../espressif/esp-lwip.git -- --[submodule "components/mqtt/esp-mqtt"] -- path = components/mqtt/esp-mqtt -- url = ../../espressif/esp-mqtt.git -- --[submodule "components/protobuf-c/protobuf-c"] -- path = components/protobuf-c/protobuf-c -- url = ../../protobuf-c/protobuf-c.git -- --[submodule "components/unity/unity"] -- path = components/unity/unity -- url = ../../ThrowTheSwitch/Unity.git -- --[submodule "examples/build_system/cmake/import_lib/main/lib/tinyxml2"] -- path = examples/build_system/cmake/import_lib/main/lib/tinyxml2 -- url = ../../leethomason/tinyxml2.git -- --[submodule "components/bt/host/nimble/nimble"] -- path = components/bt/host/nimble/nimble -- url = ../../espressif/esp-nimble.git -- --[submodule "components/cbor/tinycbor"] -- path = components/cbor/tinycbor -- url = ../../intel/tinycbor.git -- --[submodule "components/esp_wifi/lib"] -- path = components/esp_wifi/lib -- url = ../../espressif/esp32-wifi-lib.git -- --[submodule "components/tinyusb/tinyusb"] -- path = components/tinyusb/tinyusb -- url = ../../espressif/tinyusb.git -- --[submodule "examples/peripherals/secure_element/atecc608_ecdsa/components/esp-cryptoauthlib"] -- path = examples/peripherals/secure_element/atecc608_ecdsa/components/esp-cryptoauthlib -- url = ../../espressif/esp-cryptoauthlib.git -- --[submodule "components/cmock/CMock"] -- path = components/cmock/CMock -- url = ../../ThrowTheSwitch/CMock.git -- --[submodule "components/openthread/openthread"] -- path = components/openthread/openthread -- url = ../../espressif/openthread.git -- --[submodule "components/bt/controller/lib_esp32c3_family"] -- path = components/bt/controller/lib_esp32c3_family -- url = ../../espressif/esp32c3-bt-lib.git -- --[submodule "components/esp_phy/lib"] -- path = components/esp_phy/lib -- url = ../../espressif/esp-phy-lib.git -- --[submodule "components/openthread/lib"] -- path = components/openthread/lib -- url = ../../espressif/esp-thread-lib.git -- --[submodule "components/ieee802154/lib"] -- path = components/ieee802154/lib -- url = ../../espressif/esp-ieee802154-lib.git --- -2.32.0 (Apple Git-132) - - -From 29b9d1ebe7fe1c817428b856e208561ae0dc574b Mon Sep 17 00:00:00 2001 +From 394259fb2164e513abd4f0d23d88da92c2a2ac9e Mon Sep 17 00:00:00 2001 From: tangzz98 -Date: Sat, 30 Jul 2022 15:08:12 +0800 -Subject: [PATCH 3/4] Add FreeRTOS wrapper +Date: Fri, 23 Sep 2022 00:12:13 -0400 +Subject: [PATCH 2/2] Specify freertos_root in project CMakeLists.txt --- - .../include/esp_serial_slave_link/essl.h | 2 +- - .../port/arch/riscv/expression_with_stack.c | 6 + - components/esp_system/startup.c | 12 + - components/freertos/CMakeLists.txt | 73 +- - .../FreeRTOS/esp_additions/task_snapshot.c | 212 ++ - .../FreeRTOS/event_groups.c | 225 ++ - .../FreeRTOS/freertos_v8_compat.c | 33 + - .../esp_additions/freertos/FreeRTOSConfig.h | 326 +++ - .../esp_additions/freertos/task_snapshot.h | 90 + - .../FreeRTOS/include/freertos/FreeRTOS.h | 1198 +++++++++ - .../FreeRTOS/include/freertos/event_groups.h | 621 +++++ - .../FreeRTOS/include/freertos/list.h | 416 +++ - .../FreeRTOS/include/freertos/portable.h | 141 + - .../FreeRTOS/include/freertos/projdefs.h | 64 + - .../FreeRTOS/include/freertos/queue.h | 1188 +++++++++ - .../FreeRTOS/include/freertos/semphr.h | 1188 +++++++++ - .../FreeRTOS/include/freertos/task.h | 2265 +++++++++++++++++ - .../FreeRTOS/include/freertos/timers.h | 1185 +++++++++ - .../FreeRTOS/list.c | 213 ++ - .../FreeRTOS/port/MemMang/heap_1.c | 145 ++ - .../FreeRTOS/port/MemMang/heap_2.c | 277 ++ - .../FreeRTOS/port/MemMang/heap_3.c | 78 + - .../FreeRTOS/port/MemMang/heap_4.c | 447 ++++ - .../FreeRTOS/port/MemMang/heap_5.c | 506 ++++ - .../FreeRTOS/port/port_common.c | 203 ++ - .../include/freertos/FreeRTOSConfig_arch.h | 105 + - .../rt-thread/include/freertos/portmacro.h | 107 + - .../include/freertos/portmacro_deprecated.h | 94 + - .../include/freertos/portmacro_esp32c3.h | 424 +++ - .../FreeRTOS/port/rt-thread/port.c | 44 + - .../FreeRTOS/port/rt-thread/port_esp32c3.c | 197 ++ - .../FreeRTOS/queue.c | 787 ++++++ - .../FreeRTOS/tasks.c | 1254 +++++++++ - .../FreeRTOS/timers.c | 328 +++ - .../RT-Thread-wrapper-of-FreeRTOS/readme.md | 3 + - 35 files changed, 14436 insertions(+), 21 deletions(-) - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/esp_additions/task_snapshot.c - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/event_groups.c - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/freertos_v8_compat.c - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/esp_additions/freertos/FreeRTOSConfig.h - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/esp_additions/freertos/task_snapshot.h - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/FreeRTOS.h - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/event_groups.h - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/list.h - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/portable.h - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/projdefs.h - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/queue.h - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/semphr.h - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/task.h - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/timers.h - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/list.c - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_1.c - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_2.c - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_3.c - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_4.c - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_5.c - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/port_common.c - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/include/freertos/FreeRTOSConfig_arch.h - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/include/freertos/portmacro.h - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/include/freertos/portmacro_deprecated.h - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/include/freertos/portmacro_esp32c3.h - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/port.c - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/port_esp32c3.c - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/queue.c - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/tasks.c - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/timers.c - create mode 100644 components/freertos/RT-Thread-wrapper-of-FreeRTOS/readme.md + components/freertos/CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/components/esp_serial_slave_link/include/esp_serial_slave_link/essl.h b/components/esp_serial_slave_link/include/esp_serial_slave_link/essl.h -index f03274a401..e9bc4939c0 100644 ---- a/components/esp_serial_slave_link/include/esp_serial_slave_link/essl.h -+++ b/components/esp_serial_slave_link/include/esp_serial_slave_link/essl.h -@@ -160,7 +160,7 @@ esp_err_t essl_read_reg(essl_handle_t handle, uint8_t add, uint8_t *value_o, uin - * - ESP_ERR_NOT_SUPPORTED: Current device does not support this function. - * - ESP_ERR_TIMEOUT: No interrupts before timeout. - */ --esp_err_t essl_wait_int(essl_handle_t handle, uint32_t wait_ms); -+esp_err_t essl_wait_int(essl_handle_t handle, TickType_t wait_ms); - - /** Clear interrupt bits of ESSL slave. All the bits set in the mask will be cleared, while other bits will stay the same. - * -diff --git a/components/esp_system/port/arch/riscv/expression_with_stack.c b/components/esp_system/port/arch/riscv/expression_with_stack.c -index 07d22bf3aa..64c1e0689d 100644 ---- a/components/esp_system/port/arch/riscv/expression_with_stack.c -+++ b/components/esp_system/port/arch/riscv/expression_with_stack.c -@@ -18,6 +18,7 @@ - #include "freertos/FreeRTOS.h" - #include "freertos/portmacro.h" - -+#if !defined CONFIG_IDF_RTOS_RTTHREAD - static portMUX_TYPE shared_stack_spinlock = portMUX_INITIALIZER_UNLOCKED; - static void *current_task_stack = NULL; - -@@ -45,10 +46,12 @@ static StackType_t *esp_switch_stack_setup(StackType_t *stack, size_t stack_size - #endif - return ((StackType_t *)adjusted_top_of_stack); - } -+#endif - - - void esp_execute_shared_stack_function(SemaphoreHandle_t lock, void *stack, size_t stack_size, shared_stack_function function) - { -+#if !defined CONFIG_IDF_RTOS_RTTHREAD - assert(lock); - assert(stack); - assert(stack_size > 0 && stack_size >= CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE); -@@ -70,4 +73,7 @@ void esp_execute_shared_stack_function(SemaphoreHandle_t lock, void *stack, size - portEXIT_CRITICAL(&shared_stack_spinlock); - - xSemaphoreGive(lock); -+#else -+ function(); -+#endif - } -diff --git a/components/esp_system/startup.c b/components/esp_system/startup.c -index 139ae8b6a2..6c6acdf575 100644 ---- a/components/esp_system/startup.c -+++ b/components/esp_system/startup.c -@@ -56,6 +56,10 @@ - - #include "esp_rom_sys.h" - -+#if CONFIG_IDF_RTOS_RTTHREAD -+#include "rtthread.h" -+#endif -+ - // [refactor-todo] make this file completely target-independent - #if CONFIG_IDF_TARGET_ESP32 - #include "esp32/clk.h" -@@ -235,6 +239,14 @@ static void do_core_init(void) - app CPU, and when that is not up yet, the memory will be inaccessible and heap_caps_init may - fail initializing it properly. */ - heap_caps_init(); -+#if CONFIG_IDF_RTOS_RTTHREAD -+#if defined RT_USING_HEAP -+ extern int __heap_start__; -+ extern int __heap_end__; -+ rt_system_heap_init((void *)&__heap_start__, (void *)&__heap_end__); -+#endif -+ rt_system_scheduler_init(); -+#endif - - // When apptrace module is enabled, there will be SEGGER_SYSVIEW calls in the newlib init. - // SEGGER_SYSVIEW relies on apptrace module diff --git a/components/freertos/CMakeLists.txt b/components/freertos/CMakeLists.txt -index bd5acf5a2f..8db7883df6 100644 +index 5cd54494f6..33c901c187 100644 --- a/components/freertos/CMakeLists.txt +++ b/components/freertos/CMakeLists.txt -@@ -6,7 +6,29 @@ endif() - +@@ -7,7 +7,7 @@ endif() idf_build_get_property(target IDF_TARGET) --if(CONFIG_IDF_TARGET_ARCH_XTENSA) -+if(CONFIG_IDF_RTOS_RTTHREAD) -+ set(freertos_root "RT-Thread-wrapper-of-FreeRTOS/FreeRTOS") -+else() -+ set(freertos_root ".") -+endif() -+ -+if(CONFIG_IDF_RTOS_RTTHREAD) -+ set(srcs -+ "${freertos_root}/port/rt-thread/port.c" -+ "${freertos_root}/port/rt-thread/port_esp32c3.c") -+ -+ set(include_dirs -+ "${freertos_root}/include" -+ "${freertos_root}/include/esp_additions/freertos" # For files with #include "FreeRTOSConfig.h" -+ "${freertos_root}/port/rt-thread/include" # For including arch-specific FreeRTOSConfig_arch.h in port//include -+ "${freertos_root}/include/esp_additions") # For files with #include "freertos/FreeRTOSConfig.h" -+ -+ set(private_include_dirs -+ "${freertos_root}/port/rt-thread/include/freertos" -+ "${freertos_root}/port/rt-thread" -+ "${freertos_root}") -+ -+elseif(CONFIG_IDF_TARGET_ARCH_XTENSA) + if(CONFIG_IDF_RTOS_RTTHREAD) +- set(freertos_root "../../../FreeRTOS_Wrapper-latest/FreeRTOS") ++ message(${freertos_root}) set(srcs - "port/xtensa/port.c" - "port/xtensa/portasm.S" -@@ -48,21 +70,25 @@ elseif(CONFIG_IDF_TARGET_ARCH_RISCV) - endif() + "${freertos_root}/portable/esp-idf/riscv/port.c") - list(APPEND srcs -- "esp_additions/task_snapshot.c" -- "port/port_common.c" -- "port/port_systick.c" -- "croutine.c" -- "event_groups.c" -- "list.c" -- "queue.c" -- "tasks.c" -- "timers.c" -- "stream_buffer.c" -- "FreeRTOS-openocd.c" -- "freertos_v8_compat.c") -+ "${freertos_root}/port/port_common.c" -+ "${freertos_root}/event_groups.c" -+ "${freertos_root}/queue.c" -+ "${freertos_root}/tasks.c" -+ "${freertos_root}/timers.c" -+ "${freertos_root}/list.c" -+ "${freertos_root}/freertos_v8_compat.c" -+ "${freertos_root}/esp_additions/task_snapshot.c") -+ -+if(NOT CONFIG_IDF_RTOS_RTTHREAD) -+ list(APPEND srcs -+ "port/port_systick.c" -+ "croutine.c" -+ "stream_buffer.c" -+ "freertos_v8_compat.c") -+endif() - - list(APPEND private_include_dirs -- "include/freertos") -+ "${freertos_root}/include/freertos") - - if(CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY) - list(APPEND srcs "port/xtensa/xtensa_loadstore_handler.S") -@@ -71,7 +97,7 @@ endif() - # esp_timer is required by FreeRTOS because we use esp_tiemr_get_time() to do profiling - # app_trace is required by FreeRTOS headers only when CONFIG_APPTRACE_SV_ENABLE=y, - # REQUIRES can't depend on config options, so always require it. --set(required_components app_trace esp_timer) -+set(required_components app_trace esp_timer main) - - idf_component_register(SRCS "${srcs}" - INCLUDE_DIRS ${include_dirs} -@@ -88,15 +114,22 @@ if(CONFIG_FREERTOS_DEBUG_OCDAWARE) - endif() - - set_source_files_properties( -- tasks.c -- event_groups.c -- timers.c -- queue.c -- stream_buffer.c -+ "${freertos_root}/tasks.c" -+ "${freertos_root}/event_groups.c" -+ "${freertos_root}/timers.c" -+ "${freertos_root}/queue.c" - PROPERTIES COMPILE_DEFINITIONS - _ESP_FREERTOS_INTERNAL - ) - -+if(NOT CONFIG_IDF_RTOS_RTTHREAD) -+ set_source_files_properties( -+ stream_buffer.c -+ PROPERTIES COMPILE_DEFINITIONS -+ _ESP_FREERTOS_INTERNAL -+ ) -+endif() -+ - # The freertos component provides the `start_app` and `start_app_other_cores` - # if it is included in the build. It then calls `app_main` - # from the main task created, which must be provided by the user. -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/esp_additions/task_snapshot.c b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/esp_additions/task_snapshot.c -new file mode 100644 -index 0000000000..1244118b60 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/esp_additions/task_snapshot.c -@@ -0,0 +1,212 @@ -+/* -+ * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD -+ * -+ * SPDX-License-Identifier: Apache-2.0 -+ */ -+ -+#include "freertos/FreeRTOS.h" -+#include "freertos/task_snapshot.h" -+ -+#ifndef DIM -+#define DIM(t) (sizeof(t)/ sizeof(*(t))) -+#endif -+ -+#if ( configENABLE_TASK_SNAPSHOT == 1 ) -+ -+ static void prvTaskGetSnapshot( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, void *pxTCB ) -+ { -+ if (pxTCB == NULL) { -+ return; -+ } -+ pxTaskSnapshotArray[ *uxTask ].pxTCB = pxTCB; -+ pxTaskSnapshotArray[ *uxTask ].pxTopOfStack = (StackType_t *) pxTCBGetTopOfStack(pxTCB); -+ #if( portSTACK_GROWTH < 0 ) -+ { -+ pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCBGetEndOfStack(pxTCB); -+ } -+ #else -+ { -+ pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCBGetStartOfStack(pxTCB); -+ } -+ #endif -+ (*uxTask)++; -+ } -+ -+ static void prvTaskGetSnapshotsFromList( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, const UBaseType_t uxArraySize, List_t *pxList ) -+ { -+ void *pxNextTCB = NULL; -+ void *pxFirstTCB = NULL; -+ -+ if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 ) -+ { -+ listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList ); -+ do -+ { -+ if( *uxTask >= uxArraySize ) { -+ break; -+ } -+ -+ listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList ); -+ prvTaskGetSnapshot( pxTaskSnapshotArray, uxTask, pxNextTCB ); -+ } while( pxNextTCB != pxFirstTCB ); -+ } -+ else -+ { -+ mtCOVERAGE_TEST_MARKER(); -+ } -+ } -+ -+ UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz ) -+ { -+ UBaseType_t uxTask = 0; -+ UBaseType_t i = 0; -+ -+ -+ *pxTcbSz = pxTCBGetSize(); -+ /* Fill in an TaskStatus_t structure with information on each -+ task in the Ready state. */ -+ i = configMAX_PRIORITIES; -+ do -+ { -+ i--; -+ prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxListGetReadyTask(i) ); -+ } while( i > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */ -+ -+ /* Fill in an TaskStatus_t structure with information on each -+ task in the Blocked state. */ -+ prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetDelayedTaskList() ); -+ prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetOverflowDelayedTaskList() ); -+ for (i = 0; i < configNUM_CORES; i++) { -+ if( uxTask >= uxArraySize ) { -+ break; -+ } -+ prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxListGetReadyPendingTask(i) ); -+ } -+ -+ #if( INCLUDE_vTaskDelete == 1 ) -+ { -+ prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetTasksWaitingTermination() ); -+ } -+ #endif -+ -+ #if ( INCLUDE_vTaskSuspend == 1 ) -+ { -+ prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetSuspendedTaskList() ); -+ } -+ #endif -+ return uxTask; -+ } -+ -+ static void *prvFirstTaskGet( List_t *pxList ) -+ { -+ ListItem_t *pxListItem = listGET_HEAD_ENTRY( pxList ); -+ if( pxListItem != listGET_END_MARKER( pxList ) ) { -+ return listGET_LIST_ITEM_OWNER( pxListItem ); -+ } -+ return NULL; -+ } -+ -+ static void *prvNextTaskGet( void *pxTCB ) -+ { -+ List_t *pxList = listLIST_ITEM_CONTAINER( pxTCBGetStateListItem(pxTCB) ); -+ ListItem_t *pxListItem = listGET_NEXT( pxTCBGetStateListItem(pxTCB) ); -+ if( pxListItem != listGET_END_MARKER( pxList ) ) { -+ return listGET_LIST_ITEM_OWNER( pxListItem ); -+ } -+ return NULL; -+ } -+ -+ void vTaskGetSnapshot( TaskHandle_t pxTask, TaskSnapshot_t *pxTaskSnapshot ) -+ { -+ configASSERT( portVALID_TCB_MEM(pxTask) ); -+ configASSERT( pxTaskSnapshot != NULL ); -+ pxTaskSnapshot->pxTCB = (void*) pxTask; -+ pxTaskSnapshot->pxTopOfStack = pxTCBGetTopOfStack((void*) pxTask); -+ pxTaskSnapshot->pxEndOfStack = pxTCBGetEndOfStack((void*) pxTask); -+ } -+ -+ TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask ) -+ { -+ void *pxTCB = pxTask; -+ List_t *pxTaskList = NULL; -+ UBaseType_t i = configMAX_PRIORITIES; -+ UBaseType_t bCurTaskListFound = pdFALSE; -+ List_t *task_lists[] = { -+ pxGetDelayedTaskList(), -+ pxGetOverflowDelayedTaskList(), -+ #if( INCLUDE_vTaskDelete == 1 ) -+ pxGetTasksWaitingTermination(), -+ #endif -+ #if( INCLUDE_vTaskSuspend == 1 ) -+ pxGetSuspendedTaskList() -+ #endif -+ }; -+ -+ if( pxTask != NULL && !portVALID_TCB_MEM(pxTask) ) { -+ return NULL; -+ } -+ -+ if( pxTCB != NULL ) { -+ pxTCB = prvNextTaskGet( pxTCB ); -+ if( pxTCB != NULL ) { -+ // take care not to return garbage -+ return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; -+ } -+ pxTaskList = listLIST_ITEM_CONTAINER( pxTCBGetStateListItem(pxTask) ); -+ } -+ /* ready tasks lists */ -+ do -+ { -+ i--; -+ List_t *pxList = pxListGetReadyTask(i); -+ if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) { -+ /* need to find list the current task item from */ -+ if( pxTaskList == pxList ) { -+ bCurTaskListFound = pdTRUE; -+ } -+ continue; /* go to the next 'ready list' */ -+ } -+ pxTCB = prvFirstTaskGet( pxList ); -+ if( pxTCB != NULL ) { -+ // take care not to return garbage -+ return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; -+ } -+ } -+ while( i > tskIDLE_PRIORITY ); -+ /* pending ready tasks lists */ -+ for (i = 0; i < configNUM_CORES; i++) { -+ List_t *pxList = pxListGetReadyPendingTask(i); -+ if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) { -+ /* need to find list the current task item from */ -+ if( pxTaskList == pxList ) { -+ bCurTaskListFound = pdTRUE; -+ } -+ continue; /* go to the next 'ready list' */ -+ } -+ pxTCB = prvFirstTaskGet( pxList ); -+ if( pxTCB != NULL ) { -+ // take care not to return garbage -+ return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; -+ } -+ } -+ /* other tasks lists */ -+ for (i = 0; i < DIM(task_lists); i++) { -+ List_t *pxList = task_lists[ i ]; -+ if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) { -+ /* need to find list the current task item from */ -+ if( pxTaskList == pxList ) { -+ bCurTaskListFound = pdTRUE; -+ } -+ continue; /* go to the next 'ready list' */ -+ } -+ pxTCB = prvFirstTaskGet( pxList ); -+ if( pxTCB != NULL ) { -+ // take care not to return garbage -+ return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL; -+ } -+ } -+ -+ return NULL; -+ } -+ -+#endif -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/event_groups.c b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/event_groups.c -new file mode 100644 -index 0000000000..1b708564ed ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/event_groups.c -@@ -0,0 +1,225 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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 -+ -+/* FreeRTOS includes. */ -+#include "FreeRTOS.h" -+#include "task.h" -+#include "event_groups.h" -+ -+typedef struct EventGroupDef_t -+{ -+ struct rt_event event; -+} EventGroup_t; -+ -+static volatile rt_uint8_t event_index = 0; -+ -+/*-----------------------------------------------------------*/ -+ -+#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) -+ -+ EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer ) -+ { -+ char name[RT_NAME_MAX] = {0}; -+ -+ /* A StaticEventGroup_t object must be provided. */ -+ configASSERT( pxEventGroupBuffer ); -+ -+ rt_snprintf( name, RT_NAME_MAX, "event%02d", event_index++ ); -+ rt_event_init( ( rt_event_t ) pxEventGroupBuffer, name, RT_IPC_FLAG_PRIO ); -+ -+ return ( EventGroupHandle_t ) pxEventGroupBuffer; -+ } -+ -+#endif /* configSUPPORT_STATIC_ALLOCATION */ -+/*-----------------------------------------------------------*/ -+ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ -+ EventGroupHandle_t xEventGroupCreate( void ) -+ { -+ EventGroup_t * pxEventBits; -+ char name[RT_NAME_MAX] = {0}; -+ -+ rt_snprintf( name, RT_NAME_MAX, "event%02d", event_index++ ); -+ pxEventBits = ( EventGroup_t * ) rt_event_create( name, RT_IPC_FLAG_PRIO ); -+ -+ return pxEventBits; -+ } -+ -+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */ -+/*-----------------------------------------------------------*/ -+ -+EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, -+ const EventBits_t uxBitsToWaitFor, -+ const BaseType_t xClearOnExit, -+ const BaseType_t xWaitForAllBits, -+ TickType_t xTicksToWait ) -+{ -+ rt_event_t event = ( rt_event_t ) xEventGroup; -+ rt_uint8_t option = 0; -+ rt_uint32_t recved; -+ rt_base_t level; -+ rt_err_t err; -+ -+ /* 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 != 0 ); -+ #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) -+ { -+ configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); -+ } -+ #endif -+ -+ if ( xWaitForAllBits != pdFALSE ) -+ { -+ option |= RT_EVENT_FLAG_AND; -+ } -+ else -+ { -+ option |= RT_EVENT_FLAG_OR; -+ } -+ if ( xClearOnExit != pdFALSE ) -+ { -+ option |= RT_EVENT_FLAG_CLEAR; -+ } -+ err = rt_event_recv( event, ( rt_uint32_t ) uxBitsToWaitFor, option, ( rt_int32_t ) xTicksToWait, &recved ); -+ -+ if ( err != RT_EOK ) -+ { -+ level = rt_hw_interrupt_disable(); -+ recved = event->set; -+ rt_hw_interrupt_enable(level); -+ } -+ -+ return ( EventBits_t ) recved; -+} -+/*-----------------------------------------------------------*/ -+ -+EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, -+ const EventBits_t uxBitsToClear ) -+{ -+ rt_event_t event = ( rt_event_t ) xEventGroup; -+ EventBits_t uxReturn; -+ rt_base_t level; -+ -+ configASSERT( xEventGroup ); -+ -+ level = rt_hw_interrupt_disable(); -+ uxReturn = ( EventBits_t ) event->set; -+ event->set &= ~( ( rt_uint32_t ) uxBitsToClear ); -+ rt_hw_interrupt_enable( level ); -+ -+ return uxReturn; -+} -+/*-----------------------------------------------------------*/ -+ -+BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, -+ const EventBits_t uxBitsToClear ) -+{ -+ return xEventGroupClearBits( xEventGroup, uxBitsToClear ); -+} -+ -+EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) -+{ -+ rt_event_t event = ( rt_event_t ) xEventGroup; -+ EventBits_t uxReturn; -+ rt_base_t level; -+ -+ level = rt_hw_interrupt_disable(); -+ uxReturn = ( EventBits_t ) event->set; -+ rt_hw_interrupt_enable( level ); -+ -+ return uxReturn; -+} -+/*-----------------------------------------------------------*/ -+ -+EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, -+ const EventBits_t uxBitsToSet ) -+{ -+ rt_event_t event = ( rt_event_t ) xEventGroup; -+ rt_base_t level; -+ EventBits_t uxReturn; -+ -+ configASSERT( xEventGroup ); -+ -+ rt_event_send( event, ( rt_uint32_t ) uxBitsToSet); -+ -+ level = rt_hw_interrupt_disable(); -+ uxReturn = ( EventBits_t ) event->set; -+ rt_hw_interrupt_enable(level); -+ -+ return uxReturn; -+} -+/*-----------------------------------------------------------*/ -+ -+void vEventGroupDelete( EventGroupHandle_t xEventGroup ) -+{ -+ rt_event_t event = ( rt_event_t ) xEventGroup; -+ -+ configASSERT( xEventGroup ); -+ -+#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) -+ if ( rt_object_is_systemobject( ( rt_object_t ) event ) ) -+#endif -+ { -+ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) -+ rt_event_detach( event ); -+ #endif -+#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) -+ } -+ else -+ { -+#endif -+ #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ rt_event_delete( event ); -+ #endif -+ } -+} -+/*-----------------------------------------------------------*/ -+ -+#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) -+ -+ BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, -+ const EventBits_t uxBitsToSet, -+ BaseType_t * pxHigherPriorityTaskWoken ) -+ { -+ xEventGroupSetBits( xEventGroup, uxBitsToSet ); -+ if ( pxHigherPriorityTaskWoken != NULL) -+ { -+ pxHigherPriorityTaskWoken = pdFALSE; -+ } -+ -+ return pdPASS; -+ } -+ -+#endif /* if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) ) */ -+/*-----------------------------------------------------------*/ -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/freertos_v8_compat.c b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/freertos_v8_compat.c -new file mode 100644 -index 0000000000..fe8d689125 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/freertos_v8_compat.c -@@ -0,0 +1,33 @@ -+// Copyright 2020 Espressif Systems (Shanghai) Co., Ltd. -+// -+// Licensed under the Apache License, Version 2.0 (the "License"); -+// you may not use this file except in compliance with the License. -+// You may obtain a copy of the License at -+// -+// http://www.apache.org/licenses/LICENSE-2.0 -+// -+// Unless required by applicable law or agreed to in writing, software -+// distributed under the License is distributed on an "AS IS" BASIS, -+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+// See the License for the specific language governing permissions and -+// limitations under the License. -+ -+#include "FreeRTOS.h" -+#include "queue.h" -+#include "semphr.h" -+ -+/* This API is kept for backward ABI compatibility with prebuilt libraries against FreeRTOS v8/v9 in ESP-IDF */ -+BaseType_t xQueueGenericReceive( QueueHandle_t xQueue, void * const pvBuffer, TickType_t xTicksToWait, const BaseType_t xPeek ) -+{ -+ if ( xPeek == pdTRUE ) -+ { -+ return xQueuePeek( xQueue, pvBuffer, xTicksToWait ); -+ } -+ -+ if ( pvBuffer == NULL ) -+ { -+ return xQueueSemaphoreTake( xQueue, xTicksToWait ); -+ } -+ -+ return xQueueReceive( xQueue, pvBuffer, xTicksToWait ); -+} -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/esp_additions/freertos/FreeRTOSConfig.h b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/esp_additions/freertos/FreeRTOSConfig.h -new file mode 100644 -index 0000000000..8a4739a3a5 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/esp_additions/freertos/FreeRTOSConfig.h -@@ -0,0 +1,326 @@ -+/* -+ FreeRTOS V10 - Copyright (C) 2021 Real Time Engineers Ltd. -+ All rights reserved -+ -+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. -+ -+ This file is part of the FreeRTOS distribution. -+ -+ FreeRTOS is free software; you can redistribute it and/or modify it under -+ the terms of the GNU General Public License (version 2) as published by the -+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. -+ -+ *************************************************************************** -+ >>! NOTE: The modification to the GPL is included to allow you to !<< -+ >>! distribute a combined work that includes FreeRTOS without being !<< -+ >>! obliged to provide the source code for proprietary components !<< -+ >>! outside of the FreeRTOS kernel. !<< -+ *************************************************************************** -+ -+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY -+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. Full license text is available on the following -+ link: http://www.freertos.org/a00114.html -+ -+ *************************************************************************** -+ * * -+ * FreeRTOS provides completely free yet professionally developed, * -+ * robust, strictly quality controlled, supported, and cross * -+ * platform software that is more than just the market leader, it * -+ * is the industry's de facto standard. * -+ * * -+ * Help yourself get started quickly while simultaneously helping * -+ * to support the FreeRTOS project by purchasing a FreeRTOS * -+ * tutorial book, reference manual, or both: * -+ * http://www.FreeRTOS.org/Documentation * -+ * * -+ *************************************************************************** -+ -+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading -+ the FAQ page "My application does not run, what could be wrong?". Have you -+ defined configASSERT()? -+ -+ http://www.FreeRTOS.org/support - In return for receiving this top quality -+ embedded software for free we request you assist our global community by -+ participating in the support forum. -+ -+ http://www.FreeRTOS.org/training - Investing in training allows your team to -+ be as productive as possible as early as possible. Now you can receive -+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers -+ Ltd, and the world's leading authority on the world's leading RTOS. -+ -+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, -+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS -+ compatible FAT file system, and our tiny thread aware UDP/IP stack. -+ -+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. -+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. -+ -+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High -+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS -+ licenses offer ticketed support, indemnification and commercial middleware. -+ -+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety -+ engineered and independently SIL3 certified version for use in safety and -+ mission critical applications that require provable dependability. -+ -+ 1 tab == 4 spaces! -+*/ -+ -+#ifndef FREERTOS_CONFIG_H -+#define FREERTOS_CONFIG_H -+ -+#include "sdkconfig.h" -+ -+/* for likely and unlikely */ -+#include "esp_compiler.h" -+ -+// The arch-specific FreeRTOSConfig_arch.h in port//include. -+#include "freertos/FreeRTOSConfig_arch.h" -+ -+#if !(defined(FREERTOS_CONFIG_XTENSA_H) \ -+ || defined(FREERTOS_CONFIG_RISCV_H) \ -+ || defined(FREERTOS_CONFIG_LINUX_H)) -+#error "Needs architecture-speific FreeRTOSConfig.h!" -+#endif -+ -+#ifndef CONFIG_FREERTOS_UNICORE -+#define portNUM_PROCESSORS 2 -+#else -+#define portNUM_PROCESSORS 1 -+#endif -+ -+#define portUSING_MPU_WRAPPERS 0 -+#define configUSE_MUTEX 1 -+ -+#define configNUM_THREAD_LOCAL_STORAGE_POINTERS CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS -+#define configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS 1 -+ -+/* configASSERT behaviour */ -+#ifndef __ASSEMBLER__ -+#include -+ -+// If CONFIG_FREERTOS_ASSERT_DISABLE is set then configASSERT is defined empty later in FreeRTOS.h and the macro -+// configASSERT_DEFINED remains unset (meaning some warnings are avoided) -+ -+#if defined(CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE) -+#define configASSERT(a) if (unlikely(!(a))) { \ -+ esp_rom_printf("%s:%d (%s)- assert failed!\n", __FILE__, __LINE__, \ -+ __FUNCTION__); \ -+ } -+#elif defined(CONFIG_FREERTOS_ASSERT_FAIL_ABORT) -+#define configASSERT(a) assert(a) -+#endif -+ -+#if CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION -+#define UNTESTED_FUNCTION() { esp_rom_printf("Untested FreeRTOS function %s\r\n", __FUNCTION__); configASSERT(false); } while(0) -+#else -+#define UNTESTED_FUNCTION() -+#endif -+ -+#endif /* def __ASSEMBLER__ */ -+ -+/*----------------------------------------------------------- -+ * Application specific definitions. -+ * -+ * These definitions should be adjusted for your particular hardware and -+ * application requirements. -+ * -+ * Note that the default heap size is deliberately kept small so that -+ * the build is more likely to succeed for configurations with limited -+ * memory. -+ * -+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE -+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. -+ *----------------------------------------------------------*/ -+ -+#define configUSE_PREEMPTION 1 -+#define configUSE_IDLE_HOOK 1 -+#define configUSE_TICK_HOOK 1 -+#define configRECORD_STACK_HIGH_ADDRESS 1 -+#define configTICK_RATE_HZ ( CONFIG_FREERTOS_HZ ) -+ -+/* This has impact on speed of search for highest priority */ -+#define configMAX_PRIORITIES ( 32 ) -+ -+/* Various things that impact minimum stack sizes */ -+ -+/* Higher stack checker modes cause overhead on each function call */ -+#if CONFIG_STACK_CHECK_ALL || CONFIG_STACK_CHECK_STRONG -+#define configSTACK_OVERHEAD_CHECKER 256 -+#else -+#define configSTACK_OVERHEAD_CHECKER 0 -+#endif -+ -+/* with optimizations disabled, scheduler uses additional stack */ -+#if CONFIG_COMPILER_OPTIMIZATION_NONE -+#define configSTACK_OVERHEAD_OPTIMIZATION 320 -+#else -+#define configSTACK_OVERHEAD_OPTIMIZATION 0 -+#endif -+ -+/* apptrace mdule increases minimum stack usage */ -+#if CONFIG_APPTRACE_ENABLE -+#define configSTACK_OVERHEAD_APPTRACE 1280 -+#else -+#define configSTACK_OVERHEAD_APPTRACE 0 -+#endif -+ -+/* Stack watchpoint decreases minimum usable stack size by up to 60 bytes. -+ See FreeRTOS FREERTOS_WATCHPOINT_END_OF_STACK option in Kconfig. */ -+#if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK -+#define configSTACK_OVERHEAD_WATCHPOINT 60 -+#else -+#define configSTACK_OVERHEAD_WATCHPOINT 0 -+#endif -+ -+#define configSTACK_OVERHEAD_TOTAL ( \ -+ configSTACK_OVERHEAD_CHECKER + \ -+ configSTACK_OVERHEAD_OPTIMIZATION + \ -+ configSTACK_OVERHEAD_APPTRACE + \ -+ configSTACK_OVERHEAD_WATCHPOINT \ -+ ) -+ -+#define configMINIMAL_STACK_SIZE (768 + configSTACK_OVERHEAD_TOTAL) -+ -+#ifndef configIDLE_TASK_STACK_SIZE -+#define configIDLE_TASK_STACK_SIZE CONFIG_FREERTOS_IDLE_TASK_STACKSIZE -+#endif -+ -+/* Minimal heap size to make sure examples can run on memory limited -+ configs. Adjust this to suit your system. */ -+ -+ -+//We define the heap to span all of the non-statically-allocated shared RAM. ToDo: Make sure there -+//is some space left for the app and main cpu when running outside of a thread. -+#define configAPPLICATION_ALLOCATED_HEAP 1 -+#define configTOTAL_HEAP_SIZE (&_heap_end - &_heap_start)//( ( size_t ) (64 * 1024) ) -+ -+#define configMAX_TASK_NAME_LEN ( CONFIG_FREERTOS_MAX_TASK_NAME_LEN ) -+ -+#ifdef CONFIG_FREERTOS_USE_TRACE_FACILITY -+#define configUSE_TRACE_FACILITY 1 /* Used by uxTaskGetSystemState(), and other trace facility functions */ -+#endif -+ -+#ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS -+#define configUSE_STATS_FORMATTING_FUNCTIONS 1 /* Used by vTaskList() */ -+#endif -+ -+#ifdef CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID -+#define configTASKLIST_INCLUDE_COREID 1 -+#endif -+ -+#ifdef CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS -+#define configGENERATE_RUN_TIME_STATS 1 /* Used by vTaskGetRunTimeStats() */ -+#endif -+ -+#define configBENCHMARK 0 -+#define configUSE_16_BIT_TICKS 0 -+#define configIDLE_SHOULD_YIELD 0 -+#define configQUEUE_REGISTRY_SIZE CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE -+ -+#define configUSE_MUTEXES 1 -+#define configUSE_RECURSIVE_MUTEXES 1 -+#define configUSE_COUNTING_SEMAPHORES 1 -+ -+#if CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE -+#define configCHECK_FOR_STACK_OVERFLOW 0 -+#elif CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL -+#define configCHECK_FOR_STACK_OVERFLOW 1 -+#elif CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY -+#define configCHECK_FOR_STACK_OVERFLOW 2 -+#endif -+ -+ -+/* Co-routine definitions. */ -+#define configUSE_CO_ROUTINES 0 -+#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) -+ -+/* Set the following definitions to 1 to include the API function, or zero -+ to exclude the API function. */ -+ -+#define INCLUDE_vTaskPrioritySet 1 -+#define INCLUDE_uxTaskPriorityGet 1 -+#define INCLUDE_vTaskDelete 1 -+#define INCLUDE_vTaskCleanUpResources 0 -+#define INCLUDE_vTaskSuspend 1 -+#define INCLUDE_vTaskDelayUntil 1 -+#define INCLUDE_vTaskDelay 1 -+#define INCLUDE_uxTaskGetStackHighWaterMark 1 -+#define INCLUDE_pcTaskGetTaskName 1 -+#define INCLUDE_xTaskGetIdleTaskHandle 1 -+#define INCLUDE_pxTaskGetStackStart 1 -+#define INCLUDE_eTaskGetState 1 -+#define INCLUDE_xTaskAbortDelay 1 -+#define INCLUDE_xTaskGetHandle 1 -+#define INCLUDE_xSemaphoreGetMutexHolder 1 -+#define INCLUDE_xTimerPendFunctionCall 1 -+#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 //Currently there is no need for this API -+ -+/* The priority at which the tick interrupt runs. This should probably be -+ kept at 1. */ -+#define configKERNEL_INTERRUPT_PRIORITY 1 -+ -+#if !CONFIG_IDF_TARGET_LINUX -+#define configUSE_NEWLIB_REENTRANT 1 -+#endif -+ -+#define configSUPPORT_DYNAMIC_ALLOCATION 1 -+#define configSUPPORT_STATIC_ALLOCATION 1 -+ -+#ifndef __ASSEMBLER__ -+#if CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP -+extern void vPortCleanUpTCB ( void *pxTCB ); -+#define portCLEAN_UP_TCB( pxTCB ) vPortCleanUpTCB( pxTCB ) -+#endif -+#endif -+ -+/* Test FreeRTOS timers (with timer task) and more. */ -+/* Some files don't compile if this flag is disabled */ -+#define configUSE_TIMERS 1 -+#define configTIMER_TASK_PRIORITY CONFIG_FREERTOS_TIMER_TASK_PRIORITY -+#define configTIMER_QUEUE_LENGTH CONFIG_FREERTOS_TIMER_QUEUE_LENGTH -+#define configTIMER_TASK_STACK_DEPTH CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH -+ -+#define configUSE_QUEUE_SETS 1 -+ -+#define configUSE_TICKLESS_IDLE CONFIG_FREERTOS_USE_TICKLESS_IDLE -+#if configUSE_TICKLESS_IDLE -+#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP -+#endif //configUSE_TICKLESS_IDLE -+ -+ -+#if CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT -+#define configENABLE_TASK_SNAPSHOT 1 -+#endif -+#ifndef configENABLE_TASK_SNAPSHOT -+#define configENABLE_TASK_SNAPSHOT 0 -+#endif -+ -+#if CONFIG_SYSVIEW_ENABLE -+#ifndef __ASSEMBLER__ -+#include "SEGGER_SYSVIEW_FreeRTOS.h" -+#undef INLINE // to avoid redefinition -+#endif /* def __ASSEMBLER__ */ -+#endif -+ -+#if CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER -+#define configCHECK_MUTEX_GIVEN_BY_OWNER 1 -+#else -+#define configCHECK_MUTEX_GIVEN_BY_OWNER 0 -+#endif -+ -+ -+#define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1 -+ -+#define configTASK_NOTIFICATION_ARRAY_ENTRIES 1 -+ -+// backward compatibility for 4.4 -+#define xTaskRemoveFromUnorderedEventList vTaskRemoveFromUnorderedEventList -+ -+#define configNUM_CORES portNUM_PROCESSORS -+ -+/* RT-Thread wrapper */ -+#define INCLUDE_xTaskGetCurrentTaskHandle 1 -+ -+#endif /* FREERTOS_CONFIG_H */ -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/esp_additions/freertos/task_snapshot.h b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/esp_additions/freertos/task_snapshot.h -new file mode 100644 -index 0000000000..1ad04cce69 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/esp_additions/freertos/task_snapshot.h -@@ -0,0 +1,90 @@ -+// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD -+// -+// Licensed under the Apache License, Version 2.0 (the "License"); -+// you may not use this file except in compliance with the License. -+// You may obtain a copy of the License at -+// -+// http://www.apache.org/licenses/LICENSE-2.0 -+// -+// Unless required by applicable law or agreed to in writing, software -+// distributed under the License is distributed on an "AS IS" BASIS, -+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -+// See the License for the specific language governing permissions and -+// limitations under the License. -+ -+#pragma once -+ -+#include "freertos/FreeRTOS.h" -+#include "freertos/task.h" -+ -+#if ( configENABLE_TASK_SNAPSHOT == 1 ) -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** -+ * Check `freertos_tasks_c_additions.h` file for more info -+ * about these functions declaration. -+ */ -+UBaseType_t pxTCBGetSize ( void ); -+ListItem_t* pxTCBGetStateListItem ( void *pxTCB ); -+StackType_t* pxTCBGetStartOfStack ( void *pxTCB ); -+StackType_t* pxTCBGetTopOfStack ( void *pxTCB ); -+StackType_t* pxTCBGetEndOfStack ( void *pxTCB ); -+List_t* pxListGetReadyTask ( UBaseType_t idx ); -+List_t* pxListGetReadyPendingTask ( UBaseType_t idx ); -+List_t* pxGetDelayedTaskList ( void ); -+List_t* pxGetOverflowDelayedTaskList ( void ); -+List_t* pxGetTasksWaitingTermination ( void ); -+List_t* pxGetSuspendedTaskList ( void ); -+ -+/** -+ * Used with the uxTaskGetSnapshotAll() function to save memory snapshot of each task in the system. -+ * We need this struct because TCB_t is defined (hidden) in tasks.c. -+ */ -+typedef struct xTASK_SNAPSHOT -+{ -+ void *pxTCB; /*!< Address of task control block. */ -+ StackType_t *pxTopOfStack; /*!< Points to the location of the last item placed on the tasks stack. */ -+ StackType_t *pxEndOfStack; /*!< Points to the end of the stack. pxTopOfStack < pxEndOfStack, stack grows hi2lo -+ pxTopOfStack > pxEndOfStack, stack grows lo2hi*/ -+} TaskSnapshot_t; -+ -+ -+/* -+ * This function fills array with TaskSnapshot_t structures for every task in the system. -+ * Used by panic handling code to get snapshots of all tasks in the system. -+ * Only available when configENABLE_TASK_SNAPSHOT is set to 1. -+ * @param pxTaskSnapshotArray Pointer to array of TaskSnapshot_t structures to store tasks snapshot data. -+ * @param uxArraySize Size of tasks snapshots array. -+ * @param pxTcbSz Pointer to store size of TCB. -+ * @return Number of elements stored in array. -+ */ -+UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz ); -+ -+/* -+ * This function iterates over all tasks in the system. -+ * Used by panic handling code to iterate over tasks in the system. -+ * Only available when configENABLE_TASK_SNAPSHOT is set to 1. -+ * @note This function should not be used while FreeRTOS is running (as it doesn't acquire any locks). -+ * @param pxTask task handle. -+ * @return Handle for the next task. If pxTask is NULL, returns hadnle for the first task. -+ */ -+TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask ); -+ -+/* -+ * This function fills TaskSnapshot_t structure for specified task. -+ * Used by panic handling code to get snapshot of a task. -+ * Only available when configENABLE_TASK_SNAPSHOT is set to 1. -+ * @note This function should not be used while FreeRTOS is running (as it doesn't acquire any locks). -+ * @param pxTask task handle. -+ * @param pxTaskSnapshot address of TaskSnapshot_t structure to fill. -+ */ -+void vTaskGetSnapshot( TaskHandle_t pxTask, TaskSnapshot_t *pxTaskSnapshot ); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/FreeRTOS.h b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/FreeRTOS.h -new file mode 100644 -index 0000000000..b3efa13f20 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/FreeRTOS.h -@@ -0,0 +1,1198 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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_FREERTOS_H -+#define INC_FREERTOS_H -+ -+/* -+ * Include the generic headers required for the FreeRTOS port being used. -+ */ -+#include -+ -+/* -+ * If stdint.h cannot be located then: -+ * + If using GCC ensure the -nostdint options is *not* being used. -+ * + Ensure the project's include path includes the directory in which your -+ * compiler stores stdint.h. -+ * + Set any compiler options necessary for it to support C99, as technically -+ * stdint.h is only mandatory with C99 (FreeRTOS does not require C99 in any -+ * other way). -+ * + The FreeRTOS download includes a simple stdint.h definition that can be -+ * used in cases where none is provided by the compiler. The files only -+ * contains the typedefs required to build FreeRTOS. Read the instructions -+ * in FreeRTOS/source/stdint.readme for more information. -+ */ -+#include /* READ COMMENT ABOVE. */ -+ -+/* *INDENT-OFF* */ -+#ifdef __cplusplus -+ extern "C" { -+#endif -+/* *INDENT-ON* */ -+ -+#include -+#include -+ -+/* Application specific configuration options. */ -+#include "FreeRTOSConfig.h" -+ -+/* Basic FreeRTOS definitions. */ -+#include "projdefs.h" -+ -+/* Definitions specific to the port being used. */ -+#include "portable.h" -+ -+/* Must be defaulted before configUSE_NEWLIB_REENTRANT is used below. */ -+#ifndef configUSE_NEWLIB_REENTRANT -+ #define configUSE_NEWLIB_REENTRANT 0 -+#endif -+ -+/* Required if struct _reent is used. */ -+#if ( configUSE_NEWLIB_REENTRANT == 1 ) -+ #include -+#endif -+ -+/* -+ * Check all the required application specific macros have been defined. -+ * These macros are application specific and (as downloaded) are defined -+ * within FreeRTOSConfig.h. -+ */ -+ -+#ifndef configMINIMAL_STACK_SIZE -+ #error Missing definition: configMINIMAL_STACK_SIZE must be defined in FreeRTOSConfig.h. configMINIMAL_STACK_SIZE defines the size (in words) of the stack allocated to the idle task. Refer to the demo project provided for your port for a suitable value. -+#endif -+ -+#ifndef configMAX_PRIORITIES -+ #error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. -+#endif -+ -+#if configMAX_PRIORITIES < 1 -+ #error configMAX_PRIORITIES must be defined to be greater than or equal to 1. -+#endif -+ -+#ifndef configUSE_PREEMPTION -+ #error Missing definition: configUSE_PREEMPTION must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -+#endif -+ -+#ifndef configUSE_IDLE_HOOK -+ #error Missing definition: configUSE_IDLE_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -+#endif -+ -+#ifndef configUSE_TICK_HOOK -+ #error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -+#endif -+ -+#ifndef configUSE_16_BIT_TICKS -+ #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. -+#endif -+ -+#ifndef configUSE_CO_ROUTINES -+ #define configUSE_CO_ROUTINES 0 -+#endif -+ -+#ifndef INCLUDE_vTaskPrioritySet -+ #define INCLUDE_vTaskPrioritySet 0 -+#endif -+ -+#ifndef INCLUDE_uxTaskPriorityGet -+ #define INCLUDE_uxTaskPriorityGet 0 -+#endif -+ -+#ifndef INCLUDE_vTaskDelete -+ #define INCLUDE_vTaskDelete 0 -+#endif -+ -+#ifndef INCLUDE_vTaskSuspend -+ #define INCLUDE_vTaskSuspend 0 -+#endif -+ -+#ifdef INCLUDE_xTaskDelayUntil -+ #ifdef INCLUDE_vTaskDelayUntil -+ -+/* INCLUDE_vTaskDelayUntil was replaced by INCLUDE_xTaskDelayUntil. Backward -+ * compatibility is maintained if only one or the other is defined, but -+ * there is a conflict if both are defined. */ -+ #error INCLUDE_vTaskDelayUntil and INCLUDE_xTaskDelayUntil are both defined. INCLUDE_vTaskDelayUntil is no longer required and should be removed -+ #endif -+#endif -+ -+#ifndef INCLUDE_xTaskDelayUntil -+ #ifdef INCLUDE_vTaskDelayUntil -+ -+/* If INCLUDE_vTaskDelayUntil is set but INCLUDE_xTaskDelayUntil is not then -+ * the project's FreeRTOSConfig.h probably pre-dates the introduction of -+ * xTaskDelayUntil and setting INCLUDE_xTaskDelayUntil to whatever -+ * INCLUDE_vTaskDelayUntil is set to will ensure backward compatibility. -+ */ -+ #define INCLUDE_xTaskDelayUntil INCLUDE_vTaskDelayUntil -+ #endif -+#endif -+ -+#ifndef INCLUDE_xTaskDelayUntil -+ #define INCLUDE_xTaskDelayUntil 0 -+#endif -+ -+#ifndef INCLUDE_vTaskDelay -+ #define INCLUDE_vTaskDelay 0 -+#endif -+ -+#ifndef INCLUDE_xTaskGetIdleTaskHandle -+ #define INCLUDE_xTaskGetIdleTaskHandle 0 -+#endif -+ -+#ifndef INCLUDE_xTaskAbortDelay -+ #define INCLUDE_xTaskAbortDelay 0 -+#endif -+ -+#ifndef INCLUDE_xQueueGetMutexHolder -+ #define INCLUDE_xQueueGetMutexHolder 0 -+#endif -+ -+#ifndef INCLUDE_xSemaphoreGetMutexHolder -+ #define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder -+#endif -+ -+#ifndef INCLUDE_xTaskGetHandle -+ #define INCLUDE_xTaskGetHandle 0 -+#endif -+ -+#ifndef INCLUDE_uxTaskGetStackHighWaterMark -+ #define INCLUDE_uxTaskGetStackHighWaterMark 0 -+#endif -+ -+#ifndef INCLUDE_uxTaskGetStackHighWaterMark2 -+ #define INCLUDE_uxTaskGetStackHighWaterMark2 0 -+#endif -+ -+#ifndef INCLUDE_eTaskGetState -+ #define INCLUDE_eTaskGetState 0 -+#endif -+ -+#ifndef INCLUDE_xTaskResumeFromISR -+ #define INCLUDE_xTaskResumeFromISR 1 -+#endif -+ -+#ifndef INCLUDE_xTimerPendFunctionCall -+ #define INCLUDE_xTimerPendFunctionCall 0 -+#endif -+ -+#ifndef INCLUDE_xTaskGetSchedulerState -+ #define INCLUDE_xTaskGetSchedulerState 0 -+#endif -+ -+#ifndef INCLUDE_xTaskGetCurrentTaskHandle -+ #define INCLUDE_xTaskGetCurrentTaskHandle 0 -+#endif -+ -+#if configUSE_CO_ROUTINES != 0 -+ #ifndef configMAX_CO_ROUTINE_PRIORITIES -+ #error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1. -+ #endif -+#endif -+ -+#ifndef configUSE_DAEMON_TASK_STARTUP_HOOK -+ #define configUSE_DAEMON_TASK_STARTUP_HOOK 0 -+#endif -+ -+#ifndef configUSE_APPLICATION_TASK_TAG -+ #define configUSE_APPLICATION_TASK_TAG 0 -+#endif -+ -+#ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS -+ #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0 -+#endif -+ -+#ifndef configUSE_RECURSIVE_MUTEXES -+ #define configUSE_RECURSIVE_MUTEXES 0 -+#endif -+ -+#ifndef configUSE_MUTEXES -+ #define configUSE_MUTEXES 0 -+#endif -+ -+#ifndef configUSE_TIMERS -+ #define configUSE_TIMERS 0 -+#endif -+ -+#ifndef configUSE_COUNTING_SEMAPHORES -+ #define configUSE_COUNTING_SEMAPHORES 0 -+#endif -+ -+#ifndef configUSE_ALTERNATIVE_API -+ #define configUSE_ALTERNATIVE_API 0 -+#endif -+ -+#ifndef portCRITICAL_NESTING_IN_TCB -+ #define portCRITICAL_NESTING_IN_TCB 0 -+#endif -+ -+#ifndef configMAX_TASK_NAME_LEN -+ #define configMAX_TASK_NAME_LEN 16 -+#endif -+ -+#ifndef configIDLE_SHOULD_YIELD -+ #define configIDLE_SHOULD_YIELD 1 -+#endif -+ -+#if configMAX_TASK_NAME_LEN < 1 -+ #error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h -+#endif -+ -+#ifndef configASSERT -+ #define configASSERT( x ) -+ #define configASSERT_DEFINED 0 -+#else -+ #define configASSERT_DEFINED 1 -+#endif -+ -+/* configPRECONDITION should be defined as configASSERT. -+ * The CBMC proofs need a way to track assumptions and assertions. -+ * A configPRECONDITION statement should express an implicit invariant or -+ * assumption made. A configASSERT statement should express an invariant that must -+ * hold explicit before calling the code. */ -+#ifndef configPRECONDITION -+ #define configPRECONDITION( X ) configASSERT( X ) -+ #define configPRECONDITION_DEFINED 0 -+#else -+ #define configPRECONDITION_DEFINED 1 -+#endif -+ -+#ifndef portMEMORY_BARRIER -+ #define portMEMORY_BARRIER() -+#endif -+ -+#ifndef portSOFTWARE_BARRIER -+ #define portSOFTWARE_BARRIER() -+#endif -+ -+/* The timers module relies on xTaskGetSchedulerState(). */ -+#if configUSE_TIMERS == 1 -+ -+ #ifndef configTIMER_TASK_PRIORITY -+ #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined. -+ #endif /* configTIMER_TASK_PRIORITY */ -+ -+ #ifndef configTIMER_QUEUE_LENGTH -+ #error If configUSE_TIMERS is set to 1 then configTIMER_QUEUE_LENGTH must also be defined. -+ #endif /* configTIMER_QUEUE_LENGTH */ -+ -+ #ifndef configTIMER_TASK_STACK_DEPTH -+ #error If configUSE_TIMERS is set to 1 then configTIMER_TASK_STACK_DEPTH must also be defined. -+ #endif /* configTIMER_TASK_STACK_DEPTH */ -+ -+#endif /* configUSE_TIMERS */ -+ -+#ifndef portSET_INTERRUPT_MASK_FROM_ISR -+ #define portSET_INTERRUPT_MASK_FROM_ISR() 0 -+#endif -+ -+#ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR -+ #define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue -+#endif -+ -+#ifndef portCLEAN_UP_TCB -+ #define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB -+#endif -+ -+#ifndef portPRE_TASK_DELETE_HOOK -+ #define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxYieldPending ) -+#endif -+ -+#ifndef portSETUP_TCB -+ #define portSETUP_TCB( pxTCB ) ( void ) pxTCB -+#endif -+ -+#ifndef configQUEUE_REGISTRY_SIZE -+ #define configQUEUE_REGISTRY_SIZE 0U -+#endif -+ -+#if ( configQUEUE_REGISTRY_SIZE < 1 ) -+ #define vQueueAddToRegistry( xQueue, pcName ) -+ #define vQueueUnregisterQueue( xQueue ) -+ #define pcQueueGetName( xQueue ) -+#endif -+ -+#ifndef portPOINTER_SIZE_TYPE -+ #define portPOINTER_SIZE_TYPE uint32_t -+#endif -+ -+/* Remove any unused trace macros. */ -+#ifndef traceSTART -+ -+/* Used to perform any necessary initialisation - for example, open a file -+ * into which trace is to be written. */ -+ #define traceSTART() -+#endif -+ -+#ifndef traceEND -+ -+/* Use to close a trace, for example close a file into which trace has been -+ * written. */ -+ #define traceEND() -+#endif -+ -+#ifndef traceTASK_SWITCHED_IN -+ -+/* Called after a task has been selected to run. pxCurrentTCB holds a pointer -+ * to the task control block of the selected task. */ -+ #define traceTASK_SWITCHED_IN() -+#endif -+ -+#ifndef traceINCREASE_TICK_COUNT -+ -+/* Called before stepping the tick count after waking from tickless idle -+ * sleep. */ -+ #define traceINCREASE_TICK_COUNT( x ) -+#endif -+ -+#ifndef traceLOW_POWER_IDLE_BEGIN -+ /* Called immediately before entering tickless idle. */ -+ #define traceLOW_POWER_IDLE_BEGIN() -+#endif -+ -+#ifndef traceLOW_POWER_IDLE_END -+ /* Called when returning to the Idle task after a tickless idle. */ -+ #define traceLOW_POWER_IDLE_END() -+#endif -+ -+#ifndef traceTASK_SWITCHED_OUT -+ -+/* Called before a task has been selected to run. pxCurrentTCB holds a pointer -+ * to the task control block of the task being switched out. */ -+ #define traceTASK_SWITCHED_OUT() -+#endif -+ -+#ifndef traceTASK_PRIORITY_INHERIT -+ -+/* Called when a task attempts to take a mutex that is already held by a -+ * lower priority task. pxTCBOfMutexHolder is a pointer to the TCB of the task -+ * that holds the mutex. uxInheritedPriority is the priority the mutex holder -+ * will inherit (the priority of the task that is attempting to obtain the -+ * muted. */ -+ #define traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority ) -+#endif -+ -+#ifndef traceTASK_PRIORITY_DISINHERIT -+ -+/* Called when a task releases a mutex, the holding of which had resulted in -+ * the task inheriting the priority of a higher priority task. -+ * pxTCBOfMutexHolder is a pointer to the TCB of the task that is releasing the -+ * mutex. uxOriginalPriority is the task's configured (base) priority. */ -+ #define traceTASK_PRIORITY_DISINHERIT( pxTCBOfMutexHolder, uxOriginalPriority ) -+#endif -+ -+#ifndef traceBLOCKING_ON_QUEUE_RECEIVE -+ -+/* Task is about to block because it cannot read from a -+ * queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore -+ * upon which the read was attempted. pxCurrentTCB points to the TCB of the -+ * task that attempted the read. */ -+ #define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) -+#endif -+ -+#ifndef traceBLOCKING_ON_QUEUE_PEEK -+ -+/* Task is about to block because it cannot read from a -+ * queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore -+ * upon which the read was attempted. pxCurrentTCB points to the TCB of the -+ * task that attempted the read. */ -+ #define traceBLOCKING_ON_QUEUE_PEEK( pxQueue ) -+#endif -+ -+#ifndef traceBLOCKING_ON_QUEUE_SEND -+ -+/* Task is about to block because it cannot write to a -+ * queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore -+ * upon which the write was attempted. pxCurrentTCB points to the TCB of the -+ * task that attempted the write. */ -+ #define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) -+#endif -+ -+#ifndef configCHECK_FOR_STACK_OVERFLOW -+ #define configCHECK_FOR_STACK_OVERFLOW 0 -+#endif -+ -+#ifndef configRECORD_STACK_HIGH_ADDRESS -+ #define configRECORD_STACK_HIGH_ADDRESS 0 -+#endif -+ -+#ifndef configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H -+ #define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 0 -+#endif -+ -+/* The following event macros are embedded in the kernel API calls. */ -+ -+#ifndef traceMOVED_TASK_TO_READY_STATE -+ #define traceMOVED_TASK_TO_READY_STATE( pxTCB ) -+#endif -+ -+#ifndef tracePOST_MOVED_TASK_TO_READY_STATE -+ #define tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB ) -+#endif -+ -+#ifndef traceQUEUE_CREATE -+ #define traceQUEUE_CREATE( pxNewQueue ) -+#endif -+ -+#ifndef traceQUEUE_CREATE_FAILED -+ #define traceQUEUE_CREATE_FAILED( ucQueueType ) -+#endif -+ -+#ifndef traceCREATE_MUTEX -+ #define traceCREATE_MUTEX( pxNewQueue ) -+#endif -+ -+#ifndef traceCREATE_MUTEX_FAILED -+ #define traceCREATE_MUTEX_FAILED() -+#endif -+ -+#ifndef traceGIVE_MUTEX_RECURSIVE -+ #define traceGIVE_MUTEX_RECURSIVE( pxMutex ) -+#endif -+ -+#ifndef traceGIVE_MUTEX_RECURSIVE_FAILED -+ #define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) -+#endif -+ -+#ifndef traceTAKE_MUTEX_RECURSIVE -+ #define traceTAKE_MUTEX_RECURSIVE( pxMutex ) -+#endif -+ -+#ifndef traceTAKE_MUTEX_RECURSIVE_FAILED -+ #define traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ) -+#endif -+ -+#ifndef traceCREATE_COUNTING_SEMAPHORE -+ #define traceCREATE_COUNTING_SEMAPHORE() -+#endif -+ -+#ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED -+ #define traceCREATE_COUNTING_SEMAPHORE_FAILED() -+#endif -+ -+#ifndef traceQUEUE_SET_SEND -+ #define traceQUEUE_SET_SEND traceQUEUE_SEND -+#endif -+ -+#ifndef traceQUEUE_SEND -+ #define traceQUEUE_SEND( pxQueue ) -+#endif -+ -+#ifndef traceQUEUE_SEND_FAILED -+ #define traceQUEUE_SEND_FAILED( pxQueue ) -+#endif -+ -+#ifndef traceQUEUE_RECEIVE -+ #define traceQUEUE_RECEIVE( pxQueue ) -+#endif -+ -+#ifndef traceQUEUE_PEEK -+ #define traceQUEUE_PEEK( pxQueue ) -+#endif -+ -+#ifndef traceQUEUE_PEEK_FAILED -+ #define traceQUEUE_PEEK_FAILED( pxQueue ) -+#endif -+ -+#ifndef traceQUEUE_PEEK_FROM_ISR -+ #define traceQUEUE_PEEK_FROM_ISR( pxQueue ) -+#endif -+ -+#ifndef traceQUEUE_RECEIVE_FAILED -+ #define traceQUEUE_RECEIVE_FAILED( pxQueue ) -+#endif -+ -+#ifndef traceQUEUE_SEND_FROM_ISR -+ #define traceQUEUE_SEND_FROM_ISR( pxQueue ) -+#endif -+ -+#ifndef traceQUEUE_SEND_FROM_ISR_FAILED -+ #define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) -+#endif -+ -+#ifndef traceQUEUE_RECEIVE_FROM_ISR -+ #define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) -+#endif -+ -+#ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED -+ #define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) -+#endif -+ -+#ifndef traceQUEUE_PEEK_FROM_ISR_FAILED -+ #define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ) -+#endif -+ -+#ifndef traceQUEUE_DELETE -+ #define traceQUEUE_DELETE( pxQueue ) -+#endif -+ -+#ifndef traceTASK_CREATE -+ #define traceTASK_CREATE( pxNewTCB ) -+#endif -+ -+#ifndef traceTASK_CREATE_FAILED -+ #define traceTASK_CREATE_FAILED() -+#endif -+ -+#ifndef traceTASK_DELETE -+ #define traceTASK_DELETE( pxTaskToDelete ) -+#endif -+ -+#ifndef traceTASK_DELAY_UNTIL -+ #define traceTASK_DELAY_UNTIL( x ) -+#endif -+ -+#ifndef traceTASK_DELAY -+ #define traceTASK_DELAY() -+#endif -+ -+#ifndef traceTASK_PRIORITY_SET -+ #define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) -+#endif -+ -+#ifndef traceTASK_SUSPEND -+ #define traceTASK_SUSPEND( pxTaskToSuspend ) -+#endif -+ -+#ifndef traceTASK_RESUME -+ #define traceTASK_RESUME( pxTaskToResume ) -+#endif -+ -+#ifndef traceTASK_RESUME_FROM_ISR -+ #define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) -+#endif -+ -+#ifndef traceTASK_INCREMENT_TICK -+ #define traceTASK_INCREMENT_TICK( xTickCount ) -+#endif -+ -+#ifndef traceTIMER_CREATE -+ #define traceTIMER_CREATE( pxNewTimer ) -+#endif -+ -+#ifndef traceTIMER_CREATE_FAILED -+ #define traceTIMER_CREATE_FAILED() -+#endif -+ -+#ifndef traceTIMER_COMMAND_SEND -+ #define traceTIMER_COMMAND_SEND( xTimer, xMessageID, xMessageValueValue, xReturn ) -+#endif -+ -+#ifndef traceTIMER_EXPIRED -+ #define traceTIMER_EXPIRED( pxTimer ) -+#endif -+ -+#ifndef traceTIMER_COMMAND_RECEIVED -+ #define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue ) -+#endif -+ -+#ifndef traceMALLOC -+ #define traceMALLOC( pvAddress, uiSize ) -+#endif -+ -+#ifndef traceFREE -+ #define traceFREE( pvAddress, uiSize ) -+#endif -+ -+#ifndef traceEVENT_GROUP_CREATE -+ #define traceEVENT_GROUP_CREATE( xEventGroup ) -+#endif -+ -+#ifndef traceEVENT_GROUP_CREATE_FAILED -+ #define traceEVENT_GROUP_CREATE_FAILED() -+#endif -+ -+#ifndef traceEVENT_GROUP_SYNC_BLOCK -+ #define traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ) -+#endif -+ -+#ifndef traceEVENT_GROUP_SYNC_END -+ #define traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred -+#endif -+ -+#ifndef traceEVENT_GROUP_WAIT_BITS_BLOCK -+ #define traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ) -+#endif -+ -+#ifndef traceEVENT_GROUP_WAIT_BITS_END -+ #define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred -+#endif -+ -+#ifndef traceEVENT_GROUP_CLEAR_BITS -+ #define traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ) -+#endif -+ -+#ifndef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR -+ #define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ) -+#endif -+ -+#ifndef traceEVENT_GROUP_SET_BITS -+ #define traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ) -+#endif -+ -+#ifndef traceEVENT_GROUP_SET_BITS_FROM_ISR -+ #define traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ) -+#endif -+ -+#ifndef traceEVENT_GROUP_DELETE -+ #define traceEVENT_GROUP_DELETE( xEventGroup ) -+#endif -+ -+#ifndef tracePEND_FUNC_CALL -+ #define tracePEND_FUNC_CALL( xFunctionToPend, pvParameter1, ulParameter2, ret ) -+#endif -+ -+#ifndef tracePEND_FUNC_CALL_FROM_ISR -+ #define tracePEND_FUNC_CALL_FROM_ISR( xFunctionToPend, pvParameter1, ulParameter2, ret ) -+#endif -+ -+#ifndef traceQUEUE_REGISTRY_ADD -+ #define traceQUEUE_REGISTRY_ADD( xQueue, pcQueueName ) -+#endif -+ -+#ifndef traceTASK_NOTIFY_TAKE_BLOCK -+ #define traceTASK_NOTIFY_TAKE_BLOCK( uxIndexToWait ) -+#endif -+ -+#ifndef traceTASK_NOTIFY_TAKE -+ #define traceTASK_NOTIFY_TAKE( uxIndexToWait ) -+#endif -+ -+#ifndef traceTASK_NOTIFY_WAIT_BLOCK -+ #define traceTASK_NOTIFY_WAIT_BLOCK( uxIndexToWait ) -+#endif -+ -+#ifndef traceTASK_NOTIFY_WAIT -+ #define traceTASK_NOTIFY_WAIT( uxIndexToWait ) -+#endif -+ -+#ifndef traceTASK_NOTIFY -+ #define traceTASK_NOTIFY( uxIndexToNotify ) -+#endif -+ -+#ifndef traceTASK_NOTIFY_FROM_ISR -+ #define traceTASK_NOTIFY_FROM_ISR( uxIndexToNotify ) -+#endif -+ -+#ifndef traceTASK_NOTIFY_GIVE_FROM_ISR -+ #define traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify ) -+#endif -+ -+#ifndef traceSTREAM_BUFFER_CREATE_FAILED -+ #define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ) -+#endif -+ -+#ifndef traceSTREAM_BUFFER_CREATE_STATIC_FAILED -+ #define traceSTREAM_BUFFER_CREATE_STATIC_FAILED( xReturn, xIsMessageBuffer ) -+#endif -+ -+#ifndef traceSTREAM_BUFFER_CREATE -+ #define traceSTREAM_BUFFER_CREATE( pxStreamBuffer, xIsMessageBuffer ) -+#endif -+ -+#ifndef traceSTREAM_BUFFER_DELETE -+ #define traceSTREAM_BUFFER_DELETE( xStreamBuffer ) -+#endif -+ -+#ifndef traceSTREAM_BUFFER_RESET -+ #define traceSTREAM_BUFFER_RESET( xStreamBuffer ) -+#endif -+ -+#ifndef traceBLOCKING_ON_STREAM_BUFFER_SEND -+ #define traceBLOCKING_ON_STREAM_BUFFER_SEND( xStreamBuffer ) -+#endif -+ -+#ifndef traceSTREAM_BUFFER_SEND -+ #define traceSTREAM_BUFFER_SEND( xStreamBuffer, xBytesSent ) -+#endif -+ -+#ifndef traceSTREAM_BUFFER_SEND_FAILED -+ #define traceSTREAM_BUFFER_SEND_FAILED( xStreamBuffer ) -+#endif -+ -+#ifndef traceSTREAM_BUFFER_SEND_FROM_ISR -+ #define traceSTREAM_BUFFER_SEND_FROM_ISR( xStreamBuffer, xBytesSent ) -+#endif -+ -+#ifndef traceBLOCKING_ON_STREAM_BUFFER_RECEIVE -+ #define traceBLOCKING_ON_STREAM_BUFFER_RECEIVE( xStreamBuffer ) -+#endif -+ -+#ifndef traceSTREAM_BUFFER_RECEIVE -+ #define traceSTREAM_BUFFER_RECEIVE( xStreamBuffer, xReceivedLength ) -+#endif -+ -+#ifndef traceSTREAM_BUFFER_RECEIVE_FAILED -+ #define traceSTREAM_BUFFER_RECEIVE_FAILED( xStreamBuffer ) -+#endif -+ -+#ifndef traceSTREAM_BUFFER_RECEIVE_FROM_ISR -+ #define traceSTREAM_BUFFER_RECEIVE_FROM_ISR( xStreamBuffer, xReceivedLength ) -+#endif -+ -+#ifdef ESP_PLATFORM -+#ifndef traceISR_EXIT_TO_SCHEDULER -+ #define traceISR_EXIT_TO_SCHEDULER() -+#endif -+ -+#ifndef traceISR_EXIT -+ #define traceISR_EXIT() -+#endif -+ -+#ifndef traceISR_ENTER -+ #define traceISR_ENTER(_n_) -+#endif -+#endif // ESP_PLATFORM -+ -+#ifndef configGENERATE_RUN_TIME_STATS -+ #define configGENERATE_RUN_TIME_STATS 0 -+#endif -+ -+#if ( configGENERATE_RUN_TIME_STATS == 1 ) -+ -+ #ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS -+ #error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base. -+ #endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */ -+ -+ #ifndef portGET_RUN_TIME_COUNTER_VALUE -+ #ifndef portALT_GET_RUN_TIME_COUNTER_VALUE -+ #error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information. -+ #endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */ -+ #endif /* portGET_RUN_TIME_COUNTER_VALUE */ -+ -+#endif /* configGENERATE_RUN_TIME_STATS */ -+ -+#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS -+ #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() -+#endif -+ -+#ifndef configUSE_MALLOC_FAILED_HOOK -+ #define configUSE_MALLOC_FAILED_HOOK 0 -+#endif -+ -+#ifndef portPRIVILEGE_BIT -+ #define portPRIVILEGE_BIT ( ( UBaseType_t ) 0x00 ) -+#endif -+ -+#ifndef portYIELD_WITHIN_API -+ #define portYIELD_WITHIN_API portYIELD -+#endif -+ -+#ifndef portSUPPRESS_TICKS_AND_SLEEP -+ #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) -+#endif -+ -+#ifndef configEXPECTED_IDLE_TIME_BEFORE_SLEEP -+ #define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 -+#endif -+ -+#if configEXPECTED_IDLE_TIME_BEFORE_SLEEP < 2 -+ #error configEXPECTED_IDLE_TIME_BEFORE_SLEEP must not be less than 2 -+#endif -+ -+#ifndef configUSE_TICKLESS_IDLE -+ #define configUSE_TICKLESS_IDLE 0 -+#endif -+ -+#ifndef configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING -+ #define configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( x ) -+#endif -+ -+#ifndef configPRE_SLEEP_PROCESSING -+ #define configPRE_SLEEP_PROCESSING( x ) -+#endif -+ -+#ifndef configPOST_SLEEP_PROCESSING -+ #define configPOST_SLEEP_PROCESSING( x ) -+#endif -+ -+#ifndef configUSE_QUEUE_SETS -+ #define configUSE_QUEUE_SETS 0 -+#endif -+ -+#ifndef portTASK_USES_FLOATING_POINT -+ #define portTASK_USES_FLOATING_POINT() -+#endif -+ -+#ifndef portALLOCATE_SECURE_CONTEXT -+ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) -+#endif -+ -+#ifndef portDONT_DISCARD -+ #define portDONT_DISCARD -+#endif -+ -+#ifndef configUSE_TIME_SLICING -+ #define configUSE_TIME_SLICING 1 -+#endif -+ -+#ifndef configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS -+ #define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0 -+#endif -+ -+#ifndef configUSE_STATS_FORMATTING_FUNCTIONS -+ #define configUSE_STATS_FORMATTING_FUNCTIONS 0 -+#endif -+ -+#ifndef portASSERT_IF_INTERRUPT_PRIORITY_INVALID -+ #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() -+#endif -+ -+#ifndef configUSE_TRACE_FACILITY -+ #define configUSE_TRACE_FACILITY 0 -+#endif -+ -+#ifndef mtCOVERAGE_TEST_MARKER -+ #define mtCOVERAGE_TEST_MARKER() -+#endif -+ -+#ifndef mtCOVERAGE_TEST_DELAY -+ #define mtCOVERAGE_TEST_DELAY() -+#endif -+ -+#ifndef portASSERT_IF_IN_ISR -+ #define portASSERT_IF_IN_ISR() -+#endif -+ -+#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION -+ #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 -+#endif -+ -+#ifndef configAPPLICATION_ALLOCATED_HEAP -+ #define configAPPLICATION_ALLOCATED_HEAP 0 -+#endif -+ -+#ifndef configUSE_TASK_NOTIFICATIONS -+ #define configUSE_TASK_NOTIFICATIONS 1 -+#endif -+ -+#ifndef configTASK_NOTIFICATION_ARRAY_ENTRIES -+ #define configTASK_NOTIFICATION_ARRAY_ENTRIES 1 -+#endif -+ -+#if configTASK_NOTIFICATION_ARRAY_ENTRIES < 1 -+ #error configTASK_NOTIFICATION_ARRAY_ENTRIES must be at least 1 -+#endif -+ -+#ifndef configUSE_POSIX_ERRNO -+ #define configUSE_POSIX_ERRNO 0 -+#endif -+ -+#ifndef portTICK_TYPE_IS_ATOMIC -+ #define portTICK_TYPE_IS_ATOMIC 0 -+#endif -+ -+#ifndef configSUPPORT_STATIC_ALLOCATION -+ /* Defaults to 0 for backward compatibility. */ -+ #define configSUPPORT_STATIC_ALLOCATION 0 -+#endif -+ -+#ifndef configSUPPORT_DYNAMIC_ALLOCATION -+ /* Defaults to 1 for backward compatibility. */ -+ #define configSUPPORT_DYNAMIC_ALLOCATION 1 -+#endif -+ -+#ifndef configSTACK_DEPTH_TYPE -+ -+/* Defaults to uint16_t for backward compatibility, but can be overridden -+ * in FreeRTOSConfig.h if uint16_t is too restrictive. */ -+ #define configSTACK_DEPTH_TYPE uint16_t -+#endif -+ -+#ifndef configRUN_TIME_COUNTER_TYPE -+ -+/* Defaults to uint32_t for backward compatibility, but can be overridden in -+ * FreeRTOSConfig.h if uint32_t is too restrictive. */ -+ -+ #define configRUN_TIME_COUNTER_TYPE uint32_t -+#endif -+ -+#ifndef configMESSAGE_BUFFER_LENGTH_TYPE -+ -+/* Defaults to size_t for backward compatibility, but can be overridden -+ * in FreeRTOSConfig.h if lengths will always be less than the number of bytes -+ * in a size_t. */ -+ #define configMESSAGE_BUFFER_LENGTH_TYPE size_t -+#endif -+ -+/* Sanity check the configuration. */ -+#if ( configUSE_TICKLESS_IDLE != 0 ) -+ #if ( INCLUDE_vTaskSuspend != 1 ) -+ #error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0 -+ #endif /* INCLUDE_vTaskSuspend */ -+#endif /* configUSE_TICKLESS_IDLE */ -+ -+#if ( ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) ) -+ #error configSUPPORT_STATIC_ALLOCATION and configSUPPORT_DYNAMIC_ALLOCATION cannot both be 0, but can both be 1. -+#endif -+ -+#if ( ( configUSE_RECURSIVE_MUTEXES == 1 ) && ( configUSE_MUTEXES != 1 ) ) -+ #error configUSE_MUTEXES must be set to 1 to use recursive mutexes -+#endif -+ -+#ifndef configINITIAL_TICK_COUNT -+ #define configINITIAL_TICK_COUNT 0 -+#endif -+ -+#if ( portTICK_TYPE_IS_ATOMIC == 0 ) -+ -+/* Either variables of tick type cannot be read atomically, or -+ * portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when -+ * the tick count is returned to the standard critical section macros. */ -+ #define portTICK_TYPE_ENTER_CRITICAL() portENTER_CRITICAL() -+ #define portTICK_TYPE_EXIT_CRITICAL() portEXIT_CRITICAL() -+ #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() -+ #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( ( x ) ) -+#else -+ -+/* The tick type can be read atomically, so critical sections used when the -+ * tick count is returned can be defined away. */ -+ #define portTICK_TYPE_ENTER_CRITICAL() -+ #define portTICK_TYPE_EXIT_CRITICAL() -+ #define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() 0 -+ #define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) ( void ) x -+#endif /* if ( portTICK_TYPE_IS_ATOMIC == 0 ) */ -+ -+/* Definitions to allow backward compatibility with FreeRTOS versions prior to -+ * V8 if desired. */ -+#ifndef configENABLE_BACKWARD_COMPATIBILITY -+ #define configENABLE_BACKWARD_COMPATIBILITY 1 -+#endif -+ -+#ifndef configPRINTF -+ -+/* configPRINTF() was not defined, so define it away to nothing. To use -+ * configPRINTF() then define it as follows (where MyPrintFunction() is -+ * provided by the application writer): -+ * -+ * void MyPrintFunction(const char *pcFormat, ... ); -+ #define configPRINTF( X ) MyPrintFunction X -+ * -+ * Then call like a standard printf() function, but placing brackets around -+ * all parameters so they are passed as a single parameter. For example: -+ * configPRINTF( ("Value = %d", MyVariable) ); */ -+ #define configPRINTF( X ) -+#endif -+ -+#ifndef configMAX -+ -+/* The application writer has not provided their own MAX macro, so define -+ * the following generic implementation. */ -+ #define configMAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) ) -+#endif -+ -+#ifndef configMIN -+ -+/* The application writer has not provided their own MIN macro, so define -+ * the following generic implementation. */ -+ #define configMIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) ) -+#endif -+ -+#if configENABLE_BACKWARD_COMPATIBILITY == 1 -+ #define eTaskStateGet eTaskGetState -+ #define portTickType TickType_t -+ #define xTaskHandle TaskHandle_t -+ #define xQueueHandle QueueHandle_t -+ #define xSemaphoreHandle SemaphoreHandle_t -+ #define xQueueSetHandle QueueSetHandle_t -+ #define xQueueSetMemberHandle QueueSetMemberHandle_t -+ #define xTimeOutType TimeOut_t -+ #define xMemoryRegion MemoryRegion_t -+ #define xTaskParameters TaskParameters_t -+ #define xTaskStatusType TaskStatus_t -+ #define xTimerHandle TimerHandle_t -+ #define xCoRoutineHandle CoRoutineHandle_t -+ #define pdTASK_HOOK_CODE TaskHookFunction_t -+ #define portTICK_RATE_MS portTICK_PERIOD_MS -+ #define pcTaskGetTaskName pcTaskGetName -+ #define pcTimerGetTimerName pcTimerGetName -+ #define pcQueueGetQueueName pcQueueGetName -+ #define vTaskGetTaskInfo vTaskGetInfo -+ #define xTaskGetIdleRunTimeCounter ulTaskGetIdleRunTimeCounter -+ -+/* Backward compatibility within the scheduler code only - these definitions -+ * are not really required but are included for completeness. */ -+ #define tmrTIMER_CALLBACK TimerCallbackFunction_t -+ #define pdTASK_CODE TaskFunction_t -+ #define xListItem ListItem_t -+ #define xList List_t -+ -+/* For libraries that break the list data hiding, and access list structure -+ * members directly (which is not supposed to be done). */ -+ #define pxContainer pvContainer -+#endif /* configENABLE_BACKWARD_COMPATIBILITY */ -+ -+#if ( configUSE_ALTERNATIVE_API != 0 ) -+ #error The alternative API was deprecated some time ago, and was removed in FreeRTOS V9.0 0 -+#endif -+ -+/* Set configUSE_TASK_FPU_SUPPORT to 0 to omit floating point support even -+ * if floating point hardware is otherwise supported by the FreeRTOS port in use. -+ * This constant is not supported by all FreeRTOS ports that include floating -+ * point support. */ -+#ifndef configUSE_TASK_FPU_SUPPORT -+ #define configUSE_TASK_FPU_SUPPORT 1 -+#endif -+ -+/* Set configENABLE_MPU to 1 to enable MPU support and 0 to disable it. This is -+ * currently used in ARMv8M ports. */ -+#ifndef configENABLE_MPU -+ #define configENABLE_MPU 0 -+#endif -+ -+/* Set configENABLE_FPU to 1 to enable FPU support and 0 to disable it. This is -+ * currently used in ARMv8M ports. */ -+#ifndef configENABLE_FPU -+ #define configENABLE_FPU 1 -+#endif -+ -+/* Set configENABLE_TRUSTZONE to 1 enable TrustZone support and 0 to disable it. -+ * This is currently used in ARMv8M ports. */ -+#ifndef configENABLE_TRUSTZONE -+ #define configENABLE_TRUSTZONE 1 -+#endif -+ -+/* Set configRUN_FREERTOS_SECURE_ONLY to 1 to run the FreeRTOS ARMv8M port on -+ * the Secure Side only. */ -+#ifndef configRUN_FREERTOS_SECURE_ONLY -+ #define configRUN_FREERTOS_SECURE_ONLY 0 -+#endif -+ -+#ifndef configRUN_ADDITIONAL_TESTS -+ #define configRUN_ADDITIONAL_TESTS 0 -+#endif -+ -+ -+/* Sometimes the FreeRTOSConfig.h settings only allow a task to be created using -+ * dynamically allocated RAM, in which case when any task is deleted it is known -+ * that both the task's stack and TCB need to be freed. Sometimes the -+ * FreeRTOSConfig.h settings only allow a task to be created using statically -+ * allocated RAM, in which case when any task is deleted it is known that neither -+ * the task's stack or TCB should be freed. Sometimes the FreeRTOSConfig.h -+ * settings allow a task to be created using either statically or dynamically -+ * allocated RAM, in which case a member of the TCB is used to record whether the -+ * stack and/or TCB were allocated statically or dynamically, so when a task is -+ * deleted the RAM that was allocated dynamically is freed again and no attempt is -+ * made to free the RAM that was allocated statically. -+ * tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE is only true if it is possible for a -+ * task to be created using either statically or dynamically allocated RAM. Note -+ * that if portUSING_MPU_WRAPPERS is 1 then a protected task can be created with -+ * a statically allocated stack and a dynamically allocated TCB. -+ * -+ * The following table lists various combinations of portUSING_MPU_WRAPPERS, -+ * configSUPPORT_DYNAMIC_ALLOCATION and configSUPPORT_STATIC_ALLOCATION and -+ * when it is possible to have both static and dynamic allocation: -+ * +-----+---------+--------+-----------------------------+-----------------------------------+------------------+-----------+ -+ * | MPU | Dynamic | Static | Available Functions | Possible Allocations | Both Dynamic and | Need Free | -+ * | | | | | | Static Possible | | -+ * +-----+---------+--------+-----------------------------+-----------------------------------+------------------+-----------+ -+ * | 0 | 0 | 1 | xTaskCreateStatic | TCB - Static, Stack - Static | No | No | -+ * +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------| -+ * | 0 | 1 | 0 | xTaskCreate | TCB - Dynamic, Stack - Dynamic | No | Yes | -+ * +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------| -+ * | 0 | 1 | 1 | xTaskCreate, | 1. TCB - Dynamic, Stack - Dynamic | Yes | Yes | -+ * | | | | xTaskCreateStatic | 2. TCB - Static, Stack - Static | | | -+ * +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------| -+ * | 1 | 0 | 1 | xTaskCreateStatic, | TCB - Static, Stack - Static | No | No | -+ * | | | | xTaskCreateRestrictedStatic | | | | -+ * +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------| -+ * | 1 | 1 | 0 | xTaskCreate, | 1. TCB - Dynamic, Stack - Dynamic | Yes | Yes | -+ * | | | | xTaskCreateRestricted | 2. TCB - Dynamic, Stack - Static | | | -+ * +-----|---------|--------|-----------------------------|-----------------------------------|------------------|-----------| -+ * | 1 | 1 | 1 | xTaskCreate, | 1. TCB - Dynamic, Stack - Dynamic | Yes | Yes | -+ * | | | | xTaskCreateStatic, | 2. TCB - Dynamic, Stack - Static | | | -+ * | | | | xTaskCreateRestricted, | 3. TCB - Static, Stack - Static | | | -+ * | | | | xTaskCreateRestrictedStatic | | | | -+ * +-----+---------+--------+-----------------------------+-----------------------------------+------------------+-----------+ -+ */ -+#define tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE \ -+ ( ( ( portUSING_MPU_WRAPPERS == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) || \ -+ ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) ) -+ -+/* -+ * In line with software engineering best practice, especially when supplying a -+ * library that is likely to change in future versions, FreeRTOS implements a -+ * strict data hiding policy. This means the Task structure used internally by -+ * FreeRTOS is not accessible to application code. However, if the application -+ * writer wants to statically allocate the memory required to create a task then -+ * the size of the task object needs to be known. The StaticTask_t structure -+ * below is provided for this purpose. Its sizes and alignment requirements are -+ * guaranteed to match those of the genuine structure, no matter which -+ * architecture is being used, and no matter how the values in FreeRTOSConfig.h -+ * are set. Its contents are somewhat obfuscated in the hope users will -+ * recognise that it would be unwise to make direct use of the structure members. -+ */ -+typedef struct xSTATIC_TCB -+{ -+ struct rt_thread thread; -+ #if ( configUSE_APPLICATION_TASK_TAG == 1 ) -+ void * pxTaskTag; -+ #endif -+ #if ( configUSE_TASK_NOTIFICATIONS == 1 ) -+ uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; -+ uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; -+ #endif -+ #if ( INCLUDE_xTaskAbortDelay == 1 ) -+ uint8_t ucDelayAborted; -+ #endif -+} StaticTask_t; -+ -+typedef struct -+{ -+ struct rt_ipc_object *rt_ipc; -+ struct rt_messagequeue ipc_obj; -+} StaticQueue_t; -+ -+typedef struct -+{ -+ struct rt_ipc_object *rt_ipc; -+ union -+ { -+ struct rt_semaphore_wrapper semaphore; -+ struct rt_mutex mutex; -+ } ipc_obj; -+} StaticSemaphore_t; -+ -+typedef struct xSTATIC_EVENT_GROUP -+{ -+ struct rt_event event; -+} StaticEventGroup_t; -+ -+typedef struct xSTATIC_TIMER -+{ -+ struct rt_timer timer; -+ void * pvTimerID; -+} StaticTimer_t; -+ -+/* *INDENT-OFF* */ -+#ifdef __cplusplus -+ } -+#endif -+/* *INDENT-ON* */ -+ -+#endif /* INC_FREERTOS_H */ -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/event_groups.h b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/event_groups.h -new file mode 100644 -index 0000000000..591814d37f ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/event_groups.h -@@ -0,0 +1,621 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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 -+ -+/* *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'). -+ * -+ * \defgroup EventGroup -+ */ -+ -+ -+ -+/** -+ * 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 configUSE_16_BIT_TICKS (16 bits if set to 1, -+ * 32 bits if set to 0. -+ * -+ * \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 configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If -+ * configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit -+ * 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has -+ * 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store -+ * event bits within an event group. -+ * -+ * @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 ); -+#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 configUSE_16_BIT_TICKS setting in FreeRTOSConfig.h. If -+ * configUSE_16_BIT_TICKS is 1 then each event group contains 8 usable bits (bit -+ * 0 to bit 7). If configUSE_16_BIT_TICKS is set to 0 then each event group has -+ * 24 usable bits (bit 0 to bit 23). The EventBits_t type is used to store -+ * event bits within an event group. -+ * -+ * @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 ); -+#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. -+ * -+ * @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. -+ * -+ * @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 ); -+ -+/** -+ * 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. -+ * -+ * @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 ); -+ -+/** -+ * 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. -+ * -+ * @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. -+ * } -+ * } -+ * @endcode -+ * \defgroup xEventGroupClearBitsFromISR xEventGroupClearBitsFromISR -+ * \ingroup EventGroup -+ */ -+BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, -+ const EventBits_t uxBitsToClear ); -+ -+/** -+ * 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. -+ * -+ * @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. There are two reasons why the returned value -+ * might have the bits specified by the uxBitsToSet parameter cleared. First, -+ * 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()). Second, any -+ * unblocked (or otherwise Ready state) task that has a priority above that of -+ * the task that called xEventGroupSetBits() will execute and may change the -+ * event group value before the call to xEventGroupSetBits() returns. -+ * -+ * 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 ); -+ -+/** -+ * 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 -+ */ -+BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, -+ const EventBits_t uxBitsToSet, -+ BaseType_t * pxHigherPriorityTaskWoken ); -+ -+/** -+ * 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. -+ * -+ * @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. -+ * -+ * @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 ); -+ -+/** -+ * 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. -+ * -+ * @param xEventGroup The event group being deleted. -+ */ -+void vEventGroupDelete( EventGroupHandle_t xEventGroup ); -+ -+/* *INDENT-OFF* */ -+#ifdef __cplusplus -+ } -+#endif -+/* *INDENT-ON* */ -+ -+#endif /* EVENT_GROUPS_H */ -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/list.h b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/list.h -new file mode 100644 -index 0000000000..dde1f3572e ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/list.h -@@ -0,0 +1,416 @@ -+/* -+ * FreeRTOS Kernel V10.4.3 -+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. -+ * -+ * 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 -+ * descending 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 to 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 INC_FREERTOS_H -+ #error "FreeRTOS.h must be included before list.h" -+#endif -+ -+#ifndef LIST_H -+#define LIST_H -+ -+/* -+ * 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 descending 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; /* For some reason lint wants this as two separate definitions. */ -+ -+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; -+ -+/* -+ * 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. */ -+ 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 descending 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 -+ */ -+#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ -+ { \ -+ 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 )->pxIndex->pxNext; \ -+ } \ -+ ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ -+ } -+ -+ -+/* -+ * 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 ); -+ -+/* -+ * 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 ); -+ -+/* -+ * Insert a list item into a list. The item will be inserted into the list in -+ * a position determined by its item value (descending 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 ); -+ -+/* -+ * 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 ); -+ -+/* -+ * 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 ); -+ -+/* *INDENT-OFF* */ -+#ifdef __cplusplus -+ } -+#endif -+/* *INDENT-ON* */ -+ -+#endif /* ifndef LIST_H */ -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/portable.h b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/portable.h -new file mode 100644 -index 0000000000..f0b56ae166 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/portable.h -@@ -0,0 +1,141 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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 -+ -+#include "freertos/portmacro.h" -+ -+#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 */ -+ -+/* *INDENT-OFF* */ -+#ifdef __cplusplus -+ extern "C" { -+#endif -+/* *INDENT-ON* */ -+ -+#ifdef configUSE_FREERTOS_PROVIDED_HEAP -+ -+/* 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 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; -+ -+#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 -+#else // configUSE_FREERTOS_PROVIDED_HEAP -+ -+/* -+ * Map to the memory management routines required for the port. -+ * -+ * Note that libc standard malloc/free are also available for -+ * non-FreeRTOS-specific code, and behave the same as -+ * pvPortMalloc()/vPortFree(). -+ */ -+#define pvPortMalloc malloc -+#define vPortFree free -+#define xPortGetFreeHeapSize esp_get_free_heap_size -+#define xPortGetMinimumEverFreeHeapSize esp_get_minimum_free_heap_size -+ -+#endif -+ -+void vPortEndScheduler( void ); -+ -+/* *INDENT-OFF* */ -+#ifdef __cplusplus -+ } -+#endif -+/* *INDENT-ON* */ -+ -+#endif /* PORTABLE_H */ -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/projdefs.h b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/projdefs.h -new file mode 100644 -index 0000000000..8b7c01bee7 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/projdefs.h -@@ -0,0 +1,64 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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 * ); -+ -+/* 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 ) rt_tick_from_millisecond( (rt_int32_t) xTimeInMs ) ) -+#endif -+ -+#ifdef ESP_PLATFORM -+#ifndef pdTICKS_TO_MS -+ #define pdTICKS_TO_MS( xTicks ) ( ( uint32_t ) ( xTicks ) * 1000 / configTICK_RATE_HZ ) -+#endif -+#endif // ESP_PLATFORM -+ -+#define pdFALSE ( ( BaseType_t ) 0 ) -+#define pdTRUE ( ( BaseType_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 ) -+ -+#endif /* PROJDEFS_H */ -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/queue.h b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/queue.h -new file mode 100644 -index 0000000000..57fe10ee8d ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/queue.h -@@ -0,0 +1,1188 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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 QUEUE_H -+#define QUEUE_H -+ -+/* *INDENT-OFF* */ -+#ifdef __cplusplus -+ extern "C" { -+#endif -+/* *INDENT-ON* */ -+ -+#include "task.h" -+ -+/** -+ * Type by which queues are referenced. For example, a call to xQueueCreate() -+ * returns an QueueHandle_t variable that can then be used as a parameter to -+ * xQueueSend(), xQueueReceive(), etc. -+ */ -+struct QueueDefinition; /* Using old naming convention so as not to break kernel aware debuggers. */ -+typedef struct QueueDefinition * QueueHandle_t; -+ -+/* For internal use only. */ -+#define queueSEND_TO_BACK ( ( BaseType_t ) 0 ) -+#define queueSEND_TO_FRONT ( ( BaseType_t ) 1 ) -+#define queueOVERWRITE ( ( BaseType_t ) 2 ) -+ -+/* For internal use only. These definitions *must* match those in queue.c. */ -+#define queueQUEUE_TYPE_BASE ( ( uint8_t ) 0U ) -+#define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U ) -+#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U ) -+#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U ) -+#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U ) -+#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U ) -+ -+/** -+ * queue. h -+ * @code{c} -+ * QueueHandle_t xQueueCreate( -+ * UBaseType_t uxQueueLength, -+ * UBaseType_t uxItemSize -+ * ); -+ * @endcode -+ * -+ * Creates a new queue instance, and returns a handle by which the new queue -+ * can be referenced. -+ * -+ * Internally, within the FreeRTOS implementation, queues use two blocks of -+ * memory. The first block is used to hold the queue's data structures. The -+ * second block is used to hold items placed into the queue. If a queue is -+ * created using xQueueCreate() then both blocks of memory are automatically -+ * dynamically allocated inside the xQueueCreate() function. (see -+ * https://www.FreeRTOS.org/a00111.html). If a queue is created using -+ * xQueueCreateStatic() then the application writer must provide the memory that -+ * will get used by the queue. xQueueCreateStatic() therefore allows a queue to -+ * be created without using any dynamic memory allocation. -+ * -+ * https://www.FreeRTOS.org/Embedded-RTOS-Queues.html -+ * -+ * @param uxQueueLength The maximum number of items that the queue can contain. -+ * -+ * @param uxItemSize The number of bytes each item in the queue will require. -+ * Items are queued by copy, not by reference, so this is the number of bytes -+ * that will be copied for each posted item. Each item on the queue must be -+ * the same size. -+ * -+ * @return If the queue is successfully create then a handle to the newly -+ * created queue is returned. If the queue cannot be created then 0 is -+ * returned. -+ * -+ * Example usage: -+ * @code{c} -+ * struct AMessage -+ * { -+ * char ucMessageID; -+ * char ucData[ 20 ]; -+ * }; -+ * -+ * void vATask( void *pvParameters ) -+ * { -+ * QueueHandle_t xQueue1, xQueue2; -+ * -+ * // Create a queue capable of containing 10 uint32_t values. -+ * xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) ); -+ * if( xQueue1 == 0 ) -+ * { -+ * // Queue was not created and must not be used. -+ * } -+ * -+ * // Create a queue capable of containing 10 pointers to AMessage structures. -+ * // These should be passed by pointer as they contain a lot of data. -+ * xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) ); -+ * if( xQueue2 == 0 ) -+ * { -+ * // Queue was not created and must not be used. -+ * } -+ * -+ * // ... Rest of task code. -+ * } -+ * @endcode -+ * \defgroup xQueueCreate xQueueCreate -+ * \ingroup QueueManagement -+ */ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ #define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) ) -+#endif -+ -+/** -+ * queue. h -+ * @code{c} -+ * QueueHandle_t xQueueCreateStatic( -+ * UBaseType_t uxQueueLength, -+ * UBaseType_t uxItemSize, -+ * uint8_t *pucQueueStorage, -+ * StaticQueue_t *pxQueueBuffer -+ * ); -+ * @endcode -+ * -+ * Creates a new queue instance, and returns a handle by which the new queue -+ * can be referenced. -+ * -+ * Internally, within the FreeRTOS implementation, queues use two blocks of -+ * memory. The first block is used to hold the queue's data structures. The -+ * second block is used to hold items placed into the queue. If a queue is -+ * created using xQueueCreate() then both blocks of memory are automatically -+ * dynamically allocated inside the xQueueCreate() function. (see -+ * https://www.FreeRTOS.org/a00111.html). If a queue is created using -+ * xQueueCreateStatic() then the application writer must provide the memory that -+ * will get used by the queue. xQueueCreateStatic() therefore allows a queue to -+ * be created without using any dynamic memory allocation. -+ * -+ * https://www.FreeRTOS.org/Embedded-RTOS-Queues.html -+ * -+ * @param uxQueueLength The maximum number of items that the queue can contain. -+ * -+ * @param uxItemSize The number of bytes each item in the queue will require. -+ * Items are queued by copy, not by reference, so this is the number of bytes -+ * that will be copied for each posted item. Each item on the queue must be -+ * the same size. -+ * -+ * @param pucQueueStorage If uxItemSize is not zero then -+ * pucQueueStorage must point to a uint8_t array that is at least large -+ * enough to hold the maximum number of items that can be in the queue at any -+ * one time - which is ( uxQueueLength * uxItemsSize ) bytes. If uxItemSize is -+ * zero then pucQueueStorage can be NULL. -+ * -+ * @param pxQueueBuffer Must point to a variable of type StaticQueue_t, which -+ * will be used to hold the queue's data structure. -+ * -+ * @return If the queue is created then a handle to the created queue is -+ * returned. If pxQueueBuffer is NULL then NULL is returned. -+ * -+ * Example usage: -+ * @code{c} -+ * struct AMessage -+ * { -+ * char ucMessageID; -+ * char ucData[ 20 ]; -+ * }; -+ * -+ #define QUEUE_LENGTH 10 -+ #define ITEM_SIZE sizeof( uint32_t ) -+ * -+ * // xQueueBuffer will hold the queue structure. -+ * StaticQueue_t xQueueBuffer; -+ * -+ * // ucQueueStorage will hold the items posted to the queue. Must be at least -+ * // [(queue length) * ( queue item size)] bytes long. -+ * uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ]; -+ * -+ * void vATask( void *pvParameters ) -+ * { -+ * QueueHandle_t xQueue1; -+ * -+ * // Create a queue capable of containing 10 uint32_t values. -+ * xQueue1 = xQueueCreate( QUEUE_LENGTH, // The number of items the queue can hold. -+ * ITEM_SIZE // The size of each item in the queue -+ * &( ucQueueStorage[ 0 ] ), // The buffer that will hold the items in the queue. -+ * &xQueueBuffer ); // The buffer that will hold the queue structure. -+ * -+ * // The queue is guaranteed to be created successfully as no dynamic memory -+ * // allocation is used. Therefore xQueue1 is now a handle to a valid queue. -+ * -+ * // ... Rest of task code. -+ * } -+ * @endcode -+ * \defgroup xQueueCreateStatic xQueueCreateStatic -+ * \ingroup QueueManagement -+ */ -+#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) -+ #define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer ) xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ), ( queueQUEUE_TYPE_BASE ) ) -+#endif /* configSUPPORT_STATIC_ALLOCATION */ -+ -+/** -+ * queue. h -+ * @code{c} -+ * BaseType_t xQueueSendToToFront( -+ * QueueHandle_t xQueue, -+ * const void *pvItemToQueue, -+ * TickType_t xTicksToWait -+ * ); -+ * @endcode -+ * -+ * Post an item to the front of a queue. The item is queued by copy, not by -+ * reference. This function must not be called from an interrupt service -+ * routine. See xQueueSendFromISR () for an alternative which may be used -+ * in an ISR. -+ * -+ * @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 xTicksToWait The maximum amount of time the task should block -+ * waiting for space to become available on the queue, should it already -+ * be full. The call will return immediately if this is set to 0 and the -+ * queue is full. The time is defined in tick periods so the constant -+ * portTICK_PERIOD_MS should be used to convert to real time if this is required. -+ * -+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. -+ * -+ * Example usage: -+ * @code{c} -+ * struct AMessage -+ * { -+ * char ucMessageID; -+ * char ucData[ 20 ]; -+ * } xMessage; -+ * -+ * uint32_t ulVar = 10UL; -+ * -+ * void vATask( void *pvParameters ) -+ * { -+ * QueueHandle_t xQueue1, xQueue2; -+ * struct AMessage *pxMessage; -+ * -+ * // Create a queue capable of containing 10 uint32_t values. -+ * xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) ); -+ * -+ * // Create a queue capable of containing 10 pointers to AMessage structures. -+ * // These should be passed by pointer as they contain a lot of data. -+ * xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) ); -+ * -+ * // ... -+ * -+ * if( xQueue1 != 0 ) -+ * { -+ * // Send an uint32_t. Wait for 10 ticks for space to become -+ * // available if necessary. -+ * if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS ) -+ * { -+ * // Failed to post the message, even after 10 ticks. -+ * } -+ * } -+ * -+ * if( xQueue2 != 0 ) -+ * { -+ * // Send a pointer to a struct AMessage object. Don't block if the -+ * // queue is already full. -+ * pxMessage = & xMessage; -+ * xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 ); -+ * } -+ * -+ * // ... Rest of task code. -+ * } -+ * @endcode -+ * \defgroup xQueueSend xQueueSend -+ * \ingroup QueueManagement -+ */ -+#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) \ -+ xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) -+ -+/** -+ * queue. h -+ * @code{c} -+ * BaseType_t xQueueSendToBack( -+ * QueueHandle_t xQueue, -+ * const void *pvItemToQueue, -+ * TickType_t xTicksToWait -+ * ); -+ * @endcode -+ * -+ * This is a macro that calls xQueueGenericSend(). -+ * -+ * Post an item to the back of a queue. The item is queued by copy, not by -+ * reference. This function must not be called from an interrupt service -+ * routine. See xQueueSendFromISR () for an alternative which may be used -+ * in an ISR. -+ * -+ * @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 xTicksToWait The maximum amount of time the task should block -+ * waiting for space to become available on the queue, should it already -+ * be full. The call will return immediately if this is set to 0 and the queue -+ * is full. The time is defined in tick periods so the constant -+ * portTICK_PERIOD_MS should be used to convert to real time if this is required. -+ * -+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. -+ * -+ * Example usage: -+ * @code{c} -+ * struct AMessage -+ * { -+ * char ucMessageID; -+ * char ucData[ 20 ]; -+ * } xMessage; -+ * -+ * uint32_t ulVar = 10UL; -+ * -+ * void vATask( void *pvParameters ) -+ * { -+ * QueueHandle_t xQueue1, xQueue2; -+ * struct AMessage *pxMessage; -+ * -+ * // Create a queue capable of containing 10 uint32_t values. -+ * xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) ); -+ * -+ * // Create a queue capable of containing 10 pointers to AMessage structures. -+ * // These should be passed by pointer as they contain a lot of data. -+ * xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) ); -+ * -+ * // ... -+ * -+ * if( xQueue1 != 0 ) -+ * { -+ * // Send an uint32_t. Wait for 10 ticks for space to become -+ * // available if necessary. -+ * if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS ) -+ * { -+ * // Failed to post the message, even after 10 ticks. -+ * } -+ * } -+ * -+ * if( xQueue2 != 0 ) -+ * { -+ * // Send a pointer to a struct AMessage object. Don't block if the -+ * // queue is already full. -+ * pxMessage = & xMessage; -+ * xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 ); -+ * } -+ * -+ * // ... Rest of task code. -+ * } -+ * @endcode -+ * \defgroup xQueueSend xQueueSend -+ * \ingroup QueueManagement -+ */ -+#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) \ -+ xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) -+ -+/** -+ * queue. h -+ * @code{c} -+ * BaseType_t xQueueSend( -+ * QueueHandle_t xQueue, -+ * const void * pvItemToQueue, -+ * TickType_t xTicksToWait -+ * ); -+ * @endcode -+ * -+ * This is a macro that calls xQueueGenericSend(). It is included for -+ * backward compatibility with versions of FreeRTOS.org that did not -+ * include the xQueueSendToFront() and xQueueSendToBack() macros. It is -+ * equivalent to xQueueSendToBack(). -+ * -+ * Post an item on a queue. The item is queued by copy, not by reference. -+ * This function must not be called from an interrupt service routine. -+ * See xQueueSendFromISR () for an alternative which may be used in an ISR. -+ * -+ * @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 xTicksToWait The maximum amount of time the task should block -+ * waiting for space to become available on the queue, should it already -+ * be full. The call will return immediately if this is set to 0 and the -+ * queue is full. The time is defined in tick periods so the constant -+ * portTICK_PERIOD_MS should be used to convert to real time if this is required. -+ * -+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. -+ * -+ * Example usage: -+ * @code{c} -+ * struct AMessage -+ * { -+ * char ucMessageID; -+ * char ucData[ 20 ]; -+ * } xMessage; -+ * -+ * uint32_t ulVar = 10UL; -+ * -+ * void vATask( void *pvParameters ) -+ * { -+ * QueueHandle_t xQueue1, xQueue2; -+ * struct AMessage *pxMessage; -+ * -+ * // Create a queue capable of containing 10 uint32_t values. -+ * xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) ); -+ * -+ * // Create a queue capable of containing 10 pointers to AMessage structures. -+ * // These should be passed by pointer as they contain a lot of data. -+ * xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) ); -+ * -+ * // ... -+ * -+ * if( xQueue1 != 0 ) -+ * { -+ * // Send an uint32_t. Wait for 10 ticks for space to become -+ * // available if necessary. -+ * if( xQueueSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS ) -+ * { -+ * // Failed to post the message, even after 10 ticks. -+ * } -+ * } -+ * -+ * if( xQueue2 != 0 ) -+ * { -+ * // Send a pointer to a struct AMessage object. Don't block if the -+ * // queue is already full. -+ * pxMessage = & xMessage; -+ * xQueueSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 ); -+ * } -+ * -+ * // ... Rest of task code. -+ * } -+ * @endcode -+ * \defgroup xQueueSend xQueueSend -+ * \ingroup QueueManagement -+ */ -+#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) \ -+ xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) -+ -+/** -+ * queue. h -+ * @code{c} -+ * BaseType_t xQueueGenericSend( -+ * QueueHandle_t xQueue, -+ * const void * pvItemToQueue, -+ * TickType_t xTicksToWait -+ * BaseType_t xCopyPosition -+ * ); -+ * @endcode -+ * -+ * It is preferred that the macros xQueueSend(), xQueueSendToFront() and -+ * xQueueSendToBack() are used in place of calling this function directly. -+ * -+ * Post an item on a queue. The item is queued by copy, not by reference. -+ * This function must not be called from an interrupt service routine. -+ * See xQueueSendFromISR () for an alternative which may be used in an ISR. -+ * -+ * @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 xTicksToWait The maximum amount of time the task should block -+ * waiting for space to become available on the queue, should it already -+ * be full. The call will return immediately if this is set to 0 and the -+ * queue is full. The time is defined in tick periods so the constant -+ * portTICK_PERIOD_MS should be used to convert to real time if this is required. -+ * -+ * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the -+ * item at the back of the queue, or queueSEND_TO_FRONT to place the item -+ * at the front of the queue (for high priority messages). -+ * -+ * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. -+ * -+ * Example usage: -+ * @code{c} -+ * struct AMessage -+ * { -+ * char ucMessageID; -+ * char ucData[ 20 ]; -+ * } xMessage; -+ * -+ * uint32_t ulVar = 10UL; -+ * -+ * void vATask( void *pvParameters ) -+ * { -+ * QueueHandle_t xQueue1, xQueue2; -+ * struct AMessage *pxMessage; -+ * -+ * // Create a queue capable of containing 10 uint32_t values. -+ * xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) ); -+ * -+ * // Create a queue capable of containing 10 pointers to AMessage structures. -+ * // These should be passed by pointer as they contain a lot of data. -+ * xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) ); -+ * -+ * // ... -+ * -+ * if( xQueue1 != 0 ) -+ * { -+ * // Send an uint32_t. Wait for 10 ticks for space to become -+ * // available if necessary. -+ * if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10, queueSEND_TO_BACK ) != pdPASS ) -+ * { -+ * // Failed to post the message, even after 10 ticks. -+ * } -+ * } -+ * -+ * if( xQueue2 != 0 ) -+ * { -+ * // Send a pointer to a struct AMessage object. Don't block if the -+ * // queue is already full. -+ * pxMessage = & xMessage; -+ * xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0, queueSEND_TO_BACK ); -+ * } -+ * -+ * // ... Rest of task code. -+ * } -+ * @endcode -+ * \defgroup xQueueSend xQueueSend -+ * \ingroup QueueManagement -+ */ -+BaseType_t xQueueGenericSend( QueueHandle_t xQueue, -+ const void * const pvItemToQueue, -+ TickType_t xTicksToWait, -+ const BaseType_t xCopyPosition ); -+ -+/** -+ * queue. h -+ * @code{c} -+ * BaseType_t xQueueReceive( -+ * QueueHandle_t xQueue, -+ * void *pvBuffer, -+ * TickType_t xTicksToWait -+ * ); -+ * @endcode -+ * -+ * Receive an item from a queue. The item is received by copy so a buffer of -+ * adequate size must be provided. The number of bytes copied into the buffer -+ * was defined when the queue was created. -+ * -+ * Successfully received items are removed from the queue. -+ * -+ * This function must not be used in an interrupt service routine. See -+ * xQueueReceiveFromISR for an alternative that can. -+ * -+ * @param xQueue The handle to the queue from which the item is to be -+ * received. -+ * -+ * @param pvBuffer Pointer to the buffer into which the received item will -+ * be copied. -+ * -+ * @param xTicksToWait The maximum amount of time the task should block -+ * waiting for an item to receive should the queue be empty at the time -+ * of the call. xQueueReceive() will return immediately if xTicksToWait -+ * is zero and the queue is empty. The time is defined in tick periods so the -+ * constant portTICK_PERIOD_MS should be used to convert to real time if this is -+ * required. -+ * -+ * @return pdTRUE if an item was successfully received from the queue, -+ * otherwise pdFALSE. -+ * -+ * Example usage: -+ * @code{c} -+ * struct AMessage -+ * { -+ * char ucMessageID; -+ * char ucData[ 20 ]; -+ * } xMessage; -+ * -+ * QueueHandle_t xQueue; -+ * -+ * // Task to create a queue and post a value. -+ * void vATask( void *pvParameters ) -+ * { -+ * struct AMessage *pxMessage; -+ * -+ * // Create a queue capable of containing 10 pointers to AMessage structures. -+ * // These should be passed by pointer as they contain a lot of data. -+ * xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) ); -+ * if( xQueue == 0 ) -+ * { -+ * // Failed to create the queue. -+ * } -+ * -+ * // ... -+ * -+ * // Send a pointer to a struct AMessage object. Don't block if the -+ * // queue is already full. -+ * pxMessage = & xMessage; -+ * xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 ); -+ * -+ * // ... Rest of task code. -+ * } -+ * -+ * // Task to receive from the queue. -+ * void vADifferentTask( void *pvParameters ) -+ * { -+ * struct AMessage *pxRxedMessage; -+ * -+ * if( xQueue != 0 ) -+ * { -+ * // Receive a message on the created queue. Block for 10 ticks if a -+ * // message is not immediately available. -+ * if( xQueueReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) ) -+ * { -+ * // pcRxedMessage now points to the struct AMessage variable posted -+ * // by vATask. -+ * } -+ * } -+ * -+ * // ... Rest of task code. -+ * } -+ * @endcode -+ * \defgroup xQueueReceive xQueueReceive -+ * \ingroup QueueManagement -+ */ -+BaseType_t xQueueReceive( QueueHandle_t xQueue, -+ void * const pvBuffer, -+ TickType_t xTicksToWait ); -+ -+/** -+ * queue. h -+ * @code{c} -+ * UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ); -+ * @endcode -+ * -+ * Return the number of messages stored in a queue. -+ * -+ * @param xQueue A handle to the queue being queried. -+ * -+ * @return The number of messages available in the queue. -+ * -+ * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting -+ * \ingroup QueueManagement -+ */ -+UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ); -+ -+/** -+ * queue. h -+ * @code{c} -+ * UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ); -+ * @endcode -+ * -+ * Return the number of free spaces available in a queue. This is equal to the -+ * number of items that can be sent to the queue before the queue becomes full -+ * if no items are removed. -+ * -+ * @param xQueue A handle to the queue being queried. -+ * -+ * @return The number of spaces available in the queue. -+ * -+ * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting -+ * \ingroup QueueManagement -+ */ -+UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ); -+ -+/** -+ * queue. h -+ * @code{c} -+ * void vQueueDelete( QueueHandle_t xQueue ); -+ * @endcode -+ * -+ * Delete a queue - freeing all the memory allocated for storing of items -+ * placed on the queue. -+ * -+ * @param xQueue A handle to the queue to be deleted. -+ * -+ * \defgroup vQueueDelete vQueueDelete -+ * \ingroup QueueManagement -+ */ -+void vQueueDelete( QueueHandle_t xQueue ); -+ -+/** -+ * queue. h -+ * @code{c} -+ * BaseType_t xQueueSendToFrontFromISR( -+ * QueueHandle_t xQueue, -+ * const void *pvItemToQueue, -+ * BaseType_t *pxHigherPriorityTaskWoken -+ * ); -+ * @endcode -+ * -+ * This is a macro that calls xQueueGenericSendFromISR(). -+ * -+ * Post an item to the front of a queue. It is safe to use this macro from -+ * within an interrupt service routine. -+ * -+ * Items are queued by copy not reference so it is preferable to only -+ * queue small items, especially when called from an ISR. In most cases -+ * it would be preferable to store a pointer to the item being queued. -+ * -+ * @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 pxHigherPriorityTaskWoken xQueueSendToFrontFromISR() will set -+ * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task -+ * to unblock, and the unblocked task has a priority higher than the currently -+ * running task. If xQueueSendToFromFromISR() sets this value to pdTRUE then -+ * a context switch should be requested before the interrupt is exited. -+ * -+ * @return pdTRUE if the data was successfully sent to the queue, otherwise -+ * errQUEUE_FULL. -+ * -+ * Example usage for buffered IO (where the ISR can obtain more than one value -+ * per call): -+ * @code{c} -+ * void vBufferISR( void ) -+ * { -+ * char cIn; -+ * BaseType_t xHigherPrioritTaskWoken; -+ * -+ * // We have not woken a task at the start of the ISR. -+ * xHigherPriorityTaskWoken = pdFALSE; -+ * -+ * // Loop until the buffer is empty. -+ * do -+ * { -+ * // Obtain a byte from the buffer. -+ * cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS ); -+ * -+ * // Post the byte. -+ * xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken ); -+ * -+ * } while( portINPUT_BYTE( BUFFER_COUNT ) ); -+ * -+ * // Now the buffer is empty we can switch context if necessary. -+ * if( xHigherPriorityTaskWoken ) -+ * { -+ * taskYIELD (); -+ * } -+ * } -+ * @endcode -+ * -+ * \defgroup xQueueSendFromISR xQueueSendFromISR -+ * \ingroup QueueManagement -+ */ -+#define xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \ -+ xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT ) -+ -+ -+/** -+ * queue. h -+ * @code{c} -+ * BaseType_t xQueueSendToBackFromISR( -+ * QueueHandle_t xQueue, -+ * const void *pvItemToQueue, -+ * BaseType_t *pxHigherPriorityTaskWoken -+ * ); -+ * @endcode -+ * -+ * This is a macro that calls xQueueGenericSendFromISR(). -+ * -+ * Post an item to the back of a queue. It is safe to use this macro from -+ * within an interrupt service routine. -+ * -+ * Items are queued by copy not reference so it is preferable to only -+ * queue small items, especially when called from an ISR. In most cases -+ * it would be preferable to store a pointer to the item being queued. -+ * -+ * @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 pxHigherPriorityTaskWoken xQueueSendToBackFromISR() will set -+ * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task -+ * to unblock, and the unblocked task has a priority higher than the currently -+ * running task. If xQueueSendToBackFromISR() sets this value to pdTRUE then -+ * a context switch should be requested before the interrupt is exited. -+ * -+ * @return pdTRUE if the data was successfully sent to the queue, otherwise -+ * errQUEUE_FULL. -+ * -+ * Example usage for buffered IO (where the ISR can obtain more than one value -+ * per call): -+ * @code{c} -+ * void vBufferISR( void ) -+ * { -+ * char cIn; -+ * BaseType_t xHigherPriorityTaskWoken; -+ * -+ * // We have not woken a task at the start of the ISR. -+ * xHigherPriorityTaskWoken = pdFALSE; -+ * -+ * // Loop until the buffer is empty. -+ * do -+ * { -+ * // Obtain a byte from the buffer. -+ * cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS ); -+ * -+ * // Post the byte. -+ * xQueueSendToBackFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken ); -+ * -+ * } while( portINPUT_BYTE( BUFFER_COUNT ) ); -+ * -+ * // Now the buffer is empty we can switch context if necessary. -+ * if( xHigherPriorityTaskWoken ) -+ * { -+ * taskYIELD (); -+ * } -+ * } -+ * @endcode -+ * -+ * \defgroup xQueueSendFromISR xQueueSendFromISR -+ * \ingroup QueueManagement -+ */ -+#define xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \ -+ xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) -+ -+/** -+ * queue. h -+ * @code{c} -+ * BaseType_t xQueueSendFromISR( -+ * QueueHandle_t xQueue, -+ * const void *pvItemToQueue, -+ * BaseType_t *pxHigherPriorityTaskWoken -+ * ); -+ * @endcode -+ * -+ * This is a macro that calls xQueueGenericSendFromISR(). It is included -+ * for backward compatibility with versions of FreeRTOS.org that did not -+ * include the xQueueSendToBackFromISR() and xQueueSendToFrontFromISR() -+ * macros. -+ * -+ * Post an item to the back of a queue. It is safe to use this function from -+ * within an interrupt service routine. -+ * -+ * Items are queued by copy not reference so it is preferable to only -+ * queue small items, especially when called from an ISR. In most cases -+ * it would be preferable to store a pointer to the item being queued. -+ * -+ * @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 pxHigherPriorityTaskWoken xQueueSendFromISR() will set -+ * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task -+ * to unblock, and the unblocked task has a priority higher than the currently -+ * running task. If xQueueSendFromISR() sets this value to pdTRUE then -+ * a context switch should be requested before the interrupt is exited. -+ * -+ * @return pdTRUE if the data was successfully sent to the queue, otherwise -+ * errQUEUE_FULL. -+ * -+ * Example usage for buffered IO (where the ISR can obtain more than one value -+ * per call): -+ * @code{c} -+ * void vBufferISR( void ) -+ * { -+ * char cIn; -+ * BaseType_t xHigherPriorityTaskWoken; -+ * -+ * // We have not woken a task at the start of the ISR. -+ * xHigherPriorityTaskWoken = pdFALSE; -+ * -+ * // Loop until the buffer is empty. -+ * do -+ * { -+ * // Obtain a byte from the buffer. -+ * cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS ); -+ * -+ * // Post the byte. -+ * xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken ); -+ * -+ * } while( portINPUT_BYTE( BUFFER_COUNT ) ); -+ * -+ * // Now the buffer is empty we can switch context if necessary. -+ * if( xHigherPriorityTaskWoken ) -+ * { -+ * // Actual macro used here is port specific. -+ * portYIELD_FROM_ISR (); -+ * } -+ * } -+ * @endcode -+ * -+ * \defgroup xQueueSendFromISR xQueueSendFromISR -+ * \ingroup QueueManagement -+ */ -+#define xQueueSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) \ -+ xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) -+ -+/** -+ * queue. h -+ * @code{c} -+ * BaseType_t xQueueGenericSendFromISR( -+ * QueueHandle_t xQueue, -+ * const void *pvItemToQueue, -+ * BaseType_t *pxHigherPriorityTaskWoken, -+ * BaseType_t xCopyPosition -+ * ); -+ * @endcode -+ * -+ * It is preferred that the macros xQueueSendFromISR(), -+ * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place -+ * of calling this function directly. xQueueGiveFromISR() is an -+ * equivalent for use by semaphores that don't actually copy any data. -+ * -+ * Post an item on a queue. It is safe to use this function from within an -+ * interrupt service routine. -+ * -+ * Items are queued by copy not reference so it is preferable to only -+ * queue small items, especially when called from an ISR. In most cases -+ * it would be preferable to store a pointer to the item being queued. -+ * -+ * @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 pxHigherPriorityTaskWoken xQueueGenericSendFromISR() will set -+ * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task -+ * to unblock, and the unblocked task has a priority higher than the currently -+ * running task. If xQueueGenericSendFromISR() sets this value to pdTRUE then -+ * a context switch should be requested before the interrupt is exited. -+ * -+ * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the -+ * item at the back of the queue, or queueSEND_TO_FRONT to place the item -+ * at the front of the queue (for high priority messages). -+ * -+ * @return pdTRUE if the data was successfully sent to the queue, otherwise -+ * errQUEUE_FULL. -+ * -+ * Example usage for buffered IO (where the ISR can obtain more than one value -+ * per call): -+ * @code{c} -+ * void vBufferISR( void ) -+ * { -+ * char cIn; -+ * BaseType_t xHigherPriorityTaskWokenByPost; -+ * -+ * // We have not woken a task at the start of the ISR. -+ * xHigherPriorityTaskWokenByPost = pdFALSE; -+ * -+ * // Loop until the buffer is empty. -+ * do -+ * { -+ * // Obtain a byte from the buffer. -+ * cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS ); -+ * -+ * // Post each byte. -+ * xQueueGenericSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWokenByPost, queueSEND_TO_BACK ); -+ * -+ * } while( portINPUT_BYTE( BUFFER_COUNT ) ); -+ * -+ * // Now the buffer is empty we can switch context if necessary. Note that the -+ * // name of the yield function required is port specific. -+ * if( xHigherPriorityTaskWokenByPost ) -+ * { -+ * portYIELD_FROM_ISR(); -+ * } -+ * } -+ * @endcode -+ * -+ * \defgroup xQueueSendFromISR xQueueSendFromISR -+ * \ingroup QueueManagement -+ */ -+BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, -+ const void * const pvItemToQueue, -+ BaseType_t * const pxHigherPriorityTaskWoken, -+ const BaseType_t xCopyPosition ); -+BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, -+ BaseType_t * const pxHigherPriorityTaskWoken ); -+ -+/** -+ * queue. h -+ * @code{c} -+ * BaseType_t xQueueReceiveFromISR( -+ * QueueHandle_t xQueue, -+ * void *pvBuffer, -+ * BaseType_t *pxTaskWoken -+ * ); -+ * @endcode -+ * -+ * Receive an item from a queue. It is safe to use this function from within an -+ * interrupt service routine. -+ * -+ * @param xQueue The handle to the queue from which the item is to be -+ * received. -+ * -+ * @param pvBuffer Pointer to the buffer into which the received item will -+ * be copied. -+ * -+ * @param pxTaskWoken A task may be blocked waiting for space to become -+ * available on the queue. If xQueueReceiveFromISR causes such a task to -+ * unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will -+ * remain unchanged. -+ * -+ * @return pdTRUE if an item was successfully received from the queue, -+ * otherwise pdFALSE. -+ * -+ * Example usage: -+ * @code{c} -+ * -+ * QueueHandle_t xQueue; -+ * -+ * // Function to create a queue and post some values. -+ * void vAFunction( void *pvParameters ) -+ * { -+ * char cValueToPost; -+ * const TickType_t xTicksToWait = ( TickType_t )0xff; -+ * -+ * // Create a queue capable of containing 10 characters. -+ * xQueue = xQueueCreate( 10, sizeof( char ) ); -+ * if( xQueue == 0 ) -+ * { -+ * // Failed to create the queue. -+ * } -+ * -+ * // ... -+ * -+ * // Post some characters that will be used within an ISR. If the queue -+ * // is full then this task will block for xTicksToWait ticks. -+ * cValueToPost = 'a'; -+ * xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait ); -+ * cValueToPost = 'b'; -+ * xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait ); -+ * -+ * // ... keep posting characters ... this task may block when the queue -+ * // becomes full. -+ * -+ * cValueToPost = 'c'; -+ * xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait ); -+ * } -+ * -+ * // ISR that outputs all the characters received on the queue. -+ * void vISR_Routine( void ) -+ * { -+ * BaseType_t xTaskWokenByReceive = pdFALSE; -+ * char cRxedChar; -+ * -+ * while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) ) -+ * { -+ * // A character was received. Output the character now. -+ * vOutputCharacter( cRxedChar ); -+ * -+ * // If removing the character from the queue woke the task that was -+ * // posting onto the queue cTaskWokenByReceive will have been set to -+ * // pdTRUE. No matter how many times this loop iterates only one -+ * // task will be woken. -+ * } -+ * -+ * if( cTaskWokenByPost != ( char ) pdFALSE; -+ * { -+ * taskYIELD (); -+ * } -+ * } -+ * @endcode -+ * \defgroup xQueueReceiveFromISR xQueueReceiveFromISR -+ * \ingroup QueueManagement -+ */ -+BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, -+ void * const pvBuffer, -+ BaseType_t * const pxHigherPriorityTaskWoken ); -+ -+/* -+ * Utilities to query queues that are safe to use from an ISR. These utilities -+ * should be used only from witin an ISR, or within a critical section. -+ */ -+BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ); -+BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ); -+UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ); -+ -+/* -+ * For internal use only. Use xSemaphoreCreateMutex(), -+ * xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling -+ * these functions directly. -+ */ -+QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ); -+QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, -+ StaticQueue_t * pxStaticQueue ); -+QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, -+ const UBaseType_t uxInitialCount ); -+QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, -+ const UBaseType_t uxInitialCount, -+ StaticQueue_t * pxStaticQueue ); -+BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, -+ TickType_t xTicksToWait ); -+TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore ); -+TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ); -+ -+/* -+ * For internal use only. Use xSemaphoreTakeMutexRecursive() or -+ * xSemaphoreGiveMutexRecursive() instead of calling these functions directly. -+ */ -+BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, -+ TickType_t xTicksToWait ); -+BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ); -+ -+/* -+ * Reset a queue back to its original empty state. The return value is now -+ * obsolete and is always set to pdPASS. -+ */ -+#define xQueueReset( xQueue ) xQueueGenericReset( xQueue, pdFALSE ) -+ -+/* -+ * Generic version of the function used to create a queue using dynamic memory -+ * allocation. This is called by other functions and macros that create other -+ * RTOS objects that use the queue structure as their base. -+ */ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, -+ const UBaseType_t uxItemSize, -+ const uint8_t ucQueueType ); -+#endif -+ -+/* -+ * Generic version of the function used to create a queue using dynamic memory -+ * allocation. This is called by other functions and macros that create other -+ * RTOS objects that use the queue structure as their base. -+ */ -+#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) -+ QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, -+ const UBaseType_t uxItemSize, -+ uint8_t * pucQueueStorage, -+ StaticQueue_t * pxStaticQueue, -+ const uint8_t ucQueueType ); -+#endif -+ -+/* Not public API functions. */ -+BaseType_t xQueueGenericReset( QueueHandle_t xQueue, -+ BaseType_t xNewQueue ); -+ -+/* Unimplemented */ -+typedef struct QueueDefinition * QueueSetHandle_t; -+typedef struct QueueDefinition * QueueSetMemberHandle_t; -+QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ); -+BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, -+ QueueSetHandle_t xQueueSet ); -+BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, -+ QueueSetHandle_t xQueueSet ); -+QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, -+ const TickType_t xTicksToWait ); -+QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ); -+BaseType_t xQueuePeek( QueueHandle_t xQueue, -+ void * const pvBuffer, -+ TickType_t xTicksToWait ); -+BaseType_t xQueueOverwrite(QueueHandle_t xQueue, const void * pvItemToQueue); -+BaseType_t xQueueOverwriteFromISR(QueueHandle_t xQueue, const void * pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken); -+/* *INDENT-OFF* */ -+#ifdef __cplusplus -+ } -+#endif -+/* *INDENT-ON* */ -+ -+#endif /* QUEUE_H */ -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/semphr.h b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/semphr.h -new file mode 100644 -index 0000000000..053dd177cf ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/semphr.h -@@ -0,0 +1,1188 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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 SEMAPHORE_H -+#define SEMAPHORE_H -+ -+#ifndef INC_FREERTOS_H -+ #error "include FreeRTOS.h" must appear in source files before "include semphr.h" -+#endif -+ -+#include "queue.h" -+ -+typedef QueueHandle_t SemaphoreHandle_t; -+ -+#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( uint8_t ) 1U ) -+#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U ) -+#define semGIVE_BLOCK_TIME ( ( TickType_t ) 0U ) -+ -+ -+/** -+ * semphr. h -+ * @code{c} -+ * vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore ); -+ * @endcode -+ * -+ * In many usage scenarios it is faster and more memory efficient to use a -+ * direct to task notification in place of a binary semaphore! -+ * https://www.FreeRTOS.org/RTOS-task-notifications.html -+ * -+ * This old vSemaphoreCreateBinary() macro is now deprecated in favour of the -+ * xSemaphoreCreateBinary() function. Note that binary semaphores created using -+ * the vSemaphoreCreateBinary() macro are created in a state such that the -+ * first call to 'take' the semaphore would pass, whereas binary semaphores -+ * created using xSemaphoreCreateBinary() are created in a state such that the -+ * the semaphore must first be 'given' before it can be 'taken'. -+ * -+ * Macro that implements a semaphore by using the existing queue mechanism. -+ * The queue length is 1 as this is a binary semaphore. The data size is 0 -+ * as we don't want to actually store any data - we just want to know if the -+ * queue is empty or full. -+ * -+ * This type of semaphore can be used for pure synchronisation between tasks or -+ * between an interrupt and a task. The semaphore need not be given back once -+ * obtained, so one task/interrupt can continuously 'give' the semaphore while -+ * another continuously 'takes' the semaphore. For this reason this type of -+ * semaphore does not use a priority inheritance mechanism. For an alternative -+ * that does use priority inheritance see xSemaphoreCreateMutex(). -+ * -+ * @param xSemaphore Handle to the created semaphore. Should be of type SemaphoreHandle_t. -+ * -+ * Example usage: -+ * @code{c} -+ * SemaphoreHandle_t xSemaphore = NULL; -+ * -+ * void vATask( void * pvParameters ) -+ * { -+ * // Semaphore cannot be used before a call to vSemaphoreCreateBinary (). -+ * // This is a macro so pass the variable in directly. -+ * vSemaphoreCreateBinary( xSemaphore ); -+ * -+ * if( xSemaphore != NULL ) -+ * { -+ * // The semaphore was created successfully. -+ * // The semaphore can now be used. -+ * } -+ * } -+ * @endcode -+ * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary -+ * \ingroup Semaphores -+ */ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ #define vSemaphoreCreateBinary( xSemaphore ) \ -+ { \ -+ ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ -+ if( ( xSemaphore ) != NULL ) \ -+ { \ -+ ( void ) xSemaphoreGive( ( xSemaphore ) ); \ -+ } \ -+ } -+#endif -+ -+/** -+ * semphr. h -+ * @code{c} -+ * SemaphoreHandle_t xSemaphoreCreateBinary( void ); -+ * @endcode -+ * -+ * Creates a new binary semaphore instance, and returns a handle by which the -+ * new semaphore can be referenced. -+ * -+ * In many usage scenarios it is faster and more memory efficient to use a -+ * direct to task notification in place of a binary semaphore! -+ * https://www.FreeRTOS.org/RTOS-task-notifications.html -+ * -+ * Internally, within the FreeRTOS implementation, binary semaphores use a block -+ * of memory, in which the semaphore structure is stored. If a binary semaphore -+ * is created using xSemaphoreCreateBinary() then the required memory is -+ * automatically dynamically allocated inside the xSemaphoreCreateBinary() -+ * function. (see https://www.FreeRTOS.org/a00111.html). If a binary semaphore -+ * is created using xSemaphoreCreateBinaryStatic() then the application writer -+ * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a -+ * binary semaphore to be created without using any dynamic memory allocation. -+ * -+ * The old vSemaphoreCreateBinary() macro is now deprecated in favour of this -+ * xSemaphoreCreateBinary() function. Note that binary semaphores created using -+ * the vSemaphoreCreateBinary() macro are created in a state such that the -+ * first call to 'take' the semaphore would pass, whereas binary semaphores -+ * created using xSemaphoreCreateBinary() are created in a state such that the -+ * the semaphore must first be 'given' before it can be 'taken'. -+ * -+ * This type of semaphore can be used for pure synchronisation between tasks or -+ * between an interrupt and a task. The semaphore need not be given back once -+ * obtained, so one task/interrupt can continuously 'give' the semaphore while -+ * another continuously 'takes' the semaphore. For this reason this type of -+ * semaphore does not use a priority inheritance mechanism. For an alternative -+ * that does use priority inheritance see xSemaphoreCreateMutex(). -+ * -+ * @return Handle to the created semaphore, or NULL if the memory required to -+ * hold the semaphore's data structures could not be allocated. -+ * -+ * Example usage: -+ * @code{c} -+ * SemaphoreHandle_t xSemaphore = NULL; -+ * -+ * void vATask( void * pvParameters ) -+ * { -+ * // Semaphore cannot be used before a call to xSemaphoreCreateBinary(). -+ * // This is a macro so pass the variable in directly. -+ * xSemaphore = xSemaphoreCreateBinary(); -+ * -+ * if( xSemaphore != NULL ) -+ * { -+ * // The semaphore was created successfully. -+ * // The semaphore can now be used. -+ * } -+ * } -+ * @endcode -+ * \defgroup xSemaphoreCreateBinary xSemaphoreCreateBinary -+ * \ingroup Semaphores -+ */ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ #define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) -+#endif -+ -+/** -+ * semphr. h -+ * @code{c} -+ * SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer ); -+ * @endcode -+ * -+ * Creates a new binary semaphore instance, and returns a handle by which the -+ * new semaphore can be referenced. -+ * -+ * NOTE: In many usage scenarios it is faster and more memory efficient to use a -+ * direct to task notification in place of a binary semaphore! -+ * https://www.FreeRTOS.org/RTOS-task-notifications.html -+ * -+ * Internally, within the FreeRTOS implementation, binary semaphores use a block -+ * of memory, in which the semaphore structure is stored. If a binary semaphore -+ * is created using xSemaphoreCreateBinary() then the required memory is -+ * automatically dynamically allocated inside the xSemaphoreCreateBinary() -+ * function. (see https://www.FreeRTOS.org/a00111.html). If a binary semaphore -+ * is created using xSemaphoreCreateBinaryStatic() then the application writer -+ * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a -+ * binary semaphore to be created without using any dynamic memory allocation. -+ * -+ * This type of semaphore can be used for pure synchronisation between tasks or -+ * between an interrupt and a task. The semaphore need not be given back once -+ * obtained, so one task/interrupt can continuously 'give' the semaphore while -+ * another continuously 'takes' the semaphore. For this reason this type of -+ * semaphore does not use a priority inheritance mechanism. For an alternative -+ * that does use priority inheritance see xSemaphoreCreateMutex(). -+ * -+ * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t, -+ * which will then be used to hold the semaphore's data structure, removing the -+ * need for the memory to be allocated dynamically. -+ * -+ * @return If the semaphore is created then a handle to the created semaphore is -+ * returned. If pxSemaphoreBuffer is NULL then NULL is returned. -+ * -+ * Example usage: -+ * @code{c} -+ * SemaphoreHandle_t xSemaphore = NULL; -+ * StaticSemaphore_t xSemaphoreBuffer; -+ * -+ * void vATask( void * pvParameters ) -+ * { -+ * // Semaphore cannot be used before a call to xSemaphoreCreateBinary(). -+ * // The semaphore's data structures will be placed in the xSemaphoreBuffer -+ * // variable, the address of which is passed into the function. The -+ * // function's parameter is not NULL, so the function will not attempt any -+ * // dynamic memory allocation, and therefore the function will not return -+ * // return NULL. -+ * xSemaphore = xSemaphoreCreateBinary( &xSemaphoreBuffer ); -+ * -+ * // Rest of task code goes here. -+ * } -+ * @endcode -+ * \defgroup xSemaphoreCreateBinaryStatic xSemaphoreCreateBinaryStatic -+ * \ingroup Semaphores -+ */ -+#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) -+ #define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, ( StaticQueue_t * ) pxStaticSemaphore, queueQUEUE_TYPE_BINARY_SEMAPHORE ) -+#endif /* configSUPPORT_STATIC_ALLOCATION */ -+ -+/** -+ * semphr. h -+ * @code{c} -+ * xSemaphoreTake( -+ * SemaphoreHandle_t xSemaphore, -+ * TickType_t xBlockTime -+ * ); -+ * @endcode -+ * -+ * Macro to obtain a semaphore. The semaphore must have previously been -+ * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or -+ * xSemaphoreCreateCounting(). -+ * -+ * @param xSemaphore A handle to the semaphore being taken - obtained when -+ * the semaphore was created. -+ * -+ * @param xBlockTime The time in ticks to wait for the semaphore to become -+ * available. The macro portTICK_PERIOD_MS can be used to convert this to a -+ * real time. A block time of zero can be used to poll the semaphore. A block -+ * time of portMAX_DELAY can be used to block indefinitely (provided -+ * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). -+ * -+ * @return pdTRUE if the semaphore was obtained. pdFALSE -+ * if xBlockTime expired without the semaphore becoming available. -+ * -+ * Example usage: -+ * @code{c} -+ * SemaphoreHandle_t xSemaphore = NULL; -+ * -+ * // A task that creates a semaphore. -+ * void vATask( void * pvParameters ) -+ * { -+ * // Create the semaphore to guard a shared resource. -+ * xSemaphore = xSemaphoreCreateBinary(); -+ * } -+ * -+ * // A task that uses the semaphore. -+ * void vAnotherTask( void * pvParameters ) -+ * { -+ * // ... Do other things. -+ * -+ * if( xSemaphore != NULL ) -+ * { -+ * // See if we can obtain the semaphore. If the semaphore is not available -+ * // wait 10 ticks to see if it becomes free. -+ * if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE ) -+ * { -+ * // We were able to obtain the semaphore and can now access the -+ * // shared resource. -+ * -+ * // ... -+ * -+ * // We have finished accessing the shared resource. Release the -+ * // semaphore. -+ * xSemaphoreGive( xSemaphore ); -+ * } -+ * else -+ * { -+ * // We could not obtain the semaphore and can therefore not access -+ * // the shared resource safely. -+ * } -+ * } -+ * } -+ * @endcode -+ * \defgroup xSemaphoreTake xSemaphoreTake -+ * \ingroup Semaphores -+ */ -+#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueSemaphoreTake( ( xSemaphore ), ( xBlockTime ) ) -+ -+/** -+ * semphr. h -+ * @code{c} -+ * xSemaphoreTakeRecursive( -+ * SemaphoreHandle_t xMutex, -+ * TickType_t xBlockTime -+ * ); -+ * @endcode -+ * -+ * Macro to recursively obtain, or 'take', a mutex type semaphore. -+ * The mutex must have previously been created using a call to -+ * xSemaphoreCreateRecursiveMutex(); -+ * -+ * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this -+ * macro to be available. -+ * -+ * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). -+ * -+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex -+ * doesn't become available again until the owner has called -+ * xSemaphoreGiveRecursive() for each successful 'take' request. For example, -+ * if a task successfully 'takes' the same mutex 5 times then the mutex will -+ * not be available to any other task until it has also 'given' the mutex back -+ * exactly five times. -+ * -+ * @param xMutex A handle to the mutex being obtained. This is the -+ * handle returned by xSemaphoreCreateRecursiveMutex(); -+ * -+ * @param xBlockTime The time in ticks to wait for the semaphore to become -+ * available. The macro portTICK_PERIOD_MS can be used to convert this to a -+ * real time. A block time of zero can be used to poll the semaphore. If -+ * the task already owns the semaphore then xSemaphoreTakeRecursive() will -+ * return immediately no matter what the value of xBlockTime. -+ * -+ * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime -+ * expired without the semaphore becoming available. -+ * -+ * Example usage: -+ * @code{c} -+ * SemaphoreHandle_t xMutex = NULL; -+ * -+ * // A task that creates a mutex. -+ * void vATask( void * pvParameters ) -+ * { -+ * // Create the mutex to guard a shared resource. -+ * xMutex = xSemaphoreCreateRecursiveMutex(); -+ * } -+ * -+ * // A task that uses the mutex. -+ * void vAnotherTask( void * pvParameters ) -+ * { -+ * // ... Do other things. -+ * -+ * if( xMutex != NULL ) -+ * { -+ * // See if we can obtain the mutex. If the mutex is not available -+ * // wait 10 ticks to see if it becomes free. -+ * if( xSemaphoreTakeRecursive( xSemaphore, ( TickType_t ) 10 ) == pdTRUE ) -+ * { -+ * // We were able to obtain the mutex and can now access the -+ * // shared resource. -+ * -+ * // ... -+ * // For some reason due to the nature of the code further calls to -+ * // xSemaphoreTakeRecursive() are made on the same mutex. In real -+ * // code these would not be just sequential calls as this would make -+ * // no sense. Instead the calls are likely to be buried inside -+ * // a more complex call structure. -+ * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); -+ * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); -+ * -+ * // The mutex has now been 'taken' three times, so will not be -+ * // available to another task until it has also been given back -+ * // three times. Again it is unlikely that real code would have -+ * // these calls sequentially, but instead buried in a more complex -+ * // call structure. This is just for illustrative purposes. -+ * xSemaphoreGiveRecursive( xMutex ); -+ * xSemaphoreGiveRecursive( xMutex ); -+ * xSemaphoreGiveRecursive( xMutex ); -+ * -+ * // Now the mutex can be taken by other tasks. -+ * } -+ * else -+ * { -+ * // We could not obtain the mutex and can therefore not access -+ * // the shared resource safely. -+ * } -+ * } -+ * } -+ * @endcode -+ * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive -+ * \ingroup Semaphores -+ */ -+#if ( configUSE_RECURSIVE_MUTEXES == 1 ) -+ #define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) -+#endif -+ -+/** -+ * semphr. h -+ * @code{c} -+ * xSemaphoreGive( SemaphoreHandle_t xSemaphore ); -+ * @endcode -+ * -+ * Macro to release a semaphore. The semaphore must have previously been -+ * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or -+ * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake(). -+ * -+ * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for -+ * an alternative which can be used from an ISR. -+ * -+ * This macro must also not be used on semaphores created using -+ * xSemaphoreCreateRecursiveMutex(). -+ * -+ * @param xSemaphore A handle to the semaphore being released. This is the -+ * handle returned when the semaphore was created. -+ * -+ * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred. -+ * Semaphores are implemented using queues. An error can occur if there is -+ * no space on the queue to post a message - indicating that the -+ * semaphore was not first obtained correctly. -+ * -+ * Example usage: -+ * @code{c} -+ * SemaphoreHandle_t xSemaphore = NULL; -+ * -+ * void vATask( void * pvParameters ) -+ * { -+ * // Create the semaphore to guard a shared resource. -+ * xSemaphore = vSemaphoreCreateBinary(); -+ * -+ * if( xSemaphore != NULL ) -+ * { -+ * if( xSemaphoreGive( xSemaphore ) != pdTRUE ) -+ * { -+ * // We would expect this call to fail because we cannot give -+ * // a semaphore without first "taking" it! -+ * } -+ * -+ * // Obtain the semaphore - don't block if the semaphore is not -+ * // immediately available. -+ * if( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) ) -+ * { -+ * // We now have the semaphore and can access the shared resource. -+ * -+ * // ... -+ * -+ * // We have finished accessing the shared resource so can free the -+ * // semaphore. -+ * if( xSemaphoreGive( xSemaphore ) != pdTRUE ) -+ * { -+ * // We would not expect this call to fail because we must have -+ * // obtained the semaphore to get here. -+ * } -+ * } -+ * } -+ * } -+ * @endcode -+ * \defgroup xSemaphoreGive xSemaphoreGive -+ * \ingroup Semaphores -+ */ -+#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) -+ -+/** -+ * semphr. h -+ * @code{c} -+ * xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex ); -+ * @endcode -+ * -+ * Macro to recursively release, or 'give', a mutex type semaphore. -+ * The mutex must have previously been created using a call to -+ * xSemaphoreCreateRecursiveMutex(); -+ * -+ * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this -+ * macro to be available. -+ * -+ * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). -+ * -+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex -+ * doesn't become available again until the owner has called -+ * xSemaphoreGiveRecursive() for each successful 'take' request. For example, -+ * if a task successfully 'takes' the same mutex 5 times then the mutex will -+ * not be available to any other task until it has also 'given' the mutex back -+ * exactly five times. -+ * -+ * @param xMutex A handle to the mutex being released, or 'given'. This is the -+ * handle returned by xSemaphoreCreateMutex(); -+ * -+ * @return pdTRUE if the semaphore was given. -+ * -+ * Example usage: -+ * @code{c} -+ * SemaphoreHandle_t xMutex = NULL; -+ * -+ * // A task that creates a mutex. -+ * void vATask( void * pvParameters ) -+ * { -+ * // Create the mutex to guard a shared resource. -+ * xMutex = xSemaphoreCreateRecursiveMutex(); -+ * } -+ * -+ * // A task that uses the mutex. -+ * void vAnotherTask( void * pvParameters ) -+ * { -+ * // ... Do other things. -+ * -+ * if( xMutex != NULL ) -+ * { -+ * // See if we can obtain the mutex. If the mutex is not available -+ * // wait 10 ticks to see if it becomes free. -+ * if( xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ) == pdTRUE ) -+ * { -+ * // We were able to obtain the mutex and can now access the -+ * // shared resource. -+ * -+ * // ... -+ * // For some reason due to the nature of the code further calls to -+ * // xSemaphoreTakeRecursive() are made on the same mutex. In real -+ * // code these would not be just sequential calls as this would make -+ * // no sense. Instead the calls are likely to be buried inside -+ * // a more complex call structure. -+ * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); -+ * xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ); -+ * -+ * // The mutex has now been 'taken' three times, so will not be -+ * // available to another task until it has also been given back -+ * // three times. Again it is unlikely that real code would have -+ * // these calls sequentially, it would be more likely that the calls -+ * // to xSemaphoreGiveRecursive() would be called as a call stack -+ * // unwound. This is just for demonstrative purposes. -+ * xSemaphoreGiveRecursive( xMutex ); -+ * xSemaphoreGiveRecursive( xMutex ); -+ * xSemaphoreGiveRecursive( xMutex ); -+ * -+ * // Now the mutex can be taken by other tasks. -+ * } -+ * else -+ * { -+ * // We could not obtain the mutex and can therefore not access -+ * // the shared resource safely. -+ * } -+ * } -+ * } -+ * @endcode -+ * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive -+ * \ingroup Semaphores -+ */ -+#if ( configUSE_RECURSIVE_MUTEXES == 1 ) -+ #define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) -+#endif -+ -+/** -+ * semphr. h -+ * @code{c} -+ * xSemaphoreGiveFromISR( -+ * SemaphoreHandle_t xSemaphore, -+ * BaseType_t *pxHigherPriorityTaskWoken -+ * ); -+ * @endcode -+ * -+ * Macro to release a semaphore. The semaphore must have previously been -+ * created with a call to xSemaphoreCreateBinary() or xSemaphoreCreateCounting(). -+ * -+ * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) -+ * must not be used with this macro. -+ * -+ * This macro can be used from an ISR. -+ * -+ * @param xSemaphore A handle to the semaphore being released. This is the -+ * handle returned when the semaphore was created. -+ * -+ * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set -+ * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task -+ * to unblock, and the unblocked task has a priority higher than the currently -+ * running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then -+ * a context switch should be requested before the interrupt is exited. -+ * -+ * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL. -+ * -+ * Example usage: -+ * @code{c} -+ \#define LONG_TIME 0xffff -+ \#define TICKS_TO_WAIT 10 -+ * SemaphoreHandle_t xSemaphore = NULL; -+ * -+ * // Repetitive task. -+ * void vATask( void * pvParameters ) -+ * { -+ * for( ;; ) -+ * { -+ * // We want this task to run every 10 ticks of a timer. The semaphore -+ * // was created before this task was started. -+ * -+ * // Block waiting for the semaphore to become available. -+ * if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE ) -+ * { -+ * // It is time to execute. -+ * -+ * // ... -+ * -+ * // We have finished our task. Return to the top of the loop where -+ * // we will block on the semaphore until it is time to execute -+ * // again. Note when using the semaphore for synchronisation with an -+ * // ISR in this manner there is no need to 'give' the semaphore back. -+ * } -+ * } -+ * } -+ * -+ * // Timer ISR -+ * void vTimerISR( void * pvParameters ) -+ * { -+ * static uint8_t ucLocalTickCount = 0; -+ * static BaseType_t xHigherPriorityTaskWoken; -+ * -+ * // A timer tick has occurred. -+ * -+ * // ... Do other time functions. -+ * -+ * // Is it time for vATask () to run? -+ * xHigherPriorityTaskWoken = pdFALSE; -+ * ucLocalTickCount++; -+ * if( ucLocalTickCount >= TICKS_TO_WAIT ) -+ * { -+ * // Unblock the task by releasing the semaphore. -+ * xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken ); -+ * -+ * // Reset the count so we release the semaphore again in 10 ticks time. -+ * ucLocalTickCount = 0; -+ * } -+ * -+ * if( xHigherPriorityTaskWoken != pdFALSE ) -+ * { -+ * // We can force a context switch here. Context switching from an -+ * // ISR uses port specific syntax. Check the demo task for your port -+ * // to find the syntax required. -+ * } -+ * } -+ * @endcode -+ * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR -+ * \ingroup Semaphores -+ */ -+#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) ) -+ -+/** -+ * semphr. h -+ * @code{c} -+ * xSemaphoreTakeFromISR( -+ * SemaphoreHandle_t xSemaphore, -+ * BaseType_t *pxHigherPriorityTaskWoken -+ * ); -+ * @endcode -+ * -+ * Macro to take a semaphore from an ISR. The semaphore must have -+ * previously been created with a call to xSemaphoreCreateBinary() or -+ * xSemaphoreCreateCounting(). -+ * -+ * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) -+ * must not be used with this macro. -+ * -+ * This macro can be used from an ISR, however taking a semaphore from an ISR -+ * is not a common operation. It is likely to only be useful when taking a -+ * counting semaphore when an interrupt is obtaining an object from a resource -+ * pool (when the semaphore count indicates the number of resources available). -+ * -+ * @param xSemaphore A handle to the semaphore being taken. This is the -+ * handle returned when the semaphore was created. -+ * -+ * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() will set -+ * *pxHigherPriorityTaskWoken to pdTRUE if taking the semaphore caused a task -+ * to unblock, and the unblocked task has a priority higher than the currently -+ * running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then -+ * a context switch should be requested before the interrupt is exited. -+ * -+ * @return pdTRUE if the semaphore was successfully taken, otherwise -+ * pdFALSE -+ */ -+#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) ) -+ -+/** -+ * semphr. h -+ * @code{c} -+ * SemaphoreHandle_t xSemaphoreCreateMutex( void ); -+ * @endcode -+ * -+ * Creates a new mutex type semaphore instance, and returns a handle by which -+ * the new mutex can be referenced. -+ * -+ * Internally, within the FreeRTOS implementation, mutex semaphores use a block -+ * of memory, in which the mutex structure is stored. If a mutex is created -+ * using xSemaphoreCreateMutex() then the required memory is automatically -+ * dynamically allocated inside the xSemaphoreCreateMutex() function. (see -+ * https://www.FreeRTOS.org/a00111.html). If a mutex is created using -+ * xSemaphoreCreateMutexStatic() then the application writer must provided the -+ * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created -+ * without using any dynamic memory allocation. -+ * -+ * Mutexes created using this function can be accessed using the xSemaphoreTake() -+ * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and -+ * xSemaphoreGiveRecursive() macros must not be used. -+ * -+ * This type of semaphore uses a priority inheritance mechanism so a task -+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the -+ * semaphore it is no longer required. -+ * -+ * Mutex type semaphores cannot be used from within interrupt service routines. -+ * -+ * See xSemaphoreCreateBinary() for an alternative implementation that can be -+ * used for pure synchronisation (where one task or interrupt always 'gives' the -+ * semaphore and another always 'takes' the semaphore) and from within interrupt -+ * service routines. -+ * -+ * @return If the mutex was successfully created then a handle to the created -+ * semaphore is returned. If there was not enough heap to allocate the mutex -+ * data structures then NULL is returned. -+ * -+ * Example usage: -+ * @code{c} -+ * SemaphoreHandle_t xSemaphore; -+ * -+ * void vATask( void * pvParameters ) -+ * { -+ * // Semaphore cannot be used before a call to xSemaphoreCreateMutex(). -+ * // This is a macro so pass the variable in directly. -+ * xSemaphore = xSemaphoreCreateMutex(); -+ * -+ * if( xSemaphore != NULL ) -+ * { -+ * // The semaphore was created successfully. -+ * // The semaphore can now be used. -+ * } -+ * } -+ * @endcode -+ * \defgroup xSemaphoreCreateMutex xSemaphoreCreateMutex -+ * \ingroup Semaphores -+ */ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) -+#endif -+ -+/** -+ * semphr. h -+ * @code{c} -+ * SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer ); -+ * @endcode -+ * -+ * Creates a new mutex type semaphore instance, and returns a handle by which -+ * the new mutex can be referenced. -+ * -+ * Internally, within the FreeRTOS implementation, mutex semaphores use a block -+ * of memory, in which the mutex structure is stored. If a mutex is created -+ * using xSemaphoreCreateMutex() then the required memory is automatically -+ * dynamically allocated inside the xSemaphoreCreateMutex() function. (see -+ * https://www.FreeRTOS.org/a00111.html). If a mutex is created using -+ * xSemaphoreCreateMutexStatic() then the application writer must provided the -+ * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created -+ * without using any dynamic memory allocation. -+ * -+ * Mutexes created using this function can be accessed using the xSemaphoreTake() -+ * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and -+ * xSemaphoreGiveRecursive() macros must not be used. -+ * -+ * This type of semaphore uses a priority inheritance mechanism so a task -+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the -+ * semaphore it is no longer required. -+ * -+ * Mutex type semaphores cannot be used from within interrupt service routines. -+ * -+ * See xSemaphoreCreateBinary() for an alternative implementation that can be -+ * used for pure synchronisation (where one task or interrupt always 'gives' the -+ * semaphore and another always 'takes' the semaphore) and from within interrupt -+ * service routines. -+ * -+ * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t, -+ * which will be used to hold the mutex's data structure, removing the need for -+ * the memory to be allocated dynamically. -+ * -+ * @return If the mutex was successfully created then a handle to the created -+ * mutex is returned. If pxMutexBuffer was NULL then NULL is returned. -+ * -+ * Example usage: -+ * @code{c} -+ * SemaphoreHandle_t xSemaphore; -+ * StaticSemaphore_t xMutexBuffer; -+ * -+ * void vATask( void * pvParameters ) -+ * { -+ * // A mutex cannot be used before it has been created. xMutexBuffer is -+ * // into xSemaphoreCreateMutexStatic() so no dynamic memory allocation is -+ * // attempted. -+ * xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer ); -+ * -+ * // As no dynamic memory allocation was performed, xSemaphore cannot be NULL, -+ * // so there is no need to check it. -+ * } -+ * @endcode -+ * \defgroup xSemaphoreCreateMutexStatic xSemaphoreCreateMutexStatic -+ * \ingroup Semaphores -+ */ -+#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) -+ #define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( StaticQueue_t * ) ( pxMutexBuffer ) ) -+#endif /* configSUPPORT_STATIC_ALLOCATION */ -+ -+/** -+ * semphr. h -+ * @code{c} -+ * SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void ); -+ * @endcode -+ * -+ * Creates a new recursive mutex type semaphore instance, and returns a handle -+ * by which the new recursive mutex can be referenced. -+ * -+ * Internally, within the FreeRTOS implementation, recursive mutexs use a block -+ * of memory, in which the mutex structure is stored. If a recursive mutex is -+ * created using xSemaphoreCreateRecursiveMutex() then the required memory is -+ * automatically dynamically allocated inside the -+ * xSemaphoreCreateRecursiveMutex() function. (see -+ * https://www.FreeRTOS.org/a00111.html). If a recursive mutex is created using -+ * xSemaphoreCreateRecursiveMutexStatic() then the application writer must -+ * provide the memory that will get used by the mutex. -+ * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to -+ * be created without using any dynamic memory allocation. -+ * -+ * Mutexes created using this macro can be accessed using the -+ * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The -+ * xSemaphoreTake() and xSemaphoreGive() macros must not be used. -+ * -+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex -+ * doesn't become available again until the owner has called -+ * xSemaphoreGiveRecursive() for each successful 'take' request. For example, -+ * if a task successfully 'takes' the same mutex 5 times then the mutex will -+ * not be available to any other task until it has also 'given' the mutex back -+ * exactly five times. -+ * -+ * This type of semaphore uses a priority inheritance mechanism so a task -+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the -+ * semaphore it is no longer required. -+ * -+ * Mutex type semaphores cannot be used from within interrupt service routines. -+ * -+ * See xSemaphoreCreateBinary() for an alternative implementation that can be -+ * used for pure synchronisation (where one task or interrupt always 'gives' the -+ * semaphore and another always 'takes' the semaphore) and from within interrupt -+ * service routines. -+ * -+ * @return xSemaphore Handle to the created mutex semaphore. Should be of type -+ * SemaphoreHandle_t. -+ * -+ * Example usage: -+ * @code{c} -+ * SemaphoreHandle_t xSemaphore; -+ * -+ * void vATask( void * pvParameters ) -+ * { -+ * // Semaphore cannot be used before a call to xSemaphoreCreateMutex(). -+ * // This is a macro so pass the variable in directly. -+ * xSemaphore = xSemaphoreCreateRecursiveMutex(); -+ * -+ * if( xSemaphore != NULL ) -+ * { -+ * // The semaphore was created successfully. -+ * // The semaphore can now be used. -+ * } -+ * } -+ * @endcode -+ * \defgroup xSemaphoreCreateRecursiveMutex xSemaphoreCreateRecursiveMutex -+ * \ingroup Semaphores -+ */ -+#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) -+ #define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX ) -+#endif -+ -+/** -+ * semphr. h -+ * @code{c} -+ * SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic( StaticSemaphore_t *pxMutexBuffer ); -+ * @endcode -+ * -+ * Creates a new recursive mutex type semaphore instance, and returns a handle -+ * by which the new recursive mutex can be referenced. -+ * -+ * Internally, within the FreeRTOS implementation, recursive mutexs use a block -+ * of memory, in which the mutex structure is stored. If a recursive mutex is -+ * created using xSemaphoreCreateRecursiveMutex() then the required memory is -+ * automatically dynamically allocated inside the -+ * xSemaphoreCreateRecursiveMutex() function. (see -+ * https://www.FreeRTOS.org/a00111.html). If a recursive mutex is created using -+ * xSemaphoreCreateRecursiveMutexStatic() then the application writer must -+ * provide the memory that will get used by the mutex. -+ * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to -+ * be created without using any dynamic memory allocation. -+ * -+ * Mutexes created using this macro can be accessed using the -+ * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The -+ * xSemaphoreTake() and xSemaphoreGive() macros must not be used. -+ * -+ * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex -+ * doesn't become available again until the owner has called -+ * xSemaphoreGiveRecursive() for each successful 'take' request. For example, -+ * if a task successfully 'takes' the same mutex 5 times then the mutex will -+ * not be available to any other task until it has also 'given' the mutex back -+ * exactly five times. -+ * -+ * This type of semaphore uses a priority inheritance mechanism so a task -+ * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the -+ * semaphore it is no longer required. -+ * -+ * Mutex type semaphores cannot be used from within interrupt service routines. -+ * -+ * See xSemaphoreCreateBinary() for an alternative implementation that can be -+ * used for pure synchronisation (where one task or interrupt always 'gives' the -+ * semaphore and another always 'takes' the semaphore) and from within interrupt -+ * service routines. -+ * -+ * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t, -+ * which will then be used to hold the recursive mutex's data structure, -+ * removing the need for the memory to be allocated dynamically. -+ * -+ * @return If the recursive mutex was successfully created then a handle to the -+ * created recursive mutex is returned. If pxMutexBuffer was NULL then NULL is -+ * returned. -+ * -+ * Example usage: -+ * @code{c} -+ * SemaphoreHandle_t xSemaphore; -+ * StaticSemaphore_t xMutexBuffer; -+ * -+ * void vATask( void * pvParameters ) -+ * { -+ * // A recursive semaphore cannot be used before it is created. Here a -+ * // recursive mutex is created using xSemaphoreCreateRecursiveMutexStatic(). -+ * // The address of xMutexBuffer is passed into the function, and will hold -+ * // the mutexes data structures - so no dynamic memory allocation will be -+ * // attempted. -+ * xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xMutexBuffer ); -+ * -+ * // As no dynamic memory allocation was performed, xSemaphore cannot be NULL, -+ * // so there is no need to check it. -+ * } -+ * @endcode -+ * \defgroup xSemaphoreCreateRecursiveMutexStatic xSemaphoreCreateRecursiveMutexStatic -+ * \ingroup Semaphores -+ */ -+#if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) -+ #define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, ( StaticQueue_t * ) pxStaticSemaphore ) -+#endif /* configSUPPORT_STATIC_ALLOCATION */ -+ -+/** -+ * semphr. h -+ * @code{c} -+ * SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount ); -+ * @endcode -+ * -+ * Creates a new counting semaphore instance, and returns a handle by which the -+ * new counting semaphore can be referenced. -+ * -+ * In many usage scenarios it is faster and more memory efficient to use a -+ * direct to task notification in place of a counting semaphore! -+ * https://www.FreeRTOS.org/RTOS-task-notifications.html -+ * -+ * Internally, within the FreeRTOS implementation, counting semaphores use a -+ * block of memory, in which the counting semaphore structure is stored. If a -+ * counting semaphore is created using xSemaphoreCreateCounting() then the -+ * required memory is automatically dynamically allocated inside the -+ * xSemaphoreCreateCounting() function. (see -+ * https://www.FreeRTOS.org/a00111.html). If a counting semaphore is created -+ * using xSemaphoreCreateCountingStatic() then the application writer can -+ * instead optionally provide the memory that will get used by the counting -+ * semaphore. xSemaphoreCreateCountingStatic() therefore allows a counting -+ * semaphore to be created without using any dynamic memory allocation. -+ * -+ * Counting semaphores are typically used for two things: -+ * -+ * 1) Counting events. -+ * -+ * In this usage scenario an event handler will 'give' a semaphore each time -+ * an event occurs (incrementing the semaphore count value), and a handler -+ * task will 'take' a semaphore each time it processes an event -+ * (decrementing the semaphore count value). The count value is therefore -+ * the difference between the number of events that have occurred and the -+ * number that have been processed. In this case it is desirable for the -+ * initial count value to be zero. -+ * -+ * 2) Resource management. -+ * -+ * In this usage scenario the count value indicates the number of resources -+ * available. To obtain control of a resource a task must first obtain a -+ * semaphore - decrementing the semaphore count value. When the count value -+ * reaches zero there are no free resources. When a task finishes with the -+ * resource it 'gives' the semaphore back - incrementing the semaphore count -+ * value. In this case it is desirable for the initial count value to be -+ * equal to the maximum count value, indicating that all resources are free. -+ * -+ * @param uxMaxCount The maximum count value that can be reached. When the -+ * semaphore reaches this value it can no longer be 'given'. -+ * -+ * @param uxInitialCount The count value assigned to the semaphore when it is -+ * created. -+ * -+ * @return Handle to the created semaphore. Null if the semaphore could not be -+ * created. -+ * -+ * Example usage: -+ * @code{c} -+ * SemaphoreHandle_t xSemaphore; -+ * -+ * void vATask( void * pvParameters ) -+ * { -+ * SemaphoreHandle_t xSemaphore = NULL; -+ * -+ * // Semaphore cannot be used before a call to xSemaphoreCreateCounting(). -+ * // The max value to which the semaphore can count should be 10, and the -+ * // initial value assigned to the count should be 0. -+ * xSemaphore = xSemaphoreCreateCounting( 10, 0 ); -+ * -+ * if( xSemaphore != NULL ) -+ * { -+ * // The semaphore was created successfully. -+ * // The semaphore can now be used. -+ * } -+ * } -+ * @endcode -+ * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting -+ * \ingroup Semaphores -+ */ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) -+#endif -+ -+/** -+ * semphr. h -+ * @code{c} -+ * SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer ); -+ * @endcode -+ * -+ * Creates a new counting semaphore instance, and returns a handle by which the -+ * new counting semaphore can be referenced. -+ * -+ * In many usage scenarios it is faster and more memory efficient to use a -+ * direct to task notification in place of a counting semaphore! -+ * https://www.FreeRTOS.org/RTOS-task-notifications.html -+ * -+ * Internally, within the FreeRTOS implementation, counting semaphores use a -+ * block of memory, in which the counting semaphore structure is stored. If a -+ * counting semaphore is created using xSemaphoreCreateCounting() then the -+ * required memory is automatically dynamically allocated inside the -+ * xSemaphoreCreateCounting() function. (see -+ * https://www.FreeRTOS.org/a00111.html). If a counting semaphore is created -+ * using xSemaphoreCreateCountingStatic() then the application writer must -+ * provide the memory. xSemaphoreCreateCountingStatic() therefore allows a -+ * counting semaphore to be created without using any dynamic memory allocation. -+ * -+ * Counting semaphores are typically used for two things: -+ * -+ * 1) Counting events. -+ * -+ * In this usage scenario an event handler will 'give' a semaphore each time -+ * an event occurs (incrementing the semaphore count value), and a handler -+ * task will 'take' a semaphore each time it processes an event -+ * (decrementing the semaphore count value). The count value is therefore -+ * the difference between the number of events that have occurred and the -+ * number that have been processed. In this case it is desirable for the -+ * initial count value to be zero. -+ * -+ * 2) Resource management. -+ * -+ * In this usage scenario the count value indicates the number of resources -+ * available. To obtain control of a resource a task must first obtain a -+ * semaphore - decrementing the semaphore count value. When the count value -+ * reaches zero there are no free resources. When a task finishes with the -+ * resource it 'gives' the semaphore back - incrementing the semaphore count -+ * value. In this case it is desirable for the initial count value to be -+ * equal to the maximum count value, indicating that all resources are free. -+ * -+ * @param uxMaxCount The maximum count value that can be reached. When the -+ * semaphore reaches this value it can no longer be 'given'. -+ * -+ * @param uxInitialCount The count value assigned to the semaphore when it is -+ * created. -+ * -+ * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t, -+ * which will then be used to hold the semaphore's data structure, removing the -+ * need for the memory to be allocated dynamically. -+ * -+ * @return If the counting semaphore was successfully created then a handle to -+ * the created counting semaphore is returned. If pxSemaphoreBuffer was NULL -+ * then NULL is returned. -+ * -+ * Example usage: -+ * @code{c} -+ * SemaphoreHandle_t xSemaphore; -+ * StaticSemaphore_t xSemaphoreBuffer; -+ * -+ * void vATask( void * pvParameters ) -+ * { -+ * SemaphoreHandle_t xSemaphore = NULL; -+ * -+ * // Counting semaphore cannot be used before they have been created. Create -+ * // a counting semaphore using xSemaphoreCreateCountingStatic(). The max -+ * // value to which the semaphore can count is 10, and the initial value -+ * // assigned to the count will be 0. The address of xSemaphoreBuffer is -+ * // passed in and will be used to hold the semaphore structure, so no dynamic -+ * // memory allocation will be used. -+ * xSemaphore = xSemaphoreCreateCounting( 10, 0, &xSemaphoreBuffer ); -+ * -+ * // No memory allocation was attempted so xSemaphore cannot be NULL, so there -+ * // is no need to check its value. -+ * } -+ * @endcode -+ * \defgroup xSemaphoreCreateCountingStatic xSemaphoreCreateCountingStatic -+ * \ingroup Semaphores -+ */ -+#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) -+ #define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ) xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), ( uxInitialCount ), ( StaticQueue_t * ) ( pxSemaphoreBuffer ) ) -+#endif /* configSUPPORT_STATIC_ALLOCATION */ -+ -+/** -+ * semphr. h -+ * @code{c} -+ * void vSemaphoreDelete( SemaphoreHandle_t xSemaphore ); -+ * @endcode -+ * -+ * Delete a semaphore. This function must be used with care. For example, -+ * do not delete a mutex type semaphore if the mutex is held by a task. -+ * -+ * @param xSemaphore A handle to the semaphore to be deleted. -+ * -+ * \defgroup vSemaphoreDelete vSemaphoreDelete -+ * \ingroup Semaphores -+ */ -+#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) ) -+ -+/** -+ * semphr.h -+ * @code{c} -+ * TaskHandle_t xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex ); -+ * @endcode -+ * -+ * If xMutex is indeed a mutex type semaphore, return the current mutex holder. -+ * If xMutex is not a mutex type semaphore, or the mutex is available (not held -+ * by a task), return NULL. -+ * -+ * Note: This is a good way of determining if the calling task is the mutex -+ * holder, but not a good way of determining the identity of the mutex holder as -+ * the holder may change between the function exiting and the returned value -+ * being tested. -+ */ -+#define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) ) -+ -+/** -+ * semphr.h -+ * @code{c} -+ * TaskHandle_t xSemaphoreGetMutexHolderFromISR( SemaphoreHandle_t xMutex ); -+ * @endcode -+ * -+ * If xMutex is indeed a mutex type semaphore, return the current mutex holder. -+ * If xMutex is not a mutex type semaphore, or the mutex is available (not held -+ * by a task), return NULL. -+ * -+ */ -+#define xSemaphoreGetMutexHolderFromISR( xSemaphore ) xQueueGetMutexHolderFromISR( ( xSemaphore ) ) -+ -+/** -+ * semphr.h -+ * @code{c} -+ * UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore ); -+ * @endcode -+ * -+ * If the semaphore is a counting semaphore then uxSemaphoreGetCount() returns -+ * its current count value. If the semaphore is a binary semaphore then -+ * uxSemaphoreGetCount() returns 1 if the semaphore is available, and 0 if the -+ * semaphore is not available. -+ * -+ */ -+#define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) ) -+ -+/** -+ * semphr.h -+ * @code{c} -+ * UBaseType_t uxSemaphoreGetCountFromISR( SemaphoreHandle_t xSemaphore ); -+ * @endcode -+ * -+ * If the semaphore is a counting semaphore then uxSemaphoreGetCountFromISR() returns -+ * its current count value. If the semaphore is a binary semaphore then -+ * uxSemaphoreGetCountFromISR() returns 1 if the semaphore is available, and 0 if the -+ * semaphore is not available. -+ * -+ */ -+#define uxSemaphoreGetCountFromISR( xSemaphore ) uxQueueMessagesWaitingFromISR( ( QueueHandle_t ) ( xSemaphore ) ) -+ -+#endif /* SEMAPHORE_H */ -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/task.h b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/task.h -new file mode 100644 -index 0000000000..20f6a52104 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/task.h -@@ -0,0 +1,2265 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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_TASK_H -+#define INC_TASK_H -+ -+#ifndef INC_FREERTOS_H -+ #error "include FreeRTOS.h must appear in source files before include task.h" -+#endif -+ -+/* *INDENT-OFF* */ -+#ifdef __cplusplus -+ extern "C" { -+#endif -+/* *INDENT-ON* */ -+ -+/*----------------------------------------------------------- -+* MACROS AND DEFINITIONS -+*----------------------------------------------------------*/ -+ -+/* -+ * If tskKERNEL_VERSION_NUMBER ends with + it represents the version in development -+ * after the numbered release. -+ * -+ * The tskKERNEL_VERSION_MAJOR, tskKERNEL_VERSION_MINOR, tskKERNEL_VERSION_BUILD -+ * values will reflect the last released version number. -+ */ -+#define tskKERNEL_VERSION_NUMBER "V10.4.6" -+#define tskKERNEL_VERSION_MAJOR 10 -+#define tskKERNEL_VERSION_MINOR 4 -+#define tskKERNEL_VERSION_BUILD 6 -+ -+/* The direct to task notification feature used to have only a single notification -+ * per task. Now there is an array of notifications per task that is dimensioned by -+ * configTASK_NOTIFICATION_ARRAY_ENTRIES. For backward compatibility, any use of the -+ * original direct to task notification defaults to using the first index in the -+ * array. */ -+#define tskDEFAULT_INDEX_TO_NOTIFY ( 0 ) -+ -+/* ESP32 */ -+#define tskNO_AFFINITY ( 0x7FFFFFFF ) -+ -+/** -+ * task. h -+ * -+ * Type by which tasks are referenced. For example, a call to xTaskCreate -+ * returns (via a pointer parameter) an TaskHandle_t variable that can then -+ * be used as a parameter to vTaskDelete to delete the task. -+ * -+ * \defgroup TaskHandle_t TaskHandle_t -+ * \ingroup Tasks -+ */ -+struct tskTaskControlBlock; /* The old naming convention is used to prevent breaking kernel aware debuggers. */ -+typedef struct tskTaskControlBlock * TaskHandle_t; -+ -+/* -+ * Defines the prototype to which the application task hook function must -+ * conform. -+ */ -+typedef BaseType_t (* TaskHookFunction_t)( void * ); -+ -+/* Task states returned by eTaskGetState. */ -+typedef enum -+{ -+ eRunning = 0, /* A task is querying the state of itself, so must be running. */ -+ eReady, /* The task being queried is in a ready or pending ready list. */ -+ eBlocked, /* The task being queried is in the Blocked state. */ -+ eSuspended, /* The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */ -+ eDeleted, /* The task being queried has been deleted, but its TCB has not yet been freed. */ -+ eInvalid /* Used as an 'invalid state' value. */ -+} eTaskState; -+ -+/* Actions that can be performed when vTaskNotify() is called. */ -+typedef enum -+{ -+ eNoAction = 0, /* Notify the task without updating its notify value. */ -+ eSetBits, /* Set bits in the task's notification value. */ -+ eIncrement, /* Increment the task's notification value. */ -+ eSetValueWithOverwrite, /* Set the task's notification value to a specific value even if the previous value has not yet been read by the task. */ -+ eSetValueWithoutOverwrite /* Set the task's notification value if the previous value has been read by the task. */ -+} eNotifyAction; -+ -+/* -+ * Used internally only. -+ */ -+typedef struct xTIME_OUT -+{ -+ BaseType_t xOverflowCount; -+ TickType_t xTimeOnEntering; -+} TimeOut_t; -+ -+/** -+ * Defines the priority used by the idle task. This must not be modified. -+ * -+ * \ingroup TaskUtils -+ */ -+#define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U ) -+ -+/** -+ * task. h -+ * -+ * Macro for forcing a context switch. -+ * -+ * \defgroup taskYIELD taskYIELD -+ * \ingroup SchedulerControl -+ */ -+#define taskYIELD() portYIELD() -+ -+/** -+ * task. h -+ * -+ * Macro to mark the start of a critical code region. Preemptive context -+ * switches cannot occur when in a critical region. -+ * -+ * NOTE: This may alter the stack (depending on the portable implementation) -+ * so must be used with care! -+ * -+ * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL -+ * \ingroup SchedulerControl -+ */ -+#define taskENTER_CRITICAL() portENTER_CRITICAL() -+#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() -+ -+/** -+ * task. h -+ * -+ * Macro to mark the end of a critical code region. Preemptive context -+ * switches cannot occur when in a critical region. -+ * -+ * NOTE: This may alter the stack (depending on the portable implementation) -+ * so must be used with care! -+ * -+ * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL -+ * \ingroup SchedulerControl -+ */ -+#define taskEXIT_CRITICAL() portEXIT_CRITICAL() -+#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) -+ -+/** -+ * task. h -+ * -+ * Macro to disable all maskable interrupts. -+ * -+ * \defgroup taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS -+ * \ingroup SchedulerControl -+ */ -+#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() -+ -+/** -+ * task. h -+ * -+ * Macro to enable microcontroller interrupts. -+ * -+ * \defgroup taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS -+ * \ingroup SchedulerControl -+ */ -+#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() -+ -+/* Definitions returned by xTaskGetSchedulerState(). taskSCHEDULER_SUSPENDED is -+ * 0 to generate more optimal code when configASSERT() is defined as the constant -+ * is used in assert() statements. */ -+#define taskSCHEDULER_SUSPENDED ( ( BaseType_t ) 0 ) -+#define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 ) -+#define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 ) -+ -+/*----------------------------------------------------------- -+* TASK CREATION API -+*----------------------------------------------------------*/ -+ -+/** -+ * task. h -+ * @code{c} -+ * BaseType_t xTaskCreate( -+ * TaskFunction_t pxTaskCode, -+ * const char *pcName, -+ * configSTACK_DEPTH_TYPE usStackDepth, -+ * void *pvParameters, -+ * UBaseType_t uxPriority, -+ * TaskHandle_t *pxCreatedTask -+ * ); -+ * @endcode -+ * -+ * Create a new task and add it to the list of tasks that are ready to run. -+ * -+ * Internally, within the FreeRTOS implementation, tasks use two blocks of -+ * memory. The first block is used to hold the task's data structures. The -+ * second block is used by the task as its stack. If a task is created using -+ * xTaskCreate() then both blocks of memory are automatically dynamically -+ * allocated inside the xTaskCreate() function. (see -+ * https://www.FreeRTOS.org/a00111.html). If a task is created using -+ * xTaskCreateStatic() then the application writer must provide the required -+ * memory. xTaskCreateStatic() therefore allows a task to be created without -+ * using any dynamic memory allocation. -+ * -+ * See xTaskCreateStatic() for a version that does not use any dynamic memory -+ * allocation. -+ * -+ * xTaskCreate() can only be used to create a task that has unrestricted -+ * access to the entire microcontroller memory map. Systems that include MPU -+ * support can alternatively create an MPU constrained task using -+ * xTaskCreateRestricted(). -+ * -+ * @param pxTaskCode Pointer to the task entry function. Tasks -+ * must be implemented to never return (i.e. continuous loop). -+ * -+ * @param pcName A descriptive name for the task. This is mainly used to -+ * facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN - default -+ * is 16. -+ * -+ * @param usStackDepth The size of the task stack specified as the number of -+ * variables the stack can hold - not the number of bytes. For example, if -+ * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes -+ * will be allocated for stack storage. -+ * -+ * @param pvParameters Pointer that will be used as the parameter for the task -+ * being created. -+ * -+ * @param uxPriority The priority at which the task should run. Systems that -+ * include MPU support can optionally create tasks in a privileged (system) -+ * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For -+ * example, to create a privileged task at priority 2 the uxPriority parameter -+ * should be set to ( 2 | portPRIVILEGE_BIT ). -+ * -+ * @param pxCreatedTask Used to pass back a handle by which the created task -+ * can be referenced. -+ * -+ * @return pdPASS if the task was successfully created and added to a ready -+ * list, otherwise an error code defined in the file projdefs.h -+ * -+ * Example usage: -+ * @code{c} -+ * // Task to be created. -+ * void vTaskCode( void * pvParameters ) -+ * { -+ * for( ;; ) -+ * { -+ * // Task code goes here. -+ * } -+ * } -+ * -+ * // Function that creates a task. -+ * void vOtherFunction( void ) -+ * { -+ * static uint8_t ucParameterToPass; -+ * TaskHandle_t xHandle = NULL; -+ * -+ * // Create the task, storing the handle. Note that the passed parameter ucParameterToPass -+ * // must exist for the lifetime of the task, so in this case is declared static. If it was just an -+ * // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time -+ * // the new task attempts to access it. -+ * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle ); -+ * configASSERT( xHandle ); -+ * -+ * // Use the handle to delete the task. -+ * if( xHandle != NULL ) -+ * { -+ * vTaskDelete( xHandle ); -+ * } -+ * } -+ * @endcode -+ * \defgroup xTaskCreate xTaskCreate -+ * \ingroup Tasks -+ */ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, -+ const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ -+ const configSTACK_DEPTH_TYPE usStackDepth, -+ void * const pvParameters, -+ UBaseType_t uxPriority, -+ TaskHandle_t * const pxCreatedTask ); -+#endif -+/* ESP32 */ -+#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode, -+ const char * const pcName, -+ const uint32_t usStackDepth, -+ void * const pvParameters, -+ UBaseType_t uxPriority, -+ TaskHandle_t * const pvCreatedTask, -+ const BaseType_t xCoreID); -+ -+#endif -+ -+/** -+ * task. h -+ * @code{c} -+ * TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, -+ * const char *pcName, -+ * uint32_t ulStackDepth, -+ * void *pvParameters, -+ * UBaseType_t uxPriority, -+ * StackType_t *puxStackBuffer, -+ * StaticTask_t *pxTaskBuffer ); -+ * @endcode -+ * -+ * Create a new task and add it to the list of tasks that are ready to run. -+ * -+ * Internally, within the FreeRTOS implementation, tasks use two blocks of -+ * memory. The first block is used to hold the task's data structures. The -+ * second block is used by the task as its stack. If a task is created using -+ * xTaskCreate() then both blocks of memory are automatically dynamically -+ * allocated inside the xTaskCreate() function. (see -+ * https://www.FreeRTOS.org/a00111.html). If a task is created using -+ * xTaskCreateStatic() then the application writer must provide the required -+ * memory. xTaskCreateStatic() therefore allows a task to be created without -+ * using any dynamic memory allocation. -+ * -+ * @param pxTaskCode Pointer to the task entry function. Tasks -+ * must be implemented to never return (i.e. continuous loop). -+ * -+ * @param pcName A descriptive name for the task. This is mainly used to -+ * facilitate debugging. The maximum length of the string is defined by -+ * configMAX_TASK_NAME_LEN in FreeRTOSConfig.h. -+ * -+ * @param ulStackDepth The size of the task stack specified as the number of -+ * variables the stack can hold - not the number of bytes. For example, if -+ * the stack is 32-bits wide and ulStackDepth is defined as 100 then 400 bytes -+ * will be allocated for stack storage. -+ * -+ * @param pvParameters Pointer that will be used as the parameter for the task -+ * being created. -+ * -+ * @param uxPriority The priority at which the task will run. -+ * -+ * @param puxStackBuffer Must point to a StackType_t array that has at least -+ * ulStackDepth indexes - the array will then be used as the task's stack, -+ * removing the need for the stack to be allocated dynamically. -+ * -+ * @param pxTaskBuffer Must point to a variable of type StaticTask_t, which will -+ * then be used to hold the task's data structures, removing the need for the -+ * memory to be allocated dynamically. -+ * -+ * @return If neither puxStackBuffer nor pxTaskBuffer are NULL, then the task -+ * will be created and a handle to the created task is returned. If either -+ * puxStackBuffer or pxTaskBuffer are NULL then the task will not be created and -+ * NULL is returned. -+ * -+ * Example usage: -+ * @code{c} -+ * -+ * // Dimensions of the buffer that the task being created will use as its stack. -+ * // NOTE: This is the number of words the stack will hold, not the number of -+ * // bytes. For example, if each stack item is 32-bits, and this is set to 100, -+ * // then 400 bytes (100 * 32-bits) will be allocated. -+ #define STACK_SIZE 200 -+ * -+ * // Structure that will hold the TCB of the task being created. -+ * StaticTask_t xTaskBuffer; -+ * -+ * // Buffer that the task being created will use as its stack. Note this is -+ * // an array of StackType_t variables. The size of StackType_t is dependent on -+ * // the RTOS port. -+ * StackType_t xStack[ STACK_SIZE ]; -+ * -+ * // Function that implements the task being created. -+ * void vTaskCode( void * pvParameters ) -+ * { -+ * // The parameter value is expected to be 1 as 1 is passed in the -+ * // pvParameters value in the call to xTaskCreateStatic(). -+ * configASSERT( ( uint32_t ) pvParameters == 1UL ); -+ * -+ * for( ;; ) -+ * { -+ * // Task code goes here. -+ * } -+ * } -+ * -+ * // Function that creates a task. -+ * void vOtherFunction( void ) -+ * { -+ * TaskHandle_t xHandle = NULL; -+ * -+ * // Create the task without using any dynamic memory allocation. -+ * xHandle = xTaskCreateStatic( -+ * vTaskCode, // Function that implements the task. -+ * "NAME", // Text name for the task. -+ * STACK_SIZE, // Stack size in words, not bytes. -+ * ( void * ) 1, // Parameter passed into the task. -+ * tskIDLE_PRIORITY,// Priority at which the task is created. -+ * xStack, // Array to use as the task's stack. -+ * &xTaskBuffer ); // Variable to hold the task's data structure. -+ * -+ * // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have -+ * // been created, and xHandle will be the task's handle. Use the handle -+ * // to suspend the task. -+ * vTaskSuspend( xHandle ); -+ * } -+ * @endcode -+ * \defgroup xTaskCreateStatic xTaskCreateStatic -+ * \ingroup Tasks -+ */ -+#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) -+ TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, -+ const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ -+ const uint32_t ulStackDepth, -+ void * const pvParameters, -+ UBaseType_t uxPriority, -+ StackType_t * const puxStackBuffer, -+ StaticTask_t * const pxTaskBuffer ); -+#endif /* configSUPPORT_STATIC_ALLOCATION */ -+ -+/** -+ * task. h -+ * @code{c} -+ * void vTaskDelete( TaskHandle_t xTaskToDelete ); -+ * @endcode -+ * -+ * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. -+ * See the configuration section for more information. -+ * -+ * Remove a task from the RTOS real time kernel's management. The task being -+ * deleted will be removed from all ready, blocked, suspended and event lists. -+ * -+ * NOTE: The idle task is responsible for freeing the kernel allocated -+ * memory from tasks that have been deleted. It is therefore important that -+ * the idle task is not starved of microcontroller processing time if your -+ * application makes any calls to vTaskDelete (). Memory allocated by the -+ * task code is not automatically freed, and should be freed before the task -+ * is deleted. -+ * -+ * See the demo application file death.c for sample code that utilises -+ * vTaskDelete (). -+ * -+ * @param xTaskToDelete The handle of the task to be deleted. Passing NULL will -+ * cause the calling task to be deleted. -+ * -+ * Example usage: -+ * @code{c} -+ * void vOtherFunction( void ) -+ * { -+ * TaskHandle_t xHandle; -+ * -+ * // Create the task, storing the handle. -+ * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); -+ * -+ * // Use the handle to delete the task. -+ * vTaskDelete( xHandle ); -+ * } -+ * @endcode -+ * \defgroup vTaskDelete vTaskDelete -+ * \ingroup Tasks -+ */ -+void vTaskDelete( TaskHandle_t xTaskToDelete ); -+ -+/*----------------------------------------------------------- -+* TASK CONTROL API -+*----------------------------------------------------------*/ -+ -+/** -+ * task. h -+ * @code{c} -+ * void vTaskDelay( const TickType_t xTicksToDelay ); -+ * @endcode -+ * -+ * Delay a task for a given number of ticks. The actual time that the -+ * task remains blocked depends on the tick rate. The constant -+ * portTICK_PERIOD_MS can be used to calculate real time from the tick -+ * rate - with the resolution of one tick period. -+ * -+ * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. -+ * See the configuration section for more information. -+ * -+ * -+ * vTaskDelay() specifies a time at which the task wishes to unblock relative to -+ * the time at which vTaskDelay() is called. For example, specifying a block -+ * period of 100 ticks will cause the task to unblock 100 ticks after -+ * vTaskDelay() is called. vTaskDelay() does not therefore provide a good method -+ * of controlling the frequency of a periodic task as the path taken through the -+ * code, as well as other task and interrupt activity, will affect the frequency -+ * at which vTaskDelay() gets called and therefore the time at which the task -+ * next executes. See xTaskDelayUntil() for an alternative API function designed -+ * to facilitate fixed frequency execution. It does this by specifying an -+ * absolute time (rather than a relative time) at which the calling task should -+ * unblock. -+ * -+ * @param xTicksToDelay The amount of time, in tick periods, that -+ * the calling task should block. -+ * -+ * Example usage: -+ * -+ * void vTaskFunction( void * pvParameters ) -+ * { -+ * // Block for 500ms. -+ * const TickType_t xDelay = 500 / portTICK_PERIOD_MS; -+ * -+ * for( ;; ) -+ * { -+ * // Simply toggle the LED every 500ms, blocking between each toggle. -+ * vToggleLED(); -+ * vTaskDelay( xDelay ); -+ * } -+ * } -+ * -+ * \defgroup vTaskDelay vTaskDelay -+ * \ingroup TaskCtrl -+ */ -+void vTaskDelay( const TickType_t xTicksToDelay ); -+ -+/** -+ * task. h -+ * @code{c} -+ * BaseType_t xTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement ); -+ * @endcode -+ * -+ * INCLUDE_xTaskDelayUntil must be defined as 1 for this function to be available. -+ * See the configuration section for more information. -+ * -+ * Delay a task until a specified time. This function can be used by periodic -+ * tasks to ensure a constant execution frequency. -+ * -+ * This function differs from vTaskDelay () in one important aspect: vTaskDelay () will -+ * cause a task to block for the specified number of ticks from the time vTaskDelay () is -+ * called. It is therefore difficult to use vTaskDelay () by itself to generate a fixed -+ * execution frequency as the time between a task starting to execute and that task -+ * calling vTaskDelay () may not be fixed [the task may take a different path though the -+ * code between calls, or may get interrupted or preempted a different number of times -+ * each time it executes]. -+ * -+ * Whereas vTaskDelay () specifies a wake time relative to the time at which the function -+ * is called, xTaskDelayUntil () specifies the absolute (exact) time at which it wishes to -+ * unblock. -+ * -+ * The macro pdMS_TO_TICKS() can be used to calculate the number of ticks from a -+ * time specified in milliseconds with a resolution of one tick period. -+ * -+ * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the -+ * task was last unblocked. The variable must be initialised with the current time -+ * prior to its first use (see the example below). Following this the variable is -+ * automatically updated within xTaskDelayUntil (). -+ * -+ * @param xTimeIncrement The cycle time period. The task will be unblocked at -+ * time *pxPreviousWakeTime + xTimeIncrement. Calling xTaskDelayUntil with the -+ * same xTimeIncrement parameter value will cause the task to execute with -+ * a fixed interface period. -+ * -+ * @return Value which can be used to check whether the task was actually delayed. -+ * Will be pdTRUE if the task way delayed and pdFALSE otherwise. A task will not -+ * be delayed if the next expected wake time is in the past. -+ * -+ * Example usage: -+ * @code{c} -+ * // Perform an action every 10 ticks. -+ * void vTaskFunction( void * pvParameters ) -+ * { -+ * TickType_t xLastWakeTime; -+ * const TickType_t xFrequency = 10; -+ * BaseType_t xWasDelayed; -+ * -+ * // Initialise the xLastWakeTime variable with the current time. -+ * xLastWakeTime = xTaskGetTickCount (); -+ * for( ;; ) -+ * { -+ * // Wait for the next cycle. -+ * xWasDelayed = xTaskDelayUntil( &xLastWakeTime, xFrequency ); -+ * -+ * // Perform action here. xWasDelayed value can be used to determine -+ * // whether a deadline was missed if the code here took too long. -+ * } -+ * } -+ * @endcode -+ * \defgroup xTaskDelayUntil xTaskDelayUntil -+ * \ingroup TaskCtrl -+ */ -+BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, -+ const TickType_t xTimeIncrement ); -+ -+/* -+ * vTaskDelayUntil() is the older version of xTaskDelayUntil() and does not -+ * return a value. -+ */ -+#define vTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ) \ -+ { \ -+ ( void ) xTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement ); \ -+ } -+ -+/** -+ * task. h -+ * @code{c} -+ * BaseType_t xTaskAbortDelay( TaskHandle_t xTask ); -+ * @endcode -+ * -+ * INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this -+ * function to be available. -+ * -+ * A task will enter the Blocked state when it is waiting for an event. The -+ * event it is waiting for can be a temporal event (waiting for a time), such -+ * as when vTaskDelay() is called, or an event on an object, such as when -+ * xQueueReceive() or ulTaskNotifyTake() is called. If the handle of a task -+ * that is in the Blocked state is used in a call to xTaskAbortDelay() then the -+ * task will leave the Blocked state, and return from whichever function call -+ * placed the task into the Blocked state. -+ * -+ * There is no 'FromISR' version of this function as an interrupt would need to -+ * know which object a task was blocked on in order to know which actions to -+ * take. For example, if the task was blocked on a queue the interrupt handler -+ * would then need to know if the queue was locked. -+ * -+ * @param xTask The handle of the task to remove from the Blocked state. -+ * -+ * @return If the task referenced by xTask was not in the Blocked state then -+ * pdFAIL is returned. Otherwise pdPASS is returned. -+ * -+ * \defgroup xTaskAbortDelay xTaskAbortDelay -+ * \ingroup TaskCtrl -+ */ -+BaseType_t xTaskAbortDelay( TaskHandle_t xTask ); -+ -+/** -+ * task. h -+ * @code{c} -+ * UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ); -+ * @endcode -+ * -+ * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be available. -+ * See the configuration section for more information. -+ * -+ * Obtain the priority of any task. -+ * -+ * @param xTask Handle of the task to be queried. Passing a NULL -+ * handle results in the priority of the calling task being returned. -+ * -+ * @return The priority of xTask. -+ * -+ * Example usage: -+ * @code{c} -+ * void vAFunction( void ) -+ * { -+ * TaskHandle_t xHandle; -+ * -+ * // Create a task, storing the handle. -+ * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); -+ * -+ * // ... -+ * -+ * // Use the handle to obtain the priority of the created task. -+ * // It was created with tskIDLE_PRIORITY, but may have changed -+ * // it itself. -+ * if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY ) -+ * { -+ * // The task has changed it's priority. -+ * } -+ * -+ * // ... -+ * -+ * // Is our priority higher than the created task? -+ * if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) ) -+ * { -+ * // Our priority (obtained using NULL handle) is higher. -+ * } -+ * } -+ * @endcode -+ * \defgroup uxTaskPriorityGet uxTaskPriorityGet -+ * \ingroup TaskCtrl -+ */ -+UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ); -+ -+/** -+ * task. h -+ * @code{c} -+ * UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ); -+ * @endcode -+ * -+ * A version of uxTaskPriorityGet() that can be used from an ISR. -+ */ -+UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ); -+ -+/** -+ * task. h -+ * @code{c} -+ * eTaskState eTaskGetState( TaskHandle_t xTask ); -+ * @endcode -+ * -+ * INCLUDE_eTaskGetState must be defined as 1 for this function to be available. -+ * See the configuration section for more information. -+ * -+ * Obtain the state of any task. States are encoded by the eTaskState -+ * enumerated type. -+ * -+ * @param xTask Handle of the task to be queried. -+ * -+ * @return The state of xTask at the time the function was called. Note the -+ * state of the task might change between the function being called, and the -+ * functions return value being tested by the calling task. -+ */ -+eTaskState eTaskGetState( TaskHandle_t xTask ); -+ -+/** -+ * task. h -+ * @code{c} -+ * void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority ); -+ * @endcode -+ * -+ * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available. -+ * See the configuration section for more information. -+ * -+ * Set the priority of any task. -+ * -+ * A context switch will occur before the function returns if the priority -+ * being set is higher than the currently executing task. -+ * -+ * @param xTask Handle to the task for which the priority is being set. -+ * Passing a NULL handle results in the priority of the calling task being set. -+ * -+ * @param uxNewPriority The priority to which the task will be set. -+ * -+ * Example usage: -+ * @code{c} -+ * void vAFunction( void ) -+ * { -+ * TaskHandle_t xHandle; -+ * -+ * // Create a task, storing the handle. -+ * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); -+ * -+ * // ... -+ * -+ * // Use the handle to raise the priority of the created task. -+ * vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 ); -+ * -+ * // ... -+ * -+ * // Use a NULL handle to raise our priority to the same value. -+ * vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 ); -+ * } -+ * @endcode -+ * \defgroup vTaskPrioritySet vTaskPrioritySet -+ * \ingroup TaskCtrl -+ */ -+void vTaskPrioritySet( TaskHandle_t xTask, -+ UBaseType_t uxNewPriority ); -+ -+/** -+ * task. h -+ * @code{c} -+ * void vTaskSuspend( TaskHandle_t xTaskToSuspend ); -+ * @endcode -+ * -+ * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. -+ * See the configuration section for more information. -+ * -+ * Suspend any task. When suspended a task will never get any microcontroller -+ * processing time, no matter what its priority. -+ * -+ * Calls to vTaskSuspend are not accumulative - -+ * i.e. calling vTaskSuspend () twice on the same task still only requires one -+ * call to vTaskResume () to ready the suspended task. -+ * -+ * RT-Thread only supports suspending the current running thread. -+ * This function must be called with NULL as the parameter. -+ * -+ * @param xTaskToSuspend Handle to the task being suspended. Passing a NULL -+ * handle will cause the calling task to be suspended. -+ * -+ * Example usage: -+ * @code{c} -+ * void vAFunction( void ) -+ * { -+ * TaskHandle_t xHandle; -+ * -+ * // Create a task, storing the handle. -+ * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); -+ * -+ * // ... -+ * -+ * // Use the handle to suspend the created task. -+ * vTaskSuspend( xHandle ); -+ * -+ * // ... -+ * -+ * // The created task will not run during this period, unless -+ * // another task calls vTaskResume( xHandle ). -+ * -+ * //... -+ * -+ * -+ * // Suspend ourselves. -+ * vTaskSuspend( NULL ); -+ * -+ * // We cannot get here unless another task calls vTaskResume -+ * // with our handle as the parameter. -+ * } -+ * @endcode -+ * \defgroup vTaskSuspend vTaskSuspend -+ * \ingroup TaskCtrl -+ */ -+void vTaskSuspend( TaskHandle_t xTaskToSuspend ); -+ -+/** -+ * task. h -+ * @code{c} -+ * void vTaskResume( TaskHandle_t xTaskToResume ); -+ * @endcode -+ * -+ * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. -+ * See the configuration section for more information. -+ * -+ * Resumes a suspended task. -+ * -+ * A task that has been suspended by one or more calls to vTaskSuspend () -+ * will be made available for running again by a single call to -+ * vTaskResume (). -+ * -+ * @param xTaskToResume Handle to the task being readied. -+ * -+ * Example usage: -+ * @code{c} -+ * void vAFunction( void ) -+ * { -+ * TaskHandle_t xHandle; -+ * -+ * // Create a task, storing the handle. -+ * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle ); -+ * -+ * // ... -+ * -+ * // Use the handle to suspend the created task. -+ * vTaskSuspend( xHandle ); -+ * -+ * // ... -+ * -+ * // The created task will not run during this period, unless -+ * // another task calls vTaskResume( xHandle ). -+ * -+ * //... -+ * -+ * -+ * // Resume the suspended task ourselves. -+ * vTaskResume( xHandle ); -+ * -+ * // The created task will once again get microcontroller processing -+ * // time in accordance with its priority within the system. -+ * } -+ * @endcode -+ * \defgroup vTaskResume vTaskResume -+ * \ingroup TaskCtrl -+ */ -+void vTaskResume( TaskHandle_t xTaskToResume ); -+ -+/** -+ * task. h -+ * @code{c} -+ * void xTaskResumeFromISR( TaskHandle_t xTaskToResume ); -+ * @endcode -+ * -+ * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be -+ * available. See the configuration section for more information. -+ * -+ * An implementation of vTaskResume() that can be called from within an ISR. -+ * -+ * A task that has been suspended by one or more calls to vTaskSuspend () -+ * will be made available for running again by a single call to -+ * xTaskResumeFromISR (). -+ * -+ * xTaskResumeFromISR() should not be used to synchronise a task with an -+ * interrupt if there is a chance that the interrupt could arrive prior to the -+ * task being suspended - as this can lead to interrupts being missed. Use of a -+ * semaphore as a synchronisation mechanism would avoid this eventuality. -+ * -+ * @param xTaskToResume Handle to the task being readied. -+ * -+ * @return pdTRUE if resuming the task should result in a context switch, -+ * otherwise pdFALSE. This is used by the ISR to determine if a context switch -+ * may be required following the ISR. -+ * -+ * \defgroup vTaskResumeFromISR vTaskResumeFromISR -+ * \ingroup TaskCtrl -+ */ -+BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ); -+ -+/*----------------------------------------------------------- -+* SCHEDULER CONTROL -+*----------------------------------------------------------*/ -+ -+/** -+ * task. h -+ * @code{c} -+ * void vTaskStartScheduler( void ); -+ * @endcode -+ * -+ * Starts the real time kernel tick processing. After calling the kernel -+ * has control over which tasks are executed and when. -+ * -+ * See the demo application file main.c for an example of creating -+ * tasks and starting the kernel. -+ * -+ * Example usage: -+ * @code{c} -+ * void vAFunction( void ) -+ * { -+ * // Create at least one task before starting the kernel. -+ * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); -+ * -+ * // Start the real time kernel with preemption. -+ * vTaskStartScheduler (); -+ * -+ * // Will not get here unless a task calls vTaskEndScheduler () -+ * } -+ * @endcode -+ * -+ * \defgroup vTaskStartScheduler vTaskStartScheduler -+ * \ingroup SchedulerControl -+ */ -+void vTaskStartScheduler( void ); -+ -+/** -+ * task. h -+ * @code{c} -+ * void vTaskEndScheduler( void ); -+ * @endcode -+ * -+ * NOTE: At the time of writing only the x86 real mode port, which runs on a PC -+ * in place of DOS, implements this function. -+ * -+ * Stops the real time kernel tick. All created tasks will be automatically -+ * deleted and multitasking (either preemptive or cooperative) will -+ * stop. Execution then resumes from the point where vTaskStartScheduler () -+ * was called, as if vTaskStartScheduler () had just returned. -+ * -+ * See the demo application file main. c in the demo/PC directory for an -+ * example that uses vTaskEndScheduler (). -+ * -+ * vTaskEndScheduler () requires an exit function to be defined within the -+ * portable layer (see vPortEndScheduler () in port. c for the PC port). This -+ * performs hardware specific operations such as stopping the kernel tick. -+ * -+ * vTaskEndScheduler () will cause all of the resources allocated by the -+ * kernel to be freed - but will not free resources allocated by application -+ * tasks. -+ * -+ * Example usage: -+ * @code{c} -+ * void vTaskCode( void * pvParameters ) -+ * { -+ * for( ;; ) -+ * { -+ * // Task code goes here. -+ * -+ * // At some point we want to end the real time kernel processing -+ * // so call ... -+ * vTaskEndScheduler (); -+ * } -+ * } -+ * -+ * void vAFunction( void ) -+ * { -+ * // Create at least one task before starting the kernel. -+ * xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL ); -+ * -+ * // Start the real time kernel with preemption. -+ * vTaskStartScheduler (); -+ * -+ * // Will only get here when the vTaskCode () task has called -+ * // vTaskEndScheduler (). When we get here we are back to single task -+ * // execution. -+ * } -+ * @endcode -+ * -+ * \defgroup vTaskEndScheduler vTaskEndScheduler -+ * \ingroup SchedulerControl -+ */ -+void vTaskEndScheduler( void ); -+ -+/** -+ * task. h -+ * @code{c} -+ * void vTaskSuspendAll( void ); -+ * @endcode -+ * -+ * Suspends the scheduler without disabling interrupts. Context switches will -+ * not occur while the scheduler is suspended. -+ * -+ * After calling vTaskSuspendAll () the calling task will continue to execute -+ * without risk of being swapped out until a call to xTaskResumeAll () has been -+ * made. -+ * -+ * API functions that have the potential to cause a context switch (for example, -+ * xTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler -+ * is suspended. -+ * -+ * Example usage: -+ * @code{c} -+ * void vTask1( void * pvParameters ) -+ * { -+ * for( ;; ) -+ * { -+ * // Task code goes here. -+ * -+ * // ... -+ * -+ * // At some point the task wants to perform a long operation during -+ * // which it does not want to get swapped out. It cannot use -+ * // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the -+ * // operation may cause interrupts to be missed - including the -+ * // ticks. -+ * -+ * // Prevent the real time kernel swapping out the task. -+ * vTaskSuspendAll (); -+ * -+ * // Perform the operation here. There is no need to use critical -+ * // sections as we have all the microcontroller processing time. -+ * // During this time interrupts will still operate and the kernel -+ * // tick count will be maintained. -+ * -+ * // ... -+ * -+ * // The operation is complete. Restart the kernel. -+ * xTaskResumeAll (); -+ * } -+ * } -+ * @endcode -+ * \defgroup vTaskSuspendAll vTaskSuspendAll -+ * \ingroup SchedulerControl -+ */ -+void vTaskSuspendAll( void ); -+ -+/** -+ * task. h -+ * @code{c} -+ * BaseType_t xTaskResumeAll( void ); -+ * @endcode -+ * -+ * Resumes scheduler activity after it was suspended by a call to -+ * vTaskSuspendAll(). -+ * -+ * xTaskResumeAll() only resumes the scheduler. It does not unsuspend tasks -+ * that were previously suspended by a call to vTaskSuspend(). -+ * -+ * @return If resuming the scheduler caused a context switch then pdTRUE is -+ * returned, otherwise pdFALSE is returned. -+ * -+ * Example usage: -+ * @code{c} -+ * void vTask1( void * pvParameters ) -+ * { -+ * for( ;; ) -+ * { -+ * // Task code goes here. -+ * -+ * // ... -+ * -+ * // At some point the task wants to perform a long operation during -+ * // which it does not want to get swapped out. It cannot use -+ * // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the -+ * // operation may cause interrupts to be missed - including the -+ * // ticks. -+ * -+ * // Prevent the real time kernel swapping out the task. -+ * vTaskSuspendAll (); -+ * -+ * // Perform the operation here. There is no need to use critical -+ * // sections as we have all the microcontroller processing time. -+ * // During this time interrupts will still operate and the real -+ * // time kernel tick count will be maintained. -+ * -+ * // ... -+ * -+ * // The operation is complete. Restart the kernel. We want to force -+ * // a context switch - but there is no point if resuming the scheduler -+ * // caused a context switch already. -+ * if( !xTaskResumeAll () ) -+ * { -+ * taskYIELD (); -+ * } -+ * } -+ * } -+ * @endcode -+ * \defgroup xTaskResumeAll xTaskResumeAll -+ * \ingroup SchedulerControl -+ */ -+BaseType_t xTaskResumeAll( void ); -+ -+/*----------------------------------------------------------- -+* TASK UTILITIES -+*----------------------------------------------------------*/ -+ -+/** -+ * task. h -+ * @code{c} -+ * TickType_t xTaskGetTickCount( void ); -+ * @endcode -+ * -+ * @return The count of ticks since vTaskStartScheduler was called. -+ * -+ * \defgroup xTaskGetTickCount xTaskGetTickCount -+ * \ingroup TaskUtils -+ */ -+TickType_t xTaskGetTickCount( void ); -+ -+/** -+ * task. h -+ * @code{c} -+ * TickType_t xTaskGetTickCountFromISR( void ); -+ * @endcode -+ * -+ * @return The count of ticks since vTaskStartScheduler was called. -+ * -+ * This is a version of xTaskGetTickCount() that is safe to be called from an -+ * ISR - provided that TickType_t is the natural word size of the -+ * microcontroller being used or interrupt nesting is either not supported or -+ * not being used. -+ * -+ * \defgroup xTaskGetTickCountFromISR xTaskGetTickCountFromISR -+ * \ingroup TaskUtils -+ */ -+TickType_t xTaskGetTickCountFromISR( void ); -+ -+/** -+ * task. h -+ * @code{c} -+ * uint16_t uxTaskGetNumberOfTasks( void ); -+ * @endcode -+ * -+ * @return The number of tasks that the real time kernel is currently managing. -+ * This includes all ready, blocked and suspended tasks. A task that -+ * has been deleted but not yet freed by the idle task will also be -+ * included in the count. -+ * -+ * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks -+ * \ingroup TaskUtils -+ */ -+UBaseType_t uxTaskGetNumberOfTasks( void ); -+ -+/** -+ * task. h -+ * @code{c} -+ * char *pcTaskGetName( TaskHandle_t xTaskToQuery ); -+ * @endcode -+ * -+ * @return The text (human readable) name of the task referenced by the handle -+ * xTaskToQuery. A task can query its own name by either passing in its own -+ * handle, or by setting xTaskToQuery to NULL. -+ * -+ * \defgroup pcTaskGetName pcTaskGetName -+ * \ingroup TaskUtils -+ */ -+char * pcTaskGetName( TaskHandle_t xTaskToQuery ); /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ -+ -+/** -+ * task. h -+ * @code{c} -+ * TaskHandle_t xTaskGetHandle( const char *pcNameToQuery ); -+ * @endcode -+ * -+ * NOTE: This function takes a relatively long time to complete and should be -+ * used sparingly. -+ * -+ * @return The handle of the task that has the human readable name pcNameToQuery. -+ * NULL is returned if no matching name is found. INCLUDE_xTaskGetHandle -+ * must be set to 1 in FreeRTOSConfig.h for pcTaskGetHandle() to be available. -+ * -+ * \defgroup pcTaskGetHandle pcTaskGetHandle -+ * \ingroup TaskUtils -+ */ -+TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ); /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ -+ -+/** -+ * task.h -+ * @code{c} -+ * UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ); -+ * @endcode -+ * -+ * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for -+ * this function to be available. -+ * -+ * Returns the high water mark of the stack associated with xTask. That is, -+ * the minimum free stack space there has been (in words, so on a 32 bit machine -+ * a value of 1 means 4 bytes) since the task started. The smaller the returned -+ * number the closer the task has come to overflowing its stack. -+ * -+ * uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the -+ * same except for their return type. Using configSTACK_DEPTH_TYPE allows the -+ * user to determine the return type. It gets around the problem of the value -+ * overflowing on 8-bit types without breaking backward compatibility for -+ * applications that expect an 8-bit return type. -+ * -+ * @param xTask Handle of the task associated with the stack to be checked. -+ * Set xTask to NULL to check the stack of the calling task. -+ * -+ * @return The smallest amount of free stack space there has been (in words, so -+ * actual spaces on the stack rather than bytes) since the task referenced by -+ * xTask was created. -+ */ -+UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ); -+ -+/** -+ * task.h -+ * @code{c} -+ * configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ); -+ * @endcode -+ * -+ * INCLUDE_uxTaskGetStackHighWaterMark2 must be set to 1 in FreeRTOSConfig.h for -+ * this function to be available. -+ * -+ * Returns the high water mark of the stack associated with xTask. That is, -+ * the minimum free stack space there has been (in words, so on a 32 bit machine -+ * a value of 1 means 4 bytes) since the task started. The smaller the returned -+ * number the closer the task has come to overflowing its stack. -+ * -+ * uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the -+ * same except for their return type. Using configSTACK_DEPTH_TYPE allows the -+ * user to determine the return type. It gets around the problem of the value -+ * overflowing on 8-bit types without breaking backward compatibility for -+ * applications that expect an 8-bit return type. -+ * -+ * @param xTask Handle of the task associated with the stack to be checked. -+ * Set xTask to NULL to check the stack of the calling task. -+ * -+ * @return The smallest amount of free stack space there has been (in words, so -+ * actual spaces on the stack rather than bytes) since the task referenced by -+ * xTask was created. -+ */ -+configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ); -+ -+/* When using trace macros it is sometimes necessary to include task.h before -+ * FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been defined, -+ * so the following two prototypes will cause a compilation error. This can be -+ * fixed by simply guarding against the inclusion of these two prototypes unless -+ * they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration -+ * constant. */ -+#ifdef configUSE_APPLICATION_TASK_TAG -+ #if configUSE_APPLICATION_TASK_TAG == 1 -+ -+/** -+ * task.h -+ * @code{c} -+ * void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction ); -+ * @endcode -+ * -+ * Sets pxHookFunction to be the task hook function used by the task xTask. -+ * Passing xTask as NULL has the effect of setting the calling tasks hook -+ * function. -+ */ -+ void vTaskSetApplicationTaskTag( TaskHandle_t xTask, -+ TaskHookFunction_t pxHookFunction ); -+ -+/** -+ * task.h -+ * @code{c} -+ * void xTaskGetApplicationTaskTag( TaskHandle_t xTask ); -+ * @endcode -+ * -+ * Returns the pxHookFunction value assigned to the task xTask. Do not -+ * call from an interrupt service routine - call -+ * xTaskGetApplicationTaskTagFromISR() instead. -+ */ -+ TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ); -+ -+/** -+ * task.h -+ * @code{c} -+ * void xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ); -+ * @endcode -+ * -+ * Returns the pxHookFunction value assigned to the task xTask. Can -+ * be called from an interrupt service routine. -+ */ -+ TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ); -+ #endif /* configUSE_APPLICATION_TASK_TAG ==1 */ -+#endif /* ifdef configUSE_APPLICATION_TASK_TAG */ -+ -+/** -+ * task.h -+ * @code{c} -+ * BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter ); -+ * @endcode -+ * -+ * Calls the hook function associated with xTask. Passing xTask as NULL has -+ * the effect of calling the Running tasks (the calling task) hook function. -+ * -+ * pvParameter is passed to the hook function for the task to interpret as it -+ * wants. The return value is the value returned by the task hook function -+ * registered by the user. -+ */ -+BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, -+ void * pvParameter ); -+ -+/** -+ * xTaskGetIdleTaskHandle() is only available if -+ * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h. -+ * -+ * Simply returns the handle of the idle task. It is not valid to call -+ * xTaskGetIdleTaskHandle() before the scheduler has been started. -+ */ -+TaskHandle_t xTaskGetIdleTaskHandle( void ); -+ -+/** -+ * task. h -+ * @code{c} -+ * BaseType_t xTaskNotifyIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction ); -+ * BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction ); -+ * @endcode -+ * -+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. -+ * -+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these -+ * functions to be available. -+ * -+ * Sends a direct to task notification to a task, with an optional value and -+ * action. -+ * -+ * Each task has a private array of "notification values" (or 'notifications'), -+ * each of which is a 32-bit unsigned integer (uint32_t). The constant -+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the -+ * array, and (for backward compatibility) defaults to 1 if left undefined. -+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task. -+ * -+ * Events can be sent to a task using an intermediary object. Examples of such -+ * objects are queues, semaphores, mutexes and event groups. Task notifications -+ * are a method of sending an event directly to a task without the need for such -+ * an intermediary object. -+ * -+ * A notification sent to a task can optionally perform an action, such as -+ * update, overwrite or increment one of the task's notification values. In -+ * that way task notifications can be used to send data to a task, or be used as -+ * light weight and fast binary or counting semaphores. -+ * -+ * A task can use xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() to -+ * [optionally] block to wait for a notification to be pending. The task does -+ * not consume any CPU time while it is in the Blocked state. -+ * -+ * A notification sent to a task will remain pending until it is cleared by the -+ * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their -+ * un-indexed equivalents). If the task was already in the Blocked state to -+ * wait for a notification when the notification arrives then the task will -+ * automatically be removed from the Blocked state (unblocked) and the -+ * notification cleared. -+ * -+ * **NOTE** Each notification within the array operates independently - a task -+ * can only block on one notification within the array at a time and will not be -+ * unblocked by a notification sent to any other array index. -+ * -+ * Backward compatibility information: -+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and -+ * all task notification API functions operated on that value. Replacing the -+ * single notification value with an array of notification values necessitated a -+ * new set of API functions that could address specific notifications within the -+ * array. xTaskNotify() is the original API function, and remains backward -+ * compatible by always operating on the notification value at index 0 in the -+ * array. Calling xTaskNotify() is equivalent to calling xTaskNotifyIndexed() -+ * with the uxIndexToNotify parameter set to 0. -+ * -+ * @param xTaskToNotify The handle of the task being notified. The handle to a -+ * task can be returned from the xTaskCreate() API function used to create the -+ * task, and the handle of the currently running task can be obtained by calling -+ * xTaskGetCurrentTaskHandle(). -+ * -+ * @param uxIndexToNotify The index within the target task's array of -+ * notification values to which the notification is to be sent. uxIndexToNotify -+ * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotify() does -+ * not have this parameter and always sends notifications to index 0. -+ * -+ * @param ulValue Data that can be sent with the notification. How the data is -+ * used depends on the value of the eAction parameter. -+ * -+ * @param eAction Specifies how the notification updates the task's notification -+ * value, if at all. Valid values for eAction are as follows: -+ * -+ * eSetBits - -+ * The target notification value is bitwise ORed with ulValue. -+ * xTaskNotifyIndexed() always returns pdPASS in this case. -+ * -+ * eIncrement - -+ * The target notification value is incremented. ulValue is not used and -+ * xTaskNotifyIndexed() always returns pdPASS in this case. -+ * -+ * eSetValueWithOverwrite - -+ * The target notification value is set to the value of ulValue, even if the -+ * task being notified had not yet processed the previous notification at the -+ * same array index (the task already had a notification pending at that index). -+ * xTaskNotifyIndexed() always returns pdPASS in this case. -+ * -+ * eSetValueWithoutOverwrite - -+ * If the task being notified did not already have a notification pending at the -+ * same array index then the target notification value is set to ulValue and -+ * xTaskNotifyIndexed() will return pdPASS. If the task being notified already -+ * had a notification pending at the same array index then no action is -+ * performed and pdFAIL is returned. -+ * -+ * eNoAction - -+ * The task receives a notification at the specified array index without the -+ * notification value at that index being updated. ulValue is not used and -+ * xTaskNotifyIndexed() always returns pdPASS in this case. -+ * -+ * pulPreviousNotificationValue - -+ * Can be used to pass out the subject task's notification value before any -+ * bits are modified by the notify function. -+ * -+ * @return Dependent on the value of eAction. See the description of the -+ * eAction parameter. -+ * -+ * \defgroup xTaskNotifyIndexed xTaskNotifyIndexed -+ * \ingroup TaskNotifications -+ */ -+BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, -+ UBaseType_t uxIndexToNotify, -+ uint32_t ulValue, -+ eNotifyAction eAction, -+ uint32_t * pulPreviousNotificationValue ); -+#define xTaskNotify( xTaskToNotify, ulValue, eAction ) \ -+ xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), NULL ) -+#define xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction ) \ -+ xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), NULL ) -+ -+/** -+ * task. h -+ * @code{c} -+ * BaseType_t xTaskNotifyAndQueryIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotifyValue ); -+ * BaseType_t xTaskNotifyAndQuery( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotifyValue ); -+ * @endcode -+ * -+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. -+ * -+ * xTaskNotifyAndQueryIndexed() performs the same operation as -+ * xTaskNotifyIndexed() with the addition that it also returns the subject -+ * task's prior notification value (the notification value at the time the -+ * function is called rather than when the function returns) in the additional -+ * pulPreviousNotifyValue parameter. -+ * -+ * xTaskNotifyAndQuery() performs the same operation as xTaskNotify() with the -+ * addition that it also returns the subject task's prior notification value -+ * (the notification value as it was at the time the function is called, rather -+ * than when the function returns) in the additional pulPreviousNotifyValue -+ * parameter. -+ * -+ * \defgroup xTaskNotifyAndQueryIndexed xTaskNotifyAndQueryIndexed -+ * \ingroup TaskNotifications -+ */ -+#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) \ -+ xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) ) -+#define xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotifyValue ) \ -+ xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) ) -+ -+/** -+ * task. h -+ * @code{c} -+ * BaseType_t xTaskNotifyIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken ); -+ * BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken ); -+ * @endcode -+ * -+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. -+ * -+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these -+ * functions to be available. -+ * -+ * A version of xTaskNotifyIndexed() that can be used from an interrupt service -+ * routine (ISR). -+ * -+ * Each task has a private array of "notification values" (or 'notifications'), -+ * each of which is a 32-bit unsigned integer (uint32_t). The constant -+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the -+ * array, and (for backward compatibility) defaults to 1 if left undefined. -+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task. -+ * -+ * Events can be sent to a task using an intermediary object. Examples of such -+ * objects are queues, semaphores, mutexes and event groups. Task notifications -+ * are a method of sending an event directly to a task without the need for such -+ * an intermediary object. -+ * -+ * A notification sent to a task can optionally perform an action, such as -+ * update, overwrite or increment one of the task's notification values. In -+ * that way task notifications can be used to send data to a task, or be used as -+ * light weight and fast binary or counting semaphores. -+ * -+ * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a -+ * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] block -+ * to wait for a notification value to have a non-zero value. The task does -+ * not consume any CPU time while it is in the Blocked state. -+ * -+ * A notification sent to a task will remain pending until it is cleared by the -+ * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their -+ * un-indexed equivalents). If the task was already in the Blocked state to -+ * wait for a notification when the notification arrives then the task will -+ * automatically be removed from the Blocked state (unblocked) and the -+ * notification cleared. -+ * -+ * **NOTE** Each notification within the array operates independently - a task -+ * can only block on one notification within the array at a time and will not be -+ * unblocked by a notification sent to any other array index. -+ * -+ * Backward compatibility information: -+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and -+ * all task notification API functions operated on that value. Replacing the -+ * single notification value with an array of notification values necessitated a -+ * new set of API functions that could address specific notifications within the -+ * array. xTaskNotifyFromISR() is the original API function, and remains -+ * backward compatible by always operating on the notification value at index 0 -+ * within the array. Calling xTaskNotifyFromISR() is equivalent to calling -+ * xTaskNotifyIndexedFromISR() with the uxIndexToNotify parameter set to 0. -+ * -+ * @param uxIndexToNotify The index within the target task's array of -+ * notification values to which the notification is to be sent. uxIndexToNotify -+ * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyFromISR() -+ * does not have this parameter and always sends notifications to index 0. -+ * -+ * @param xTaskToNotify The handle of the task being notified. The handle to a -+ * task can be returned from the xTaskCreate() API function used to create the -+ * task, and the handle of the currently running task can be obtained by calling -+ * xTaskGetCurrentTaskHandle(). -+ * -+ * @param ulValue Data that can be sent with the notification. How the data is -+ * used depends on the value of the eAction parameter. -+ * -+ * @param eAction Specifies how the notification updates the task's notification -+ * value, if at all. Valid values for eAction are as follows: -+ * -+ * eSetBits - -+ * The task's notification value is bitwise ORed with ulValue. xTaskNotify() -+ * always returns pdPASS in this case. -+ * -+ * eIncrement - -+ * The task's notification value is incremented. ulValue is not used and -+ * xTaskNotify() always returns pdPASS in this case. -+ * -+ * eSetValueWithOverwrite - -+ * The task's notification value is set to the value of ulValue, even if the -+ * task being notified had not yet processed the previous notification (the -+ * task already had a notification pending). xTaskNotify() always returns -+ * pdPASS in this case. -+ * -+ * eSetValueWithoutOverwrite - -+ * If the task being notified did not already have a notification pending then -+ * the task's notification value is set to ulValue and xTaskNotify() will -+ * return pdPASS. If the task being notified already had a notification -+ * pending then no action is performed and pdFAIL is returned. -+ * -+ * eNoAction - -+ * The task receives a notification without its notification value being -+ * updated. ulValue is not used and xTaskNotify() always returns pdPASS in -+ * this case. -+ * -+ * @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set -+ * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the -+ * task to which the notification was sent to leave the Blocked state, and the -+ * unblocked task has a priority higher than the currently running task. If -+ * xTaskNotifyFromISR() sets this value to pdTRUE then a context switch should -+ * be requested before the interrupt is exited. How a context switch is -+ * requested from an ISR is dependent on the port - see the documentation page -+ * for the port in use. -+ * -+ * @return Dependent on the value of eAction. See the description of the -+ * eAction parameter. -+ * -+ * \defgroup xTaskNotifyIndexedFromISR xTaskNotifyIndexedFromISR -+ * \ingroup TaskNotifications -+ */ -+BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, -+ UBaseType_t uxIndexToNotify, -+ uint32_t ulValue, -+ eNotifyAction eAction, -+ uint32_t * pulPreviousNotificationValue, -+ BaseType_t * pxHigherPriorityTaskWoken ); -+#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) \ -+ xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) ) -+#define xTaskNotifyIndexedFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) \ -+ xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) ) -+ -+/** -+ * task. h -+ * @code{c} -+ * BaseType_t xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ); -+ * BaseType_t xTaskNotifyAndQueryFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ); -+ * @endcode -+ * -+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. -+ * -+ * xTaskNotifyAndQueryIndexedFromISR() performs the same operation as -+ * xTaskNotifyIndexedFromISR() with the addition that it also returns the -+ * subject task's prior notification value (the notification value at the time -+ * the function is called rather than at the time the function returns) in the -+ * additional pulPreviousNotifyValue parameter. -+ * -+ * xTaskNotifyAndQueryFromISR() performs the same operation as -+ * xTaskNotifyFromISR() with the addition that it also returns the subject -+ * task's prior notification value (the notification value at the time the -+ * function is called rather than at the time the function returns) in the -+ * additional pulPreviousNotifyValue parameter. -+ * -+ * \defgroup xTaskNotifyAndQueryIndexedFromISR xTaskNotifyAndQueryIndexedFromISR -+ * \ingroup TaskNotifications -+ */ -+#define xTaskNotifyAndQueryIndexedFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) \ -+ xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) ) -+#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) \ -+ xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) ) -+ -+/** -+ * task. h -+ * @code{c} -+ * BaseType_t xTaskNotifyWaitIndexed( UBaseType_t uxIndexToWaitOn, uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ); -+ * -+ * BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ); -+ * @endcode -+ * -+ * Waits for a direct to task notification to be pending at a given index within -+ * an array of direct to task notifications. -+ * -+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. -+ * -+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this -+ * function to be available. -+ * -+ * Each task has a private array of "notification values" (or 'notifications'), -+ * each of which is a 32-bit unsigned integer (uint32_t). The constant -+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the -+ * array, and (for backward compatibility) defaults to 1 if left undefined. -+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task. -+ * -+ * Events can be sent to a task using an intermediary object. Examples of such -+ * objects are queues, semaphores, mutexes and event groups. Task notifications -+ * are a method of sending an event directly to a task without the need for such -+ * an intermediary object. -+ * -+ * A notification sent to a task can optionally perform an action, such as -+ * update, overwrite or increment one of the task's notification values. In -+ * that way task notifications can be used to send data to a task, or be used as -+ * light weight and fast binary or counting semaphores. -+ * -+ * A notification sent to a task will remain pending until it is cleared by the -+ * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their -+ * un-indexed equivalents). If the task was already in the Blocked state to -+ * wait for a notification when the notification arrives then the task will -+ * automatically be removed from the Blocked state (unblocked) and the -+ * notification cleared. -+ * -+ * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a -+ * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] block -+ * to wait for a notification value to have a non-zero value. The task does -+ * not consume any CPU time while it is in the Blocked state. -+ * -+ * **NOTE** Each notification within the array operates independently - a task -+ * can only block on one notification within the array at a time and will not be -+ * unblocked by a notification sent to any other array index. -+ * -+ * Backward compatibility information: -+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and -+ * all task notification API functions operated on that value. Replacing the -+ * single notification value with an array of notification values necessitated a -+ * new set of API functions that could address specific notifications within the -+ * array. xTaskNotifyWait() is the original API function, and remains backward -+ * compatible by always operating on the notification value at index 0 in the -+ * array. Calling xTaskNotifyWait() is equivalent to calling -+ * xTaskNotifyWaitIndexed() with the uxIndexToWaitOn parameter set to 0. -+ * -+ * @param uxIndexToWaitOn The index within the calling task's array of -+ * notification values on which the calling task will wait for a notification to -+ * be received. uxIndexToWaitOn must be less than -+ * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyWait() does -+ * not have this parameter and always waits for notifications on index 0. -+ * -+ * @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value -+ * will be cleared in the calling task's notification value before the task -+ * checks to see if any notifications are pending, and optionally blocks if no -+ * notifications are pending. Setting ulBitsToClearOnEntry to ULONG_MAX (if -+ * limits.h is included) or 0xffffffffUL (if limits.h is not included) will have -+ * the effect of resetting the task's notification value to 0. Setting -+ * ulBitsToClearOnEntry to 0 will leave the task's notification value unchanged. -+ * -+ * @param ulBitsToClearOnExit If a notification is pending or received before -+ * the calling task exits the xTaskNotifyWait() function then the task's -+ * notification value (see the xTaskNotify() API function) is passed out using -+ * the pulNotificationValue parameter. Then any bits that are set in -+ * ulBitsToClearOnExit will be cleared in the task's notification value (note -+ * *pulNotificationValue is set before any bits are cleared). Setting -+ * ulBitsToClearOnExit to ULONG_MAX (if limits.h is included) or 0xffffffffUL -+ * (if limits.h is not included) will have the effect of resetting the task's -+ * notification value to 0 before the function exits. Setting -+ * ulBitsToClearOnExit to 0 will leave the task's notification value unchanged -+ * when the function exits (in which case the value passed out in -+ * pulNotificationValue will match the task's notification value). -+ * -+ * @param pulNotificationValue Used to pass the task's notification value out -+ * of the function. Note the value passed out will not be effected by the -+ * clearing of any bits caused by ulBitsToClearOnExit being non-zero. -+ * -+ * @param xTicksToWait The maximum amount of time that the task should wait in -+ * the Blocked state for a notification to be received, should a notification -+ * not already be pending when xTaskNotifyWait() was called. The task -+ * will not consume any processing time while it is in the Blocked state. This -+ * is specified in kernel ticks, the macro pdMS_TO_TICKS( value_in_ms ) can be -+ * used to convert a time specified in milliseconds to a time specified in -+ * ticks. -+ * -+ * @return If a notification was received (including notifications that were -+ * already pending when xTaskNotifyWait was called) then pdPASS is -+ * returned. Otherwise pdFAIL is returned. -+ * -+ * \defgroup xTaskNotifyWaitIndexed xTaskNotifyWaitIndexed -+ * \ingroup TaskNotifications -+ */ -+BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn, -+ uint32_t ulBitsToClearOnEntry, -+ uint32_t ulBitsToClearOnExit, -+ uint32_t * pulNotificationValue, -+ TickType_t xTicksToWait ); -+#define xTaskNotifyWait( ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ) \ -+ xTaskGenericNotifyWait( tskDEFAULT_INDEX_TO_NOTIFY, ( ulBitsToClearOnEntry ), ( ulBitsToClearOnExit ), ( pulNotificationValue ), ( xTicksToWait ) ) -+#define xTaskNotifyWaitIndexed( uxIndexToWaitOn, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ) \ -+ xTaskGenericNotifyWait( ( uxIndexToWaitOn ), ( ulBitsToClearOnEntry ), ( ulBitsToClearOnExit ), ( pulNotificationValue ), ( xTicksToWait ) ) -+ -+/** -+ * task. h -+ * @code{c} -+ * BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify ); -+ * BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify ); -+ * @endcode -+ * -+ * Sends a direct to task notification to a particular index in the target -+ * task's notification array in a manner similar to giving a counting semaphore. -+ * -+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details. -+ * -+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these -+ * macros to be available. -+ * -+ * Each task has a private array of "notification values" (or 'notifications'), -+ * each of which is a 32-bit unsigned integer (uint32_t). The constant -+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the -+ * array, and (for backward compatibility) defaults to 1 if left undefined. -+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task. -+ * -+ * Events can be sent to a task using an intermediary object. Examples of such -+ * objects are queues, semaphores, mutexes and event groups. Task notifications -+ * are a method of sending an event directly to a task without the need for such -+ * an intermediary object. -+ * -+ * A notification sent to a task can optionally perform an action, such as -+ * update, overwrite or increment one of the task's notification values. In -+ * that way task notifications can be used to send data to a task, or be used as -+ * light weight and fast binary or counting semaphores. -+ * -+ * xTaskNotifyGiveIndexed() is a helper macro intended for use when task -+ * notifications are used as light weight and faster binary or counting -+ * semaphore equivalents. Actual FreeRTOS semaphores are given using the -+ * xSemaphoreGive() API function, the equivalent action that instead uses a task -+ * notification is xTaskNotifyGiveIndexed(). -+ * -+ * When task notifications are being used as a binary or counting semaphore -+ * equivalent then the task being notified should wait for the notification -+ * using the ulTaskNotificationTakeIndexed() API function rather than the -+ * xTaskNotifyWaitIndexed() API function. -+ * -+ * **NOTE** Each notification within the array operates independently - a task -+ * can only block on one notification within the array at a time and will not be -+ * unblocked by a notification sent to any other array index. -+ * -+ * Backward compatibility information: -+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and -+ * all task notification API functions operated on that value. Replacing the -+ * single notification value with an array of notification values necessitated a -+ * new set of API functions that could address specific notifications within the -+ * array. xTaskNotifyGive() is the original API function, and remains backward -+ * compatible by always operating on the notification value at index 0 in the -+ * array. Calling xTaskNotifyGive() is equivalent to calling -+ * xTaskNotifyGiveIndexed() with the uxIndexToNotify parameter set to 0. -+ * -+ * @param xTaskToNotify The handle of the task being notified. The handle to a -+ * task can be returned from the xTaskCreate() API function used to create the -+ * task, and the handle of the currently running task can be obtained by calling -+ * xTaskGetCurrentTaskHandle(). -+ * -+ * @param uxIndexToNotify The index within the target task's array of -+ * notification values to which the notification is to be sent. uxIndexToNotify -+ * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyGive() -+ * does not have this parameter and always sends notifications to index 0. -+ * -+ * @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the -+ * eAction parameter set to eIncrement - so pdPASS is always returned. -+ * -+ * \defgroup xTaskNotifyGiveIndexed xTaskNotifyGiveIndexed -+ * \ingroup TaskNotifications -+ */ -+#define xTaskNotifyGive( xTaskToNotify ) \ -+ xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( 0 ), eIncrement, NULL ) -+#define xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify ) \ -+ xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( 0 ), eIncrement, NULL ) -+ -+/** -+ * task. h -+ * @code{c} -+ * void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle, UBaseType_t uxIndexToNotify, BaseType_t *pxHigherPriorityTaskWoken ); -+ * void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken ); -+ * @endcode -+ * -+ * A version of xTaskNotifyGiveIndexed() that can be called from an interrupt -+ * service routine (ISR). -+ * -+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details. -+ * -+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro -+ * to be available. -+ * -+ * Each task has a private array of "notification values" (or 'notifications'), -+ * each of which is a 32-bit unsigned integer (uint32_t). The constant -+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the -+ * array, and (for backward compatibility) defaults to 1 if left undefined. -+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task. -+ * -+ * Events can be sent to a task using an intermediary object. Examples of such -+ * objects are queues, semaphores, mutexes and event groups. Task notifications -+ * are a method of sending an event directly to a task without the need for such -+ * an intermediary object. -+ * -+ * A notification sent to a task can optionally perform an action, such as -+ * update, overwrite or increment one of the task's notification values. In -+ * that way task notifications can be used to send data to a task, or be used as -+ * light weight and fast binary or counting semaphores. -+ * -+ * vTaskNotifyGiveIndexedFromISR() is intended for use when task notifications -+ * are used as light weight and faster binary or counting semaphore equivalents. -+ * Actual FreeRTOS semaphores are given from an ISR using the -+ * xSemaphoreGiveFromISR() API function, the equivalent action that instead uses -+ * a task notification is vTaskNotifyGiveIndexedFromISR(). -+ * -+ * When task notifications are being used as a binary or counting semaphore -+ * equivalent then the task being notified should wait for the notification -+ * using the ulTaskNotificationTakeIndexed() API function rather than the -+ * xTaskNotifyWaitIndexed() API function. -+ * -+ * **NOTE** Each notification within the array operates independently - a task -+ * can only block on one notification within the array at a time and will not be -+ * unblocked by a notification sent to any other array index. -+ * -+ * Backward compatibility information: -+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and -+ * all task notification API functions operated on that value. Replacing the -+ * single notification value with an array of notification values necessitated a -+ * new set of API functions that could address specific notifications within the -+ * array. xTaskNotifyFromISR() is the original API function, and remains -+ * backward compatible by always operating on the notification value at index 0 -+ * within the array. Calling xTaskNotifyGiveFromISR() is equivalent to calling -+ * xTaskNotifyGiveIndexedFromISR() with the uxIndexToNotify parameter set to 0. -+ * -+ * @param xTaskToNotify The handle of the task being notified. The handle to a -+ * task can be returned from the xTaskCreate() API function used to create the -+ * task, and the handle of the currently running task can be obtained by calling -+ * xTaskGetCurrentTaskHandle(). -+ * -+ * @param uxIndexToNotify The index within the target task's array of -+ * notification values to which the notification is to be sent. uxIndexToNotify -+ * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. -+ * xTaskNotifyGiveFromISR() does not have this parameter and always sends -+ * notifications to index 0. -+ * -+ * @param pxHigherPriorityTaskWoken vTaskNotifyGiveFromISR() will set -+ * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the -+ * task to which the notification was sent to leave the Blocked state, and the -+ * unblocked task has a priority higher than the currently running task. If -+ * vTaskNotifyGiveFromISR() sets this value to pdTRUE then a context switch -+ * should be requested before the interrupt is exited. How a context switch is -+ * requested from an ISR is dependent on the port - see the documentation page -+ * for the port in use. -+ * -+ * \defgroup vTaskNotifyGiveIndexedFromISR vTaskNotifyGiveIndexedFromISR -+ * \ingroup TaskNotifications -+ */ -+void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify, -+ UBaseType_t uxIndexToNotify, -+ BaseType_t * pxHigherPriorityTaskWoken ); -+#define vTaskNotifyGiveFromISR( xTaskToNotify, pxHigherPriorityTaskWoken ) \ -+ vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( pxHigherPriorityTaskWoken ) ); -+#define vTaskNotifyGiveIndexedFromISR( xTaskToNotify, uxIndexToNotify, pxHigherPriorityTaskWoken ) \ -+ vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( pxHigherPriorityTaskWoken ) ); -+ -+/** -+ * task. h -+ * @code{c} -+ * uint32_t ulTaskNotifyTakeIndexed( UBaseType_t uxIndexToWaitOn, BaseType_t xClearCountOnExit, TickType_t xTicksToWait ); -+ * -+ * uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ); -+ * @endcode -+ * -+ * Waits for a direct to task notification on a particular index in the calling -+ * task's notification array in a manner similar to taking a counting semaphore. -+ * -+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. -+ * -+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this -+ * function to be available. -+ * -+ * Each task has a private array of "notification values" (or 'notifications'), -+ * each of which is a 32-bit unsigned integer (uint32_t). The constant -+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the -+ * array, and (for backward compatibility) defaults to 1 if left undefined. -+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task. -+ * -+ * Events can be sent to a task using an intermediary object. Examples of such -+ * objects are queues, semaphores, mutexes and event groups. Task notifications -+ * are a method of sending an event directly to a task without the need for such -+ * an intermediary object. -+ * -+ * A notification sent to a task can optionally perform an action, such as -+ * update, overwrite or increment one of the task's notification values. In -+ * that way task notifications can be used to send data to a task, or be used as -+ * light weight and fast binary or counting semaphores. -+ * -+ * ulTaskNotifyTakeIndexed() is intended for use when a task notification is -+ * used as a faster and lighter weight binary or counting semaphore alternative. -+ * Actual FreeRTOS semaphores are taken using the xSemaphoreTake() API function, -+ * the equivalent action that instead uses a task notification is -+ * ulTaskNotifyTakeIndexed(). -+ * -+ * When a task is using its notification value as a binary or counting semaphore -+ * other tasks should send notifications to it using the xTaskNotifyGiveIndexed() -+ * macro, or xTaskNotifyIndex() function with the eAction parameter set to -+ * eIncrement. -+ * -+ * ulTaskNotifyTakeIndexed() can either clear the task's notification value at -+ * the array index specified by the uxIndexToWaitOn parameter to zero on exit, -+ * in which case the notification value acts like a binary semaphore, or -+ * decrement the notification value on exit, in which case the notification -+ * value acts like a counting semaphore. -+ * -+ * A task can use ulTaskNotifyTakeIndexed() to [optionally] block to wait for -+ * a notification. The task does not consume any CPU time while it is in the -+ * Blocked state. -+ * -+ * Where as xTaskNotifyWaitIndexed() will return when a notification is pending, -+ * ulTaskNotifyTakeIndexed() will return when the task's notification value is -+ * not zero. -+ * -+ * **NOTE** Each notification within the array operates independently - a task -+ * can only block on one notification within the array at a time and will not be -+ * unblocked by a notification sent to any other array index. -+ * -+ * Backward compatibility information: -+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and -+ * all task notification API functions operated on that value. Replacing the -+ * single notification value with an array of notification values necessitated a -+ * new set of API functions that could address specific notifications within the -+ * array. ulTaskNotifyTake() is the original API function, and remains backward -+ * compatible by always operating on the notification value at index 0 in the -+ * array. Calling ulTaskNotifyTake() is equivalent to calling -+ * ulTaskNotifyTakeIndexed() with the uxIndexToWaitOn parameter set to 0. -+ * -+ * @param uxIndexToWaitOn The index within the calling task's array of -+ * notification values on which the calling task will wait for a notification to -+ * be non-zero. uxIndexToWaitOn must be less than -+ * configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyTake() does -+ * not have this parameter and always waits for notifications on index 0. -+ * -+ * @param xClearCountOnExit if xClearCountOnExit is pdFALSE then the task's -+ * notification value is decremented when the function exits. In this way the -+ * notification value acts like a counting semaphore. If xClearCountOnExit is -+ * not pdFALSE then the task's notification value is cleared to zero when the -+ * function exits. In this way the notification value acts like a binary -+ * semaphore. -+ * -+ * @param xTicksToWait The maximum amount of time that the task should wait in -+ * the Blocked state for the task's notification value to be greater than zero, -+ * should the count not already be greater than zero when -+ * ulTaskNotifyTake() was called. The task will not consume any processing -+ * time while it is in the Blocked state. This is specified in kernel ticks, -+ * the macro pdMS_TO_TICKS( value_in_ms ) can be used to convert a time -+ * specified in milliseconds to a time specified in ticks. -+ * -+ * @return The task's notification count before it is either cleared to zero or -+ * decremented (see the xClearCountOnExit parameter). -+ * -+ * \defgroup ulTaskNotifyTakeIndexed ulTaskNotifyTakeIndexed -+ * \ingroup TaskNotifications -+ */ -+uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn, -+ BaseType_t xClearCountOnExit, -+ TickType_t xTicksToWait ); -+#define ulTaskNotifyTake( xClearCountOnExit, xTicksToWait ) \ -+ ulTaskGenericNotifyTake( ( tskDEFAULT_INDEX_TO_NOTIFY ), ( xClearCountOnExit ), ( xTicksToWait ) ) -+#define ulTaskNotifyTakeIndexed( uxIndexToWaitOn, xClearCountOnExit, xTicksToWait ) \ -+ ulTaskGenericNotifyTake( ( uxIndexToWaitOn ), ( xClearCountOnExit ), ( xTicksToWait ) ) -+ -+/** -+ * task. h -+ * @code{c} -+ * BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToCLear ); -+ * -+ * BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ); -+ * @endcode -+ * -+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. -+ * -+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these -+ * functions to be available. -+ * -+ * Each task has a private array of "notification values" (or 'notifications'), -+ * each of which is a 32-bit unsigned integer (uint32_t). The constant -+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the -+ * array, and (for backward compatibility) defaults to 1 if left undefined. -+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task. -+ * -+ * If a notification is sent to an index within the array of notifications then -+ * the notification at that index is said to be 'pending' until it is read or -+ * explicitly cleared by the receiving task. xTaskNotifyStateClearIndexed() -+ * is the function that clears a pending notification without reading the -+ * notification value. The notification value at the same array index is not -+ * altered. Set xTask to NULL to clear the notification state of the calling -+ * task. -+ * -+ * Backward compatibility information: -+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and -+ * all task notification API functions operated on that value. Replacing the -+ * single notification value with an array of notification values necessitated a -+ * new set of API functions that could address specific notifications within the -+ * array. xTaskNotifyStateClear() is the original API function, and remains -+ * backward compatible by always operating on the notification value at index 0 -+ * within the array. Calling xTaskNotifyStateClear() is equivalent to calling -+ * xTaskNotifyStateClearIndexed() with the uxIndexToNotify parameter set to 0. -+ * -+ * @param xTask The handle of the RTOS task that will have a notification state -+ * cleared. Set xTask to NULL to clear a notification state in the calling -+ * task. To obtain a task's handle create the task using xTaskCreate() and -+ * make use of the pxCreatedTask parameter, or create the task using -+ * xTaskCreateStatic() and store the returned value, or use the task's name in -+ * a call to xTaskGetHandle(). -+ * -+ * @param uxIndexToClear The index within the target task's array of -+ * notification values to act upon. For example, setting uxIndexToClear to 1 -+ * will clear the state of the notification at index 1 within the array. -+ * uxIndexToClear must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. -+ * ulTaskNotifyStateClear() does not have this parameter and always acts on the -+ * notification at index 0. -+ * -+ * @return pdTRUE if the task's notification state was set to -+ * eNotWaitingNotification, otherwise pdFALSE. -+ * -+ * \defgroup xTaskNotifyStateClearIndexed xTaskNotifyStateClearIndexed -+ * \ingroup TaskNotifications -+ */ -+BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask, -+ UBaseType_t uxIndexToClear ); -+#define xTaskNotifyStateClear( xTask ) \ -+ xTaskGenericNotifyStateClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ) ) -+#define xTaskNotifyStateClearIndexed( xTask, uxIndexToClear ) \ -+ xTaskGenericNotifyStateClear( ( xTask ), ( uxIndexToClear ) ) -+ -+/** -+ * task. h -+ * @code{c} -+ * uint32_t ulTaskNotifyValueClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToClear, uint32_t ulBitsToClear ); -+ * -+ * uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear ); -+ * @endcode -+ * -+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. -+ * -+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these -+ * functions to be available. -+ * -+ * Each task has a private array of "notification values" (or 'notifications'), -+ * each of which is a 32-bit unsigned integer (uint32_t). The constant -+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the -+ * array, and (for backward compatibility) defaults to 1 if left undefined. -+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task. -+ * -+ * ulTaskNotifyValueClearIndexed() clears the bits specified by the -+ * ulBitsToClear bit mask in the notification value at array index uxIndexToClear -+ * of the task referenced by xTask. -+ * -+ * Backward compatibility information: -+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and -+ * all task notification API functions operated on that value. Replacing the -+ * single notification value with an array of notification values necessitated a -+ * new set of API functions that could address specific notifications within the -+ * array. ulTaskNotifyValueClear() is the original API function, and remains -+ * backward compatible by always operating on the notification value at index 0 -+ * within the array. Calling ulTaskNotifyValueClear() is equivalent to calling -+ * ulTaskNotifyValueClearIndexed() with the uxIndexToClear parameter set to 0. -+ * -+ * @param xTask The handle of the RTOS task that will have bits in one of its -+ * notification values cleared. Set xTask to NULL to clear bits in a -+ * notification value of the calling task. To obtain a task's handle create the -+ * task using xTaskCreate() and make use of the pxCreatedTask parameter, or -+ * create the task using xTaskCreateStatic() and store the returned value, or -+ * use the task's name in a call to xTaskGetHandle(). -+ * -+ * @param uxIndexToClear The index within the target task's array of -+ * notification values in which to clear the bits. uxIndexToClear -+ * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES. -+ * ulTaskNotifyValueClear() does not have this parameter and always clears bits -+ * in the notification value at index 0. -+ * -+ * @param ulBitsToClear Bit mask of the bits to clear in the notification value of -+ * xTask. Set a bit to 1 to clear the corresponding bits in the task's notification -+ * value. Set ulBitsToClear to 0xffffffff (UINT_MAX on 32-bit architectures) to clear -+ * the notification value to 0. Set ulBitsToClear to 0 to query the task's -+ * notification value without clearing any bits. -+ * -+ * -+ * @return The value of the target task's notification value before the bits -+ * specified by ulBitsToClear were cleared. -+ * \defgroup ulTaskNotifyValueClear ulTaskNotifyValueClear -+ * \ingroup TaskNotifications -+ */ -+uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask, -+ UBaseType_t uxIndexToClear, -+ uint32_t ulBitsToClear ); -+#define ulTaskNotifyValueClear( xTask, ulBitsToClear ) \ -+ ulTaskGenericNotifyValueClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulBitsToClear ) ) -+#define ulTaskNotifyValueClearIndexed( xTask, uxIndexToClear, ulBitsToClear ) \ -+ ulTaskGenericNotifyValueClear( ( xTask ), ( uxIndexToClear ), ( ulBitsToClear ) ) -+ -+/** -+ * task.h -+ * @code{c} -+ * void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ); -+ * @endcode -+ * -+ * Capture the current time for future use with xTaskCheckForTimeOut(). -+ * -+ * @param pxTimeOut Pointer to a timeout object into which the current time -+ * is to be captured. The captured time includes the tick count and the number -+ * of times the tick count has overflowed since the system first booted. -+ * \defgroup vTaskSetTimeOutState vTaskSetTimeOutState -+ * \ingroup TaskCtrl -+ */ -+void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ); -+ -+/** -+ * task.h -+ * @code{c} -+ * BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait ); -+ * @endcode -+ * -+ * Determines if pxTicksToWait ticks has passed since a time was captured -+ * using a call to vTaskSetTimeOutState(). The captured time includes the tick -+ * count and the number of times the tick count has overflowed. -+ * -+ * @param pxTimeOut The time status as captured previously using -+ * vTaskSetTimeOutState. If the timeout has not yet occurred, it is updated -+ * to reflect the current time status. -+ * @param pxTicksToWait The number of ticks to check for timeout i.e. if -+ * pxTicksToWait ticks have passed since pxTimeOut was last updated (either by -+ * vTaskSetTimeOutState() or xTaskCheckForTimeOut()), the timeout has occurred. -+ * If the timeout has not occurred, pxTicksToWait is updated to reflect the -+ * number of remaining ticks. -+ * -+ * @return If timeout has occurred, pdTRUE is returned. Otherwise pdFALSE is -+ * returned and pxTicksToWait is updated to reflect the number of remaining -+ * ticks. -+ * -+ * @see https://www.FreeRTOS.org/xTaskCheckForTimeOut.html -+ * -+ * Example Usage: -+ * @code{c} -+ * // Driver library function used to receive uxWantedBytes from an Rx buffer -+ * // that is filled by a UART interrupt. If there are not enough bytes in the -+ * // Rx buffer then the task enters the Blocked state until it is notified that -+ * // more data has been placed into the buffer. If there is still not enough -+ * // data then the task re-enters the Blocked state, and xTaskCheckForTimeOut() -+ * // is used to re-calculate the Block time to ensure the total amount of time -+ * // spent in the Blocked state does not exceed MAX_TIME_TO_WAIT. This -+ * // continues until either the buffer contains at least uxWantedBytes bytes, -+ * // or the total amount of time spent in the Blocked state reaches -+ * // MAX_TIME_TO_WAIT - at which point the task reads however many bytes are -+ * // available up to a maximum of uxWantedBytes. -+ * -+ * size_t xUART_Receive( uint8_t *pucBuffer, size_t uxWantedBytes ) -+ * { -+ * size_t uxReceived = 0; -+ * TickType_t xTicksToWait = MAX_TIME_TO_WAIT; -+ * TimeOut_t xTimeOut; -+ * -+ * // Initialize xTimeOut. This records the time at which this function -+ * // was entered. -+ * vTaskSetTimeOutState( &xTimeOut ); -+ * -+ * // Loop until the buffer contains the wanted number of bytes, or a -+ * // timeout occurs. -+ * while( UART_bytes_in_rx_buffer( pxUARTInstance ) < uxWantedBytes ) -+ * { -+ * // The buffer didn't contain enough data so this task is going to -+ * // enter the Blocked state. Adjusting xTicksToWait to account for -+ * // any time that has been spent in the Blocked state within this -+ * // function so far to ensure the total amount of time spent in the -+ * // Blocked state does not exceed MAX_TIME_TO_WAIT. -+ * if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) != pdFALSE ) -+ * { -+ * //Timed out before the wanted number of bytes were available, -+ * // exit the loop. -+ * break; -+ * } -+ * -+ * // Wait for a maximum of xTicksToWait ticks to be notified that the -+ * // receive interrupt has placed more data into the buffer. -+ * ulTaskNotifyTake( pdTRUE, xTicksToWait ); -+ * } -+ * -+ * // Attempt to read uxWantedBytes from the receive buffer into pucBuffer. -+ * // The actual number of bytes read (which might be less than -+ * // uxWantedBytes) is returned. -+ * uxReceived = UART_read_from_receive_buffer( pxUARTInstance, -+ * pucBuffer, -+ * uxWantedBytes ); -+ * -+ * return uxReceived; -+ * } -+ * @endcode -+ * \defgroup xTaskCheckForTimeOut xTaskCheckForTimeOut -+ * \ingroup TaskCtrl -+ */ -+BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, -+ TickType_t * const pxTicksToWait ); -+ -+/*----------------------------------------------------------- -+* SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES -+*----------------------------------------------------------*/ -+ -+/* -+ * Return the handle of the calling task. -+ */ -+TaskHandle_t xTaskGetCurrentTaskHandle( void ); -+ -+/* -+ * Returns the scheduler state as taskSCHEDULER_RUNNING, -+ * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED. -+ */ -+BaseType_t xTaskGetSchedulerState( void ); -+ -+/* ESP32 */ -+BaseType_t xTaskGetAffinity( TaskHandle_t xTask ); -+TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t cpuid ); -+TaskHandle_t xTaskGetIdleTaskHandleForCPU( UBaseType_t cpuid ); -+/* Unimplemented */ -+#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) -+void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, -+ BaseType_t xIndex, -+ void * pvValue ); -+void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, -+ BaseType_t xIndex ); -+#if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) -+typedef void (*TlsDeleteCallbackFunction_t)( int, void * ); -+void vTaskSetThreadLocalStoragePointerAndDelCallback( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue, TlsDeleteCallbackFunction_t pvDelCallback); -+#endif -+#endif -+ -+/* *INDENT-OFF* */ -+#ifdef __cplusplus -+ } -+#endif -+/* *INDENT-ON* */ -+#endif /* INC_TASK_H */ -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/timers.h b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/timers.h -new file mode 100644 -index 0000000000..c5d1acf4d4 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/include/freertos/timers.h -@@ -0,0 +1,1185 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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 TIMERS_H -+#define TIMERS_H -+ -+#ifndef INC_FREERTOS_H -+ #error "include FreeRTOS.h must appear in source files before include timers.h" -+#endif -+ -+#include "task.h" -+ -+/* *INDENT-OFF* */ -+#ifdef __cplusplus -+ extern "C" { -+#endif -+/* *INDENT-ON* */ -+ -+/*----------------------------------------------------------- -+* MACROS AND DEFINITIONS -+*----------------------------------------------------------*/ -+ -+/* IDs for commands that can be sent/received on the timer queue. These are to -+ * be used solely through the macros that make up the public software timer API, -+ * as defined below. The commands that are sent from interrupts must use the -+ * highest numbers as tmrFIRST_FROM_ISR_COMMAND is used to determine if the task -+ * or interrupt version of the queue send function should be used. */ -+#define tmrCOMMAND_EXECUTE_CALLBACK_FROM_ISR ( ( BaseType_t ) -2 ) -+#define tmrCOMMAND_EXECUTE_CALLBACK ( ( BaseType_t ) -1 ) -+#define tmrCOMMAND_START_DONT_TRACE ( ( BaseType_t ) 0 ) -+#define tmrCOMMAND_START ( ( BaseType_t ) 1 ) -+#define tmrCOMMAND_RESET ( ( BaseType_t ) 2 ) -+#define tmrCOMMAND_STOP ( ( BaseType_t ) 3 ) -+#define tmrCOMMAND_CHANGE_PERIOD ( ( BaseType_t ) 4 ) -+#define tmrCOMMAND_DELETE ( ( BaseType_t ) 5 ) -+ -+#define tmrFIRST_FROM_ISR_COMMAND ( ( BaseType_t ) 6 ) -+#define tmrCOMMAND_START_FROM_ISR ( ( BaseType_t ) 6 ) -+#define tmrCOMMAND_RESET_FROM_ISR ( ( BaseType_t ) 7 ) -+#define tmrCOMMAND_STOP_FROM_ISR ( ( BaseType_t ) 8 ) -+#define tmrCOMMAND_CHANGE_PERIOD_FROM_ISR ( ( BaseType_t ) 9 ) -+ -+/** -+ * Type by which software timers are referenced. For example, a call to -+ * xTimerCreate() returns an TimerHandle_t variable that can then be used to -+ * reference the subject timer in calls to other software timer API functions -+ * (for example, xTimerStart(), xTimerReset(), etc.). -+ */ -+struct tmrTimerControl; /* The old naming convention is used to prevent breaking kernel aware debuggers. */ -+typedef struct tmrTimerControl * TimerHandle_t; -+ -+/* -+ * Defines the prototype to which timer callback functions must conform. -+ */ -+typedef void (* TimerCallbackFunction_t)( TimerHandle_t xTimer ); -+ -+/** -+ * TimerHandle_t xTimerCreate( const char * const pcTimerName, -+ * TickType_t xTimerPeriodInTicks, -+ * UBaseType_t uxAutoReload, -+ * void * pvTimerID, -+ * TimerCallbackFunction_t pxCallbackFunction ); -+ * -+ * Creates a new software timer instance, and returns a handle by which the -+ * created software timer can be referenced. -+ * -+ * Internally, within the FreeRTOS implementation, software timers use a block -+ * of memory, in which the timer data structure is stored. If a software timer -+ * is created using xTimerCreate() then the required memory is automatically -+ * dynamically allocated inside the xTimerCreate() function. (see -+ * https://www.FreeRTOS.org/a00111.html). If a software timer is created using -+ * xTimerCreateStatic() then the application writer must provide the memory that -+ * will get used by the software timer. xTimerCreateStatic() therefore allows a -+ * software timer to be created without using any dynamic memory allocation. -+ * -+ * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), -+ * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and -+ * xTimerChangePeriodFromISR() API functions can all be used to transition a -+ * timer into the active state. -+ * -+ * @param pcTimerName A text name that is assigned to the timer. This is done -+ * purely to assist debugging. The kernel itself only ever references a timer -+ * by its handle, and never by its name. -+ * -+ * @param xTimerPeriodInTicks The timer period. The time is defined in tick -+ * periods so the constant portTICK_PERIOD_MS can be used to convert a time that -+ * has been specified in milliseconds. For example, if the timer must expire -+ * after 100 ticks, then xTimerPeriodInTicks should be set to 100. -+ * Alternatively, if the timer must expire after 500ms, then xPeriod can be set -+ * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or -+ * equal to 1000. Time timer period must be greater than 0. -+ * -+ * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will -+ * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter. -+ * If uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and -+ * enter the dormant state after it expires. -+ * -+ * @param pvTimerID An identifier that is assigned to the timer being created. -+ * Typically this would be used in the timer callback function to identify which -+ * timer expired when the same callback function is assigned to more than one -+ * timer. -+ * -+ * @param pxCallbackFunction The function to call when the timer expires. -+ * Callback functions must have the prototype defined by TimerCallbackFunction_t, -+ * which is "void vCallbackFunction( TimerHandle_t xTimer );". -+ * -+ * @return If the timer is successfully created then a handle to the newly -+ * created timer is returned. If the timer cannot be created because there is -+ * insufficient FreeRTOS heap remaining to allocate the timer -+ * structures then NULL is returned. -+ * -+ * Example usage: -+ * @verbatim -+ * #define NUM_TIMERS 5 -+ * -+ * // An array to hold handles to the created timers. -+ * TimerHandle_t xTimers[ NUM_TIMERS ]; -+ * -+ * // An array to hold a count of the number of times each timer expires. -+ * int32_t lExpireCounters[ NUM_TIMERS ] = { 0 }; -+ * -+ * // Define a callback function that will be used by multiple timer instances. -+ * // The callback function does nothing but count the number of times the -+ * // associated timer expires, and stop the timer once the timer has expired -+ * // 10 times. -+ * void vTimerCallback( TimerHandle_t pxTimer ) -+ * { -+ * int32_t lArrayIndex; -+ * const int32_t xMaxExpiryCountBeforeStopping = 10; -+ * -+ * // Optionally do something if the pxTimer parameter is NULL. -+ * configASSERT( pxTimer ); -+ * -+ * // Which timer expired? -+ * lArrayIndex = ( int32_t ) pvTimerGetTimerID( pxTimer ); -+ * -+ * // Increment the number of times that pxTimer has expired. -+ * lExpireCounters[ lArrayIndex ] += 1; -+ * -+ * // If the timer has expired 10 times then stop it from running. -+ * if( lExpireCounters[ lArrayIndex ] == xMaxExpiryCountBeforeStopping ) -+ * { -+ * // Do not use a block time if calling a timer API function from a -+ * // timer callback function, as doing so could cause a deadlock! -+ * xTimerStop( pxTimer, 0 ); -+ * } -+ * } -+ * -+ * void main( void ) -+ * { -+ * int32_t x; -+ * -+ * // Create then start some timers. Starting the timers before the scheduler -+ * // has been started means the timers will start running immediately that -+ * // the scheduler starts. -+ * for( x = 0; x < NUM_TIMERS; x++ ) -+ * { -+ * xTimers[ x ] = xTimerCreate( "Timer", // Just a text name, not used by the kernel. -+ * ( 100 * x ), // The timer period in ticks. -+ * pdTRUE, // The timers will auto-reload themselves when they expire. -+ * ( void * ) x, // Assign each timer a unique id equal to its array index. -+ * vTimerCallback // Each timer calls the same callback when it expires. -+ * ); -+ * -+ * if( xTimers[ x ] == NULL ) -+ * { -+ * // The timer was not created. -+ * } -+ * else -+ * { -+ * // Start the timer. No block time is specified, and even if one was -+ * // it would be ignored because the scheduler has not yet been -+ * // started. -+ * if( xTimerStart( xTimers[ x ], 0 ) != pdPASS ) -+ * { -+ * // The timer could not be set into the Active state. -+ * } -+ * } -+ * } -+ * -+ * // ... -+ * // Create tasks here. -+ * // ... -+ * -+ * // Starting the scheduler will start the timers running as they have already -+ * // been set into the active state. -+ * vTaskStartScheduler(); -+ * -+ * // Should not reach here. -+ * for( ;; ); -+ * } -+ * @endverbatim -+ */ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ TimerHandle_t xTimerCreate( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ -+ const TickType_t xTimerPeriodInTicks, -+ const UBaseType_t uxAutoReload, -+ void * const pvTimerID, -+ TimerCallbackFunction_t pxCallbackFunction ); -+#endif -+ -+/** -+ * TimerHandle_t xTimerCreateStatic(const char * const pcTimerName, -+ * TickType_t xTimerPeriodInTicks, -+ * UBaseType_t uxAutoReload, -+ * void * pvTimerID, -+ * TimerCallbackFunction_t pxCallbackFunction, -+ * StaticTimer_t *pxTimerBuffer ); -+ * -+ * Creates a new software timer instance, and returns a handle by which the -+ * created software timer can be referenced. -+ * -+ * Internally, within the FreeRTOS implementation, software timers use a block -+ * of memory, in which the timer data structure is stored. If a software timer -+ * is created using xTimerCreate() then the required memory is automatically -+ * dynamically allocated inside the xTimerCreate() function. (see -+ * https://www.FreeRTOS.org/a00111.html). If a software timer is created using -+ * xTimerCreateStatic() then the application writer must provide the memory that -+ * will get used by the software timer. xTimerCreateStatic() therefore allows a -+ * software timer to be created without using any dynamic memory allocation. -+ * -+ * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), -+ * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and -+ * xTimerChangePeriodFromISR() API functions can all be used to transition a -+ * timer into the active state. -+ * -+ * @param pcTimerName A text name that is assigned to the timer. This is done -+ * purely to assist debugging. The kernel itself only ever references a timer -+ * by its handle, and never by its name. -+ * -+ * @param xTimerPeriodInTicks The timer period. The time is defined in tick -+ * periods so the constant portTICK_PERIOD_MS can be used to convert a time that -+ * has been specified in milliseconds. For example, if the timer must expire -+ * after 100 ticks, then xTimerPeriodInTicks should be set to 100. -+ * Alternatively, if the timer must expire after 500ms, then xPeriod can be set -+ * to ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than or -+ * equal to 1000. The timer period must be greater than 0. -+ * -+ * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will -+ * expire repeatedly with a frequency set by the xTimerPeriodInTicks parameter. -+ * If uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and -+ * enter the dormant state after it expires. -+ * -+ * @param pvTimerID An identifier that is assigned to the timer being created. -+ * Typically this would be used in the timer callback function to identify which -+ * timer expired when the same callback function is assigned to more than one -+ * timer. -+ * -+ * @param pxCallbackFunction The function to call when the timer expires. -+ * Callback functions must have the prototype defined by TimerCallbackFunction_t, -+ * which is "void vCallbackFunction( TimerHandle_t xTimer );". -+ * -+ * @param pxTimerBuffer Must point to a variable of type StaticTimer_t, which -+ * will be then be used to hold the software timer's data structures, removing -+ * the need for the memory to be allocated dynamically. -+ * -+ * @return If the timer is created then a handle to the created timer is -+ * returned. If pxTimerBuffer was NULL then NULL is returned. -+ * -+ * Example usage: -+ * @verbatim -+ * -+ * // The buffer used to hold the software timer's data structure. -+ * static StaticTimer_t xTimerBuffer; -+ * -+ * // A variable that will be incremented by the software timer's callback -+ * // function. -+ * UBaseType_t uxVariableToIncrement = 0; -+ * -+ * // A software timer callback function that increments a variable passed to -+ * // it when the software timer was created. After the 5th increment the -+ * // callback function stops the software timer. -+ * static void prvTimerCallback( TimerHandle_t xExpiredTimer ) -+ * { -+ * UBaseType_t *puxVariableToIncrement; -+ * BaseType_t xReturned; -+ * -+ * // Obtain the address of the variable to increment from the timer ID. -+ * puxVariableToIncrement = ( UBaseType_t * ) pvTimerGetTimerID( xExpiredTimer ); -+ * -+ * // Increment the variable to show the timer callback has executed. -+ * ( *puxVariableToIncrement )++; -+ * -+ * // If this callback has executed the required number of times, stop the -+ * // timer. -+ * if( *puxVariableToIncrement == 5 ) -+ * { -+ * // This is called from a timer callback so must not block. -+ * xTimerStop( xExpiredTimer, staticDONT_BLOCK ); -+ * } -+ * } -+ * -+ * -+ * void main( void ) -+ * { -+ * // Create the software time. xTimerCreateStatic() has an extra parameter -+ * // than the normal xTimerCreate() API function. The parameter is a pointer -+ * // to the StaticTimer_t structure that will hold the software timer -+ * // structure. If the parameter is passed as NULL then the structure will be -+ * // allocated dynamically, just as if xTimerCreate() had been called. -+ * xTimer = xTimerCreateStatic( "T1", // Text name for the task. Helps debugging only. Not used by FreeRTOS. -+ * xTimerPeriod, // The period of the timer in ticks. -+ * pdTRUE, // This is an auto-reload timer. -+ * ( void * ) &uxVariableToIncrement, // A variable incremented by the software timer's callback function -+ * prvTimerCallback, // The function to execute when the timer expires. -+ * &xTimerBuffer ); // The buffer that will hold the software timer structure. -+ * -+ * // The scheduler has not started yet so a block time is not used. -+ * xReturned = xTimerStart( xTimer, 0 ); -+ * -+ * // ... -+ * // Create tasks here. -+ * // ... -+ * -+ * // Starting the scheduler will start the timers running as they have already -+ * // been set into the active state. -+ * vTaskStartScheduler(); -+ * -+ * // Should not reach here. -+ * for( ;; ); -+ * } -+ * @endverbatim -+ */ -+#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) -+ TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ -+ const TickType_t xTimerPeriodInTicks, -+ const UBaseType_t uxAutoReload, -+ void * const pvTimerID, -+ TimerCallbackFunction_t pxCallbackFunction, -+ StaticTimer_t * pxTimerBuffer ); -+#endif /* configSUPPORT_STATIC_ALLOCATION */ -+ -+/** -+ * void *pvTimerGetTimerID( TimerHandle_t xTimer ); -+ * -+ * Returns the ID assigned to the timer. -+ * -+ * IDs are assigned to timers using the pvTimerID parameter of the call to -+ * xTimerCreated() that was used to create the timer, and by calling the -+ * vTimerSetTimerID() API function. -+ * -+ * If the same callback function is assigned to multiple timers then the timer -+ * ID can be used as time specific (timer local) storage. -+ * -+ * @param xTimer The timer being queried. -+ * -+ * @return The ID assigned to the timer being queried. -+ * -+ * Example usage: -+ * -+ * See the xTimerCreate() API function example usage scenario. -+ */ -+void * pvTimerGetTimerID( const TimerHandle_t xTimer ); -+ -+/** -+ * void vTimerSetTimerID( TimerHandle_t xTimer, void *pvNewID ); -+ * -+ * Sets the ID assigned to the timer. -+ * -+ * IDs are assigned to timers using the pvTimerID parameter of the call to -+ * xTimerCreated() that was used to create the timer. -+ * -+ * If the same callback function is assigned to multiple timers then the timer -+ * ID can be used as time specific (timer local) storage. -+ * -+ * @param xTimer The timer being updated. -+ * -+ * @param pvNewID The ID to assign to the timer. -+ * -+ * Example usage: -+ * -+ * See the xTimerCreate() API function example usage scenario. -+ */ -+void vTimerSetTimerID( TimerHandle_t xTimer, -+ void * pvNewID ); -+ -+/** -+ * BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ); -+ * -+ * Queries a timer to see if it is active or dormant. -+ * -+ * A timer will be dormant if: -+ * 1) It has been created but not started, or -+ * 2) It is an expired one-shot timer that has not been restarted. -+ * -+ * Timers are created in the dormant state. The xTimerStart(), xTimerReset(), -+ * xTimerStartFromISR(), xTimerResetFromISR(), xTimerChangePeriod() and -+ * xTimerChangePeriodFromISR() API functions can all be used to transition a timer into the -+ * active state. -+ * -+ * @param xTimer The timer being queried. -+ * -+ * @return pdFALSE will be returned if the timer is dormant. A value other than -+ * pdFALSE will be returned if the timer is active. -+ * -+ * Example usage: -+ * @verbatim -+ * // This function assumes xTimer has already been created. -+ * void vAFunction( TimerHandle_t xTimer ) -+ * { -+ * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" -+ * { -+ * // xTimer is active, do something. -+ * } -+ * else -+ * { -+ * // xTimer is not active, do something else. -+ * } -+ * } -+ * @endverbatim -+ */ -+BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ); -+ -+/** -+ * TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); -+ * -+ * Simply returns the handle of the timer service/daemon task. It it not valid -+ * to call xTimerGetTimerDaemonTaskHandle() before the scheduler has been started. -+ */ -+TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ); -+ -+/** -+ * BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait ); -+ * -+ * Timer functionality is provided by a timer service/daemon task. Many of the -+ * public FreeRTOS timer API functions send commands to the timer service task -+ * through a queue called the timer command queue. The timer command queue is -+ * private to the kernel itself and is not directly accessible to application -+ * code. The length of the timer command queue is set by the -+ * configTIMER_QUEUE_LENGTH configuration constant. -+ * -+ * xTimerStart() starts a timer that was previously created using the -+ * xTimerCreate() API function. If the timer had already been started and was -+ * already in the active state, then xTimerStart() has equivalent functionality -+ * to the xTimerReset() API function. -+ * -+ * Starting a timer ensures the timer is in the active state. If the timer -+ * is not stopped, deleted, or reset in the mean time, the callback function -+ * associated with the timer will get called 'n' ticks after xTimerStart() was -+ * called, where 'n' is the timers defined period. -+ * -+ * It is valid to call xTimerStart() before the scheduler has been started, but -+ * when this is done the timer will not actually start until the scheduler is -+ * started, and the timers expiry time will be relative to when the scheduler is -+ * started, not relative to when xTimerStart() was called. -+ * -+ * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStart() -+ * to be available. -+ * -+ * @param xTimer The handle of the timer being started/restarted. -+ * -+ * @param xTicksToWait Specifies the time, in ticks, that the calling task should -+ * be held in the Blocked state to wait for the start command to be successfully -+ * sent to the timer command queue, should the queue already be full when -+ * xTimerStart() was called. xTicksToWait is ignored if xTimerStart() is called -+ * before the scheduler is started. -+ * -+ * @return pdFAIL will be returned if the start command could not be sent to -+ * the timer command queue even after xTicksToWait ticks had passed. pdPASS will -+ * be returned if the command was successfully sent to the timer command queue. -+ * When the command is actually processed will depend on the priority of the -+ * timer service/daemon task relative to other tasks in the system, although the -+ * timers expiry time is relative to when xTimerStart() is actually called. The -+ * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY -+ * configuration constant. -+ * -+ * Example usage: -+ * -+ * See the xTimerCreate() API function example usage scenario. -+ * -+ */ -+#define xTimerStart( xTimer, xTicksToWait ) \ -+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) -+ -+/** -+ * BaseType_t xTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait ); -+ * -+ * Timer functionality is provided by a timer service/daemon task. Many of the -+ * public FreeRTOS timer API functions send commands to the timer service task -+ * through a queue called the timer command queue. The timer command queue is -+ * private to the kernel itself and is not directly accessible to application -+ * code. The length of the timer command queue is set by the -+ * configTIMER_QUEUE_LENGTH configuration constant. -+ * -+ * xTimerStop() stops a timer that was previously started using either of the -+ * The xTimerStart(), xTimerReset(), xTimerStartFromISR(), xTimerResetFromISR(), -+ * xTimerChangePeriod() or xTimerChangePeriodFromISR() API functions. -+ * -+ * Stopping a timer ensures the timer is not in the active state. -+ * -+ * The configUSE_TIMERS configuration constant must be set to 1 for xTimerStop() -+ * to be available. -+ * -+ * @param xTimer The handle of the timer being stopped. -+ * -+ * @param xTicksToWait Specifies the time, in ticks, that the calling task should -+ * be held in the Blocked state to wait for the stop command to be successfully -+ * sent to the timer command queue, should the queue already be full when -+ * xTimerStop() was called. xTicksToWait is ignored if xTimerStop() is called -+ * before the scheduler is started. -+ * -+ * @return pdFAIL will be returned if the stop command could not be sent to -+ * the timer command queue even after xTicksToWait ticks had passed. pdPASS will -+ * be returned if the command was successfully sent to the timer command queue. -+ * When the command is actually processed will depend on the priority of the -+ * timer service/daemon task relative to other tasks in the system. The timer -+ * service/daemon task priority is set by the configTIMER_TASK_PRIORITY -+ * configuration constant. -+ * -+ * Example usage: -+ * -+ * See the xTimerCreate() API function example usage scenario. -+ * -+ */ -+#define xTimerStop( xTimer, xTicksToWait ) \ -+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) ) -+ -+/** -+ * BaseType_t xTimerChangePeriod( TimerHandle_t xTimer, -+ * TickType_t xNewPeriod, -+ * TickType_t xTicksToWait ); -+ * -+ * Timer functionality is provided by a timer service/daemon task. Many of the -+ * public FreeRTOS timer API functions send commands to the timer service task -+ * through a queue called the timer command queue. The timer command queue is -+ * private to the kernel itself and is not directly accessible to application -+ * code. The length of the timer command queue is set by the -+ * configTIMER_QUEUE_LENGTH configuration constant. -+ * -+ * xTimerChangePeriod() changes the period of a timer that was previously -+ * created using the xTimerCreate() API function. -+ * -+ * xTimerChangePeriod() can be called to change the period of an active or -+ * dormant state timer. -+ * -+ * The configUSE_TIMERS configuration constant must be set to 1 for -+ * xTimerChangePeriod() to be available. -+ * -+ * @param xTimer The handle of the timer that is having its period changed. -+ * -+ * @param xNewPeriod The new period for xTimer. Timer periods are specified in -+ * tick periods, so the constant portTICK_PERIOD_MS can be used to convert a time -+ * that has been specified in milliseconds. For example, if the timer must -+ * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, -+ * if the timer must expire after 500ms, then xNewPeriod can be set to -+ * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than -+ * or equal to 1000. -+ * -+ * @param xTicksToWait Specifies the time, in ticks, that the calling task should -+ * be held in the Blocked state to wait for the change period command to be -+ * successfully sent to the timer command queue, should the queue already be -+ * full when xTimerChangePeriod() was called. xTicksToWait is ignored if -+ * xTimerChangePeriod() is called before the scheduler is started. -+ * -+ * @return pdFAIL will be returned if the change period command could not be -+ * sent to the timer command queue even after xTicksToWait ticks had passed. -+ * pdPASS will be returned if the command was successfully sent to the timer -+ * command queue. When the command is actually processed will depend on the -+ * priority of the timer service/daemon task relative to other tasks in the -+ * system. The timer service/daemon task priority is set by the -+ * configTIMER_TASK_PRIORITY configuration constant. -+ * -+ * Example usage: -+ * @verbatim -+ * // This function assumes xTimer has already been created. If the timer -+ * // referenced by xTimer is already active when it is called, then the timer -+ * // is deleted. If the timer referenced by xTimer is not active when it is -+ * // called, then the period of the timer is set to 500ms and the timer is -+ * // started. -+ * void vAFunction( TimerHandle_t xTimer ) -+ * { -+ * if( xTimerIsTimerActive( xTimer ) != pdFALSE ) // or more simply and equivalently "if( xTimerIsTimerActive( xTimer ) )" -+ * { -+ * // xTimer is already active - delete it. -+ * xTimerDelete( xTimer ); -+ * } -+ * else -+ * { -+ * // xTimer is not active, change its period to 500ms. This will also -+ * // cause the timer to start. Block for a maximum of 100 ticks if the -+ * // change period command cannot immediately be sent to the timer -+ * // command queue. -+ * if( xTimerChangePeriod( xTimer, 500 / portTICK_PERIOD_MS, 100 ) == pdPASS ) -+ * { -+ * // The command was successfully sent. -+ * } -+ * else -+ * { -+ * // The command could not be sent, even after waiting for 100 ticks -+ * // to pass. Take appropriate action here. -+ * } -+ * } -+ * } -+ * @endverbatim -+ */ -+#define xTimerChangePeriod( xTimer, xNewPeriod, xTicksToWait ) \ -+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD, ( xNewPeriod ), NULL, ( xTicksToWait ) ) -+ -+/** -+ * BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait ); -+ * -+ * Timer functionality is provided by a timer service/daemon task. Many of the -+ * public FreeRTOS timer API functions send commands to the timer service task -+ * through a queue called the timer command queue. The timer command queue is -+ * private to the kernel itself and is not directly accessible to application -+ * code. The length of the timer command queue is set by the -+ * configTIMER_QUEUE_LENGTH configuration constant. -+ * -+ * xTimerDelete() deletes a timer that was previously created using the -+ * xTimerCreate() API function. -+ * -+ * The configUSE_TIMERS configuration constant must be set to 1 for -+ * xTimerDelete() to be available. -+ * -+ * @param xTimer The handle of the timer being deleted. -+ * -+ * @param xTicksToWait Specifies the time, in ticks, that the calling task should -+ * be held in the Blocked state to wait for the delete command to be -+ * successfully sent to the timer command queue, should the queue already be -+ * full when xTimerDelete() was called. xTicksToWait is ignored if xTimerDelete() -+ * is called before the scheduler is started. -+ * -+ * @return pdFAIL will be returned if the delete command could not be sent to -+ * the timer command queue even after xTicksToWait ticks had passed. pdPASS will -+ * be returned if the command was successfully sent to the timer command queue. -+ * When the command is actually processed will depend on the priority of the -+ * timer service/daemon task relative to other tasks in the system. The timer -+ * service/daemon task priority is set by the configTIMER_TASK_PRIORITY -+ * configuration constant. -+ * -+ * Example usage: -+ * -+ * See the xTimerChangePeriod() API function example usage scenario. -+ */ -+#define xTimerDelete( xTimer, xTicksToWait ) \ -+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_DELETE, 0U, NULL, ( xTicksToWait ) ) -+ -+/** -+ * BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait ); -+ * -+ * Timer functionality is provided by a timer service/daemon task. Many of the -+ * public FreeRTOS timer API functions send commands to the timer service task -+ * through a queue called the timer command queue. The timer command queue is -+ * private to the kernel itself and is not directly accessible to application -+ * code. The length of the timer command queue is set by the -+ * configTIMER_QUEUE_LENGTH configuration constant. -+ * -+ * xTimerReset() re-starts a timer that was previously created using the -+ * xTimerCreate() API function. If the timer had already been started and was -+ * already in the active state, then xTimerReset() will cause the timer to -+ * re-evaluate its expiry time so that it is relative to when xTimerReset() was -+ * called. If the timer was in the dormant state then xTimerReset() has -+ * equivalent functionality to the xTimerStart() API function. -+ * -+ * Resetting a timer ensures the timer is in the active state. If the timer -+ * is not stopped, deleted, or reset in the mean time, the callback function -+ * associated with the timer will get called 'n' ticks after xTimerReset() was -+ * called, where 'n' is the timers defined period. -+ * -+ * It is valid to call xTimerReset() before the scheduler has been started, but -+ * when this is done the timer will not actually start until the scheduler is -+ * started, and the timers expiry time will be relative to when the scheduler is -+ * started, not relative to when xTimerReset() was called. -+ * -+ * The configUSE_TIMERS configuration constant must be set to 1 for xTimerReset() -+ * to be available. -+ * -+ * @param xTimer The handle of the timer being reset/started/restarted. -+ * -+ * @param xTicksToWait Specifies the time, in ticks, that the calling task should -+ * be held in the Blocked state to wait for the reset command to be successfully -+ * sent to the timer command queue, should the queue already be full when -+ * xTimerReset() was called. xTicksToWait is ignored if xTimerReset() is called -+ * before the scheduler is started. -+ * -+ * @return pdFAIL will be returned if the reset command could not be sent to -+ * the timer command queue even after xTicksToWait ticks had passed. pdPASS will -+ * be returned if the command was successfully sent to the timer command queue. -+ * When the command is actually processed will depend on the priority of the -+ * timer service/daemon task relative to other tasks in the system, although the -+ * timers expiry time is relative to when xTimerStart() is actually called. The -+ * timer service/daemon task priority is set by the configTIMER_TASK_PRIORITY -+ * configuration constant. -+ * -+ * Example usage: -+ * @verbatim -+ * // When a key is pressed, an LCD back-light is switched on. If 5 seconds pass -+ * // without a key being pressed, then the LCD back-light is switched off. In -+ * // this case, the timer is a one-shot timer. -+ * -+ * TimerHandle_t xBacklightTimer = NULL; -+ * -+ * // The callback function assigned to the one-shot timer. In this case the -+ * // parameter is not used. -+ * void vBacklightTimerCallback( TimerHandle_t pxTimer ) -+ * { -+ * // The timer expired, therefore 5 seconds must have passed since a key -+ * // was pressed. Switch off the LCD back-light. -+ * vSetBacklightState( BACKLIGHT_OFF ); -+ * } -+ * -+ * // The key press event handler. -+ * void vKeyPressEventHandler( char cKey ) -+ * { -+ * // Ensure the LCD back-light is on, then reset the timer that is -+ * // responsible for turning the back-light off after 5 seconds of -+ * // key inactivity. Wait 10 ticks for the command to be successfully sent -+ * // if it cannot be sent immediately. -+ * vSetBacklightState( BACKLIGHT_ON ); -+ * if( xTimerReset( xBacklightTimer, 100 ) != pdPASS ) -+ * { -+ * // The reset command was not executed successfully. Take appropriate -+ * // action here. -+ * } -+ * -+ * // Perform the rest of the key processing here. -+ * } -+ * -+ * void main( void ) -+ * { -+ * int32_t x; -+ * -+ * // Create then start the one-shot timer that is responsible for turning -+ * // the back-light off if no keys are pressed within a 5 second period. -+ * xBacklightTimer = xTimerCreate( "BacklightTimer", // Just a text name, not used by the kernel. -+ * ( 5000 / portTICK_PERIOD_MS), // The timer period in ticks. -+ * pdFALSE, // The timer is a one-shot timer. -+ * 0, // The id is not used by the callback so can take any value. -+ * vBacklightTimerCallback // The callback function that switches the LCD back-light off. -+ * ); -+ * -+ * if( xBacklightTimer == NULL ) -+ * { -+ * // The timer was not created. -+ * } -+ * else -+ * { -+ * // Start the timer. No block time is specified, and even if one was -+ * // it would be ignored because the scheduler has not yet been -+ * // started. -+ * if( xTimerStart( xBacklightTimer, 0 ) != pdPASS ) -+ * { -+ * // The timer could not be set into the Active state. -+ * } -+ * } -+ * -+ * // ... -+ * // Create tasks here. -+ * // ... -+ * -+ * // Starting the scheduler will start the timer running as it has already -+ * // been set into the active state. -+ * vTaskStartScheduler(); -+ * -+ * // Should not reach here. -+ * for( ;; ); -+ * } -+ * @endverbatim -+ */ -+#define xTimerReset( xTimer, xTicksToWait ) \ -+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) ) -+ -+/** -+ * BaseType_t xTimerStartFromISR( TimerHandle_t xTimer, -+ * BaseType_t *pxHigherPriorityTaskWoken ); -+ * -+ * A version of xTimerStart() that can be called from an interrupt service -+ * routine. -+ * -+ * @param xTimer The handle of the timer being started/restarted. -+ * -+ * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most -+ * of its time in the Blocked state, waiting for messages to arrive on the timer -+ * command queue. Calling xTimerStartFromISR() writes a message to the timer -+ * command queue, so has the potential to transition the timer service/daemon -+ * task out of the Blocked state. If calling xTimerStartFromISR() causes the -+ * timer service/daemon task to leave the Blocked state, and the timer service/ -+ * daemon task has a priority equal to or greater than the currently executing -+ * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will -+ * get set to pdTRUE internally within the xTimerStartFromISR() function. If -+ * xTimerStartFromISR() sets this value to pdTRUE then a context switch should -+ * be performed before the interrupt exits. -+ * -+ * @return pdFAIL will be returned if the start command could not be sent to -+ * the timer command queue. pdPASS will be returned if the command was -+ * successfully sent to the timer command queue. When the command is actually -+ * processed will depend on the priority of the timer service/daemon task -+ * relative to other tasks in the system, although the timers expiry time is -+ * relative to when xTimerStartFromISR() is actually called. The timer -+ * service/daemon task priority is set by the configTIMER_TASK_PRIORITY -+ * configuration constant. -+ * -+ * Example usage: -+ * @verbatim -+ * // This scenario assumes xBacklightTimer has already been created. When a -+ * // key is pressed, an LCD back-light is switched on. If 5 seconds pass -+ * // without a key being pressed, then the LCD back-light is switched off. In -+ * // this case, the timer is a one-shot timer, and unlike the example given for -+ * // the xTimerReset() function, the key press event handler is an interrupt -+ * // service routine. -+ * -+ * // The callback function assigned to the one-shot timer. In this case the -+ * // parameter is not used. -+ * void vBacklightTimerCallback( TimerHandle_t pxTimer ) -+ * { -+ * // The timer expired, therefore 5 seconds must have passed since a key -+ * // was pressed. Switch off the LCD back-light. -+ * vSetBacklightState( BACKLIGHT_OFF ); -+ * } -+ * -+ * // The key press interrupt service routine. -+ * void vKeyPressEventInterruptHandler( void ) -+ * { -+ * BaseType_t xHigherPriorityTaskWoken = pdFALSE; -+ * -+ * // Ensure the LCD back-light is on, then restart the timer that is -+ * // responsible for turning the back-light off after 5 seconds of -+ * // key inactivity. This is an interrupt service routine so can only -+ * // call FreeRTOS API functions that end in "FromISR". -+ * vSetBacklightState( BACKLIGHT_ON ); -+ * -+ * // xTimerStartFromISR() or xTimerResetFromISR() could be called here -+ * // as both cause the timer to re-calculate its expiry time. -+ * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was -+ * // declared (in this function). -+ * if( xTimerStartFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS ) -+ * { -+ * // The start command was not executed successfully. Take appropriate -+ * // action here. -+ * } -+ * -+ * // Perform the rest of the key processing here. -+ * -+ * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch -+ * // should be performed. The syntax required to perform a context switch -+ * // from inside an ISR varies from port to port, and from compiler to -+ * // compiler. Inspect the demos for the port you are using to find the -+ * // actual syntax required. -+ * if( xHigherPriorityTaskWoken != pdFALSE ) -+ * { -+ * // Call the interrupt safe yield function here (actual function -+ * // depends on the FreeRTOS port being used). -+ * } -+ * } -+ * @endverbatim -+ */ -+#define xTimerStartFromISR( xTimer, pxHigherPriorityTaskWoken ) \ -+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) -+ -+/** -+ * BaseType_t xTimerStopFromISR( TimerHandle_t xTimer, -+ * BaseType_t *pxHigherPriorityTaskWoken ); -+ * -+ * A version of xTimerStop() that can be called from an interrupt service -+ * routine. -+ * -+ * @param xTimer The handle of the timer being stopped. -+ * -+ * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most -+ * of its time in the Blocked state, waiting for messages to arrive on the timer -+ * command queue. Calling xTimerStopFromISR() writes a message to the timer -+ * command queue, so has the potential to transition the timer service/daemon -+ * task out of the Blocked state. If calling xTimerStopFromISR() causes the -+ * timer service/daemon task to leave the Blocked state, and the timer service/ -+ * daemon task has a priority equal to or greater than the currently executing -+ * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will -+ * get set to pdTRUE internally within the xTimerStopFromISR() function. If -+ * xTimerStopFromISR() sets this value to pdTRUE then a context switch should -+ * be performed before the interrupt exits. -+ * -+ * @return pdFAIL will be returned if the stop command could not be sent to -+ * the timer command queue. pdPASS will be returned if the command was -+ * successfully sent to the timer command queue. When the command is actually -+ * processed will depend on the priority of the timer service/daemon task -+ * relative to other tasks in the system. The timer service/daemon task -+ * priority is set by the configTIMER_TASK_PRIORITY configuration constant. -+ * -+ * Example usage: -+ * @verbatim -+ * // This scenario assumes xTimer has already been created and started. When -+ * // an interrupt occurs, the timer should be simply stopped. -+ * -+ * // The interrupt service routine that stops the timer. -+ * void vAnExampleInterruptServiceRoutine( void ) -+ * { -+ * BaseType_t xHigherPriorityTaskWoken = pdFALSE; -+ * -+ * // The interrupt has occurred - simply stop the timer. -+ * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined -+ * // (within this function). As this is an interrupt service routine, only -+ * // FreeRTOS API functions that end in "FromISR" can be used. -+ * if( xTimerStopFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS ) -+ * { -+ * // The stop command was not executed successfully. Take appropriate -+ * // action here. -+ * } -+ * -+ * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch -+ * // should be performed. The syntax required to perform a context switch -+ * // from inside an ISR varies from port to port, and from compiler to -+ * // compiler. Inspect the demos for the port you are using to find the -+ * // actual syntax required. -+ * if( xHigherPriorityTaskWoken != pdFALSE ) -+ * { -+ * // Call the interrupt safe yield function here (actual function -+ * // depends on the FreeRTOS port being used). -+ * } -+ * } -+ * @endverbatim -+ */ -+#define xTimerStopFromISR( xTimer, pxHigherPriorityTaskWoken ) \ -+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP_FROM_ISR, 0, ( pxHigherPriorityTaskWoken ), 0U ) -+ -+/** -+ * BaseType_t xTimerChangePeriodFromISR( TimerHandle_t xTimer, -+ * TickType_t xNewPeriod, -+ * BaseType_t *pxHigherPriorityTaskWoken ); -+ * -+ * A version of xTimerChangePeriod() that can be called from an interrupt -+ * service routine. -+ * -+ * @param xTimer The handle of the timer that is having its period changed. -+ * -+ * @param xNewPeriod The new period for xTimer. Timer periods are specified in -+ * tick periods, so the constant portTICK_PERIOD_MS can be used to convert a time -+ * that has been specified in milliseconds. For example, if the timer must -+ * expire after 100 ticks, then xNewPeriod should be set to 100. Alternatively, -+ * if the timer must expire after 500ms, then xNewPeriod can be set to -+ * ( 500 / portTICK_PERIOD_MS ) provided configTICK_RATE_HZ is less than -+ * or equal to 1000. -+ * -+ * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most -+ * of its time in the Blocked state, waiting for messages to arrive on the timer -+ * command queue. Calling xTimerChangePeriodFromISR() writes a message to the -+ * timer command queue, so has the potential to transition the timer service/ -+ * daemon task out of the Blocked state. If calling xTimerChangePeriodFromISR() -+ * causes the timer service/daemon task to leave the Blocked state, and the -+ * timer service/daemon task has a priority equal to or greater than the -+ * currently executing task (the task that was interrupted), then -+ * *pxHigherPriorityTaskWoken will get set to pdTRUE internally within the -+ * xTimerChangePeriodFromISR() function. If xTimerChangePeriodFromISR() sets -+ * this value to pdTRUE then a context switch should be performed before the -+ * interrupt exits. -+ * -+ * @return pdFAIL will be returned if the command to change the timers period -+ * could not be sent to the timer command queue. pdPASS will be returned if the -+ * command was successfully sent to the timer command queue. When the command -+ * is actually processed will depend on the priority of the timer service/daemon -+ * task relative to other tasks in the system. The timer service/daemon task -+ * priority is set by the configTIMER_TASK_PRIORITY configuration constant. -+ * -+ * Example usage: -+ * @verbatim -+ * // This scenario assumes xTimer has already been created and started. When -+ * // an interrupt occurs, the period of xTimer should be changed to 500ms. -+ * -+ * // The interrupt service routine that changes the period of xTimer. -+ * void vAnExampleInterruptServiceRoutine( void ) -+ * { -+ * BaseType_t xHigherPriorityTaskWoken = pdFALSE; -+ * -+ * // The interrupt has occurred - change the period of xTimer to 500ms. -+ * // xHigherPriorityTaskWoken was set to pdFALSE where it was defined -+ * // (within this function). As this is an interrupt service routine, only -+ * // FreeRTOS API functions that end in "FromISR" can be used. -+ * if( xTimerChangePeriodFromISR( xTimer, &xHigherPriorityTaskWoken ) != pdPASS ) -+ * { -+ * // The command to change the timers period was not executed -+ * // successfully. Take appropriate action here. -+ * } -+ * -+ * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch -+ * // should be performed. The syntax required to perform a context switch -+ * // from inside an ISR varies from port to port, and from compiler to -+ * // compiler. Inspect the demos for the port you are using to find the -+ * // actual syntax required. -+ * if( xHigherPriorityTaskWoken != pdFALSE ) -+ * { -+ * // Call the interrupt safe yield function here (actual function -+ * // depends on the FreeRTOS port being used). -+ * } -+ * } -+ * @endverbatim -+ */ -+#define xTimerChangePeriodFromISR( xTimer, xNewPeriod, pxHigherPriorityTaskWoken ) \ -+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_CHANGE_PERIOD_FROM_ISR, ( xNewPeriod ), ( pxHigherPriorityTaskWoken ), 0U ) -+ -+/** -+ * BaseType_t xTimerResetFromISR( TimerHandle_t xTimer, -+ * BaseType_t *pxHigherPriorityTaskWoken ); -+ * -+ * A version of xTimerReset() that can be called from an interrupt service -+ * routine. -+ * -+ * @param xTimer The handle of the timer that is to be started, reset, or -+ * restarted. -+ * -+ * @param pxHigherPriorityTaskWoken The timer service/daemon task spends most -+ * of its time in the Blocked state, waiting for messages to arrive on the timer -+ * command queue. Calling xTimerResetFromISR() writes a message to the timer -+ * command queue, so has the potential to transition the timer service/daemon -+ * task out of the Blocked state. If calling xTimerResetFromISR() causes the -+ * timer service/daemon task to leave the Blocked state, and the timer service/ -+ * daemon task has a priority equal to or greater than the currently executing -+ * task (the task that was interrupted), then *pxHigherPriorityTaskWoken will -+ * get set to pdTRUE internally within the xTimerResetFromISR() function. If -+ * xTimerResetFromISR() sets this value to pdTRUE then a context switch should -+ * be performed before the interrupt exits. -+ * -+ * @return pdFAIL will be returned if the reset command could not be sent to -+ * the timer command queue. pdPASS will be returned if the command was -+ * successfully sent to the timer command queue. When the command is actually -+ * processed will depend on the priority of the timer service/daemon task -+ * relative to other tasks in the system, although the timers expiry time is -+ * relative to when xTimerResetFromISR() is actually called. The timer service/daemon -+ * task priority is set by the configTIMER_TASK_PRIORITY configuration constant. -+ * -+ * Example usage: -+ * @verbatim -+ * // This scenario assumes xBacklightTimer has already been created. When a -+ * // key is pressed, an LCD back-light is switched on. If 5 seconds pass -+ * // without a key being pressed, then the LCD back-light is switched off. In -+ * // this case, the timer is a one-shot timer, and unlike the example given for -+ * // the xTimerReset() function, the key press event handler is an interrupt -+ * // service routine. -+ * -+ * // The callback function assigned to the one-shot timer. In this case the -+ * // parameter is not used. -+ * void vBacklightTimerCallback( TimerHandle_t pxTimer ) -+ * { -+ * // The timer expired, therefore 5 seconds must have passed since a key -+ * // was pressed. Switch off the LCD back-light. -+ * vSetBacklightState( BACKLIGHT_OFF ); -+ * } -+ * -+ * // The key press interrupt service routine. -+ * void vKeyPressEventInterruptHandler( void ) -+ * { -+ * BaseType_t xHigherPriorityTaskWoken = pdFALSE; -+ * -+ * // Ensure the LCD back-light is on, then reset the timer that is -+ * // responsible for turning the back-light off after 5 seconds of -+ * // key inactivity. This is an interrupt service routine so can only -+ * // call FreeRTOS API functions that end in "FromISR". -+ * vSetBacklightState( BACKLIGHT_ON ); -+ * -+ * // xTimerStartFromISR() or xTimerResetFromISR() could be called here -+ * // as both cause the timer to re-calculate its expiry time. -+ * // xHigherPriorityTaskWoken was initialised to pdFALSE when it was -+ * // declared (in this function). -+ * if( xTimerResetFromISR( xBacklightTimer, &xHigherPriorityTaskWoken ) != pdPASS ) -+ * { -+ * // The reset command was not executed successfully. Take appropriate -+ * // action here. -+ * } -+ * -+ * // Perform the rest of the key processing here. -+ * -+ * // If xHigherPriorityTaskWoken equals pdTRUE, then a context switch -+ * // should be performed. The syntax required to perform a context switch -+ * // from inside an ISR varies from port to port, and from compiler to -+ * // compiler. Inspect the demos for the port you are using to find the -+ * // actual syntax required. -+ * if( xHigherPriorityTaskWoken != pdFALSE ) -+ * { -+ * // Call the interrupt safe yield function here (actual function -+ * // depends on the FreeRTOS port being used). -+ * } -+ * } -+ * @endverbatim -+ */ -+#define xTimerResetFromISR( xTimer, pxHigherPriorityTaskWoken ) \ -+ xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET_FROM_ISR, ( xTaskGetTickCountFromISR() ), ( pxHigherPriorityTaskWoken ), 0U ) -+ -+/** -+ * const char * const pcTimerGetName( TimerHandle_t xTimer ); -+ * -+ * Returns the name that was assigned to a timer when the timer was created. -+ * -+ * @param xTimer The handle of the timer being queried. -+ * -+ * @return The name assigned to the timer specified by the xTimer parameter. -+ */ -+const char * pcTimerGetName( TimerHandle_t xTimer ); -+ -+/** -+ * void vTimerSetReloadMode( TimerHandle_t xTimer, const UBaseType_t uxAutoReload ); -+ * -+ * Updates a timer to be either an auto-reload timer, in which case the timer -+ * automatically resets itself each time it expires, or a one-shot timer, in -+ * which case the timer will only expire once unless it is manually restarted. -+ * -+ * @param xTimer The handle of the timer being updated. -+ * -+ * @param uxAutoReload If uxAutoReload is set to pdTRUE then the timer will -+ * expire repeatedly with a frequency set by the timer's period (see the -+ * xTimerPeriodInTicks parameter of the xTimerCreate() API function). If -+ * uxAutoReload is set to pdFALSE then the timer will be a one-shot timer and -+ * enter the dormant state after it expires. -+ */ -+void vTimerSetReloadMode( TimerHandle_t xTimer, -+ const UBaseType_t uxAutoReload ); -+ -+/** -+ * UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ); -+ * -+ * Queries a timer to determine if it is an auto-reload timer, in which case the timer -+ * automatically resets itself each time it expires, or a one-shot timer, in -+ * which case the timer will only expire once unless it is manually restarted. -+ * -+ * @param xTimer The handle of the timer being queried. -+ * -+ * @return If the timer is an auto-reload timer then pdTRUE is returned, otherwise -+ * pdFALSE is returned. -+ */ -+UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ); -+ -+/** -+ * TickType_t xTimerGetPeriod( TimerHandle_t xTimer ); -+ * -+ * Returns the period of a timer. -+ * -+ * @param xTimer The handle of the timer being queried. -+ * -+ * @return The period of the timer in ticks. -+ */ -+TickType_t xTimerGetPeriod( TimerHandle_t xTimer ); -+ -+/** -+ * TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ); -+ * -+ * Returns the time in ticks at which the timer will expire. If this is less -+ * than the current tick count then the expiry time has overflowed from the -+ * current time. -+ * -+ * @param xTimer The handle of the timer being queried. -+ * -+ * @return If the timer is running then the time in ticks at which the timer -+ * will next expire is returned. If the timer is not running then the return -+ * value is undefined. -+ */ -+TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ); -+ -+/* -+ * Functions beyond this part are not part of the public API and are intended -+ * for use by the kernel only. -+ */ -+BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, -+ const BaseType_t xCommandID, -+ const TickType_t xOptionalValue, -+ BaseType_t * const pxHigherPriorityTaskWoken, -+ const TickType_t xTicksToWait ); -+ -+/* *INDENT-OFF* */ -+#ifdef __cplusplus -+ } -+#endif -+/* *INDENT-ON* */ -+#endif /* TIMERS_H */ -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/list.c b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/list.c -new file mode 100644 -index 0000000000..5eec523162 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/list.c -@@ -0,0 +1,213 @@ -+/* -+ * FreeRTOS Kernel V10.4.3 -+ * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. -+ * -+ * 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 -+ -+/* 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" -+ -+/* Lint e9021, e961 and e750 are suppressed as a MISRA exception justified -+ * because 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 /*lint !e961 !e750 !e9021. */ -+ -+/*----------------------------------------------------------- -+* PUBLIC LIST API documented in list.h -+*----------------------------------------------------------*/ -+ -+void vListInitialise( List_t * const 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 ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ -+ -+ /* 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 ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ -+ pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */ -+ -+ 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 ); -+} -+/*-----------------------------------------------------------*/ -+ -+void vListInitialiseItem( ListItem_t * const 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 ); -+} -+/*-----------------------------------------------------------*/ -+ -+void vListInsertEnd( List_t * const pxList, -+ ListItem_t * const pxNewListItem ) -+{ -+ 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; -+ -+ /* 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 )++; -+} -+/*-----------------------------------------------------------*/ -+ -+void vListInsert( List_t * const pxList, -+ ListItem_t * const pxNewListItem ) -+{ -+ ListItem_t * pxIterator; -+ const TickType_t xValueOfInsertion = pxNewListItem->xItemValue; -+ -+ /* 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/FAQHelp.html 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 ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */ -+ { -+ /* There is nothing to do here, just iterating to the wanted -+ * insertion position. */ -+ } -+ } -+ -+ 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 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; -+ -+ 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 )--; -+ -+ return pxList->uxNumberOfItems; -+} -+/*-----------------------------------------------------------*/ -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_1.c b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_1.c -new file mode 100644 -index 0000000000..cebc240892 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_1.c -@@ -0,0 +1,145 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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 -+ * -+ */ -+ -+ -+/* -+ * The simplest possible implementation of pvPortMalloc(). Note that this -+ * implementation does NOT allow allocated memory to be freed again. -+ * -+ * See heap_2.c, heap_3.c and heap_4.c for alternative implementations, and the -+ * memory management pages of https://www.FreeRTOS.org for more information. -+ */ -+#include -+ -+#include "FreeRTOS.h" -+#include "task.h" -+ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) -+ #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0 -+#endif -+ -+/* A few bytes might be lost to byte aligning the heap start address. */ -+#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) -+ -+/* 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[ configTOTAL_HEAP_SIZE ]; -+#else -+ static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; -+#endif /* configAPPLICATION_ALLOCATED_HEAP */ -+ -+/* Index into the ucHeap array. */ -+static size_t xNextFreeByte = ( size_t ) 0; -+ -+/*-----------------------------------------------------------*/ -+ -+void * pvPortMalloc( size_t xWantedSize ) -+{ -+ void * pvReturn = NULL; -+ static uint8_t * pucAlignedHeap = NULL; -+ -+ /* Ensure that blocks are always aligned. */ -+ #if ( portBYTE_ALIGNMENT != 1 ) -+ { -+ if( xWantedSize & portBYTE_ALIGNMENT_MASK ) -+ { -+ /* Byte alignment required. Check for overflow. */ -+ if ( (xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) )) > xWantedSize ) -+ { -+ xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); -+ } -+ else -+ { -+ xWantedSize = 0; -+ } -+ } -+ } -+ #endif -+ -+ vTaskSuspendAll(); -+ { -+ if( pucAlignedHeap == NULL ) -+ { -+ /* Ensure the heap starts on a correctly aligned boundary. */ -+ pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) & ucHeap[ portBYTE_ALIGNMENT - 1 ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); -+ } -+ -+ /* Check there is enough room left for the allocation and. */ -+ if( ( xWantedSize > 0 ) && /* valid size */ -+ ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) && -+ ( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) ) /* Check for overflow. */ -+ { -+ /* Return the next free byte then increment the index past this -+ * block. */ -+ pvReturn = pucAlignedHeap + xNextFreeByte; -+ xNextFreeByte += xWantedSize; -+ } -+ -+ } -+ ( void ) xTaskResumeAll(); -+ -+ #if ( configUSE_MALLOC_FAILED_HOOK == 1 ) -+ { -+ if( pvReturn == NULL ) -+ { -+ extern void vApplicationMallocFailedHook( void ); -+ vApplicationMallocFailedHook(); -+ } -+ } -+ #endif -+ -+ return pvReturn; -+} -+/*-----------------------------------------------------------*/ -+ -+void vPortFree( void * pv ) -+{ -+ /* Memory cannot be freed using this scheme. See heap_2.c, heap_3.c and -+ * heap_4.c for alternative implementations, and the memory management pages of -+ * https://www.FreeRTOS.org for more information. */ -+ ( void ) pv; -+ -+ /* Force an assert as it is invalid to call this function. */ -+ configASSERT( pv == NULL ); -+} -+/*-----------------------------------------------------------*/ -+ -+void vPortInitialiseBlocks( void ) -+{ -+ /* Only required when static memory is not cleared. */ -+ xNextFreeByte = ( size_t ) 0; -+} -+/*-----------------------------------------------------------*/ -+ -+size_t xPortGetFreeHeapSize( void ) -+{ -+ return( configADJUSTED_HEAP_SIZE - xNextFreeByte ); -+} -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_2.c b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_2.c -new file mode 100644 -index 0000000000..00a68b26b4 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_2.c -@@ -0,0 +1,277 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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 -+ * -+ */ -+ -+/* -+ * A sample implementation of pvPortMalloc() and vPortFree() that permits -+ * allocated blocks to be freed, but does not combine adjacent free blocks -+ * into a single larger block (and so will fragment memory). See heap_4.c for -+ * an equivalent that does combine adjacent blocks into single larger blocks. -+ * -+ * See heap_1.c, heap_3.c and heap_4.c for alternative implementations, and the -+ * memory management pages of https://www.FreeRTOS.org for more information. -+ */ -+#include -+ -+#include "FreeRTOS.h" -+#include "task.h" -+ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) -+ #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0 -+#endif -+ -+/* A few bytes might be lost to byte aligning the heap start address. */ -+#define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) -+ -+/* -+ * Initialises the heap structures before their first use. -+ */ -+static void prvHeapInit( void ); -+ -+/* 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[ configTOTAL_HEAP_SIZE ]; -+#else -+ static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; -+#endif /* configAPPLICATION_ALLOCATED_HEAP */ -+ -+ -+/* Define the linked list structure. This is used to link free blocks in order -+ * of their size. */ -+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; -+ -+ -+static const uint16_t heapSTRUCT_SIZE = ( ( sizeof( BlockLink_t ) + ( portBYTE_ALIGNMENT - 1 ) ) & ~portBYTE_ALIGNMENT_MASK ); -+#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( heapSTRUCT_SIZE * 2 ) ) -+ -+/* Create a couple of list links to mark the start and end of the list. */ -+static BlockLink_t xStart, xEnd; -+ -+/* Keeps track of the number of free bytes remaining, but says nothing about -+ * fragmentation. */ -+static size_t xFreeBytesRemaining = configADJUSTED_HEAP_SIZE; -+ -+/* STATIC FUNCTIONS ARE DEFINED AS MACROS TO MINIMIZE THE FUNCTION CALL DEPTH. */ -+ -+/* -+ * Insert a block into the list of free blocks - which is ordered by size of -+ * the block. Small blocks at the start of the list and large blocks at the end -+ * of the list. -+ */ -+#define prvInsertBlockIntoFreeList( pxBlockToInsert ) \ -+ { \ -+ BlockLink_t * pxIterator; \ -+ size_t xBlockSize; \ -+ \ -+ xBlockSize = pxBlockToInsert->xBlockSize; \ -+ \ -+ /* Iterate through the list until a block is found that has a larger size */ \ -+ /* than the block we are inserting. */ \ -+ for( pxIterator = &xStart; pxIterator->pxNextFreeBlock->xBlockSize < xBlockSize; pxIterator = pxIterator->pxNextFreeBlock ) \ -+ { \ -+ /* There is nothing to do here - just iterate to the correct position. */ \ -+ } \ -+ \ -+ /* Update the list to include the block being inserted in the correct */ \ -+ /* position. */ \ -+ pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; \ -+ pxIterator->pxNextFreeBlock = pxBlockToInsert; \ -+ } -+/*-----------------------------------------------------------*/ -+ -+void * pvPortMalloc( size_t xWantedSize ) -+{ -+ BlockLink_t * pxBlock, * pxPreviousBlock, * pxNewBlockLink; -+ static BaseType_t xHeapHasBeenInitialised = pdFALSE; -+ void * pvReturn = NULL; -+ -+ vTaskSuspendAll(); -+ { -+ /* If this is the first call to malloc then the heap will require -+ * initialisation to setup the list of free blocks. */ -+ if( xHeapHasBeenInitialised == pdFALSE ) -+ { -+ prvHeapInit(); -+ xHeapHasBeenInitialised = pdTRUE; -+ } -+ -+ /* The wanted size must be increased so it can contain a BlockLink_t -+ * structure in addition to the requested amount of bytes. */ -+ if( ( xWantedSize > 0 ) && -+ ( ( xWantedSize + heapSTRUCT_SIZE ) > xWantedSize ) ) /* Overflow check */ -+ { -+ xWantedSize += heapSTRUCT_SIZE; -+ -+ /* Byte alignment required. Check for overflow. */ -+ if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) ) -+ > xWantedSize ) -+ { -+ xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); -+ configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 ); -+ } -+ else -+ { -+ xWantedSize = 0; -+ } -+ } -+ else -+ { -+ xWantedSize = 0; -+ } -+ -+ -+ if( ( xWantedSize > 0 ) && ( xWantedSize <= xFreeBytesRemaining ) ) -+ { -+ /* Blocks are stored in byte order - traverse the list from the start -+ * (smallest) 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 we found the end marker then a block of adequate size was not found. */ -+ if( pxBlock != &xEnd ) -+ { -+ /* Return the memory space - jumping over the BlockLink_t structure -+ * at its start. */ -+ pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE ); -+ -+ /* 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 ) > heapMINIMUM_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 ); -+ -+ /* 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. */ -+ prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); -+ } -+ -+ xFreeBytesRemaining -= pxBlock->xBlockSize; -+ } -+ } -+ -+ } -+ ( void ) xTaskResumeAll(); -+ -+ #if ( configUSE_MALLOC_FAILED_HOOK == 1 ) -+ { -+ if( pvReturn == NULL ) -+ { -+ extern void vApplicationMallocFailedHook( void ); -+ vApplicationMallocFailedHook(); -+ } -+ } -+ #endif -+ -+ 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 -= heapSTRUCT_SIZE; -+ -+ /* This unexpected casting is to keep some compilers from issuing -+ * byte alignment warnings. */ -+ pxLink = ( void * ) puc; -+ -+ vTaskSuspendAll(); -+ { -+ /* Add this block to the list of free blocks. */ -+ prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); -+ xFreeBytesRemaining += pxLink->xBlockSize; -+ } -+ ( void ) xTaskResumeAll(); -+ } -+} -+/*-----------------------------------------------------------*/ -+ -+size_t xPortGetFreeHeapSize( void ) -+{ -+ return xFreeBytesRemaining; -+} -+/*-----------------------------------------------------------*/ -+ -+void vPortInitialiseBlocks( void ) -+{ -+ /* This just exists to keep the linker quiet. */ -+} -+/*-----------------------------------------------------------*/ -+ -+static void prvHeapInit( void ) -+{ -+ BlockLink_t * pxFirstFreeBlock; -+ uint8_t * pucAlignedHeap; -+ -+ /* Ensure the heap starts on a correctly aligned boundary. */ -+ pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) & ucHeap[ portBYTE_ALIGNMENT - 1 ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); -+ -+ /* 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; -+ -+ /* xEnd is used to mark the end of the list of free blocks. */ -+ xEnd.xBlockSize = configADJUSTED_HEAP_SIZE; -+ xEnd.pxNextFreeBlock = NULL; -+ -+ /* To start with there is a single free block that is sized to take up the -+ * entire heap space. */ -+ pxFirstFreeBlock = ( void * ) pucAlignedHeap; -+ pxFirstFreeBlock->xBlockSize = configADJUSTED_HEAP_SIZE; -+ pxFirstFreeBlock->pxNextFreeBlock = &xEnd; -+} -+/*-----------------------------------------------------------*/ -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_3.c b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_3.c -new file mode 100644 -index 0000000000..7cdd9bb18a ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_3.c -@@ -0,0 +1,78 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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 pvPortMalloc() and vPortFree() that relies on the -+ * compilers own malloc() and free() implementations. -+ * -+ * This file can only be used if the linker is configured to to generate -+ * a heap memory area. -+ * -+ * See heap_1.c, heap_2.c and heap_4.c for alternative implementations, and the -+ * memory management pages of https://www.FreeRTOS.org for more information. -+ */ -+ -+#include -+ -+#include "FreeRTOS.h" -+#include "task.h" -+ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) -+ #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0 -+#endif -+ -+/*-----------------------------------------------------------*/ -+ -+void * pvPortMalloc( size_t xWantedSize ) -+{ -+ void * pvReturn; -+ -+ pvReturn = RT_KERNEL_MALLOC( xWantedSize ); -+ -+ #if ( configUSE_MALLOC_FAILED_HOOK == 1 ) -+ { -+ if( pvReturn == NULL ) -+ { -+ extern void vApplicationMallocFailedHook( void ); -+ vApplicationMallocFailedHook(); -+ } -+ } -+ #endif -+ -+ return pvReturn; -+} -+/*-----------------------------------------------------------*/ -+ -+void vPortFree( void * pv ) -+{ -+ if( pv ) -+ { -+ RT_KERNEL_FREE( pv ); -+ } -+} -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_4.c b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_4.c -new file mode 100644 -index 0000000000..53536b7025 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_4.c -@@ -0,0 +1,447 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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 -+ * -+ */ -+ -+/* -+ * A sample implementation of pvPortMalloc() and vPortFree() that combines -+ * (coalescences) adjacent memory blocks as they are freed, and in so doing -+ * limits memory fragmentation. -+ * -+ * See heap_1.c, heap_2.c and heap_3.c for alternative implementations, and the -+ * memory management pages of https://www.FreeRTOS.org for more information. -+ */ -+#include -+ -+#include "FreeRTOS.h" -+#include "task.h" -+ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) -+ #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0 -+#endif -+ -+/* Block sizes must not get too small. */ -+#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) ) -+ -+/* Assumes 8bit bytes! */ -+#define heapBITS_PER_BYTE ( ( size_t ) 8 ) -+ -+/* 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[ configTOTAL_HEAP_SIZE ]; -+#else -+ static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; -+#endif /* configAPPLICATION_ALLOCATED_HEAP */ -+ -+/* Define 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; -+ -+/*-----------------------------------------------------------*/ -+ -+/* -+ * 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. -+ */ -+static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ); -+ -+/* -+ * Called automatically to setup the required heap structures the first time -+ * pvPortMalloc() is called. -+ */ -+static void prvHeapInit( void ); -+ -+/*-----------------------------------------------------------*/ -+ -+/* 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 ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); -+ -+/* Create a couple of list links to mark the start and end of the list. */ -+static BlockLink_t xStart, * pxEnd = NULL; -+ -+/* Keeps track of the number of calls to allocate and free memory as well as the -+ * number of free bytes remaining, but says nothing about fragmentation. */ -+static size_t xFreeBytesRemaining = 0U; -+static size_t xMinimumEverFreeBytesRemaining = 0U; -+static size_t xNumberOfSuccessfulAllocations = 0; -+static size_t xNumberOfSuccessfulFrees = 0; -+ -+/* Gets set to the top bit of an size_t type. When this bit in 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. */ -+static size_t xBlockAllocatedBit = 0; -+ -+/*-----------------------------------------------------------*/ -+ -+void * pvPortMalloc( size_t xWantedSize ) -+{ -+ BlockLink_t * pxBlock, * pxPreviousBlock, * pxNewBlockLink; -+ void * pvReturn = NULL; -+ -+ vTaskSuspendAll(); -+ { -+ /* 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(); -+ } -+ -+ /* 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( ( xWantedSize & xBlockAllocatedBit ) == 0 ) -+ { -+ /* The wanted size must be increased so it can contain a BlockLink_t -+ * structure in addition to the requested amount of bytes. */ -+ if( ( xWantedSize > 0 ) && -+ ( ( xWantedSize + xHeapStructSize ) > xWantedSize ) ) /* Overflow check */ -+ { -+ xWantedSize += xHeapStructSize; -+ -+ /* Ensure that blocks are always aligned. */ -+ if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) -+ { -+ /* Byte alignment required. Check for overflow. */ -+ if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) ) -+ > xWantedSize ) -+ { -+ xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); -+ configASSERT( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) == 0 ); -+ } -+ else -+ { -+ xWantedSize = 0; -+ } -+ } -+ } -+ else -+ { -+ 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 ) > heapMINIMUM_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 ); -+ configASSERT( ( ( ( size_t ) pxNewBlockLink ) & portBYTE_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. */ -+ prvInsertBlockIntoFreeList( pxNewBlockLink ); -+ } -+ -+ xFreeBytesRemaining -= pxBlock->xBlockSize; -+ -+ if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) -+ { -+ xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; -+ } -+ -+ /* The block is being returned - it is allocated and owned -+ * by the application and has no "next" block. */ -+ pxBlock->xBlockSize |= xBlockAllocatedBit; -+ pxBlock->pxNextFreeBlock = NULL; -+ xNumberOfSuccessfulAllocations++; -+ } -+ } -+ } -+ -+ } -+ ( void ) xTaskResumeAll(); -+ -+ #if ( configUSE_MALLOC_FAILED_HOOK == 1 ) -+ { -+ if( pvReturn == NULL ) -+ { -+ extern void vApplicationMallocFailedHook( void ); -+ vApplicationMallocFailedHook(); -+ } -+ } -+ #endif /* if ( configUSE_MALLOC_FAILED_HOOK == 1 ) */ -+ -+ configASSERT( ( ( ( size_t ) pvReturn ) & ( size_t ) portBYTE_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. */ -+ configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); -+ configASSERT( pxLink->pxNextFreeBlock == NULL ); -+ -+ if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) -+ { -+ if( pxLink->pxNextFreeBlock == NULL ) -+ { -+ /* The block is being returned to the heap - it is no longer -+ * allocated. */ -+ pxLink->xBlockSize &= ~xBlockAllocatedBit; -+ -+ vTaskSuspendAll(); -+ { -+ /* Add this block to the list of free blocks. */ -+ xFreeBytesRemaining += pxLink->xBlockSize; -+ prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); -+ xNumberOfSuccessfulFrees++; -+ } -+ ( void ) xTaskResumeAll(); -+ } -+ } -+ } -+} -+/*-----------------------------------------------------------*/ -+ -+size_t xPortGetFreeHeapSize( void ) -+{ -+ return xFreeBytesRemaining; -+} -+/*-----------------------------------------------------------*/ -+ -+size_t xPortGetMinimumEverFreeHeapSize( void ) -+{ -+ return xMinimumEverFreeBytesRemaining; -+} -+/*-----------------------------------------------------------*/ -+ -+void vPortInitialiseBlocks( void ) -+{ -+ /* This just exists to keep the linker quiet. */ -+} -+/*-----------------------------------------------------------*/ -+ -+static void prvHeapInit( void ) /* PRIVILEGED_FUNCTION */ -+{ -+ BlockLink_t * pxFirstFreeBlock; -+ uint8_t * pucAlignedHeap; -+ size_t uxAddress; -+ size_t xTotalHeapSize = configTOTAL_HEAP_SIZE; -+ -+ /* Ensure the heap starts on a correctly aligned boundary. */ -+ uxAddress = ( size_t ) ucHeap; -+ -+ if( ( uxAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) -+ { -+ uxAddress += ( portBYTE_ALIGNMENT - 1 ); -+ uxAddress &= ~( ( size_t ) portBYTE_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 ) portBYTE_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; -+ -+ /* Work out the position of the top bit in a size_t variable. */ -+ xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ); -+} -+/*-----------------------------------------------------------*/ -+ -+static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ) /* PRIVILEGED_FUNCTION */ -+{ -+ 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; -+ } -+ -+ /* 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 gab, 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; -+ } -+} -+/*-----------------------------------------------------------*/ -+ -+void vPortGetHeapStats( HeapStats_t * pxHeapStats ) -+{ -+ BlockLink_t * pxBlock; -+ size_t xBlocks = 0, xMaxSize = 0, xMinSize = portMAX_DELAY; /* portMAX_DELAY used as a portable way of getting the maximum value. */ -+ -+ vTaskSuspendAll(); -+ { -+ pxBlock = xStart.pxNextFreeBlock; -+ -+ /* pxBlock will be NULL if the heap has not been initialised. The heap -+ * is initialised automatically when the first allocation is made. */ -+ if( pxBlock != NULL ) -+ { -+ do -+ { -+ /* Increment the number of blocks and record the largest block seen -+ * so far. */ -+ xBlocks++; -+ -+ if( pxBlock->xBlockSize > xMaxSize ) -+ { -+ xMaxSize = pxBlock->xBlockSize; -+ } -+ -+ if( pxBlock->xBlockSize < xMinSize ) -+ { -+ xMinSize = pxBlock->xBlockSize; -+ } -+ -+ /* Move to the next block in the chain until the last block is -+ * reached. */ -+ pxBlock = pxBlock->pxNextFreeBlock; -+ } while( pxBlock != pxEnd ); -+ } -+ } -+ ( void ) xTaskResumeAll(); -+ -+ pxHeapStats->xSizeOfLargestFreeBlockInBytes = xMaxSize; -+ pxHeapStats->xSizeOfSmallestFreeBlockInBytes = xMinSize; -+ pxHeapStats->xNumberOfFreeBlocks = xBlocks; -+ -+ taskENTER_CRITICAL(); -+ { -+ pxHeapStats->xAvailableHeapSpaceInBytes = xFreeBytesRemaining; -+ pxHeapStats->xNumberOfSuccessfulAllocations = xNumberOfSuccessfulAllocations; -+ pxHeapStats->xNumberOfSuccessfulFrees = xNumberOfSuccessfulFrees; -+ pxHeapStats->xMinimumEverFreeBytesRemaining = xMinimumEverFreeBytesRemaining; -+ } -+ taskEXIT_CRITICAL(); -+} -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_5.c b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_5.c -new file mode 100644 -index 0000000000..7fadbd4b0f ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/MemMang/heap_5.c -@@ -0,0 +1,506 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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 -+ * -+ */ -+ -+/* -+ * A sample implementation of pvPortMalloc() that allows the heap to be defined -+ * across multiple non-contigous blocks and combines (coalescences) adjacent -+ * memory blocks as they are freed. -+ * -+ * See heap_1.c, heap_2.c, heap_3.c and heap_4.c for alternative -+ * implementations, and the memory management pages of https://www.FreeRTOS.org -+ * for more information. -+ * -+ * Usage notes: -+ * -+ * vPortDefineHeapRegions() ***must*** be called before pvPortMalloc(). -+ * pvPortMalloc() will be called if any task objects (tasks, queues, event -+ * groups, etc.) are created, therefore vPortDefineHeapRegions() ***must*** be -+ * called before any other objects are defined. -+ * -+ * vPortDefineHeapRegions() takes a single parameter. The parameter is an array -+ * of HeapRegion_t structures. HeapRegion_t is defined in portable.h as -+ * -+ * typedef struct HeapRegion -+ * { -+ * uint8_t *pucStartAddress; << Start address of a block of memory that will be part of the heap. -+ * size_t xSizeInBytes; << Size of the block of memory. -+ * } HeapRegion_t; -+ * -+ * The array is terminated using a NULL zero sized region definition, and the -+ * memory regions defined in the array ***must*** appear in address order from -+ * low address to high address. So the following is a valid example of how -+ * to use the function. -+ * -+ * HeapRegion_t xHeapRegions[] = -+ * { -+ * { ( uint8_t * ) 0x80000000UL, 0x10000 }, << Defines a block of 0x10000 bytes starting at address 0x80000000 -+ * { ( uint8_t * ) 0x90000000UL, 0xa0000 }, << Defines a block of 0xa0000 bytes starting at address of 0x90000000 -+ * { NULL, 0 } << Terminates the array. -+ * }; -+ * -+ * vPortDefineHeapRegions( xHeapRegions ); << Pass the array into vPortDefineHeapRegions(). -+ * -+ * Note 0x80000000 is the lower address so appears in the array first. -+ * -+ */ -+#include -+ -+#include "FreeRTOS.h" -+#include "task.h" -+ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) -+ #error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0 -+#endif -+ -+/* Block sizes must not get too small. */ -+#define heapMINIMUM_BLOCK_SIZE ( ( size_t ) ( xHeapStructSize << 1 ) ) -+ -+/* Assumes 8bit bytes! */ -+#define heapBITS_PER_BYTE ( ( size_t ) 8 ) -+ -+/* Define 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; -+ -+/*-----------------------------------------------------------*/ -+ -+/* -+ * 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. -+ */ -+static void prvInsertBlockIntoFreeList( BlockLink_t * pxBlockToInsert ); -+ -+/*-----------------------------------------------------------*/ -+ -+/* 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 ) ( portBYTE_ALIGNMENT - 1 ) ) ) & ~( ( size_t ) portBYTE_ALIGNMENT_MASK ); -+ -+/* Create a couple of list links to mark the start and end of the list. */ -+static BlockLink_t xStart, * pxEnd = NULL; -+ -+/* Keeps track of the number of calls to allocate and free memory as well as the -+ * number of free bytes remaining, but says nothing about fragmentation. */ -+static size_t xFreeBytesRemaining = 0U; -+static size_t xMinimumEverFreeBytesRemaining = 0U; -+static size_t xNumberOfSuccessfulAllocations = 0; -+static size_t xNumberOfSuccessfulFrees = 0; -+ -+/* Gets set to the top bit of an size_t type. When this bit in 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. */ -+static size_t xBlockAllocatedBit = 0; -+ -+/*-----------------------------------------------------------*/ -+ -+void * pvPortMalloc( size_t xWantedSize ) -+{ -+ BlockLink_t * pxBlock, * pxPreviousBlock, * pxNewBlockLink; -+ void * pvReturn = NULL; -+ -+ /* The heap must be initialised before the first call to -+ * prvPortMalloc(). */ -+ configASSERT( pxEnd ); -+ -+ vTaskSuspendAll(); -+ { -+ /* 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( ( xWantedSize & xBlockAllocatedBit ) == 0 ) -+ { -+ /* The wanted size is increased so it can contain a BlockLink_t -+ * structure in addition to the requested amount of bytes. */ -+ if( ( xWantedSize > 0 ) && -+ ( ( xWantedSize + xHeapStructSize ) > xWantedSize ) ) /* Overflow check */ -+ { -+ xWantedSize += xHeapStructSize; -+ -+ /* Ensure that blocks are always aligned */ -+ if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0x00 ) -+ { -+ /* Byte alignment required. Check for overflow */ -+ if( ( xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ) ) > -+ xWantedSize ) -+ { -+ xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); -+ } -+ else -+ { -+ xWantedSize = 0; -+ } -+ } -+ } -+ else -+ { -+ 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 ) > heapMINIMUM_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 ); -+ -+ /* 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. */ -+ prvInsertBlockIntoFreeList( ( pxNewBlockLink ) ); -+ } -+ -+ xFreeBytesRemaining -= pxBlock->xBlockSize; -+ -+ if( xFreeBytesRemaining < xMinimumEverFreeBytesRemaining ) -+ { -+ xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; -+ } -+ -+ /* The block is being returned - it is allocated and owned -+ * by the application and has no "next" block. */ -+ pxBlock->xBlockSize |= xBlockAllocatedBit; -+ pxBlock->pxNextFreeBlock = NULL; -+ xNumberOfSuccessfulAllocations++; -+ } -+ } -+ } -+ -+ } -+ ( void ) xTaskResumeAll(); -+ -+ #if ( configUSE_MALLOC_FAILED_HOOK == 1 ) -+ { -+ if( pvReturn == NULL ) -+ { -+ extern void vApplicationMallocFailedHook( void ); -+ vApplicationMallocFailedHook(); -+ } -+ } -+ #endif /* if ( configUSE_MALLOC_FAILED_HOOK == 1 ) */ -+ -+ 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. */ -+ configASSERT( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ); -+ configASSERT( pxLink->pxNextFreeBlock == NULL ); -+ -+ if( ( pxLink->xBlockSize & xBlockAllocatedBit ) != 0 ) -+ { -+ if( pxLink->pxNextFreeBlock == NULL ) -+ { -+ /* The block is being returned to the heap - it is no longer -+ * allocated. */ -+ pxLink->xBlockSize &= ~xBlockAllocatedBit; -+ -+ vTaskSuspendAll(); -+ { -+ /* Add this block to the list of free blocks. */ -+ xFreeBytesRemaining += pxLink->xBlockSize; -+ prvInsertBlockIntoFreeList( ( ( BlockLink_t * ) pxLink ) ); -+ xNumberOfSuccessfulFrees++; -+ } -+ ( void ) xTaskResumeAll(); -+ } -+ } -+ } -+} -+/*-----------------------------------------------------------*/ -+ -+size_t xPortGetFreeHeapSize( void ) -+{ -+ return xFreeBytesRemaining; -+} -+/*-----------------------------------------------------------*/ -+ -+size_t xPortGetMinimumEverFreeHeapSize( void ) -+{ -+ return xMinimumEverFreeBytesRemaining; -+} -+/*-----------------------------------------------------------*/ -+ -+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; -+ } -+ -+ /* 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 gab, 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; -+ } -+} -+/*-----------------------------------------------------------*/ -+ -+void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ) -+{ -+ BlockLink_t * pxFirstFreeBlockInRegion = NULL, * pxPreviousFreeBlock; -+ size_t xAlignedHeap; -+ size_t xTotalRegionSize, xTotalHeapSize = 0; -+ BaseType_t xDefinedRegions = 0; -+ size_t xAddress; -+ const HeapRegion_t * pxHeapRegion; -+ -+ /* Can only call once! */ -+ configASSERT( pxEnd == NULL ); -+ -+ pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] ); -+ -+ while( pxHeapRegion->xSizeInBytes > 0 ) -+ { -+ xTotalRegionSize = pxHeapRegion->xSizeInBytes; -+ -+ /* Ensure the heap region starts on a correctly aligned boundary. */ -+ xAddress = ( size_t ) pxHeapRegion->pucStartAddress; -+ -+ if( ( xAddress & portBYTE_ALIGNMENT_MASK ) != 0 ) -+ { -+ xAddress += ( portBYTE_ALIGNMENT - 1 ); -+ xAddress &= ~portBYTE_ALIGNMENT_MASK; -+ -+ /* Adjust the size for the bytes lost to alignment. */ -+ xTotalRegionSize -= xAddress - ( size_t ) pxHeapRegion->pucStartAddress; -+ } -+ -+ xAlignedHeap = xAddress; -+ -+ /* Set xStart if it has not already been set. */ -+ if( xDefinedRegions == 0 ) -+ { -+ /* 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 = ( BlockLink_t * ) xAlignedHeap; -+ xStart.xBlockSize = ( size_t ) 0; -+ } -+ else -+ { -+ /* Should only get here if one region has already been added to the -+ * heap. */ -+ configASSERT( pxEnd != NULL ); -+ -+ /* Check blocks are passed in with increasing start addresses. */ -+ configASSERT( xAddress > ( size_t ) pxEnd ); -+ } -+ -+ /* Remember the location of the end marker in the previous region, if -+ * any. */ -+ pxPreviousFreeBlock = pxEnd; -+ -+ /* pxEnd is used to mark the end of the list of free blocks and is -+ * inserted at the end of the region space. */ -+ xAddress = xAlignedHeap + xTotalRegionSize; -+ xAddress -= xHeapStructSize; -+ xAddress &= ~portBYTE_ALIGNMENT_MASK; -+ pxEnd = ( BlockLink_t * ) xAddress; -+ pxEnd->xBlockSize = 0; -+ pxEnd->pxNextFreeBlock = NULL; -+ -+ /* To start with there is a single free block in this region that is -+ * sized to take up the entire heap region minus the space taken by the -+ * free block structure. */ -+ pxFirstFreeBlockInRegion = ( BlockLink_t * ) xAlignedHeap; -+ pxFirstFreeBlockInRegion->xBlockSize = xAddress - ( size_t ) pxFirstFreeBlockInRegion; -+ pxFirstFreeBlockInRegion->pxNextFreeBlock = pxEnd; -+ -+ /* If this is not the first region that makes up the entire heap space -+ * then link the previous region to this region. */ -+ if( pxPreviousFreeBlock != NULL ) -+ { -+ pxPreviousFreeBlock->pxNextFreeBlock = pxFirstFreeBlockInRegion; -+ } -+ -+ xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize; -+ -+ /* Move onto the next HeapRegion_t structure. */ -+ xDefinedRegions++; -+ pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] ); -+ } -+ -+ xMinimumEverFreeBytesRemaining = xTotalHeapSize; -+ xFreeBytesRemaining = xTotalHeapSize; -+ -+ /* Check something was actually defined before it is accessed. */ -+ configASSERT( xTotalHeapSize ); -+ -+ /* Work out the position of the top bit in a size_t variable. */ -+ xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 ); -+} -+/*-----------------------------------------------------------*/ -+ -+void vPortGetHeapStats( HeapStats_t * pxHeapStats ) -+{ -+ BlockLink_t * pxBlock; -+ size_t xBlocks = 0, xMaxSize = 0, xMinSize = portMAX_DELAY; /* portMAX_DELAY used as a portable way of getting the maximum value. */ -+ -+ vTaskSuspendAll(); -+ { -+ pxBlock = xStart.pxNextFreeBlock; -+ -+ /* pxBlock will be NULL if the heap has not been initialised. The heap -+ * is initialised automatically when the first allocation is made. */ -+ if( pxBlock != NULL ) -+ { -+ do -+ { -+ /* Increment the number of blocks and record the largest block seen -+ * so far. */ -+ xBlocks++; -+ -+ if( pxBlock->xBlockSize > xMaxSize ) -+ { -+ xMaxSize = pxBlock->xBlockSize; -+ } -+ -+ /* Heap five will have a zero sized block at the end of each -+ * each region - the block is only used to link to the next -+ * heap region so it not a real block. */ -+ if( pxBlock->xBlockSize != 0 ) -+ { -+ if( pxBlock->xBlockSize < xMinSize ) -+ { -+ xMinSize = pxBlock->xBlockSize; -+ } -+ } -+ -+ /* Move to the next block in the chain until the last block is -+ * reached. */ -+ pxBlock = pxBlock->pxNextFreeBlock; -+ } while( pxBlock != pxEnd ); -+ } -+ } -+ ( void ) xTaskResumeAll(); -+ -+ pxHeapStats->xSizeOfLargestFreeBlockInBytes = xMaxSize; -+ pxHeapStats->xSizeOfSmallestFreeBlockInBytes = xMinSize; -+ pxHeapStats->xNumberOfFreeBlocks = xBlocks; -+ -+ taskENTER_CRITICAL(); -+ { -+ pxHeapStats->xAvailableHeapSpaceInBytes = xFreeBytesRemaining; -+ pxHeapStats->xNumberOfSuccessfulAllocations = xNumberOfSuccessfulAllocations; -+ pxHeapStats->xNumberOfSuccessfulFrees = xNumberOfSuccessfulFrees; -+ pxHeapStats->xMinimumEverFreeBytesRemaining = xMinimumEverFreeBytesRemaining; -+ } -+ taskEXIT_CRITICAL(); -+} -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/port_common.c b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/port_common.c -new file mode 100644 -index 0000000000..9d8159f588 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/port_common.c -@@ -0,0 +1,203 @@ -+/* -+ * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD -+ * -+ * SPDX-License-Identifier: Apache-2.0 -+ */ -+ -+#include -+#include "FreeRTOS.h" -+#include "task.h" -+#include "portmacro.h" -+#include "esp_system.h" -+#include "esp_heap_caps_init.h" -+#include "esp_int_wdt.h" -+#include "esp_task_wdt.h" -+#include "esp_task.h" -+#include "esp_private/crosscore_int.h" -+#include "esp_private/startup_internal.h" /* Required by g_spiram_ok. [refactor-todo] for g_spiram_ok */ -+#include "esp_log.h" -+#include "soc/soc_memory_types.h" -+#include "soc/dport_access.h" -+#include "sdkconfig.h" -+ -+#if CONFIG_IDF_TARGET_ESP32 -+#include "esp32/spiram.h" -+#elif CONFIG_IDF_TARGET_ESP32S2 -+#include "esp32s2/spiram.h" -+#elif CONFIG_IDF_TARGET_ESP32S3 -+#include "esp32s3/spiram.h" -+#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2 -+// SPIRAM is not supported on ESP32-C3 -+#endif -+ -+#if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL -+static const char* TAG = "cpu_start"; -+#endif -+ -+/* Architecture-agnostic parts of the FreeRTOS ESP-IDF port layer can go here. -+ * -+ * The actual call flow will be to call esp_startup_start_app() in /port.c, -+ * which will then call esp_startup_start_app_common() -+ */ -+ -+// Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting -+volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; -+ -+// For now, running FreeRTOS on one core and a bare metal on the other (or other OSes) -+// is not supported. For now CONFIG_FREERTOS_UNICORE and CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE -+// should mirror each other's values. -+// -+// And since this should be true, we can just check for CONFIG_FREERTOS_UNICORE. -+#if CONFIG_FREERTOS_UNICORE != CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE -+ #error "FreeRTOS and system configuration mismatch regarding the use of multiple cores." -+#endif -+ -+static void main_task(void* args); -+ -+#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME -+void esp_gdbstub_init(void); -+#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME -+ -+extern void app_main(void); -+ -+void esp_startup_start_app_common(void) -+{ -+#if CONFIG_ESP_INT_WDT -+ esp_int_wdt_init(); -+ //Initialize the interrupt watch dog for CPU0. -+ esp_int_wdt_cpu_init(); -+#endif -+ -+ esp_crosscore_int_init(); -+ -+#ifdef CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME -+ esp_gdbstub_init(); -+#endif // CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME -+ -+#ifdef CONFIG_IDF_RTOS_RTTHREAD -+ app_main(); -+#else -+ portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main", -+ ESP_TASK_MAIN_STACK, NULL, -+ ESP_TASK_MAIN_PRIO, NULL, ESP_TASK_MAIN_CORE); -+ assert(res == pdTRUE); -+ (void)res; -+#endif -+ -+} -+ -+static void main_task(void* args) -+{ -+#if !CONFIG_FREERTOS_UNICORE -+ // Wait for FreeRTOS initialization to finish on APP CPU, before replacing its startup stack -+ while (port_xSchedulerRunning[1] == 0) { -+ ; -+ } -+#endif -+ -+ // [refactor-todo] check if there is a way to move the following block to esp_system startup -+ heap_caps_enable_nonos_stack_heaps(); -+ -+ // Now we have startup stack RAM available for heap, enable any DMA pool memory -+#if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL -+ if (g_spiram_ok) { -+ esp_err_t r = esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL); -+ if (r != ESP_OK) { -+ ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool (error 0x%x)", r); -+ abort(); -+ } -+ } -+#endif -+ -+ //Initialize task wdt if configured to do so -+#ifdef CONFIG_ESP_TASK_WDT_PANIC -+ ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, true)); -+#elif CONFIG_ESP_TASK_WDT -+ ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false)); -+#endif -+ -+ //Add IDLE 0 to task wdt -+#ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 -+ TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0); -+ if(idle_0 != NULL){ -+ ESP_ERROR_CHECK(esp_task_wdt_add(idle_0)); -+ } -+#endif -+ //Add IDLE 1 to task wdt -+#ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 -+ TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1); -+ if(idle_1 != NULL){ -+ ESP_ERROR_CHECK(esp_task_wdt_add(idle_1)); -+ } -+#endif -+ -+ app_main(); -+ vTaskDelete(NULL); -+} -+ -+// -------------------- Heap Related ----------------------- -+ -+bool xPortCheckValidTCBMem(const void *ptr) -+{ -+ return esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr); -+} -+ -+bool xPortcheckValidStackMem(const void *ptr) -+{ -+#ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY -+ return esp_ptr_byte_accessible(ptr); -+#else -+ return esp_ptr_internal(ptr) && esp_ptr_byte_accessible(ptr); -+#endif -+} -+ -+// ------------- FreeRTOS Static Allocation ---------------- -+ -+/* -+This function is required by FreeRTOS when configSUPPORT_STATIC_ALLOCATION is -+enabled and is used by FreeRTOS to obtain memory for its IDLE tasks. -+ -+Like the pvPortMallocTcbMem() and pvPortMallocStackMem() macros, TCB and stack -+memory MUST be placed in internal RAM. -+*/ -+void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer, -+ StackType_t **ppxIdleTaskStackBuffer, -+ uint32_t *pulIdleTaskStackSize ) -+{ -+ StaticTask_t *pxTCBBufferTemp; -+ StackType_t *pxStackBufferTemp; -+ //Allocate TCB and stack buffer in internal memory -+ pxTCBBufferTemp = pvPortMallocTcbMem(sizeof(StaticTask_t)); -+ pxStackBufferTemp = pvPortMallocStackMem(configIDLE_TASK_STACK_SIZE); -+ assert(pxTCBBufferTemp != NULL); -+ assert(pxStackBufferTemp != NULL); -+ //Write back pointers -+ *ppxIdleTaskTCBBuffer = pxTCBBufferTemp; -+ *ppxIdleTaskStackBuffer = pxStackBufferTemp; -+ *pulIdleTaskStackSize = configIDLE_TASK_STACK_SIZE; -+} -+ -+/* -+This function is required by FreeRTOS when configSUPPORT_STATIC_ALLOCATION is -+enabled and is used by the FreeRTOS Timer to obtain memory for its daemone task. -+ -+ -+Like the pvPortMallocTcbMem() and pvPortMallocStackMem() macros, TCB and stack -+memory MUST be placed in internal RAM. -+*/ -+void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer, -+ StackType_t **ppxTimerTaskStackBuffer, -+ uint32_t *pulTimerTaskStackSize ) -+{ -+ StaticTask_t *pxTCBBufferTemp; -+ StackType_t *pxStackBufferTemp; -+ //Allocate TCB and stack buffer in internal memory -+ pxTCBBufferTemp = pvPortMallocTcbMem(sizeof(StaticTask_t)); -+ pxStackBufferTemp = pvPortMallocStackMem(configTIMER_TASK_STACK_DEPTH); -+ assert(pxTCBBufferTemp != NULL); -+ assert(pxStackBufferTemp != NULL); -+ //Write back pointers -+ *ppxTimerTaskTCBBuffer = pxTCBBufferTemp; -+ *ppxTimerTaskStackBuffer = pxStackBufferTemp; -+ *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; -+} -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/include/freertos/FreeRTOSConfig_arch.h b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/include/freertos/FreeRTOSConfig_arch.h -new file mode 100644 -index 0000000000..a7d534343f ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/include/freertos/FreeRTOSConfig_arch.h -@@ -0,0 +1,105 @@ -+/* -+ FreeRTOS V10 - Copyright (C) 2021 Real Time Engineers Ltd. -+ All rights reserved -+ -+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. -+ -+ This file is part of the FreeRTOS distribution. -+ -+ FreeRTOS is free software; you can redistribute it and/or modify it under -+ the terms of the GNU General Public License (version 2) as published by the -+ Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. -+ -+ *************************************************************************** -+ >>! NOTE: The modification to the GPL is included to allow you to !<< -+ >>! distribute a combined work that includes FreeRTOS without being !<< -+ >>! obliged to provide the source code for proprietary components !<< -+ >>! outside of the FreeRTOS kernel. !<< -+ *************************************************************************** -+ -+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY -+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. Full license text is available on the following -+ link: http://www.freertos.org/a00114.html -+ -+ *************************************************************************** -+ * * -+ * FreeRTOS provides completely free yet professionally developed, * -+ * robust, strictly quality controlled, supported, and cross * -+ * platform software that is more than just the market leader, it * -+ * is the industry's de facto standard. * -+ * * -+ * Help yourself get started quickly while simultaneously helping * -+ * to support the FreeRTOS project by purchasing a FreeRTOS * -+ * tutorial book, reference manual, or both: * -+ * http://www.FreeRTOS.org/Documentation * -+ * * -+ *************************************************************************** -+ -+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading -+ the FAQ page "My application does not run, what could be wrong?". Have you -+ defined configASSERT()? -+ -+ http://www.FreeRTOS.org/support - In return for receiving this top quality -+ embedded software for free we request you assist our global community by -+ participating in the support forum. -+ -+ http://www.FreeRTOS.org/training - Investing in training allows your team to -+ be as productive as possible as early as possible. Now you can receive -+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers -+ Ltd, and the world's leading authority on the world's leading RTOS. -+ -+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, -+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS -+ compatible FAT file system, and our tiny thread aware UDP/IP stack. -+ -+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. -+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. -+ -+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High -+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS -+ licenses offer ticketed support, indemnification and commercial middleware. -+ -+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety -+ engineered and independently SIL3 certified version for use in safety and -+ mission critical applications that require provable dependability. -+ -+ 1 tab == 4 spaces! -+*/ -+ -+#ifndef FREERTOS_CONFIG_RISCV_H -+#define FREERTOS_CONFIG_RISCV_H -+ -+// This file is included in the common FreeRTOSConfig.h. -+ -+#include "sdkconfig.h" -+ -+#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 -+ -+#ifndef __ASSEMBLER__ -+#if CONFIG_IDF_TARGET_ESP32C3 -+#include "esp32c3/rom/ets_sys.h" -+#elif CONFIG_IDF_TARGET_ESP32H2 -+#include "esp32h2/rom/ets_sys.h" -+#endif -+#endif // __ASSEMBLER__ -+ -+/* The maximum interrupt priority from which FreeRTOS.org API functions can -+ be called. Only API functions that end in ...FromISR() can be used within -+ interrupts. */ -+#define configMAX_SYSCALL_INTERRUPT_PRIORITY 0 -+ -+#ifndef configISR_STACK_SIZE -+#define configISR_STACK_SIZE (CONFIG_FREERTOS_ISR_STACKSIZE) -+#endif -+ -+#ifndef __ASSEMBLER__ -+#if CONFIG_APPTRACE_SV_ENABLE -+extern int xPortSwitchFlag; -+#define os_task_switch_is_pended(_cpu_) (xPortSwitchFlag) -+#else -+#define os_task_switch_is_pended(_cpu_) (false) -+#endif -+#endif -+ -+#endif // FREERTOS_CONFIG_RISCV_H -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/include/freertos/portmacro.h b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/include/freertos/portmacro.h -new file mode 100644 -index 0000000000..ce683ac301 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/include/freertos/portmacro.h -@@ -0,0 +1,107 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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. */ -+ #define portCHAR char -+ #define portFLOAT float -+ #define portDOUBLE double -+ #define portLONG long -+ #define portSHORT short -+ #define portSTACK_TYPE rt_ubase_t -+ #define portBASE_TYPE rt_base_t -+ -+ typedef portSTACK_TYPE StackType_t; -+ typedef rt_base_t BaseType_t; -+ typedef rt_ubase_t UBaseType_t; -+ typedef rt_tick_t TickType_t; -+ #define portMAX_DELAY ( TickType_t ) RT_TICK_MAX -+ -+ struct rt_semaphore_wrapper -+ { -+ struct rt_semaphore sem; -+ rt_uint16_t max_value; -+ }; -+ -+/*-----------------------------------------------------------*/ -+ -+/* Architecture specifics. */ -+ #define portBYTE_ALIGNMENT RT_ALIGN_SIZE -+ #define portPOINTER_SIZE_TYPE rt_size_t -+/*-----------------------------------------------------------*/ -+ -+/* Scheduler utilities. */ -+ #define portYIELD() rt_thread_yield() -+ #define portYIELD_FROM_ISR( x ) rt_thread_yield() -+ -+/*-----------------------------------------------------------*/ -+ -+/* Critical section management. */ -+ extern void vPortEnterCritical( void ); -+ extern void vPortExitCritical( void ); -+ #define portSET_INTERRUPT_MASK_FROM_ISR() rt_hw_interrupt_disable() -+ #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) rt_hw_interrupt_enable( x ) -+ #define portDISABLE_INTERRUPTS() vPortEnterCritical() -+ #define portENABLE_INTERRUPTS() vPortExitCritical() -+ //#define portENTER_CRITICAL() vPortEnterCritical() -+ //#define portEXIT_CRITICAL() vPortExitCritical() -+ -+/*-----------------------------------------------------------*/ -+ -+/* Use this macro to calculate the buffer size when allocating a queue statically -+ * To ensure the buffer can fit the desired number of messages -+ */ -+ #define QUEUE_BUFFER_SIZE( uxQueueLength, uxItemSize ) ( ( RT_ALIGN( uxItemSize, RT_ALIGN_SIZE ) + sizeof( void * ) ) * uxQueueLength ) -+ -+ BaseType_t rt_err_to_freertos(rt_err_t rt_err); -+ -+/* For ESP32 */ -+ #include "portmacro_esp32c3.h" -+ -+ #ifdef __cplusplus -+ } -+ #endif -+ -+#endif /* PORTMACRO_H */ -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/include/freertos/portmacro_deprecated.h b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/include/freertos/portmacro_deprecated.h -new file mode 100644 -index 0000000000..597d99c333 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/include/freertos/portmacro_deprecated.h -@@ -0,0 +1,94 @@ -+/* -+ * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD -+ * -+ * SPDX-License-Identifier: Apache-2.0 -+ */ -+ -+/* ---------------------------------------------------- Deprecate ------------------------------------------------------ -+ * - Macros or functions that should be deprecated in v5.0, then removed in the next major release -+ * - Kept as not to cause a breaking change -+ * - Include this header at the end of portmacro.h -+ * ------------------------------------------------------------------------------------------------------------------ */ -+ -+/** -+ * @brief Disable interrupts in a nested manner -+ * -+ * Does the exact same thing as portSET_INTERRUPT_MASK_FROM_ISR() -+ * -+ * @deprecated This function is deprecated. Call portSET_INTERRUPT_MASK_FROM_ISR() instead -+ */ -+static inline __attribute__((deprecated)) UBaseType_t portENTER_CRITICAL_NESTED(void) { -+ return portSET_INTERRUPT_MASK_FROM_ISR(); -+} -+ -+/** -+ * @brief Reenables interrupts in a nested manner -+ * -+ * Does the exact same thing as portCLEAR_INTERRUPT_MASK_FROM_ISR() -+ * -+ * @deprecated This function is deprecated. Call portCLEAR_INTERRUPT_MASK_FROM_ISR() instead -+ */ -+static inline void __attribute__((deprecated)) portEXIT_CRITICAL_NESTED(UBaseType_t prev_level) -+{ -+ portCLEAR_INTERRUPT_MASK_FROM_ISR(prev_level); -+} -+ -+/* ---------------------- Spinlocks --------------------- */ -+ -+/** -+ * @brief Deprecated placed holder function to initialize a spinlock -+ * -+ * Currently does nothing. -+ * -+ * @deprecated This function is deprecated. If on multi-core, use spinlock_initialize() instead -+ * @param[in] mux Spinlock -+ */ -+static inline void __attribute__((deprecated)) __attribute__((always_inline)) vPortCPUInitializeMutex(portMUX_TYPE *mux) -+{ -+ (void)mux; -+} -+ -+/** -+ * @brief Deprecated placed holder function to acquire a spinlock -+ * -+ * Currently does nothing. -+ * -+ * @deprecated This function is deprecated. If on multi-core, use spinlock_acquire() instead -+ * @param[in] mux Spinlock -+ */ -+static inline void __attribute__((deprecated)) __attribute__((always_inline)) vPortCPUAcquireMutex(portMUX_TYPE *mux) -+{ -+ (void)mux; -+} -+ -+/** -+ * @brief Deprecated placed holder function to acquire a spinlock but with a specified timeout -+ * -+ * Currently just returns true -+ * -+ * @deprecated This function is deprecated. If on multi-core, use spinlock_acquire() instead -+ * @note Does not have deprecated attribute due to usage in app_trace_util.c -+ * @param[in] mux Spinlock -+ * @param[in] timeout Timeout in number of CPU cycles -+ * @return true Always returns true -+ */ -+static inline bool __attribute__((always_inline)) vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles) -+{ -+ (void)mux; -+ (void)timeout_cycles; -+ return true; -+} -+ -+/** -+ * @brief Deprecated placed holder function to release a spinlock -+ * -+ * Currently does nothing. -+ * -+ * @deprecated This function is deprecated. If on multi-core, use spinlock_release() instead -+ * @note Does not have deprecated attribute due to usage in app_trace_util.c -+ * @param[in] mux Spinlock -+ */ -+static inline void __attribute__((always_inline)) vPortCPUReleaseMutex(portMUX_TYPE *mux) -+{ -+ (void)mux; -+} -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/include/freertos/portmacro_esp32c3.h b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/include/freertos/portmacro_esp32c3.h -new file mode 100644 -index 0000000000..88459bb6a2 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/include/freertos/portmacro_esp32c3.h -@@ -0,0 +1,424 @@ -+/* -+ * FreeRTOS Kernel V10.4.3 -+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. -+ * -+ * 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. -+ * -+ * http://www.FreeRTOS.org -+ * http://aws.amazon.com/freertos -+ * -+ * 1 tab == 4 spaces! -+ */ -+ -+#ifndef PORTMACRO_ESP32C3_H -+#define PORTMACRO_ESP32C3_H -+ -+#ifndef __ASSEMBLER__ -+ -+#include "sdkconfig.h" -+#include -+#include -+#include -+#include -+#include "soc/spinlock.h" -+#include "soc/interrupt_core0_reg.h" -+#include "soc/cpu.h" -+#include "esp_attr.h" -+#include "esp_rom_sys.h" -+#include "esp_timer.h" /* required for FreeRTOS run time stats */ -+#include "esp_heap_caps.h" -+#include "esp_system.h" /* required by esp_get_...() functions in portable.h. [refactor-todo] Update portable.h */ -+#include "esp_newlib.h" -+//#include "portbenchmark.h" -+ -+/* [refactor-todo] These includes are not directly used in this file. They are kept into to prevent a breaking change. Remove these. */ -+#include -+#ifdef CONFIG_LEGACY_INCLUDE_COMMON_HEADERS -+#include "soc/soc_memory_layout.h" -+#endif -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+ -+ -+/* --------------------------------------------------- Port Types ------------------------------------------------------ -+ * - Port specific types. -+ * - The settings in this file configure FreeRTOS correctly for the given hardware and compiler. -+ * - These settings should not be altered. -+ * - The port types must come first as they are used further down in this file -+ * ------------------------------------------------------------------------------------------------------------------ */ -+ -+/* 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) -+ -+// interrupt module will mask interrupt with priority less than threshold -+#define RVHAL_EXCM_LEVEL 4 -+ -+ -+/* ----------------------------------------------- Port Configurations ------------------------------------------------- -+ * - Configurations values supplied by each port -+ * - Required by FreeRTOS -+ * ------------------------------------------------------------------------------------------------------------------ */ -+ -+#define portCRITICAL_NESTING_IN_TCB 0 -+#define portSTACK_GROWTH (-1) -+#define portTICK_PERIOD_MS ((TickType_t) (1000 / configTICK_RATE_HZ)) -+#define portNOP() __asm volatile (" nop ") -+ -+ -+ -+/* ---------------------------------------------- Forward Declarations ------------------------------------------------- -+ * - Forward declarations of all the port functions and macros need to implement the FreeRTOS porting interface -+ * - These must come before definition/declaration of the FreeRTOS porting interface -+ * ------------------------------------------------------------------------------------------------------------------ */ -+ -+// --------------------- Interrupts ------------------------ -+ -+/** -+ * @brief Checks if the current core is in an ISR context -+ * -+ * - ISR context consist of Low/Mid priority ISR, or time tick ISR -+ * - High priority ISRs aren't detected here, but they normally cannot call C code, so that should not be an issue anyway. -+ * -+ * @note [refactor-todo] Check if this should be inlined -+ * @return -+ * - pdTRUE if in ISR -+ * - pdFALSE otherwise -+ */ -+BaseType_t xPortInIsrContext(void); -+ -+/** -+ * @brief Check if in ISR context from High priority ISRs -+ * -+ * - Called from High priority ISR -+ * - Checks if the previous context (before high priority interrupt) was in ISR context (meaning low/med priority) -+ * -+ * @note [refactor-todo] Check if this should be inlined -+ * @return -+ * - pdTRUE if in previous in ISR context -+ * - pdFALSE otherwise -+ */ -+BaseType_t xPortInterruptedFromISRContext(void); -+ -+/* ---------------------- Spinlocks ------------------------ -+ - Spinlocks added to match API with SMP FreeRTOS. Single core RISC-V does not need spin locks -+ - Because single core does not have a primitive spinlock data type, we have to implement one here -+ * @note [refactor-todo] Refactor critical section API so that this is no longer required -+ * ------------------------------------------------------ */ -+ -+/** -+ * @brief Spinlock object -+ * Owner: -+ * - Set to 0 if uninitialized -+ * - Set to portMUX_FREE_VAL when free -+ * - Set to CORE_ID_REGVAL_PRO or CORE_ID_REGVAL_AP when locked -+ * - Any other value indicates corruption -+ * Count: -+ * - 0 if unlocked -+ * - Recursive count if locked -+ * -+ * @note Not a true spinlock as single core RISC-V does not have atomic compare and set instruction -+ * @note Keep portMUX_INITIALIZER_UNLOCKED in sync with this struct -+ */ -+typedef struct { -+ uint32_t owner; -+ uint32_t count; -+} portMUX_TYPE; -+/**< Spinlock initializer */ -+#define portMUX_INITIALIZER_UNLOCKED { \ -+ .owner = portMUX_FREE_VAL, \ -+ .count = 0, \ -+ } -+#define portMUX_FREE_VAL SPINLOCK_FREE /**< Spinlock is free. [refactor-todo] check if this is still required */ -+#define portMUX_NO_TIMEOUT SPINLOCK_WAIT_FOREVER /**< When passed for 'timeout_cycles', spin forever if necessary. [refactor-todo] check if this is still required */ -+#define portMUX_TRY_LOCK SPINLOCK_NO_WAIT /**< Try to acquire the spinlock a single time only. [refactor-todo] check if this is still required */ -+#define portMUX_INITIALIZE(mux) ({ \ -+ (mux)->owner = portMUX_FREE_VAL; \ -+ (mux)->count = 0; \ -+}) -+ -+/** -+ * @brief Wrapper for atomic compare-and-set instruction -+ * -+ * @note Isn't a real atomic CAS. -+ * @note [refactor-todo] check if we still need this -+ * @note [refactor-todo] Check if this function should be renamed (due to void return type) -+ * -+ * @param[inout] addr Pointer to target address -+ * @param[in] compare Compare value -+ * @param[inout] set Pointer to set value -+ */ -+static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set); -+ -+/** -+ * @brief Wrapper for atomic compare-and-set instruction in external RAM -+ * -+ * @note Isn't a real atomic CAS. -+ * @note [refactor-todo] check if we still need this -+ * @note [refactor-todo] Check if this function should be renamed (due to void return type) -+ * -+ * @param[inout] addr Pointer to target address -+ * @param[in] compare Compare value -+ * @param[inout] set Pointer to set value -+ */ -+static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set); -+ -+// ---------------------- Yielding ------------------------- -+ -+/** -+ * @brief Perform a context switch from a task -+ * -+ * @note [refactor-todo] The rest of ESP-IDF should call taskYield() instead -+ */ -+#define vPortYield() portYIELD() -+ -+/** -+ * @brief Perform a context switch from an ISR -+ */ -+#define vPortYieldFromISR() portYIELD_FROM_ISR(0) -+ -+/** -+ * @brief Checks if the current core can yield -+ * -+ * - A core cannot yield if its in an ISR or in a critical section -+ * -+ * @note [refactor-todo] See if this can be separated from port macro -+ * @note [refactor-todo] Check if this function should be renamed (due to bool return type) -+ * @return true Core can yield -+ * @return false Core cannot yield -+ */ -+static inline bool IRAM_ATTR xPortCanYield(void); -+ -+// ------------------- Hook Functions ---------------------- -+ -+extern void esp_vApplicationIdleHook(void); -+extern void esp_vApplicationTickHook(void); -+ -+/** -+ * @brief Hook function called on entry to tickless idle -+ * -+ * - Implemented in pm_impl.c -+ * -+ * @param xExpectedIdleTime Expected idle time -+ */ -+void vApplicationSleep(TickType_t xExpectedIdleTime); -+ -+// ----------------------- System -------------------------- -+ -+/** -+ * @brief Get the tick rate per second -+ * -+ * @note [refactor-todo] make this inline -+ * @note [refactor-todo] Check if this function should be renamed (due to uint return type) -+ * @return uint32_t Tick rate in Hz -+ */ -+uint32_t xPortGetTickRateHz(void); -+ -+/** -+ * @brief Set a watchpoint to watch the last 32 bytes of the stack -+ * -+ * Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack watchpoint -+ * around. -+ * -+ * @param pxStackStart Pointer to the start of the stack -+ */ -+void vPortSetStackWatchpoint(void *pxStackStart); -+ -+/** -+ * @brief Get the current core's ID -+ * -+ * @note Added to be compatible with SMP API -+ * @note [refactor-todo] IDF should call a FreeRTOS like macro instead of port function directly -+ * @return BaseType_t Core ID -+ */ -+static inline BaseType_t IRAM_ATTR xPortGetCoreID(void) -+{ -+ return (uint32_t) cpu_hal_get_core_id(); -+} -+ -+ -+ -+/* ------------------------------------------- FreeRTOS Porting Interface ---------------------------------------------- -+ * - Contains all the mappings of the macros required by FreeRTOS -+ * - Most come after forward declare as porting macros map to declared functions -+ * - Maps to forward declared functions -+ * ------------------------------------------------------------------------------------------------------------------ */ -+ -+// ----------------------- Memory -------------------------- -+ -+/** -+ * @brief Task memory allocation macros -+ * -+ * @note Because the ROM routines don't necessarily handle a stack in external RAM correctly, we force the stack -+ * memory to always be internal. -+ * @note [refactor-todo] Update portable.h to match v10.4.3 to use new malloc prototypes -+ */ -+#define portTcbMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT) -+#define portStackMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT) -+#define pvPortMallocTcbMem(size) pvPortMalloc(size) -+#define pvPortMallocStackMem(size) pvPortMalloc(size) -+ -+// ------------------ Critical Sections -------------------- -+#define portENTER_CRITICAL(mux) {(void)mux; vPortEnterCritical();} -+#define portEXIT_CRITICAL(mux) {(void)mux; vPortExitCritical();} -+#define portTRY_ENTER_CRITICAL(mux, timeout) ({ \ -+ (void)mux; (void)timeout; \ -+ vPortEnterCritical(); \ -+ BaseType_t ret = pdPASS; \ -+ ret; \ -+}) -+//In single-core RISC-V, we can use the same critical section API -+#define portENTER_CRITICAL_ISR(mux) portENTER_CRITICAL(mux) -+#define portEXIT_CRITICAL_ISR(mux) portEXIT_CRITICAL(mux) -+#define portTRY_ENTER_CRITICAL_ISR(mux, timeout) portTRY_ENTER_CRITICAL(mux, timeout) -+ -+/* [refactor-todo] on RISC-V, both ISR and non-ISR cases result in the same call. We can redefine this macro */ -+#define portENTER_CRITICAL_SAFE(mux) ({ \ -+ if (xPortInIsrContext()) { \ -+ portENTER_CRITICAL_ISR(mux); \ -+ } else { \ -+ portENTER_CRITICAL(mux); \ -+ } \ -+}) -+#define portEXIT_CRITICAL_SAFE(mux) ({ \ -+ if (xPortInIsrContext()) { \ -+ portEXIT_CRITICAL_ISR(mux); \ -+ } else { \ -+ portEXIT_CRITICAL(mux); \ -+ } \ -+}) -+#define portTRY_ENTER_CRITICAL_SAFE(mux, timeout) portENTER_CRITICAL_SAFE(mux, timeout) -+ -+// ---------------------- Yielding ------------------------- -+ -+#define portEND_SWITCHING_ISR(xSwitchRequired) if(xSwitchRequired) vPortYield() -+/* Yielding within an API call (when interrupts are off), means the yield should be delayed -+ until interrupts are re-enabled. -+ To do this, we use the "cross-core" interrupt as a trigger to yield on this core when interrupts are re-enabled.This -+ is the same interrupt & code path which is used to trigger a yield between CPUs, although in this case the yield is -+ happening on the same CPU. -+*/ -+#define portYIELD_WITHIN_API() portYIELD() -+ -+// ------------------- Hook Functions ---------------------- -+ -+#ifndef CONFIG_FREERTOS_LEGACY_HOOKS -+#define vApplicationIdleHook esp_vApplicationIdleHook -+#define vApplicationTickHook esp_vApplicationTickHook -+#endif /* !CONFIG_FREERTOS_LEGACY_HOOKS */ -+#define portSUPPRESS_TICKS_AND_SLEEP(idleTime) vApplicationSleep(idleTime) -+ -+// ------------------- Run Time Stats ---------------------- -+ -+#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() -+#define portGET_RUN_TIME_COUNTER_VALUE() 0 -+#ifdef CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER -+/* Coarse resolution time (us) */ -+#define portALT_GET_RUN_TIME_COUNTER_VALUE(x) do {x = (uint32_t)esp_timer_get_time();} while(0) -+#endif -+ -+ -+ -+/* --------------------------------------------- Inline Implementations ------------------------------------------------ -+ * - Implementation of inline functions of the forward declares -+ * - Should come after forward declare and FreeRTOS Porting interface, as implementation may use both. -+ * - For implementation of non-inlined functions, see port.c, port_common.c, or other assembly files -+ * ------------------------------------------------------------------------------------------------------------------ */ -+ -+// --------------------- Interrupts ------------------------ -+ -+ -+ -+// ---------------------- Spinlocks ------------------------ -+ -+static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set) -+{ -+ compare_and_set_native(addr, compare, set); -+} -+ -+static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set) -+{ -+#if defined(CONFIG_SPIRAM) -+ compare_and_set_extram(addr, compare, set); -+#endif -+} -+ -+// ---------------------- Yielding ------------------------- -+ -+static inline bool IRAM_ATTR xPortCanYield(void) -+{ -+ uint32_t threshold = REG_READ(INTERRUPT_CORE0_CPU_INT_THRESH_REG); -+ /* when enter critical code, FreeRTOS will mask threshold to RVHAL_EXCM_LEVEL -+ * and exit critical code, will recover threshold value (1). so threshold <= 1 -+ * means not in critical code -+ */ -+ return (threshold <= 1); -+} -+ -+ -+ -+/* ------------------------------------------------------ Misc --------------------------------------------------------- -+ * - Miscellaneous porting macros -+ * - These are not port of the FreeRTOS porting interface, but are used by other FreeRTOS dependent components -+ * ------------------------------------------------------------------------------------------------------------------ */ -+ -+// -------------------- Heap Related ----------------------- -+ -+/** -+ * @brief Checks if a given piece of memory can be used to store a task's TCB -+ * -+ * - Defined in port_common.c -+ * -+ * @param ptr Pointer to memory -+ * @return true Memory can be used to store a TCB -+ * @return false Otherwise -+ */ -+bool xPortCheckValidTCBMem(const void *ptr); -+ -+/** -+ * @brief Checks if a given piece of memory can be used to store a task's stack -+ * -+ * - Defined in port_common.c -+ * -+ * @param ptr Pointer to memory -+ * @return true Memory can be used to store a task stack -+ * @return false Otherwise -+ */ -+bool xPortcheckValidStackMem(const void *ptr); -+ -+#define portVALID_TCB_MEM(ptr) xPortCheckValidTCBMem(ptr) -+#define portVALID_STACK_MEM(ptr) xPortcheckValidStackMem(ptr) -+ -+ -+ -+/* ---------------------------------------------------- Deprecate ------------------------------------------------------ -+ * - Pull in header containing deprecated macros here -+ * ------------------------------------------------------------------------------------------------------------------ */ -+ -+#include "portmacro_deprecated.h" -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif //__ASSEMBLER__ -+ -+#endif /* PORTMACRO_H */ -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/port.c b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/port.c -new file mode 100644 -index 0000000000..9d8195f832 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/port.c -@@ -0,0 +1,44 @@ -+#include -+ -+static rt_base_t level = 0; -+static rt_base_t critical_nesting = 0; -+ -+void vPortEnterCritical( void ) -+{ -+ if ( critical_nesting == 0 ) -+ { -+ level = rt_hw_interrupt_disable(); -+ } -+ critical_nesting += 1; -+} -+ -+void vPortExitCritical( void ) -+{ -+ critical_nesting -= 1; -+ if ( critical_nesting == 0 ) -+ { -+ rt_hw_interrupt_enable( level ); -+ } -+} -+ -+void vPortEndScheduler( void ) -+{ -+ /* Not implemented in ports where there is nothing to return to. */ -+} -+ -+BaseType_t rt_err_to_freertos(rt_err_t rt_err) -+{ -+ switch(-rt_err) -+ { -+ case RT_EOK: -+ return pdPASS; -+ case RT_ENOMEM: -+ return errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; -+ case RT_EFULL: -+ return errQUEUE_FULL; -+ case RT_EEMPTY: -+ return errQUEUE_EMPTY; -+ default: -+ return pdFAIL; -+ } -+} -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/port_esp32c3.c b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/port_esp32c3.c -new file mode 100644 -index 0000000000..64fbe9b15b ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/port/rt-thread/port_esp32c3.c -@@ -0,0 +1,197 @@ -+/* -+ FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd. -+ All rights reserved -+ -+ VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. -+ -+ This file is part of the FreeRTOS distribution and was contributed -+ to the project by Technolution B.V. (www.technolution.nl, -+ freertos-riscv@technolution.eu) under the terms of the FreeRTOS -+ contributors license. -+ -+ FreeRTOS is free software; you can redistribute it and/or modify it under -+ the terms of the GNU General Public License (version 2) as published by the -+ Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. -+ -+ *************************************************************************** -+ >>! NOTE: The modification to the GPL is included to allow you to !<< -+ >>! distribute a combined work that includes FreeRTOS without being !<< -+ >>! obliged to provide the source code for proprietary components !<< -+ >>! outside of the FreeRTOS kernel. !<< -+ *************************************************************************** -+ -+ FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY -+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -+ FOR A PARTICULAR PURPOSE. Full license text is available on the following -+ link: http://www.freertos.org/a00114.html -+ -+ *************************************************************************** -+ * * -+ * FreeRTOS provides completely free yet professionally developed, * -+ * robust, strictly quality controlled, supported, and cross * -+ * platform software that is more than just the market leader, it * -+ * is the industry's de facto standard. * -+ * * -+ * Help yourself get started quickly while simultaneously helping * -+ * to support the FreeRTOS project by purchasing a FreeRTOS * -+ * tutorial book, reference manual, or both: * -+ * http://www.FreeRTOS.org/Documentation * -+ * * -+ *************************************************************************** -+ -+ http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading -+ the FAQ page "My application does not run, what could be wrong?". Have you -+ defined configASSERT()? -+ -+ http://www.FreeRTOS.org/support - In return for receiving this top quality -+ embedded software for free we request you assist our global community by -+ participating in the support forum. -+ -+ http://www.FreeRTOS.org/training - Investing in training allows your team to -+ be as productive as possible as early as possible. Now you can receive -+ FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers -+ Ltd, and the world's leading authority on the world's leading RTOS. -+ -+ http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, -+ including FreeRTOS+Trace - an indispensable productivity tool, a DOS -+ compatible FAT file system, and our tiny thread aware UDP/IP stack. -+ -+ http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. -+ Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. -+ -+ http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High -+ Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS -+ licenses offer ticketed support, indemnification and commercial middleware. -+ -+ http://www.SafeRTOS.com - High Integrity Systems also provide a safety -+ engineered and independently SIL3 certified version for use in safety and -+ mission critical applications that require provable dependability. -+ -+ 1 tab == 4 spaces! -+*/ -+ -+/*----------------------------------------------------------------------- -+ * Implementation of functions defined in portable.h for the RISC-V port. -+ *----------------------------------------------------------------------*/ -+ -+#include "sdkconfig.h" -+#include -+#include "soc/soc_caps.h" -+#include "soc/periph_defs.h" -+#include "soc/system_reg.h" -+#include "hal/systimer_hal.h" -+#include "hal/systimer_ll.h" -+#include "riscv/rvruntime-frames.h" -+#include "riscv/riscv_interrupts.h" -+#include "riscv/interrupt.h" -+#include "esp_private/crosscore_int.h" -+#include "esp_private/pm_trace.h" -+#include "esp_attr.h" -+#include "esp_system.h" -+#include "esp_intr_alloc.h" -+#include "esp_debug_helpers.h" -+#include "esp_log.h" -+#include "FreeRTOS.h" /* This pulls in portmacro.h */ -+#include "task.h" -+#include "portmacro.h" -+//#include "port_systick.h" -+ -+ -+ -+/* ---------------------------------------------------- Variables ------------------------------------------------------ -+ * -+ * ------------------------------------------------------------------------------------------------------------------ */ -+ -+static const char *TAG = "cpu_start"; // [refactor-todo]: might be appropriate to change in the future, but -+ -+/** -+ * @brief A variable is used to keep track of the critical section nesting. -+ * @note This variable has to be stored as part of the task context and must be initialized to a non zero value -+ * to ensure interrupts don't inadvertently become unmasked before the scheduler starts. -+ * As it is stored as part of the task context it will automatically be set to 0 when the first task is started. -+ */ -+static UBaseType_t uxCriticalNesting = 0; -+static UBaseType_t uxSavedInterruptState = 0; -+BaseType_t uxSchedulerRunning = 0; -+UBaseType_t uxInterruptNesting = 0; -+BaseType_t xPortSwitchFlag = 0; -+__attribute__((aligned(16))) static StackType_t xIsrStack[configISR_STACK_SIZE]; -+StackType_t *xIsrStackTop = &xIsrStack[0] + (configISR_STACK_SIZE & (~((portPOINTER_SIZE_TYPE)portBYTE_ALIGNMENT_MASK))); -+ -+ -+ -+/* ---------------------------------------------- Port Implementations ------------------------------------------------- -+ * -+ * ------------------------------------------------------------------------------------------------------------------ */ -+ -+// --------------------- Interrupts ------------------------ -+ -+BaseType_t xPortInIsrContext(void) -+{ -+ return (BaseType_t)rt_interrupt_get_nest(); -+} -+ -+BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void) -+{ -+ /* For single core, this can be the same as xPortInIsrContext() because reading it is atomic */ -+ return (BaseType_t)rt_interrupt_get_nest(); -+} -+ -+// ---------------------- Spinlocks ------------------------ -+ -+ -+// ---------------------- Yielding ------------------------- -+ -+ -+// ------------------- Hook Functions ---------------------- -+ -+void __attribute__((weak)) vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) -+{ -+#define ERR_STR1 "***ERROR*** A stack overflow in task " -+#define ERR_STR2 " has been detected." -+ const char *str[] = {ERR_STR1, pcTaskName, ERR_STR2}; -+ -+ char buf[sizeof(ERR_STR1) + CONFIG_FREERTOS_MAX_TASK_NAME_LEN + sizeof(ERR_STR2) + 1 /* null char */] = {0}; -+ -+ char *dest = buf; -+ for (int i = 0; i < sizeof(str) / sizeof(str[0]); i++) { -+ dest = strcat(dest, str[i]); -+ } -+ esp_system_abort(buf); -+} -+ -+// ----------------------- System -------------------------- -+ -+uint32_t xPortGetTickRateHz(void) -+{ -+ return (uint32_t)configTICK_RATE_HZ; -+} -+ -+#define STACK_WATCH_AREA_SIZE 32 -+#define STACK_WATCH_POINT_NUMBER (SOC_CPU_WATCHPOINTS_NUM - 1) -+ -+void vPortSetStackWatchpoint(void *pxStackStart) -+{ -+ uint32_t addr = (uint32_t)pxStackStart; -+ addr = (addr + (STACK_WATCH_AREA_SIZE - 1)) & (~(STACK_WATCH_AREA_SIZE - 1)); -+ esp_cpu_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char *)addr, STACK_WATCH_AREA_SIZE, ESP_WATCHPOINT_STORE); -+} -+ -+ -+ -+/* ---------------------------------------------- Misc Implementations ------------------------------------------------- -+ * -+ * ------------------------------------------------------------------------------------------------------------------ */ -+ -+// --------------------- App Start-up ---------------------- -+ -+/* [refactor-todo]: See if we can include this through a header */ -+extern void esp_startup_start_app_common(void); -+ -+void esp_startup_start_app(void) -+{ -+ esp_startup_start_app_common(); -+ -+ ESP_LOGI(TAG, "Starting scheduler."); -+ vTaskStartScheduler(); -+} -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/queue.c b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/queue.c -new file mode 100644 -index 0000000000..8965e193d0 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/queue.c -@@ -0,0 +1,787 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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 -+#include -+ -+#include "FreeRTOS.h" -+#include "queue.h" -+ -+/* Semaphores do not actually store or copy data, so have an item size of -+ * zero. */ -+#define queueSEMAPHORE_QUEUE_ITEM_LENGTH ( ( UBaseType_t ) 0 ) -+#define queueMUTEX_GIVE_BLOCK_TIME ( ( TickType_t ) 0U ) -+ -+typedef struct QueueDefinition -+{ -+ struct rt_ipc_object *rt_ipc; -+} xQUEUE; -+typedef xQUEUE Queue_t; -+ -+static volatile rt_uint8_t mutex_index = 0; -+static volatile rt_uint8_t sem_index = 0; -+static volatile rt_uint8_t queue_index = 0; -+ -+/*-----------------------------------------------------------*/ -+ -+BaseType_t xQueueGenericReset( QueueHandle_t xQueue, -+ BaseType_t xNewQueue ) -+{ -+ Queue_t * const pxQueue = xQueue; -+ struct rt_ipc_object *pipc; -+ rt_uint8_t type; -+ -+ configASSERT( pxQueue ); -+ -+ pipc = pxQueue->rt_ipc; -+ RT_ASSERT( pipc != RT_NULL ); -+ type = rt_object_get_type( &pipc->parent ); -+ -+ if ( type == RT_Object_Class_Semaphore ) -+ { -+ rt_sem_control( ( rt_sem_t ) pipc, RT_IPC_CMD_RESET, ( void * ) 0); -+ } -+ else if ( type == RT_Object_Class_MessageQueue ) -+ { -+ rt_mq_control( ( rt_mq_t ) pipc, RT_IPC_CMD_RESET, RT_NULL ); -+ } -+ -+ return pdPASS; -+} -+/*-----------------------------------------------------------*/ -+ -+#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) -+ -+ QueueHandle_t xQueueGenericCreateStatic( const UBaseType_t uxQueueLength, -+ const UBaseType_t uxItemSize, -+ uint8_t * pucQueueStorage, -+ StaticQueue_t * pxStaticQueue, -+ const uint8_t ucQueueType ) -+ { -+ Queue_t * pxNewQueue = NULL; -+ char name[RT_NAME_MAX] = {0}; -+ -+ /* The StaticQueue_t structure and the queue storage area must be -+ * supplied. */ -+ configASSERT( pxStaticQueue ); -+ -+ if( ( uxQueueLength > ( UBaseType_t ) 0 ) && -+ ( pxStaticQueue != NULL ) && -+ -+ /* A queue storage area should be provided if the item size is not 0, and -+ * should not be provided if the item size is 0. */ -+ ( !( ( pucQueueStorage != NULL ) && ( uxItemSize == 0 ) ) ) && -+ ( !( ( pucQueueStorage == NULL ) && ( uxItemSize != 0 ) ) ) ) -+ { -+ if ( ucQueueType == queueQUEUE_TYPE_RECURSIVE_MUTEX || ucQueueType == queueQUEUE_TYPE_MUTEX ) -+ { -+ rt_snprintf( name, RT_NAME_MAX, "mutex%02d", mutex_index++ ); -+ rt_mutex_init( ( rt_mutex_t ) &( ( StaticSemaphore_t * ) pxStaticQueue )->ipc_obj.mutex, name, RT_IPC_FLAG_PRIO ); -+ } -+ else if ( ucQueueType == queueQUEUE_TYPE_BINARY_SEMAPHORE || ucQueueType == queueQUEUE_TYPE_COUNTING_SEMAPHORE ) -+ { -+ rt_snprintf( name, RT_NAME_MAX, "sem%02d", sem_index++ ); -+ rt_sem_init( ( rt_sem_t ) &( ( StaticSemaphore_t * ) pxStaticQueue )->ipc_obj.semaphore, name, 0, RT_IPC_FLAG_PRIO ); -+ ( ( StaticSemaphore_t * ) pxStaticQueue )->ipc_obj.semaphore.max_value = uxQueueLength; -+ } -+ else if ( ucQueueType == queueQUEUE_TYPE_BASE ) -+ { -+ rt_snprintf( name, RT_NAME_MAX, "queue%02d", queue_index++ ); -+ rt_mq_init( &( pxStaticQueue->ipc_obj ), name, pucQueueStorage, uxItemSize, QUEUE_BUFFER_SIZE( uxQueueLength, uxItemSize ), RT_IPC_FLAG_PRIO ); -+ } -+ else -+ { -+ return pxNewQueue; -+ } -+ pxStaticQueue->rt_ipc = ( struct rt_ipc_object * ) &pxStaticQueue->ipc_obj; -+ pxNewQueue = ( QueueHandle_t ) pxStaticQueue; -+ } -+ -+ return pxNewQueue; -+ } -+ -+#endif /* configSUPPORT_STATIC_ALLOCATION */ -+/*-----------------------------------------------------------*/ -+ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ -+ QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength, -+ const UBaseType_t uxItemSize, -+ const uint8_t ucQueueType ) -+ { -+ Queue_t * pxNewQueue = NULL; -+ char name[RT_NAME_MAX] = {0}; -+ struct rt_ipc_object * pipc = RT_NULL; -+ -+ if( ( uxQueueLength > ( UBaseType_t ) 0 ) && -+ /* Check for multiplication overflow. */ -+ ( ( SIZE_MAX / uxQueueLength ) >= uxItemSize ) && -+ /* Check for addition overflow. */ -+ ( ( SIZE_MAX - sizeof( Queue_t ) ) >= ( uxQueueLength * uxItemSize ) ) ) -+ { -+ pxNewQueue = ( Queue_t * ) RT_KERNEL_MALLOC( sizeof( Queue_t ) ); -+ if ( pxNewQueue == NULL ) -+ { -+ return ( QueueHandle_t ) pxNewQueue; -+ } -+ if ( ucQueueType == queueQUEUE_TYPE_RECURSIVE_MUTEX || ucQueueType == queueQUEUE_TYPE_MUTEX ) -+ { -+ rt_snprintf( name, RT_NAME_MAX, "mutex%02d", mutex_index++ ); -+ pipc = ( struct rt_ipc_object * ) rt_mutex_create( name, RT_IPC_FLAG_PRIO ); -+ } -+ else if ( ucQueueType == queueQUEUE_TYPE_BINARY_SEMAPHORE || ucQueueType == queueQUEUE_TYPE_COUNTING_SEMAPHORE ) -+ { -+ rt_snprintf( name, RT_NAME_MAX, "sem%02d", sem_index++ ); -+ pipc = ( struct rt_ipc_object * ) RT_KERNEL_MALLOC( sizeof( struct rt_semaphore_wrapper ) ); -+ if ( pipc != RT_NULL ) -+ { -+ rt_sem_init( ( rt_sem_t ) pipc, name, 0, RT_IPC_FLAG_PRIO ); -+ ( ( struct rt_semaphore_wrapper * ) pipc )->max_value = uxQueueLength; -+ /* Mark as dynamic so we can distinguish in vQueueDelete */ -+ pipc->parent.type &= ~RT_Object_Class_Static; -+ } -+ } -+ else if ( ucQueueType == queueQUEUE_TYPE_BASE ) -+ { -+ rt_snprintf( name, RT_NAME_MAX, "queue%02d", queue_index++ ); -+ pipc = ( struct rt_ipc_object * ) rt_mq_create( name, uxItemSize, uxQueueLength, RT_IPC_FLAG_PRIO); -+ } -+ -+ if ( pipc == RT_NULL ) -+ { -+ RT_KERNEL_FREE( pxNewQueue ); -+ return NULL; -+ } -+ pxNewQueue->rt_ipc = pipc; -+ } -+ -+ return ( QueueHandle_t ) pxNewQueue; -+ } -+ -+#endif /* configSUPPORT_STATIC_ALLOCATION */ -+/*-----------------------------------------------------------*/ -+ -+#if ( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) -+ -+ QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType ) -+ { -+ QueueHandle_t xNewQueue; -+ const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0; -+ -+ xNewQueue = xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType ); -+ return xNewQueue; -+ } -+ -+#endif /* configUSE_MUTEXES */ -+/*-----------------------------------------------------------*/ -+ -+#if ( ( configUSE_MUTEXES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) -+ -+ QueueHandle_t xQueueCreateMutexStatic( const uint8_t ucQueueType, -+ StaticQueue_t * pxStaticQueue ) -+ { -+ QueueHandle_t xNewQueue; -+ const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0; -+ -+ xNewQueue = xQueueGenericCreateStatic( uxMutexLength, uxMutexSize, NULL, pxStaticQueue, ucQueueType ); -+ -+ return xNewQueue; -+ } -+ -+#endif /* configUSE_MUTEXES */ -+/*-----------------------------------------------------------*/ -+ -+#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) -+ -+ TaskHandle_t xQueueGetMutexHolder( QueueHandle_t xSemaphore ) -+ { -+ TaskHandle_t pxReturn; -+ struct rt_ipc_object *pipc; -+ rt_uint8_t type; -+ rt_base_t level; -+ -+ configASSERT( xSemaphore ); -+ -+ pipc = xSemaphore->rt_ipc; -+ RT_ASSERT( pipc != RT_NULL ); -+ type = rt_object_get_type( &pipc->parent ); -+ -+ if ( type == RT_Object_Class_Mutex ) -+ { -+ level = rt_hw_interrupt_disable(); -+ pxReturn = ( TaskHandle_t ) ( ( rt_mutex_t ) pipc )->owner; -+ rt_hw_interrupt_enable( level ); -+ } -+ else -+ { -+ pxReturn = NULL; -+ } -+ -+ return pxReturn; -+ } -+ -+#endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */ -+/*-----------------------------------------------------------*/ -+ -+#if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) -+ -+ TaskHandle_t xQueueGetMutexHolderFromISR( QueueHandle_t xSemaphore ) -+ { -+ return xQueueGetMutexHolder( xSemaphore ); -+ } -+ -+#endif /* if ( ( configUSE_MUTEXES == 1 ) && ( INCLUDE_xSemaphoreGetMutexHolder == 1 ) ) */ -+/*-----------------------------------------------------------*/ -+ -+#if ( configUSE_RECURSIVE_MUTEXES == 1 ) -+ -+ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ) -+ { -+ Queue_t * const pxMutex = ( Queue_t * ) xMutex; -+ configASSERT( pxMutex ); -+ return xQueueGenericSend( pxMutex, NULL, queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK ); -+ } -+ -+#endif /* configUSE_RECURSIVE_MUTEXES */ -+/*-----------------------------------------------------------*/ -+ -+#if ( configUSE_RECURSIVE_MUTEXES == 1 ) -+ -+ BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, -+ TickType_t xTicksToWait ) -+ { -+ Queue_t * const pxMutex = ( Queue_t * ) xMutex; -+ configASSERT( pxMutex ); -+ return xQueueSemaphoreTake( pxMutex, xTicksToWait ); -+ } -+ -+#endif /* configUSE_RECURSIVE_MUTEXES */ -+/*-----------------------------------------------------------*/ -+ -+#if ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) -+ -+ QueueHandle_t xQueueCreateCountingSemaphoreStatic( const UBaseType_t uxMaxCount, -+ const UBaseType_t uxInitialCount, -+ StaticQueue_t * pxStaticQueue ) -+ { -+ QueueHandle_t xHandle = NULL; -+ -+ if( ( uxMaxCount != 0 ) && -+ ( uxInitialCount <= uxMaxCount ) ) -+ { -+ xHandle = xQueueGenericCreateStatic( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticQueue, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); -+ -+ if( xHandle != NULL ) -+ { -+ ( ( rt_sem_t ) ( ( Queue_t * ) xHandle )->rt_ipc )->value = uxInitialCount; -+ } -+ } -+ else -+ { -+ configASSERT( xHandle ); -+ } -+ -+ return xHandle; -+ } -+ -+#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */ -+/*-----------------------------------------------------------*/ -+ -+#if ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) -+ -+ QueueHandle_t xQueueCreateCountingSemaphore( const UBaseType_t uxMaxCount, -+ const UBaseType_t uxInitialCount ) -+ { -+ QueueHandle_t xHandle = NULL; -+ -+ if( ( uxMaxCount != 0 ) && -+ ( uxInitialCount <= uxMaxCount ) ) -+ { -+ xHandle = xQueueGenericCreate( uxMaxCount, queueSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_COUNTING_SEMAPHORE ); -+ -+ if( xHandle != NULL ) -+ { -+ ( ( rt_sem_t ) ( ( Queue_t * ) xHandle )->rt_ipc )->value = uxInitialCount; -+ } -+ } -+ else -+ { -+ configASSERT( xHandle ); -+ } -+ -+ return xHandle; -+ } -+ -+#endif /* ( ( configUSE_COUNTING_SEMAPHORES == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */ -+/*-----------------------------------------------------------*/ -+ -+BaseType_t xQueueGenericSend( QueueHandle_t xQueue, -+ const void * const pvItemToQueue, -+ TickType_t xTicksToWait, -+ const BaseType_t xCopyPosition ) -+{ -+ Queue_t * const pxQueue = xQueue; -+ struct rt_ipc_object *pipc; -+ rt_uint8_t type; -+ rt_base_t level; -+ rt_err_t err = -RT_ERROR; -+ -+ configASSERT( pxQueue ); -+ #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) -+ { -+ configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); -+ } -+ #endif -+ -+ pipc = pxQueue->rt_ipc; -+ RT_ASSERT( pipc != RT_NULL ); -+ type = rt_object_get_type( &pipc->parent ); -+ if ( type == RT_Object_Class_Mutex ) -+ { -+ err = rt_mutex_release( ( rt_mutex_t ) pipc ); -+ } -+ else if ( type == RT_Object_Class_Semaphore ) -+ { -+ level = rt_hw_interrupt_disable(); -+ if ( ( ( rt_sem_t ) pipc )->value < ( ( struct rt_semaphore_wrapper * ) pipc )->max_value ) -+ { -+ err = rt_sem_release( ( rt_sem_t ) pipc ); -+ } -+ rt_hw_interrupt_enable( level ); -+ } -+ else if ( type == RT_Object_Class_MessageQueue ) -+ { -+ if ( xCopyPosition == queueSEND_TO_BACK ) -+ { -+ err = rt_mq_send_wait( ( rt_mq_t ) pipc, pvItemToQueue, ( ( rt_mq_t ) pipc )->msg_size, ( rt_int32_t ) xTicksToWait ); -+ } -+ else if ( xCopyPosition == queueSEND_TO_FRONT ) -+ { -+ // TODO: need to implement the timeout for LIFO -+ err = rt_mq_urgent( ( rt_mq_t ) pipc, pvItemToQueue, ( ( rt_mq_t ) pipc )->msg_size ); -+ } -+ } -+ -+ return rt_err_to_freertos( err ); -+} -+/*-----------------------------------------------------------*/ -+ -+BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue, -+ const void * const pvItemToQueue, -+ BaseType_t * const pxHigherPriorityTaskWoken, -+ const BaseType_t xCopyPosition ) -+{ -+ Queue_t * const pxQueue = xQueue; -+ struct rt_ipc_object *pipc; -+ rt_uint8_t type; -+ rt_err_t err = -RT_ERROR; -+ -+ configASSERT( pxQueue ); -+ -+ pipc = pxQueue->rt_ipc; -+ RT_ASSERT( pipc != RT_NULL ); -+ type = rt_object_get_type( &pipc->parent ); -+ if ( type == RT_Object_Class_MessageQueue ) -+ { -+ if ( xCopyPosition == queueSEND_TO_BACK ) -+ { -+ err = rt_mq_send( ( rt_mq_t ) pipc, pvItemToQueue, ( ( rt_mq_t ) pipc )->msg_size); -+ } -+ else if ( xCopyPosition == queueSEND_TO_FRONT ) -+ { -+ err = rt_mq_urgent( ( rt_mq_t ) pipc, pvItemToQueue, ( ( rt_mq_t ) pipc )->msg_size ); -+ } -+ } -+ -+ return rt_err_to_freertos( err ); -+} -+/*-----------------------------------------------------------*/ -+ -+BaseType_t xQueueGiveFromISR( QueueHandle_t xQueue, -+ BaseType_t * const pxHigherPriorityTaskWoken ) -+{ -+ Queue_t * const pxQueue = xQueue; -+ struct rt_ipc_object *pipc; -+ rt_uint8_t type; -+ rt_base_t level; -+ rt_err_t err = -RT_ERROR; -+ -+ configASSERT( pxQueue ); -+ -+ pipc = pxQueue->rt_ipc; -+ RT_ASSERT( pipc != RT_NULL ); -+ type = rt_object_get_type( &pipc->parent ); -+ RT_ASSERT( type != RT_Object_Class_Mutex ); -+ if ( type == RT_Object_Class_Semaphore ) -+ { -+ level = rt_hw_interrupt_disable(); -+ if ( ( ( rt_sem_t ) pipc )->value < ( ( struct rt_semaphore_wrapper * ) pipc )->max_value ) -+ { -+ err = rt_sem_release( ( rt_sem_t ) pipc ); -+ } -+ rt_hw_interrupt_enable( level ); -+ } -+ if ( pxHigherPriorityTaskWoken != NULL ) -+ { -+ *pxHigherPriorityTaskWoken = pdFALSE; -+ } -+ -+ return rt_err_to_freertos( err ); -+} -+/*-----------------------------------------------------------*/ -+ -+BaseType_t xQueueReceive( QueueHandle_t xQueue, -+ void * const pvBuffer, -+ TickType_t xTicksToWait ) -+{ -+ Queue_t * const pxQueue = xQueue; -+ struct rt_ipc_object *pipc; -+ rt_uint8_t type; -+ rt_err_t err = -RT_ERROR; -+ -+ /* Check the queue pointer is not NULL. */ -+ configASSERT( ( pxQueue ) ); -+ -+ /* Cannot block if the scheduler is suspended. */ -+ #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) -+ { -+ configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); -+ } -+ #endif -+ -+ pipc = pxQueue->rt_ipc; -+ RT_ASSERT( pipc != RT_NULL ); -+ type = rt_object_get_type( &pipc->parent ); -+ if ( type == RT_Object_Class_MessageQueue ) -+ { -+ err = rt_mq_recv( ( rt_mq_t ) pipc, pvBuffer, ( ( rt_mq_t ) pipc )->msg_size, ( rt_int32_t ) xTicksToWait ); -+ } -+ -+ return rt_err_to_freertos( err ); -+} -+/*-----------------------------------------------------------*/ -+ -+BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, -+ TickType_t xTicksToWait ) -+{ -+ Queue_t * const pxQueue = xQueue; -+ struct rt_ipc_object *pipc; -+ rt_uint8_t type; -+ rt_err_t err = -RT_ERROR; -+ -+ /* Check the queue pointer is not NULL. */ -+ configASSERT( ( pxQueue ) ); -+ -+ /* Cannot block if the scheduler is suspended. */ -+ #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) -+ { -+ configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) ); -+ } -+ #endif -+ -+ pipc = pxQueue->rt_ipc; -+ RT_ASSERT( pipc != RT_NULL ); -+ type = rt_object_get_type( &pipc->parent ); -+ if ( type == RT_Object_Class_Mutex ) -+ { -+ err = rt_mutex_take( ( rt_mutex_t ) pipc, ( rt_int32_t ) xTicksToWait ); -+ } -+ else if ( type == RT_Object_Class_Semaphore ) -+ { -+ err = rt_sem_take( ( rt_sem_t ) pipc, ( rt_int32_t ) xTicksToWait ); -+ } -+ -+ return rt_err_to_freertos( err ); -+} -+/*-----------------------------------------------------------*/ -+ -+BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, -+ void * const pvBuffer, -+ BaseType_t * const pxHigherPriorityTaskWoken ) -+{ -+ Queue_t * const pxQueue = xQueue; -+ struct rt_ipc_object *pipc; -+ rt_uint8_t type; -+ rt_err_t err = -RT_ERROR; -+ -+ configASSERT( pxQueue ); -+ -+ pipc = pxQueue->rt_ipc; -+ RT_ASSERT( pipc != RT_NULL ); -+ type = rt_object_get_type( &pipc->parent ); -+ RT_ASSERT( type != RT_Object_Class_Mutex ); -+ if ( type == RT_Object_Class_Semaphore ) -+ { -+ err = rt_sem_take( ( rt_sem_t ) pipc, RT_WAITING_NO ); -+ } -+ else if ( type == RT_Object_Class_MessageQueue ) -+ { -+ err = rt_mq_recv( ( rt_mq_t ) pipc, pvBuffer, ( ( rt_mq_t ) pipc )->msg_size, RT_WAITING_NO ); -+ } -+ if ( pxHigherPriorityTaskWoken != NULL ) -+ { -+ *pxHigherPriorityTaskWoken = pdFALSE; -+ } -+ -+ return rt_err_to_freertos( err ); -+} -+/*-----------------------------------------------------------*/ -+ -+UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue ) -+{ -+ UBaseType_t uxReturn = 0; -+ struct rt_ipc_object *pipc; -+ rt_uint8_t type; -+ rt_base_t level; -+ -+ configASSERT( xQueue ); -+ -+ pipc = xQueue->rt_ipc; -+ RT_ASSERT( pipc != RT_NULL ); -+ type = rt_object_get_type( &pipc->parent ); -+ -+ level = rt_hw_interrupt_disable(); -+ -+ if ( type == RT_Object_Class_Mutex ) -+ { -+ uxReturn = ( ( rt_mutex_t ) pipc )->value; -+ } -+ else if ( type == RT_Object_Class_Semaphore ) -+ { -+ uxReturn = ( ( rt_sem_t ) pipc )->value; -+ } -+ else if ( type == RT_Object_Class_MessageQueue ) -+ { -+ uxReturn = ( ( rt_mq_t ) pipc )->entry; -+ } -+ -+ rt_hw_interrupt_enable( level ); -+ -+ return uxReturn; -+} -+/*-----------------------------------------------------------*/ -+ -+UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue ) -+{ -+ UBaseType_t uxReturn = 0; -+ struct rt_ipc_object *pipc; -+ rt_uint8_t type; -+ rt_base_t level; -+ -+ configASSERT( xQueue ); -+ -+ pipc = xQueue->rt_ipc; -+ RT_ASSERT( pipc != RT_NULL ); -+ type = rt_object_get_type( &pipc->parent ); -+ -+ level = rt_hw_interrupt_disable(); -+ -+ if ( type == RT_Object_Class_Mutex ) -+ { -+ uxReturn = 1 - ( ( rt_mutex_t ) pipc )->value; -+ } -+ else if ( type == RT_Object_Class_Semaphore ) -+ { -+ uxReturn = ( ( struct rt_semaphore_wrapper * ) pipc )->max_value - ( ( rt_sem_t ) pipc )->value; -+ } -+ else if ( type == RT_Object_Class_MessageQueue ) -+ { -+ uxReturn = ( ( rt_mq_t ) pipc )->max_msgs - ( ( rt_mq_t ) pipc )->entry; -+ } -+ -+ rt_hw_interrupt_enable( level ); -+ -+ return uxReturn; -+} -+/*-----------------------------------------------------------*/ -+ -+UBaseType_t uxQueueMessagesWaitingFromISR( const QueueHandle_t xQueue ) -+{ -+ return uxQueueMessagesWaiting( xQueue ); -+} -+/*-----------------------------------------------------------*/ -+ -+void vQueueDelete( QueueHandle_t xQueue ) -+{ -+ Queue_t * const pxQueue = xQueue; -+ struct rt_ipc_object *pipc; -+ rt_uint8_t type; -+ -+ configASSERT( pxQueue ); -+ -+ pipc = pxQueue->rt_ipc; -+ RT_ASSERT( pipc != RT_NULL ); -+ type = rt_object_get_type( &pipc->parent ); -+#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) -+ if ( rt_object_is_systemobject( ( rt_object_t ) pipc ) ) -+#endif -+ { -+ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) -+ if ( type == RT_Object_Class_Mutex ) -+ { -+ rt_mutex_detach( ( rt_mutex_t ) pipc ); -+ } -+ else if ( type == RT_Object_Class_Semaphore ) -+ { -+ rt_sem_detach( ( rt_sem_t ) pipc ); -+ } -+ else if ( type == RT_Object_Class_MessageQueue ) -+ { -+ rt_mq_detach( ( rt_mq_t ) pipc ); -+ } -+ #endif -+#if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) -+ } -+ else -+ { -+#endif -+ #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ if ( type == RT_Object_Class_Mutex ) -+ { -+ rt_mutex_delete( ( rt_mutex_t ) pipc ); -+ } -+ else if ( type == RT_Object_Class_Semaphore ) -+ { -+ /* Allocated with rt_sem_init in xQueueGenericCreate */ -+ pipc->parent.type |= RT_Object_Class_Static; -+ rt_sem_detach( ( rt_sem_t ) pipc ); -+ RT_KERNEL_FREE( pipc ); -+ } -+ else if ( type == RT_Object_Class_MessageQueue ) -+ { -+ rt_mq_delete( ( rt_mq_t ) pipc ); -+ } -+ else -+ { -+ return; -+ } -+ RT_KERNEL_FREE( pxQueue ); -+ #endif -+ } -+} -+/*-----------------------------------------------------------*/ -+ -+BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue ) -+{ -+ BaseType_t xReturn; -+ -+ configASSERT( xQueue ); -+ -+ if( uxQueueMessagesWaiting( xQueue ) == ( UBaseType_t ) 0 ) -+ { -+ xReturn = pdTRUE; -+ } -+ else -+ { -+ xReturn = pdFALSE; -+ } -+ -+ return xReturn; -+} -+/*-----------------------------------------------------------*/ -+ -+BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue ) -+{ -+ BaseType_t xReturn; -+ -+ configASSERT( xQueue ); -+ -+ if ( uxQueueSpacesAvailable( xQueue ) == ( UBaseType_t ) 0 ) -+ { -+ xReturn = pdTRUE; -+ } -+ else -+ { -+ xReturn = pdFALSE; -+ } -+ -+ return xReturn; -+} -+/*-----------------------------------------------------------*/ -+ -+/* Unimplemented */ -+#include "esp_log.h" -+QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength ) -+{ -+ ESP_LOGE("freertos", "xQueueCreateSet unimplemented"); -+ RT_ASSERT(0); -+ return NULL; -+} -+BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore, -+ QueueSetHandle_t xQueueSet ) -+{ -+ ESP_LOGE("freertos", "xQueueAddToSet unimplemented"); -+ RT_ASSERT(0); -+ return pdFAIL; -+} -+ -+BaseType_t xQueueRemoveFromSet( QueueSetMemberHandle_t xQueueOrSemaphore, -+ QueueSetHandle_t xQueueSet ) -+{ -+ ESP_LOGE("freertos", "xQueueRemoveFromSet unimplemented"); -+ RT_ASSERT(0); -+ return pdFAIL; -+} -+ -+QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, -+ const TickType_t xTicksToWait ) -+{ -+ ESP_LOGE("freertos", "xQueueSelectFromSet unimplemented"); -+ RT_ASSERT(0); -+ return NULL; -+} -+ -+QueueSetMemberHandle_t xQueueSelectFromSetFromISR( QueueSetHandle_t xQueueSet ) -+{ -+ ESP_LOGE("freertos", "xQueueSelectFromSetFromISR unimplemented"); -+ RT_ASSERT(0); -+ return NULL; -+} -+ -+BaseType_t xQueuePeek( QueueHandle_t xQueue, -+ void * const pvBuffer, -+ TickType_t xTicksToWait ) -+{ -+ ESP_LOGE("freertos", "xQueuePeek unimplemented"); -+ RT_ASSERT(0); -+ return pdFAIL; -+} -+ -+BaseType_t xQueueOverwrite(QueueHandle_t xQueue, const void * pvItemToQueue) -+{ -+ ESP_LOGE("freertos", "xQueueOverwrite unimplemented"); -+ RT_ASSERT(0); -+ return pdFAIL; -+} -+ -+BaseType_t xQueueOverwriteFromISR(QueueHandle_t xQueue, const void * pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken) -+{ -+ ESP_LOGE("freertos", "xQueueOverwriteFromISR unimplemented"); -+ RT_ASSERT(0); -+ return pdFAIL; -+} -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/tasks.c b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/tasks.c -new file mode 100644 -index 0000000000..d3e8c27a09 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/tasks.c -@@ -0,0 +1,1254 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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 -+#include -+ -+/* FreeRTOS includes. */ -+#include "FreeRTOS.h" -+#include "task.h" -+ -+//TODO: check configMAX_PRIORITIES == RT_THREAD_PRIORITY_MAX -+#define FREERTOS_PRIORITY_TO_RTTHREAD(priority) ( configMAX_PRIORITIES - 1 - ( priority ) ) -+#define RTTHREAD_PRIORITY_TO_FREERTOS(priority) ( RT_THREAD_PRIORITY_MAX - 1 - ( priority ) ) -+ -+/* Values that can be assigned to the ucNotifyState member of the TCB. */ -+#define taskNOT_WAITING_NOTIFICATION ( ( uint8_t ) 0 ) /* Must be zero as it is the initialised value. */ -+#define taskWAITING_NOTIFICATION ( ( uint8_t ) 1 ) -+#define taskNOTIFICATION_RECEIVED ( ( uint8_t ) 2 ) -+ -+/* -+ * Several functions take a TaskHandle_t parameter that can optionally be NULL, -+ * where NULL is used to indicate that the handle of the currently executing -+ * task should be used in place of the parameter. This macro simply checks to -+ * see if the parameter is NULL and returns a pointer to the appropriate TCB. -+ */ -+#define prvGetTCBFromHandle( pxHandle ) ( ( ( pxHandle ) == NULL ) ? ( xTaskGetCurrentTaskHandle() ) : ( pxHandle ) ) -+ -+/* -+ * Task control block. A task control block (TCB) is allocated for each task, -+ * and stores task state information, including a pointer to the task's context -+ * (the task's run time environment, including register values) -+ */ -+typedef struct tskTaskControlBlock -+{ -+ struct rt_thread thread; -+ #if ( configUSE_APPLICATION_TASK_TAG == 1 ) -+ TaskHookFunction_t pxTaskTag; -+ #endif -+ #if ( configUSE_TASK_NOTIFICATIONS == 1 ) -+ volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; -+ volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; -+ #endif -+ #if ( INCLUDE_xTaskAbortDelay == 1 ) -+ uint8_t ucDelayAborted; -+ #endif -+} tskTCB; -+typedef tskTCB TCB_t; -+ -+/* Other file private variables. --------------------------------*/ -+static volatile BaseType_t xSchedulerRunning = pdFALSE; -+ -+/*-----------------------------------------------------------*/ -+ -+/* -+ * Called after a Task_t structure has been allocated either statically or -+ * dynamically to fill in the structure's members. -+ */ -+static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, -+ const char * const pcName, -+ const uint32_t ulStackDepth, -+ void * const pvParameters, -+ UBaseType_t uxPriority, -+ TaskHandle_t * const pxCreatedTask, -+ TCB_t * pxNewTCB, -+ StackType_t * const puxStackBuffer ); -+ -+#if ( configSUPPORT_STATIC_ALLOCATION == 1 ) -+ -+ TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode, -+ const char * const pcName, -+ const uint32_t ulStackDepth, -+ void * const pvParameters, -+ UBaseType_t uxPriority, -+ StackType_t * const puxStackBuffer, -+ StaticTask_t * const pxTaskBuffer ) -+ { -+ TCB_t * pxNewTCB; -+ TaskHandle_t xReturn = NULL; -+ -+ configASSERT( puxStackBuffer != NULL ); -+ configASSERT( pxTaskBuffer != NULL ); -+ -+ #if ( configASSERT_DEFINED == 1 ) -+ { -+ /* Sanity check that the size of the structure used to declare a -+ * variable of type StaticTask_t equals the size of the real task -+ * structure. */ -+ volatile size_t xSize = sizeof( StaticTask_t ); -+ configASSERT( xSize == sizeof( TCB_t ) ); -+ ( void ) xSize; /* Prevent lint warning when configASSERT() is not used. */ -+ } -+ #endif /* configASSERT_DEFINED */ -+ -+ if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) ) -+ { -+ pxNewTCB = ( TCB_t * ) pxTaskBuffer; -+ prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, puxStackBuffer ); -+ rt_thread_startup( ( rt_thread_t ) pxNewTCB ); -+ } -+ -+ return xReturn; -+ } -+ -+#endif /* SUPPORT_STATIC_ALLOCATION */ -+ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ -+ BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, -+ const char * const pcName, -+ const configSTACK_DEPTH_TYPE usStackDepth, -+ void * const pvParameters, -+ UBaseType_t uxPriority, -+ TaskHandle_t * const pxCreatedTask ) -+ { -+ TCB_t * pxNewTCB; -+ BaseType_t xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; -+ void * stack_start = RT_NULL; -+ -+ pxNewTCB = ( TCB_t * ) RT_KERNEL_MALLOC( sizeof( TCB_t ) ); -+ if ( pxNewTCB != NULL ) -+ { -+ stack_start = RT_KERNEL_MALLOC( usStackDepth * sizeof( StackType_t ) ); -+ if ( stack_start != RT_NULL ) -+ { -+ prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, ( StackType_t * ) stack_start ); -+ xReturn = pdPASS; -+ /* Mark as dynamic */ -+ ( ( struct rt_thread * ) pxNewTCB )->type &= ~RT_Object_Class_Static; -+ rt_thread_startup( ( rt_thread_t ) pxNewTCB ); -+ } -+ else -+ { -+ RT_KERNEL_FREE( pxNewTCB ); -+ } -+ } -+ -+ return xReturn; -+ } -+ -+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */ -+/*-----------------------------------------------------------*/ -+ -+/* ESP32 */ -+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ -+ BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pvTaskCode, -+ const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ -+ const uint32_t usStackDepth, -+ void * const pvParameters, -+ UBaseType_t uxPriority, -+ TaskHandle_t * const pvCreatedTask, -+ const BaseType_t xCoreID) -+ { -+ ( void ) xCoreID; -+ return xTaskCreate( pvTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pvCreatedTask ); -+ } -+ -+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */ -+/*-----------------------------------------------------------*/ -+ -+static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, -+ const char * const pcName, -+ const uint32_t ulStackDepth, -+ void * const pvParameters, -+ UBaseType_t uxPriority, -+ TaskHandle_t * const pxCreatedTask, -+ TCB_t * pxNewTCB, -+ StackType_t * const puxStackBuffer ) -+{ -+ /* This is used as an array index so must ensure it's not too large. */ -+ configASSERT( uxPriority < configMAX_PRIORITIES ); -+ -+ if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) -+ { -+ uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; -+ } -+ -+ rt_thread_init( ( struct rt_thread * ) pxNewTCB, pcName, pxTaskCode, pvParameters, -+ puxStackBuffer, ulStackDepth * sizeof( StackType_t ), FREERTOS_PRIORITY_TO_RTTHREAD( uxPriority ), 1 ); -+ -+#if ( configUSE_APPLICATION_TASK_TAG == 1 ) -+ pxNewTCB->pxTaskTag = NULL; -+#endif -+ -+#if ( configUSE_TASK_NOTIFICATIONS == 1 ) -+ rt_memset( ( void * ) &( pxNewTCB->ulNotifiedValue[ 0 ] ), 0x00, sizeof( pxNewTCB->ulNotifiedValue ) ); -+ rt_memset( ( void * ) &( pxNewTCB->ucNotifyState[ 0 ] ), 0x00, sizeof( pxNewTCB->ucNotifyState ) ); -+#endif -+ -+#if ( INCLUDE_xTaskAbortDelay == 1 ) -+ pxNewTCB->ucDelayAborted = pdFALSE; -+#endif -+ -+ if ( pxCreatedTask != NULL ) -+ { -+ *pxCreatedTask = ( TaskHandle_t ) pxNewTCB; -+ } -+} -+/*-----------------------------------------------------------*/ -+ -+#if ( INCLUDE_vTaskDelete == 1 ) -+ -+ void vTaskDelete( TaskHandle_t xTaskToDelete ) -+ { -+ rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTaskToDelete ); -+ if ( thread == RT_NULL ) -+ { -+ thread = rt_thread_self(); -+ } -+ #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) -+ if ( rt_object_is_systemobject( ( rt_object_t ) thread ) ) -+ #endif -+ { -+ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) -+ rt_thread_detach( thread ); -+ #endif -+ #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) -+ } -+ else -+ { -+ #endif -+ #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ rt_thread_delete( thread ); -+ #endif -+ } -+ -+ if ( thread == rt_thread_self() ) -+ { -+ rt_schedule(); -+ } -+ } -+ -+#endif /* INCLUDE_vTaskDelete */ -+/*-----------------------------------------------------------*/ -+ -+#if ( INCLUDE_xTaskDelayUntil == 1 ) -+ -+ BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime, -+ const TickType_t xTimeIncrement ) -+ { -+ BaseType_t xShouldDelay = pdFALSE; -+ rt_base_t level; -+ rt_tick_t cur_tick; -+ -+ RT_ASSERT( pxPreviousWakeTime != RT_NULL ); -+ RT_ASSERT( xTimeIncrement > 0U ); -+ -+ level = rt_hw_interrupt_disable(); -+ cur_tick = rt_tick_get(); -+ if (cur_tick - *pxPreviousWakeTime < xTimeIncrement) -+ { -+ rt_thread_delay_until( pxPreviousWakeTime, xTimeIncrement ); -+ xShouldDelay = pdTRUE; -+ } -+ rt_hw_interrupt_enable( level ); -+ -+ return xShouldDelay; -+ } -+ -+#endif /* INCLUDE_xTaskDelayUntil */ -+/*-----------------------------------------------------------*/ -+ -+#if ( INCLUDE_vTaskDelay == 1 ) -+ -+ void vTaskDelay( const TickType_t xTicksToDelay ) -+ { -+ rt_thread_delay( xTicksToDelay ); -+ } -+ -+#endif /* INCLUDE_vTaskDelay */ -+/*-----------------------------------------------------------*/ -+ -+#if ( ( INCLUDE_eTaskGetState == 1 ) || ( configUSE_TRACE_FACILITY == 1 ) || ( INCLUDE_xTaskAbortDelay == 1 ) ) -+ -+ eTaskState eTaskGetState( TaskHandle_t xTask ) -+ { -+ eTaskState eReturn; -+ rt_thread_t thread = ( rt_thread_t ) xTask; -+ rt_base_t level; -+ -+ configASSERT( xTask ); -+ -+ level = rt_hw_interrupt_disable(); -+ -+ switch ( thread->stat & RT_THREAD_STAT_MASK ) -+ { -+ case RT_THREAD_READY: -+ { -+ eReturn = eReady; -+ break; -+ } -+ case RT_THREAD_SUSPEND: -+ { -+ /* If thread timer is activated it is blocked with a timeout */ -+ if ( thread->thread_timer.parent.flag & RT_TIMER_FLAG_ACTIVATED ) -+ { -+ eReturn = eBlocked; -+ } -+ /* Otherwise it is suspended or blocked with an infinite timeout */ -+ else -+ { -+ eReturn = eSuspended; -+ } -+ break; -+ } -+ case RT_THREAD_RUNNING: -+ { -+ eReturn = eRunning; -+ break; -+ } -+ case RT_THREAD_CLOSE: -+ { -+ eReturn = eDeleted; -+ break; -+ } -+ default: -+ eReturn = eInvalid; -+ } -+ -+ rt_hw_interrupt_enable( level ); -+ -+ return eReturn; -+ } -+ -+#endif /* INCLUDE_eTaskGetState */ -+/*-----------------------------------------------------------*/ -+ -+#if ( INCLUDE_uxTaskPriorityGet == 1 ) -+ -+ UBaseType_t uxTaskPriorityGet( const TaskHandle_t xTask ) -+ { -+ UBaseType_t uxReturn; -+ rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTask ); -+ rt_base_t level; -+ -+ level = rt_hw_interrupt_disable(); -+ uxReturn = thread->current_priority; -+ rt_hw_interrupt_enable( level ); -+ -+ return RTTHREAD_PRIORITY_TO_FREERTOS( uxReturn ); -+ } -+ -+#endif /* INCLUDE_uxTaskPriorityGet */ -+/*-----------------------------------------------------------*/ -+ -+#if ( INCLUDE_uxTaskPriorityGet == 1 ) -+ -+ UBaseType_t uxTaskPriorityGetFromISR( const TaskHandle_t xTask ) -+ { -+ return uxTaskPriorityGet( xTask ); -+ } -+ -+#endif /* INCLUDE_uxTaskPriorityGet */ -+/*-----------------------------------------------------------*/ -+ -+#if ( INCLUDE_vTaskPrioritySet == 1 ) -+ -+ void vTaskPrioritySet( TaskHandle_t xTask, -+ UBaseType_t uxNewPriority ) -+ { -+ extern rt_thread_t rt_current_thread; -+ rt_thread_t thread; -+ rt_uint8_t current_priority; -+ rt_bool_t need_schedule = RT_FALSE; -+ rt_base_t level; -+ -+ configASSERT( uxNewPriority < configMAX_PRIORITIES ); -+ -+ /* Ensure the new priority is valid. */ -+ if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES ) -+ { -+ uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U; -+ } -+ uxNewPriority = FREERTOS_PRIORITY_TO_RTTHREAD( uxNewPriority ); -+ -+ level = rt_hw_interrupt_disable(); -+ -+ thread = ( rt_thread_t ) prvGetTCBFromHandle( xTask ); -+ current_priority = thread->current_priority; -+ if ( current_priority != uxNewPriority ) -+ { -+ rt_thread_control( thread, RT_THREAD_CTRL_CHANGE_PRIORITY, &uxNewPriority); -+ if ( uxNewPriority < current_priority ) -+ { -+ /* The priority of a task other than the currently running task is being raised. -+ * Need to schedule if the priority is raised above that of the running task */ -+ if ( thread != rt_current_thread && uxNewPriority <= rt_current_thread->current_priority ) -+ { -+ need_schedule = RT_TRUE; -+ } -+ } -+ /* Setting the priority of the running task down means -+ * there may now be another task of higher priority that -+ * is ready to execute. */ -+ else if ( thread == rt_current_thread ) -+ { -+ need_schedule = RT_TRUE; -+ } -+ } -+ -+ rt_hw_interrupt_enable( level ); -+ -+ if ( need_schedule == RT_TRUE ) -+ { -+ rt_schedule(); -+ } -+ } -+ -+#endif /* INCLUDE_vTaskPrioritySet */ -+/*-----------------------------------------------------------*/ -+ -+#if ( INCLUDE_vTaskSuspend == 1 ) -+ -+ void vTaskSuspend( TaskHandle_t xTaskToSuspend ) -+ { -+ rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTaskToSuspend ); -+ if ( rt_thread_suspend( thread ) == RT_EOK ) -+ { -+ rt_schedule(); -+ } -+ } -+ -+#endif /* INCLUDE_vTaskSuspend */ -+/*-----------------------------------------------------------*/ -+ -+#if ( INCLUDE_vTaskSuspend == 1 ) -+ -+ void vTaskResume( TaskHandle_t xTaskToResume ) -+ { -+ rt_thread_t thread = ( rt_thread_t ) xTaskToResume; -+ rt_bool_t need_schedule = RT_FALSE; -+ rt_base_t level; -+ -+ /* It does not make sense to resume the calling task. */ -+ configASSERT( xTaskToResume ); -+ -+ if ( thread != NULL && thread != rt_thread_self() ) -+ { -+ level = rt_hw_interrupt_disable(); -+ /* A task with higher priority than the current running task is ready */ -+ if ( rt_thread_resume( thread ) == RT_EOK && thread->current_priority <= rt_thread_self()->current_priority ) -+ { -+ need_schedule = RT_TRUE; -+ } -+ rt_hw_interrupt_enable( level ); -+ } -+ if (need_schedule == RT_TRUE) -+ { -+ rt_schedule(); -+ } -+ } -+ -+#endif /* INCLUDE_vTaskSuspend */ -+ -+/*-----------------------------------------------------------*/ -+ -+#if ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) -+ -+ BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume ) -+ { -+ vTaskResume( xTaskToResume ); -+ return pdFALSE; -+ } -+ -+#endif /* ( ( INCLUDE_xTaskResumeFromISR == 1 ) && ( INCLUDE_vTaskSuspend == 1 ) ) */ -+/*-----------------------------------------------------------*/ -+ -+void vTaskStartScheduler( void ) -+{ -+ xSchedulerRunning = pdTRUE; -+} -+/*-----------------------------------------------------------*/ -+ -+void vTaskEndScheduler( void ) -+{ -+ xSchedulerRunning = pdFALSE; -+ vPortEndScheduler(); -+} -+/*----------------------------------------------------------*/ -+ -+#if ( configUSE_NEWLIB_REENTRANT == 1 ) -+struct _reent* __getreent(void) { -+ return _GLOBAL_REENT; -+} -+#endif -+ -+void vTaskSuspendAll( void ) -+{ -+ rt_enter_critical(); -+} -+/*----------------------------------------------------------*/ -+ -+BaseType_t xTaskResumeAll( void ) -+{ -+ rt_exit_critical(); -+ return pdFALSE; -+} -+/*-----------------------------------------------------------*/ -+ -+TickType_t xTaskGetTickCount( void ) -+{ -+ return rt_tick_get(); -+} -+/*-----------------------------------------------------------*/ -+ -+TickType_t xTaskGetTickCountFromISR( void ) -+{ -+ return rt_tick_get(); -+} -+/*-----------------------------------------------------------*/ -+ -+UBaseType_t uxTaskGetNumberOfTasks( void ) -+{ -+ UBaseType_t uxReturn = 0; -+ rt_base_t level; -+ struct rt_object_information *information; -+ struct rt_list_node *node = RT_NULL; -+ -+ information = rt_object_get_information( RT_Object_Class_Thread ); -+ RT_ASSERT( information != RT_NULL ); -+ -+ level = rt_hw_interrupt_disable(); -+ -+ rt_list_for_each( node, &( information->object_list ) ) -+ { -+ uxReturn += 1; -+ } -+ -+ rt_hw_interrupt_enable( level ); -+ -+ return uxReturn; -+} -+/*-----------------------------------------------------------*/ -+ -+char * pcTaskGetName( TaskHandle_t xTaskToQuery ) -+{ -+ rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTaskToQuery ); -+ return &( thread->name[ 0 ] ); -+} -+/*-----------------------------------------------------------*/ -+ -+#if ( INCLUDE_xTaskGetHandle == 1 ) -+ -+ TaskHandle_t xTaskGetHandle( const char * pcNameToQuery ) -+ { -+ return ( TaskHandle_t ) rt_thread_find( ( char * ) pcNameToQuery ); -+ } -+ -+#endif /* INCLUDE_xTaskGetHandle */ -+/*-----------------------------------------------------------*/ -+ -+#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) -+ -+ TaskHandle_t xTaskGetIdleTaskHandle( void ) -+ { -+ return ( TaskHandle_t ) rt_thread_find( "tidle0" ); -+ } -+ -+#endif /* INCLUDE_xTaskGetIdleTaskHandle */ -+/*----------------------------------------------------------*/ -+ -+#if ( INCLUDE_xTaskAbortDelay == 1 ) -+ -+ BaseType_t xTaskAbortDelay( TaskHandle_t xTask ) -+ { -+ TCB_t * pxTCB = xTask; -+ BaseType_t xReturn; -+ rt_thread_t thread = ( rt_thread_t ) xTask; -+ rt_bool_t need_schedule = RT_FALSE; -+ rt_base_t level; -+ -+ configASSERT( pxTCB ); -+ -+ level = rt_hw_interrupt_disable(); -+ -+ if ( eTaskGetState( xTask ) == eBlocked ) -+ { -+ rt_thread_resume( thread ); -+ thread->error = -RT_ETIMEOUT; -+ pxTCB->ucDelayAborted = pdTRUE; -+ if ( thread->current_priority < rt_thread_self()->current_priority ){ -+ need_schedule = RT_TRUE; -+ } -+ xReturn = pdPASS; -+ } -+ else -+ { -+ xReturn = pdFAIL; -+ } -+ -+ rt_hw_interrupt_enable( level ); -+ -+ if ( need_schedule == RT_TRUE ) -+ { -+ rt_schedule(); -+ } -+ -+ return xReturn; -+ } -+ -+#endif /* INCLUDE_xTaskAbortDelay */ -+/*----------------------------------------------------------*/ -+ -+#if ( configUSE_APPLICATION_TASK_TAG == 1 ) -+ -+ void vTaskSetApplicationTaskTag( TaskHandle_t xTask, -+ TaskHookFunction_t pxHookFunction ) -+ { -+ TCB_t * xTCB = prvGetTCBFromHandle( xTask ); -+ rt_base_t level; -+ -+ level = rt_hw_interrupt_disable(); -+ xTCB->pxTaskTag = pxHookFunction; -+ rt_hw_interrupt_enable( level ); -+ } -+ -+#endif /* configUSE_APPLICATION_TASK_TAG */ -+/*-----------------------------------------------------------*/ -+ -+#if ( configUSE_APPLICATION_TASK_TAG == 1 ) -+ -+ TaskHookFunction_t xTaskGetApplicationTaskTag( TaskHandle_t xTask ) -+ { -+ TaskHookFunction_t xReturn; -+ TCB_t * xTCB = prvGetTCBFromHandle( xTask ); -+ rt_base_t level; -+ -+ level = rt_hw_interrupt_disable(); -+ xReturn = xTCB->pxTaskTag; -+ rt_hw_interrupt_enable( level ); -+ -+ return xReturn; -+ } -+ -+#endif /* configUSE_APPLICATION_TASK_TAG */ -+/*-----------------------------------------------------------*/ -+ -+#if ( configUSE_APPLICATION_TASK_TAG == 1 ) -+ -+ TaskHookFunction_t xTaskGetApplicationTaskTagFromISR( TaskHandle_t xTask ) -+ { -+ return xTaskGetApplicationTaskTag( xTask ); -+ } -+ -+#endif /* configUSE_APPLICATION_TASK_TAG */ -+/*-----------------------------------------------------------*/ -+ -+#if ( configUSE_APPLICATION_TASK_TAG == 1 ) -+ -+ BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, -+ void * pvParameter ) -+ { -+ BaseType_t xReturn; -+ TCB_t * xTCB = prvGetTCBFromHandle( xTask ); -+ -+ if( xTCB->pxTaskTag != NULL ) -+ { -+ xReturn = xTCB->pxTaskTag( pvParameter ); -+ } -+ else -+ { -+ xReturn = pdFAIL; -+ } -+ -+ return xReturn; -+ } -+ -+#endif /* configUSE_APPLICATION_TASK_TAG */ -+/*-----------------------------------------------------------*/ -+ -+void vTaskSetTimeOutState( TimeOut_t * const pxTimeOut ) -+{ -+ rt_base_t level; -+ -+ configASSERT( pxTimeOut ); -+ level = rt_hw_interrupt_disable(); -+ pxTimeOut->xOverflowCount = 0; -+ pxTimeOut->xTimeOnEntering = ( TickType_t ) rt_tick_get(); -+ rt_hw_interrupt_enable( level ); -+} -+/*-----------------------------------------------------------*/ -+ -+void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) -+{ -+ /* For internal use only as it does not use a critical section. */ -+ pxTimeOut->xOverflowCount = 0; -+ pxTimeOut->xTimeOnEntering = ( TickType_t ) rt_tick_get();; -+} -+/*-----------------------------------------------------------*/ -+ -+BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, -+ TickType_t * const pxTicksToWait ) -+{ -+ TCB_t * pxCurrentTCB = ( TCB_t * ) rt_thread_self(); -+ BaseType_t xReturn; -+ rt_base_t level; -+ -+ configASSERT( pxTimeOut ); -+ configASSERT( pxTicksToWait ); -+ -+ level = rt_hw_interrupt_disable(); -+ /* Minor optimisation. The tick count cannot change in this block. */ -+ const TickType_t xConstTickCount = ( TickType_t ) rt_tick_get(); -+ const TickType_t xElapsedTime = xConstTickCount - pxTimeOut->xTimeOnEntering; -+ -+#if ( INCLUDE_xTaskAbortDelay == 1 ) -+ if( pxCurrentTCB->ucDelayAborted != ( uint8_t ) pdFALSE ) -+ { -+ /* The delay was aborted, which is not the same as a time out, -+ * but has the same result. */ -+ pxCurrentTCB->ucDelayAborted = pdFALSE; -+ xReturn = pdTRUE; -+ } -+ else -+#endif -+ -+#if ( INCLUDE_vTaskSuspend == 1 ) -+ if( *pxTicksToWait == portMAX_DELAY ) -+ { -+ /* If INCLUDE_vTaskSuspend is set to 1 and the block time -+ * specified is the maximum block time then the task should block -+ * indefinitely, and therefore never time out. */ -+ xReturn = pdFALSE; -+ } -+ else -+#endif -+ -+ if( xElapsedTime < *pxTicksToWait ) -+ { -+ /* Not a genuine timeout. Adjust parameters for time remaining. */ -+ *pxTicksToWait -= xElapsedTime; -+ vTaskInternalSetTimeOutState( pxTimeOut ); -+ xReturn = pdFALSE; -+ } -+ else -+ { -+ *pxTicksToWait = ( TickType_t ) 0; -+ xReturn = pdTRUE; -+ } -+ rt_hw_interrupt_enable( level ); -+ -+ return xReturn; -+} -+/*-----------------------------------------------------------*/ -+ -+#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) ) -+ -+ TaskHandle_t xTaskGetCurrentTaskHandle( void ) -+ { -+ TaskHandle_t xReturn; -+ -+ /* A critical section is not required as this is not called from -+ * an interrupt and the current TCB will always be the same for any -+ * individual execution thread. */ -+ xReturn = ( TaskHandle_t ) rt_thread_self(); -+ -+ return xReturn; -+ } -+ -+#endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */ -+/*-----------------------------------------------------------*/ -+ -+#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) ) -+ -+ BaseType_t xTaskGetSchedulerState( void ) -+ { -+ BaseType_t xReturn; -+ -+ if( xSchedulerRunning == pdFALSE ) -+ { -+ xReturn = taskSCHEDULER_NOT_STARTED; -+ } -+ else -+ { -+ if( rt_critical_level() == 0 ) -+ { -+ xReturn = taskSCHEDULER_RUNNING; -+ } -+ else -+ { -+ xReturn = taskSCHEDULER_SUSPENDED; -+ } -+ } -+ -+ return xReturn; -+ } -+ -+#endif /* ( ( INCLUDE_xTaskGetSchedulerState == 1 ) ) */ -+/*-----------------------------------------------------------*/ -+ -+#if ( configUSE_TASK_NOTIFICATIONS == 1 ) -+ -+ uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait, -+ BaseType_t xClearCountOnExit, -+ TickType_t xTicksToWait ) -+ { -+ uint32_t ulReturn; -+ TCB_t * pxCurrentTCB = ( TCB_t * ) rt_thread_self(); -+ rt_thread_t thread = ( rt_thread_t ) pxCurrentTCB; -+ rt_base_t level; -+ -+ configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES ); -+ -+ level = rt_hw_interrupt_disable(); -+ /* Only block if the notification count is not already non-zero. */ -+ if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL ) -+ { -+ /* Mark this task as waiting for a notification. */ -+ pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION; -+ -+ if( xTicksToWait > ( TickType_t ) 0 ) -+ { -+ rt_thread_suspend( thread ); -+ if ( ( rt_int32_t ) xTicksToWait > 0 ) -+ { -+ rt_timer_control(&(thread->thread_timer), -+ RT_TIMER_CTRL_SET_TIME, -+ &xTicksToWait); -+ rt_timer_start(&(thread->thread_timer)); -+ } -+ rt_hw_interrupt_enable(level); -+ rt_schedule(); -+ /* Clear thread error. */ -+ thread->error = RT_EOK; -+ } -+ } -+ rt_hw_interrupt_enable( level ); -+ -+ level = rt_hw_interrupt_disable(); -+ ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ]; -+ -+ if( ulReturn != 0UL ) -+ { -+ if( xClearCountOnExit != pdFALSE ) -+ { -+ pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = 0UL; -+ } -+ else -+ { -+ pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = ulReturn - ( uint32_t ) 1; -+ } -+ } -+ -+ pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION; -+ rt_hw_interrupt_enable( level ); -+ -+ return ulReturn; -+ } -+ -+#endif /* configUSE_TASK_NOTIFICATIONS */ -+/*-----------------------------------------------------------*/ -+ -+#if ( configUSE_TASK_NOTIFICATIONS == 1 ) -+ -+ BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait, -+ uint32_t ulBitsToClearOnEntry, -+ uint32_t ulBitsToClearOnExit, -+ uint32_t * pulNotificationValue, -+ TickType_t xTicksToWait ) -+ { -+ BaseType_t xReturn; -+ TCB_t * pxCurrentTCB = ( TCB_t * ) rt_thread_self(); -+ rt_thread_t thread = ( rt_thread_t ) pxCurrentTCB; -+ rt_base_t level; -+ -+ configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES ); -+ -+ level = rt_hw_interrupt_disable(); -+ /* Only block if a notification is not already pending. */ -+ if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED ) -+ { -+ /* Clear bits in the task's notification value as bits may get -+ * set by the notifying task or interrupt. This can be used to -+ * clear the value to zero. */ -+ pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnEntry; -+ -+ /* Mark this task as waiting for a notification. */ -+ pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION; -+ -+ if( xTicksToWait > ( TickType_t ) 0 ) -+ { -+ rt_thread_suspend( thread ); -+ if ( ( rt_int32_t ) xTicksToWait > 0 ) -+ { -+ rt_timer_control(&(thread->thread_timer), -+ RT_TIMER_CTRL_SET_TIME, -+ &xTicksToWait); -+ rt_timer_start(&(thread->thread_timer)); -+ } -+ rt_hw_interrupt_enable(level); -+ rt_schedule(); -+ /* Clear thread error. It is not used to determine the function return value. */ -+ thread->error = RT_EOK; -+ } -+ else -+ { -+ rt_hw_interrupt_enable( level ); -+ } -+ } -+ else -+ { -+ rt_hw_interrupt_enable( level ); -+ } -+ -+ level = rt_hw_interrupt_disable(); -+ -+ if( pulNotificationValue != NULL ) -+ { -+ /* Output the current notification value, which may or may not -+ * have changed. */ -+ *pulNotificationValue = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ]; -+ } -+ -+ /* If ucNotifyValue is set then either the task never entered the -+ * blocked state (because a notification was already pending) or the -+ * task unblocked because of a notification. Otherwise the task -+ * unblocked because of a timeout. */ -+ if( pxCurrentTCB->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED ) -+ { -+ /* A notification was not received. */ -+ xReturn = pdFALSE; -+ } -+ else -+ { -+ /* A notification was already pending or a notification was -+ * received while the task was waiting. */ -+ pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnExit; -+ xReturn = pdTRUE; -+ } -+ -+ pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION; -+ rt_hw_interrupt_enable( level ); -+ -+ return xReturn; -+ } -+ -+#endif /* configUSE_TASK_NOTIFICATIONS */ -+/*-----------------------------------------------------------*/ -+ -+#if ( configUSE_TASK_NOTIFICATIONS == 1 ) -+ -+ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, -+ UBaseType_t uxIndexToNotify, -+ uint32_t ulValue, -+ eNotifyAction eAction, -+ uint32_t * pulPreviousNotificationValue ) -+ { -+ TCB_t * pxTCB; -+ BaseType_t xReturn = pdPASS; -+ uint8_t ucOriginalNotifyState; -+ rt_base_t level; -+ -+ configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES ); -+ configASSERT( xTaskToNotify ); -+ pxTCB = xTaskToNotify; -+ -+ level = rt_hw_interrupt_disable(); -+ -+ if( pulPreviousNotificationValue != NULL ) -+ { -+ *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ]; -+ } -+ -+ ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ]; -+ -+ pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED; -+ -+ switch( eAction ) -+ { -+ case eSetBits: -+ pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue; -+ break; -+ -+ case eIncrement: -+ ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++; -+ break; -+ -+ case eSetValueWithOverwrite: -+ pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue; -+ break; -+ -+ case eSetValueWithoutOverwrite: -+ -+ if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) -+ { -+ pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue; -+ } -+ else -+ { -+ /* The value could not be written to the task. */ -+ xReturn = pdFAIL; -+ } -+ -+ break; -+ -+ case eNoAction: -+ -+ /* The task is being notified without its notify value being -+ * updated. */ -+ break; -+ -+ default: -+ -+ /* Should not get here if all enums are handled. -+ * Artificially force an assert by testing a value the -+ * compiler can't assume is const. */ -+ configASSERT( xTaskToNotify == NULL ); -+ -+ break; -+ } -+ -+ -+ /* If the task is in the blocked state specifically to wait for a -+ * notification then unblock it now. */ -+ if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) -+ { -+ rt_thread_resume( ( rt_thread_t ) pxTCB ); -+ -+ if( ( ( rt_thread_t ) pxTCB )->current_priority < rt_thread_self()->current_priority ) -+ { -+ /* The notified task has a priority above the currently -+ * executing task so a schedule is required. */ -+ rt_schedule(); -+ } -+ } -+ rt_hw_interrupt_enable( level ); -+ -+ return xReturn; -+ } -+ -+#endif /* configUSE_TASK_NOTIFICATIONS */ -+/*-----------------------------------------------------------*/ -+ -+#if ( configUSE_TASK_NOTIFICATIONS == 1 ) -+ -+ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, -+ UBaseType_t uxIndexToNotify, -+ uint32_t ulValue, -+ eNotifyAction eAction, -+ uint32_t * pulPreviousNotificationValue, -+ BaseType_t * pxHigherPriorityTaskWoken ) -+ { -+ BaseType_t xReturn; -+ -+ xReturn = xTaskGenericNotify( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue ); -+ if ( pxHigherPriorityTaskWoken != NULL ) -+ { -+ *pxHigherPriorityTaskWoken = pdFALSE; -+ } -+ -+ return xReturn; -+ } -+ -+#endif /* configUSE_TASK_NOTIFICATIONS */ -+/*-----------------------------------------------------------*/ -+ -+#if ( configUSE_TASK_NOTIFICATIONS == 1 ) -+ -+ void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify, -+ UBaseType_t uxIndexToNotify, -+ BaseType_t * pxHigherPriorityTaskWoken ) -+ { -+ xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify ); -+ if ( pxHigherPriorityTaskWoken != NULL ) -+ { -+ *pxHigherPriorityTaskWoken = pdFALSE; -+ } -+ } -+ -+#endif /* configUSE_TASK_NOTIFICATIONS */ -+/*-----------------------------------------------------------*/ -+ -+#if ( configUSE_TASK_NOTIFICATIONS == 1 ) -+ -+ BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask, -+ UBaseType_t uxIndexToClear ) -+ { -+ TCB_t * pxTCB; -+ BaseType_t xReturn; -+ rt_base_t level; -+ -+ configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES ); -+ -+ /* If null is passed in here then it is the calling task that is having -+ * its notification state cleared. */ -+ pxTCB = prvGetTCBFromHandle( xTask ); -+ -+ level = rt_hw_interrupt_disable(); -+ -+ if( pxTCB->ucNotifyState[ uxIndexToClear ] == taskNOTIFICATION_RECEIVED ) -+ { -+ pxTCB->ucNotifyState[ uxIndexToClear ] = taskNOT_WAITING_NOTIFICATION; -+ xReturn = pdPASS; -+ } -+ else -+ { -+ xReturn = pdFAIL; -+ } -+ -+ rt_hw_interrupt_enable( level ); -+ -+ return xReturn; -+ } -+ -+#endif /* configUSE_TASK_NOTIFICATIONS */ -+/*-----------------------------------------------------------*/ -+ -+#if ( configUSE_TASK_NOTIFICATIONS == 1 ) -+ -+ uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask, -+ UBaseType_t uxIndexToClear, -+ uint32_t ulBitsToClear ) -+ { -+ TCB_t * pxTCB; -+ uint32_t ulReturn; -+ rt_base_t level; -+ -+ /* If null is passed in here then it is the calling task that is having -+ * its notification state cleared. */ -+ pxTCB = prvGetTCBFromHandle( xTask ); -+ -+ level = rt_hw_interrupt_disable(); -+ -+ /* Return the notification as it was before the bits were cleared, -+ * then clear the bit mask. */ -+ ulReturn = pxTCB->ulNotifiedValue[ uxIndexToClear ]; -+ pxTCB->ulNotifiedValue[ uxIndexToClear ] &= ~ulBitsToClear; -+ -+ rt_hw_interrupt_enable( level ); -+ -+ return ulReturn; -+ } -+ -+#endif /* configUSE_TASK_NOTIFICATIONS */ -+/*-----------------------------------------------------------*/ -+ -+#if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 ) -+ -+/* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the -+ * same except for their return type. Using configSTACK_DEPTH_TYPE allows the -+ * user to determine the return type. It gets around the problem of the value -+ * overflowing on 8-bit types without breaking backward compatibility for -+ * applications that expect an 8-bit return type. */ -+ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) -+ { -+ uint32_t ulCount = 0U; -+ rt_thread_t thread = ( rt_thread_t ) prvGetTCBFromHandle( xTask ); -+ rt_uint8_t * stack_addr = thread->stack_addr; -+ -+ #ifdef ARCH_CPU_STACK_GROWS_UPWARD -+ stack_addr = stack_addr + thread->stack_size - 1; -+ while ( *stack_addr == '#' ) -+ { -+ ulCount += 1; -+ stack_addr -= 1; -+ } -+ #else -+ while ( *stack_addr == '#' ) -+ { -+ ulCount += 1; -+ stack_addr += 1; -+ } -+ #endif -+ -+ ulCount /= ( uint32_t ) sizeof( StackType_t ); -+ -+ return ( configSTACK_DEPTH_TYPE ) ulCount; -+ } -+ -+#endif /* INCLUDE_uxTaskGetStackHighWaterMark2 */ -+/*-----------------------------------------------------------*/ -+ -+#if ( INCLUDE_uxTaskGetStackHighWaterMark == 1 ) -+ -+ UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) -+ { -+ return ( UBaseType_t ) uxTaskGetStackHighWaterMark2( xTask ); -+ } -+ -+#endif /* INCLUDE_uxTaskGetStackHighWaterMark */ -+/*-----------------------------------------------------------*/ -+ -+ -+/* ESP32 */ -+BaseType_t xTaskGetAffinity( TaskHandle_t xTask ) -+{ -+ ( void ) xTask; -+ return 0; -+} -+ -+TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t cpuid ) -+{ -+ ( void ) cpuid; -+ return xTaskGetCurrentTaskHandle(); -+} -+ -+TaskHandle_t xTaskGetIdleTaskHandleForCPU( UBaseType_t cpuid ) -+{ -+ ( void ) cpuid; -+ return xTaskGetIdleTaskHandle(); -+} -+ -+/* Unimplemented */ -+#include "esp_log.h" -+#if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) -+void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, -+ BaseType_t xIndex, -+ void * pvValue ) -+{ -+ ESP_LOGE("freertos", "vTaskSetThreadLocalStoragePointer unimplemented"); -+ RT_ASSERT(0); -+} -+void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery, -+ BaseType_t xIndex ) -+{ -+ ESP_LOGE("freertos", "pvTaskGetThreadLocalStoragePointer unimplemented"); -+ RT_ASSERT(0); -+ return NULL; -+} -+#if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS ) -+typedef void (*TlsDeleteCallbackFunction_t)( int, void * ); -+void vTaskSetThreadLocalStoragePointerAndDelCallback( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue, TlsDeleteCallbackFunction_t pvDelCallback) -+{ -+ ESP_LOGE("freertos", "vTaskSetThreadLocalStoragePointerAndDelCallback unimplemented"); -+ RT_ASSERT(0); -+} -+#endif -+#endif -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/timers.c b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/timers.c -new file mode 100644 -index 0000000000..b5b5693d53 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/FreeRTOS/timers.c -@@ -0,0 +1,328 @@ -+/* -+ * FreeRTOS Kernel V10.4.6 -+ * 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 -+ -+#include "FreeRTOS.h" -+#include "task.h" -+#include "queue.h" -+#include "timers.h" -+ -+/* This entire source file will be skipped if the application is not configured -+ * to include software timer functionality. This #if is closed at the very bottom -+ * of this file. If you want to include software timer functionality then ensure -+ * configUSE_TIMERS is set to 1 in FreeRTOSConfig.h. */ -+#if ( configUSE_TIMERS == 1 ) -+ -+ typedef void (* rt_timer_callback_t)(void *); -+ -+/* The definition of the timers themselves. */ -+ typedef struct tmrTimerControl -+ { -+ struct rt_timer timer; -+ void * pvTimerID; /*<< An ID to identify the timer. This allows the timer to be identified when the same callback is used for multiple timers. */ -+ } xTIMER; -+ -+ typedef xTIMER Timer_t; -+ -+/*-----------------------------------------------------------*/ -+ -+ #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ -+ TimerHandle_t xTimerCreate( const char * const pcTimerName, -+ const TickType_t xTimerPeriodInTicks, -+ const UBaseType_t uxAutoReload, -+ void * const pvTimerID, -+ TimerCallbackFunction_t pxCallbackFunction ) -+ { -+ Timer_t * pxNewTimer; -+ rt_uint8_t flag = RT_TIMER_FLAG_SOFT_TIMER; -+ -+ pxNewTimer = ( Timer_t * ) RT_KERNEL_MALLOC( sizeof( Timer_t ) ); -+ -+ if( pxNewTimer != RT_NULL ) -+ { -+ if ( uxAutoReload != pdFALSE ) -+ { -+ flag |= RT_TIMER_FLAG_PERIODIC; -+ } -+ else -+ { -+ flag |= RT_TIMER_FLAG_ONE_SHOT; -+ } -+ rt_timer_init( ( rt_timer_t ) pxNewTimer, pcTimerName, ( rt_timer_callback_t ) pxCallbackFunction, pxNewTimer, xTimerPeriodInTicks, flag ); -+ pxNewTimer->pvTimerID = pvTimerID; -+ /* Mark as dynamic so we can distinguish when deleting */ -+ ( ( rt_timer_t ) pxNewTimer )->parent.type &= ~RT_Object_Class_Static; -+ } -+ -+ return pxNewTimer; -+ } -+ -+ #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ -+/*-----------------------------------------------------------*/ -+ -+ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) -+ -+ TimerHandle_t xTimerCreateStatic( const char * const pcTimerName, -+ const TickType_t xTimerPeriodInTicks, -+ const UBaseType_t uxAutoReload, -+ void * const pvTimerID, -+ TimerCallbackFunction_t pxCallbackFunction, -+ StaticTimer_t * pxTimerBuffer ) -+ { -+ Timer_t * pxNewTimer; -+ rt_uint8_t flag = RT_TIMER_FLAG_SOFT_TIMER; -+ -+ #if ( configASSERT_DEFINED == 1 ) -+ { -+ /* Sanity check that the size of the structure used to declare a -+ * variable of type StaticTimer_t equals the size of the real timer -+ * structure. */ -+ volatile size_t xSize = sizeof( StaticTimer_t ); -+ configASSERT( xSize == sizeof( Timer_t ) ); -+ ( void ) xSize; /* Keeps lint quiet when configASSERT() is not defined. */ -+ } -+ #endif /* configASSERT_DEFINED */ -+ -+ /* A pointer to a StaticTimer_t structure MUST be provided, use it. */ -+ configASSERT( pxTimerBuffer ); -+ pxNewTimer = ( Timer_t * ) pxTimerBuffer; -+ -+ if( pxNewTimer != NULL ) -+ { -+ if ( uxAutoReload != pdFALSE ) -+ { -+ flag |= RT_TIMER_FLAG_PERIODIC; -+ } -+ else -+ { -+ flag |= RT_TIMER_FLAG_ONE_SHOT; -+ } -+ rt_timer_init( ( rt_timer_t ) pxNewTimer, pcTimerName, ( rt_timer_callback_t ) pxCallbackFunction, pxNewTimer, xTimerPeriodInTicks, flag ); -+ pxNewTimer->pvTimerID = pvTimerID; -+ } -+ -+ return pxNewTimer; -+ } -+ -+ #endif /* configSUPPORT_STATIC_ALLOCATION */ -+/*-----------------------------------------------------------*/ -+ -+ BaseType_t xTimerGenericCommand( TimerHandle_t xTimer, -+ const BaseType_t xCommandID, -+ const TickType_t xOptionalValue, -+ BaseType_t * const pxHigherPriorityTaskWoken, -+ const TickType_t xTicksToWait ) -+ { -+ rt_err_t err = -RT_ERROR; -+ -+ configASSERT( xTimer ); -+ -+ if ( ( xCommandID == tmrCOMMAND_START ) || ( xCommandID == tmrCOMMAND_START_FROM_ISR ) -+ || ( xCommandID == tmrCOMMAND_RESET ) || ( xCommandID == tmrCOMMAND_RESET_FROM_ISR ) ) -+ { -+ err = rt_timer_start( ( rt_timer_t ) xTimer ); -+ } -+ else if ( ( xCommandID == tmrCOMMAND_STOP ) || ( xCommandID == tmrCOMMAND_STOP_FROM_ISR ) ) -+ { -+ err = rt_timer_stop( ( rt_timer_t ) xTimer ); -+ } -+ else if ( ( xCommandID == tmrCOMMAND_CHANGE_PERIOD ) || ( xCommandID == tmrCOMMAND_CHANGE_PERIOD_FROM_ISR ) ) -+ { -+ if ( rt_timer_stop( ( rt_timer_t ) xTimer ) == RT_EOK ) -+ { -+ if ( rt_timer_control( ( rt_timer_t ) xTimer, RT_TIMER_CTRL_SET_TIME, ( void * ) &xOptionalValue ) == RT_EOK ) -+ { -+ err = rt_timer_start( ( rt_timer_t ) xTimer ); -+ } -+ } -+ } -+ else if ( xCommandID == tmrCOMMAND_DELETE ) -+ { -+ #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) -+ if ( rt_object_is_systemobject( ( rt_object_t ) xTimer ) ) -+ #endif -+ { -+ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) -+ err = rt_timer_detach( ( rt_timer_t ) xTimer ); -+ #endif -+ #if ( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) -+ } -+ else -+ { -+ #endif -+ #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) -+ ( ( rt_timer_t ) xTimer )->parent.type |= RT_Object_Class_Static; -+ err = rt_timer_detach( ( rt_timer_t ) xTimer ); -+ RT_KERNEL_FREE( xTimer ); -+ #endif -+ } -+ } -+ -+ if ( ( xCommandID >= tmrFIRST_FROM_ISR_COMMAND ) && ( xCommandID <= tmrCOMMAND_CHANGE_PERIOD_FROM_ISR ) && ( pxHigherPriorityTaskWoken != NULL ) ) -+ { -+ *pxHigherPriorityTaskWoken = pdFALSE; -+ } -+ -+ return rt_err_to_freertos( err ); -+ } -+/*-----------------------------------------------------------*/ -+ -+ TaskHandle_t xTimerGetTimerDaemonTaskHandle( void ) -+ { -+ return ( TaskHandle_t ) rt_thread_find( "timer" ); -+ } -+/*-----------------------------------------------------------*/ -+ -+ TickType_t xTimerGetPeriod( TimerHandle_t xTimer ) -+ { -+ Timer_t * pxTimer = xTimer; -+ rt_tick_t arg; -+ -+ configASSERT( xTimer ); -+ rt_timer_control( ( rt_timer_t ) pxTimer, RT_TIMER_CTRL_GET_TIME, &arg ); -+ -+ return ( TickType_t ) arg; -+ } -+/*-----------------------------------------------------------*/ -+ -+ void vTimerSetReloadMode( TimerHandle_t xTimer, -+ const UBaseType_t uxAutoReload ) -+ { -+ Timer_t * pxTimer = xTimer; -+ -+ configASSERT( xTimer ); -+ if ( uxAutoReload != pdFALSE ) -+ { -+ rt_timer_control( ( rt_timer_t ) pxTimer, RT_TIMER_CTRL_SET_PERIODIC, RT_NULL ); -+ } -+ else -+ { -+ rt_timer_control( ( rt_timer_t ) pxTimer, RT_TIMER_CTRL_SET_ONESHOT, RT_NULL ); -+ } -+ } -+/*-----------------------------------------------------------*/ -+ -+ UBaseType_t uxTimerGetReloadMode( TimerHandle_t xTimer ) -+ { -+ Timer_t * pxTimer = xTimer; -+ UBaseType_t uxReturn; -+ rt_base_t level; -+ -+ configASSERT( xTimer ); -+ level = rt_hw_interrupt_disable(); -+ if ( ( ( rt_timer_t ) pxTimer )->parent.flag & RT_TIMER_FLAG_PERIODIC ) -+ { -+ uxReturn = ( UBaseType_t ) pdTRUE; -+ } -+ else -+ { -+ uxReturn = ( UBaseType_t ) pdFALSE; -+ } -+ rt_hw_interrupt_enable( level ); -+ -+ return uxReturn; -+ } -+/*-----------------------------------------------------------*/ -+ -+ TickType_t xTimerGetExpiryTime( TimerHandle_t xTimer ) -+ { -+ Timer_t * pxTimer = xTimer; -+ TickType_t xReturn; -+ -+ configASSERT( xTimer ); -+ rt_timer_control( ( rt_timer_t ) pxTimer, RT_TIMER_CTRL_GET_REMAIN_TIME, &xReturn ); -+ -+ return xReturn; -+ } -+/*-----------------------------------------------------------*/ -+ -+ const char * pcTimerGetName( TimerHandle_t xTimer ) -+ { -+ Timer_t * pxTimer = xTimer; -+ -+ configASSERT( xTimer ); -+ return ( ( rt_timer_t ) pxTimer )->parent.name; -+ } -+/*-----------------------------------------------------------*/ -+ -+ BaseType_t xTimerIsTimerActive( TimerHandle_t xTimer ) -+ { -+ BaseType_t xReturn; -+ Timer_t * pxTimer = xTimer; -+ rt_uint32_t arg; -+ -+ configASSERT( xTimer ); -+ -+ rt_timer_control( ( rt_timer_t ) pxTimer, RT_TIMER_CTRL_GET_STATE, &arg ); -+ if ( arg == RT_TIMER_FLAG_ACTIVATED ) -+ { -+ xReturn = pdTRUE; -+ } -+ else -+ { -+ xReturn = pdFALSE; -+ } -+ -+ return xReturn; -+ } -+/*-----------------------------------------------------------*/ -+ -+ void * pvTimerGetTimerID( const TimerHandle_t xTimer ) -+ { -+ Timer_t * const pxTimer = xTimer; -+ void * pvReturn; -+ rt_base_t level; -+ -+ configASSERT( xTimer ); -+ -+ level = rt_hw_interrupt_disable(); -+ pvReturn = pxTimer->pvTimerID; -+ rt_hw_interrupt_enable( level ); -+ -+ return pvReturn; -+ } -+/*-----------------------------------------------------------*/ -+ -+ void vTimerSetTimerID( TimerHandle_t xTimer, -+ void * pvNewID ) -+ { -+ Timer_t * const pxTimer = xTimer; -+ rt_base_t level; -+ -+ configASSERT( xTimer ); -+ -+ level = rt_hw_interrupt_disable(); -+ pxTimer->pvTimerID = pvNewID; -+ rt_hw_interrupt_enable( level ); -+ } -+/*-----------------------------------------------------------*/ -+ -+#endif /* configUSE_TIMERS == 1 */ -diff --git a/components/freertos/RT-Thread-wrapper-of-FreeRTOS/readme.md b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/readme.md -new file mode 100644 -index 0000000000..6a0fafb4c7 ---- /dev/null -+++ b/components/freertos/RT-Thread-wrapper-of-FreeRTOS/readme.md -@@ -0,0 +1,3 @@ -+# RT-Thread操作系统的FreeRTOS兼容层 -+## FreeRTOS Application Compatibility Layer (ACL) for RT-Thread -+## 让基于FreeRTOS开发的应用层无感地迁移到RT-Thread操作系统 --- -2.32.0 (Apple Git-132) - - -From 9981521890074b517074bf85a4e0a1f71cef851e Mon Sep 17 00:00:00 2001 -From: tangzz98 -Date: Wed, 3 Aug 2022 16:17:06 +0800 -Subject: [PATCH 4/4] Update linker script for finsh - ---- - components/esp_system/ld/esp32c3/sections.ld.in | 10 ++++++++++ - 1 file changed, 10 insertions(+) - -diff --git a/components/esp_system/ld/esp32c3/sections.ld.in b/components/esp_system/ld/esp32c3/sections.ld.in -index 8215237fff..561ae92318 100644 ---- a/components/esp_system/ld/esp32c3/sections.ld.in -+++ b/components/esp_system/ld/esp32c3/sections.ld.in -@@ -248,6 +248,16 @@ SECTIONS - *(.fini.literal) - *(.fini) - *(.gnu.version) -+ -+ /* section information for finsh shell */ -+ . = ALIGN(4); -+ __fsymtab_start = .; -+ KEEP(*(FSymTab)) -+ __fsymtab_end = .; -+ . = ALIGN(4); -+ __vsymtab_start = .; -+ KEEP(*(VSymTab)) -+ __vsymtab_end = .; - - /** CPU will try to prefetch up to 16 bytes of - * of instructions. This means that any configuration (e.g. MMU, PMS) must allow -- 2.32.0 (Apple Git-132) diff --git a/tools/esp_idf.py b/tools/esp_idf.py index 2977b3a507..dc14f4ff2f 100644 --- a/tools/esp_idf.py +++ b/tools/esp_idf.py @@ -34,13 +34,23 @@ def GenerateCFiles(env,project): cm_file.write( "\t" + path.replace("\\", "/") + "\n") cm_file.write(")\n\n") - print(init_export) n = len(init_export) if n: cm_file.write("target_link_libraries(${COMPONENT_LIB}\n") for i in range(n): cm_file.write("\tINTERFACE \"-u __rt_init_" + init_export[i] + "\"\n") cm_file.write(")\n") + cm_file.close() + + cm_file = open('CMakeLists.txt', 'w') + if cm_file: + cm_file.write("cmake_minimum_required(VERSION 3.16)\n") + cm_file.write("set(COMPONENTS esptool_py main)\n") + cm_file.write("include($ENV{IDF_PATH}/tools/cmake/project.cmake)\n") + freertos_root = os.getcwd().replace('\\', '/') + '/packages/FreeRTOS_Wrapper-latest/FreeRTOS' + cm_file.write("set(freertos_root " + freertos_root + ')\n') + cm_file.write("project(rtthread)\n") + cm_file.close() def ESPIDFProject(env,project): print('Update setting files for CMakeLists.txt...')