freertos: Remove legacy hooks

This commit refactors the legacy hooks as follows:

- Removed CONFIG_FREERTOS_LEGACY_HOOKS
- FreeRTOS hooks are now enabled via:
    - CONFIG_FREERTOS_USE_IDLE_HOOK
    - CONFIG_FREERTOS_USE_TICK_HOOK
- Update IDF hooks documentation
This commit is contained in:
Darian Leung 2022-02-17 16:40:52 +08:00
parent 82c78db4df
commit 5f5daaa420
9 changed files with 76 additions and 76 deletions

View File

@ -273,9 +273,6 @@ 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
*
@ -411,10 +408,6 @@ static inline BaseType_t IRAM_ATTR xPortGetCoreID(void)
// ------------------- 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 ----------------------

View File

@ -363,9 +363,6 @@ static inline bool IRAM_ATTR xPortCanYield(void);
// ------------------- Hook Functions ----------------------
extern void esp_vApplicationIdleHook(void); /* Required by tasks.c */
extern void esp_vApplicationTickHook(void); /* Required by tasks.c */
/**
* @brief Hook function called on entry to tickless idle
*
@ -543,11 +540,6 @@ extern void _frxt_setup_switch( void ); //Defined in portasm.S
// ------------------- 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 ----------------------

View File

@ -58,7 +58,9 @@
#define taskEXIT_CRITICAL_ISR( ) portEXIT_CRITICAL_ISR( taskCRITICAL_MUX )
#undef _REENT_INIT_PTR
#define _REENT_INIT_PTR esp_reent_init
#endif
extern void esp_vApplicationTickHook(void);
extern void esp_vApplicationIdleHook(void);
#endif //ESP_PLATFORM
/* 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
@ -3101,10 +3103,7 @@ BaseType_t xTaskIncrementTick( void )
#if ( configUSE_TICK_HOOK == 1 )
vApplicationTickHook();
#endif /* configUSE_TICK_HOOK */
#if ( CONFIG_FREERTOS_LEGACY_HOOKS == 1 )
esp_vApplicationTickHook();
#endif /* CONFIG_FREERTOS_LEGACY_HOOKS */
if (xPortGetCoreID() != 0 )
{
return pdTRUE;
@ -3980,12 +3979,11 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
vApplicationIdleHook();
}
#endif /* configUSE_IDLE_HOOK */
#if ( CONFIG_FREERTOS_LEGACY_HOOKS == 1 )
{
/* Call the esp-idf hook system */
esp_vApplicationIdleHook();
}
#endif /* CONFIG_FREERTOS_LEGACY_HOOKS */
#ifdef ESP_PLATFORM
/* Call the esp-idf idle hook system */
esp_vApplicationIdleHook();
#endif // ESP_PLATFORM
/* This conditional compilation should use inequality to 0, not equality
* to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when

View File

@ -197,15 +197,25 @@ menu "FreeRTOS"
The interrupt handlers have their own stack. The size of the stack can be defined here.
Each processor has its own stack, so the total size occupied will be twice this.
config FREERTOS_LEGACY_HOOKS
bool "Use FreeRTOS legacy hooks"
config FREERTOS_USE_IDLE_HOOK
bool "Use FreeRTOS idle hook"
default n
help
FreeRTOS offers a number of hooks/callback functions that are called when a timer
tick happens, the idle thread runs etc. esp-idf replaces these by runtime registerable
hooks using the esp_register_freertos_xxx_hook system, but for legacy reasons the old
hooks can also still be enabled. Please enable this only if you have code that for some
reason can't be migrated to the esp_register_freertos_xxx_hook system.
- If enabled, configUSE_IDLE_HOOK will be defined as 1 in FreeRTOS.
- The application must provide the hook function ``void vApplicationIdleHook( void );``
- ``vApplicationIdleHook()`` is called from FreeRTOS idle task(s)
- The FreeRTOS idle hook is NOT the same as the ESP-IDF Idle Hook, but both can be enabled
simultaneously.
config FREERTOS_USE_TICK_HOOK
bool "Use FreeRTOS tick hook"
default n
help
- If enabled, configUSE_TICK_HOOK will be defined as 1 in FreeRTOS.
- The application must provide the hook function ``void vApplicationTickHook( void );``
- ``vApplicationTickHook()`` is called from FreeRTOS's tick handling function ``xTaskIncrementTick()``
- The FreeRTOS tick hook is NOT the same as the ESP-IDF Tick Interrupt Hook, but both can be enabled
simultaneously.
config FREERTOS_MAX_TASK_NAME_LEN
int "Maximum task name length"

View File

@ -140,8 +140,8 @@ This file get's pulled into assembly sources. Therefore, some includes need to b
// ------------------------ Hooks --------------------------
#define configUSE_IDLE_HOOK 1
#define configUSE_TICK_HOOK 1
#define configUSE_IDLE_HOOK CONFIG_FREERTOS_USE_IDLE_HOOK
#define configUSE_TICK_HOOK CONFIG_FREERTOS_USE_TICK_HOOK
#if CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE
#define configCHECK_FOR_STACK_OVERFLOW 0
#elif CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL

View File

@ -1,8 +1,9 @@
/*
Test of FreeRTOS "legacy" hook functions, and delete hook
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Only compiled in if the relevant options are enabled.
*/
#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
@ -11,7 +12,10 @@
#include "unity.h"
#include "test_utils.h"
#if CONFIG_FREERTOS_LEGACY_HOOKS
/*
Test FreeRTOS idle hook. Only compiled in if FreeRTOS idle hooks are enabled.
*/
#if ( configUSE_IDLE_HOOK == 1 )
static volatile unsigned idle_count;
@ -20,31 +24,38 @@ void vApplicationIdleHook(void)
idle_count++;
}
TEST_CASE("legacy idle hook is correctly called based on config", "[freertos]")
TEST_CASE("FreeRTOS idle hook", "[freertos]")
{
idle_count = 0;
vTaskDelay(10);
TEST_ASSERT_NOT_EQUAL(0, idle_count); // The legacy idle hook should be called at least once
}
#endif // configUSE_IDLE_HOOK
/*
Test the FreeRTOS tick hook. Only compiled in if FreeRTOS tick hooks are enabled.
*/
#if ( configUSE_TICK_HOOK == 1 )
static volatile unsigned tick_count;
void IRAM_ATTR vApplicationTickHook(void)
void vApplicationTickHook(void)
{
tick_count++;
}
TEST_CASE("legacy tick hook is called based on config", "[freertos]")
TEST_CASE("FreeRTOS tick hook", "[freertos]")
{
unsigned before = xTaskGetTickCount();
const unsigned SLEEP_FOR = 20;
tick_count = before;
vTaskDelay(SLEEP_FOR);
TEST_ASSERT_UINT32_WITHIN_MESSAGE(3 * portNUM_PROCESSORS, before + SLEEP_FOR * portNUM_PROCESSORS, tick_count,
"The legacy tick hook should have been called approx 1 time per tick per CPU");
"The FreeRTOS tick hook should have been called approx 1 time per tick per CPU");
}
#endif // CONFIG_FREERTOS_LEGACY_HOOKS
#endif // configUSE_TICK_HOOK
#if CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP

View File

@ -156,14 +156,6 @@ extern void vPortClearInterruptMask(int);
extern void vPortEnterCritical(void);
extern void vPortExitCritical(void);
extern void esp_vApplicationIdleHook(void);
extern void esp_vApplicationTickHook(void);
#ifndef CONFIG_FREERTOS_LEGACY_HOOKS
#define vApplicationIdleHook esp_vApplicationIdleHook
#define vApplicationTickHook esp_vApplicationTickHook
#endif /* !CONFIG_FREERTOS_LEGACY_HOOKS */
/* 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)

View File

@ -1,12 +1,13 @@
FreeRTOS Additions
==================
FreeRTOS Supplemental Features
==============================
This document describes the additional features added to ESP-IDF FreeRTOS. This document is split into the following parts:
ESP-IDF uses a modified version of FreeRTOS v10.4.3 that contains significant changes for SMP compatibility (see :doc:`ESP-IDF FreeRTOS SMP Changes<../../api-guides/freertos-smp>`). However, in addition to ESP-IDF FreeRTOS, various features are also provided by ESP-IDF to supplement the features offered by FreeRTOS.
This document describes these supplemental features added to ESP-IDF. This document is split into the following sections:
.. contents:: Contents
:depth: 2
.. ---------------------------------------------------- Overview -------------------------------------------------------
Overview
@ -15,7 +16,7 @@ Overview
ESP-IDF FreeRTOS is modified version of based on the Xtensa port of FreeRTOS v10.4.3 with significant modifications for SMP compatibility (see :doc:`ESP-IDF FreeRTOS SMP Changes<../../api-guides/freertos-smp>`). However, various new features specific to ESP-IDF FreeRTOS have been added. The features are as follows:
- **Ring buffers**: Ring buffers provide a FIFO buffer that can accept entries of arbitrary lengths.
- **Hooks**: ESP-IDF FreeRTOS hooks provides support for registering extra Idle and Tick hooks at run time. Moreover, the hooks can be asymmetric among both CPUs.
- **ESP-IDF Tick and Idle Hooks**: ESP-IDF provides multiple custom tick interrupt hooks and idle task hooks that are more numerous and more flexible when compared to FreeRTOS tick and idle hooks.
- **Thread Local Storage Pointer (TLSP) Deletion Callbacks**: TLSP Deletion callbacks are run automatically when a task is deleted, thus allowing users to clean up their TLSPs automatically.
- **Component Specific Properties**: Currently added only one component specific property ``ORIG_INCLUDE_PATH``.
@ -375,40 +376,43 @@ However, in between iterations of acquiring the semaphore, there is a **gap in t
This side effect will not affect ring buffer performance drastically given if the number of tasks using the ring buffer simultaneously is low, and the ring buffer is not operating near maximum capacity.
.. ------------------------------------------------------ Hooks --------------------------------------------------------
.. ------------------------------------------- ESP-IDF Tick and Idle Hooks ---------------------------------------------
Hooks
-----
ESP-IDF Tick and Idle Hooks
---------------------------
FreeRTOS consists of Idle Hooks and Tick Hooks which allow for application specific functionality to be added to the Idle Task and Tick Interrupt. ESP-IDF provides its own Idle and Tick Hook API in addition to the hooks provided by vanilla FreeRTOS. ESP-IDF hooks have the added benefit of being run time configurable and asymmetrical.
FreeRTOS allows applications to provide a tick hook and an idle hook at compile time:
Vanilla FreeRTOS Hooks
^^^^^^^^^^^^^^^^^^^^^^
- FreeRTOS tick hook can be enabled via the :ref:`CONFIG_FREERTOS_USE_TICK_HOOK` option. The application must provide the ``void vApplicationTickHook( void )`` callback.
- FreeRTOS idle hook can be enabled via the :ref:`CONFIG_FREERTOS_USE_IDLE_HOOK` option. The application must provide the ``void vApplicationIdleHook( void )`` callback.
Idle and Tick Hooks in vanilla FreeRTOS are implemented by the user defining the functions ``vApplicationIdleHook()`` and ``vApplicationTickHook()`` respectively somewhere in the application. Vanilla FreeRTOS will run the user defined Idle Hook and Tick Hook on every iteration of the Idle Task and Tick Interrupt respectively.
However, the FreeRTOS tick hook and idle hook have the following draw backs:
Vanilla FreeRTOS hooks are referred to as **Legacy Hooks** in ESP-IDF FreeRTOS. To enable legacy hooks, :ref:`CONFIG_FREERTOS_LEGACY_HOOKS` should be enabled in :doc:`project configuration menu </api-reference/kconfig>`.
- The FreeRTOS hooks are registered at compile time
- Only one of each hook can be registered
- On multi-core targets, the FreeRTOS hooks are symmetric, meaning each CPU's tick interrupt and idle tasks ends up calling the same hook.
.. only:: not CONFIG_FREERTOS_UNICORE
Therefore, ESP-IDF tick and idle hooks are provided to supplement the features of FreeRTOS tick and idle hooks. The ESP-IDF hooks have the following features:
Due to vanilla FreeRTOS being designed for single core, ``vApplicationIdleHook()`` and ``vApplicationTickHook()`` can only be defined once. However, the {IDF_TARGET_NAME} is dual-core in nature, therefore same Idle Hook and Tick Hook are used for both cores (in other words, the hooks are symmetrical for both cores).
- The hooks can be registered and deregistered at run-time
- Multiple hooks can be registered (with a maximum of 8 hooks of each type per CPU)
- On multi-core targets, the hooks can be asymmetric, meaning different hooks can be registered to each CPU
ESP-IDF Idle and Tick Hooks
^^^^^^^^^^^^^^^^^^^^^^^^^^^
ESP-IDF hooks can be registered and deregistered using the following API:
For some use-cases it may be necessary for the Idle Tasks or Tick Interrupts to execute multiple hooks that are configurable at run time.
- For tick hooks:
.. only:: not CONFIG_FREERTOS_UNICORE
- Register using :cpp:func:`esp_register_freertos_tick_hook` or :cpp:func:`esp_register_freertos_tick_hook_for_cpu`
- Deregister using :cpp:func:`esp_deregister_freertos_tick_hook` or :cpp:func:`esp_deregister_freertos_tick_hook_for_cpu`
Furthermore, due to the dual-core nature of the {IDF_TARGET_NAME}, it may be necessary for some applications to have separate hooks for each core.
- For idle hooks:
Therefore, ESP-IDF provides its own hooks API in addition to the legacy hooks provided by vanilla FreeRTOS.
The ESP-IDF tick and idle hooks are registered at run time. Each tick hook and idle hook must be registered to a specific CPU. When the idle task runs or a tick interrupt occurs on a particular CPU, the CPU will run each of its registered idle hook and tick hook in turn.
- Register using :cpp:func:`esp_register_freertos_idle_hook` or :cpp:func:`esp_register_freertos_idle_hook_for_cpu`
- Deregister using :cpp:func:`esp_deregister_freertos_idle_hook` or :cpp:func:`esp_deregister_freertos_idle_hook_for_cpu`
.. note::
Tick interrupt stays active whilst cache is disabled and hence ``vApplicationTickHook()`` (legacy case) or ESP-IDF tick hooks must be placed in internal RAM. Please refer to the :ref:`SPI flash API documentation <iram-safe-interrupt-handlers>` for more details.
The tick interrupt stays active while the cache is disabled, therefore any tick hook (FreeRTOS or ESP-IDF) functions must be placed in internal RAM. Please refer to the :ref:`SPI flash API documentation <iram-safe-interrupt-handlers>` for more details.
.. -------------------------------------------------- TLSP Callback ----------------------------------------------------

View File

@ -14,7 +14,7 @@ System API
POSIX Threads Support <pthread>
Event Loop Library <esp_event>
FreeRTOS <freertos>
FreeRTOS Additions <freertos_additions>
FreeRTOS Supplemental Features <freertos_additions>
Heap Memory Allocation <mem_alloc>
Heap Memory Debugging <heap_debug>
High Resolution Timer <esp_timer>