mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
freertos: Add CHOOSE_MACRO_VA_ARG selector
This commit adds a CHOOSE_MACRO_VA_ARG() selector to allow selection between two versions of a macro based on the number of arguments. This replaces the previous portGET_ARGUMENT_COUNT() selector. - portYIELD_FROM_ISR() now uses CHOOSE_MACRO_VA_ARG() - portYIELD_FROM_ISR(arg) version added to risc-v port - Old vPortEvaluateYieldFromISR() and portGET_ARGUMENT_COUNT removed
This commit is contained in:
parent
6ddf2ea05e
commit
c5fd79547a
46
components/esp_common/include/esp_macro.h
Normal file
46
components/esp_common/include/esp_macro.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*
|
||||||
|
This header contains various general purpose helper macros used across ESP-IDF
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Macro to select different versions of other macros based on whether VA_ARGS has an argument or no argument
|
||||||
|
*
|
||||||
|
* Some macros (such as in FreeRTOS) have two versions (one that accepts arguments and another that does not). The
|
||||||
|
* following "CHOOSE_MACRO_VA_ARG" selector allows automatic selection between two different versions of a macro.
|
||||||
|
*
|
||||||
|
* "CHOOSE_MACRO_VA_ARG" make use of the fact that "##__VA_ARGS__," will eliminate the trailing comma if there are no
|
||||||
|
* arguments, thus allows subsequent arguments in "CHOOSE_MACRO_VA_ARG" to be left shifted in the parameter list.
|
||||||
|
* Therefore, if we call "CHOOSE_MACRO_VA_ARG(_0, ##__VA_ARGS__, MACRO1, MACRO2)(__VA_ARGS__)", the result will be:
|
||||||
|
*
|
||||||
|
* - MACRO1(__VA_ARGS__) if __VA_ARGS__ was not empty
|
||||||
|
* - MACRO2() if __VA_ARGS__ was empty
|
||||||
|
*
|
||||||
|
* @note In the future, we want to switch to C++20. We also want to become compatible with clang. Hence, we provide two
|
||||||
|
* versions of the following macros which are using variadic arguments. The first one is using the GNU extension
|
||||||
|
* ##__VA_ARGS__. The second one is using the C++20 feature __VA_OPT__(,). This allows users to compile their code with
|
||||||
|
* standard C++20 enabled instead of the GNU extension. Below C++20, we haven't found any good alternative to using
|
||||||
|
* ##__VA_ARGS__.
|
||||||
|
*/
|
||||||
|
#if defined(__cplusplus) && (__cplusplus > 201703L)
|
||||||
|
#define CHOOSE_MACRO_VA_ARG(_0 __VA_OPT__(,) __VA_ARGS__, MACRO, ...) MACRO
|
||||||
|
#else
|
||||||
|
#define CHOOSE_MACRO_VA_ARG(_0, _1, MACRO, ...) MACRO
|
||||||
|
#endif
|
||||||
|
_Static_assert(CHOOSE_MACRO_VA_ARG(_0, x, 0, 1) == 0, "CHOOSE_MACRO_VA_ARG() result does not match for 0 arguments");
|
||||||
|
_Static_assert(CHOOSE_MACRO_VA_ARG(_0, 0, 1) == 1, "CHOOSE_MACRO_VA_ARG() result does not match for 1 argument");
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -44,6 +44,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "soc/spinlock.h"
|
#include "soc/spinlock.h"
|
||||||
#include "soc/interrupt_core0_reg.h"
|
#include "soc/interrupt_core0_reg.h"
|
||||||
|
#include "esp_macro.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_rom_sys.h"
|
#include "esp_rom_sys.h"
|
||||||
#include "esp_timer.h" /* required for FreeRTOS run time stats */
|
#include "esp_timer.h" /* required for FreeRTOS run time stats */
|
||||||
@ -58,8 +59,6 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* --------------------------------------------------- Port Types ------------------------------------------------------
|
/* --------------------------------------------------- Port Types ------------------------------------------------------
|
||||||
* - Port specific types.
|
* - Port specific types.
|
||||||
* - The settings in this file configure FreeRTOS correctly for the given hardware and compiler.
|
* - The settings in this file configure FreeRTOS correctly for the given hardware and compiler.
|
||||||
@ -383,7 +382,24 @@ static inline BaseType_t IRAM_ATTR xPortGetCoreID(void)
|
|||||||
// ---------------------- Yielding -------------------------
|
// ---------------------- Yielding -------------------------
|
||||||
|
|
||||||
#define portYIELD() vPortYield()
|
#define portYIELD() vPortYield()
|
||||||
#define portYIELD_FROM_ISR() vPortYieldFromISR()
|
#define portYIELD_FROM_ISR_NO_ARG() vPortYieldFromISR()
|
||||||
|
#define portYIELD_FROM_ISR_ARG(xHigherPriorityTaskWoken) ({ \
|
||||||
|
if (xHigherPriorityTaskWoken == pdTRUE) { \
|
||||||
|
vPortYieldFromISR(); \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* @note The macro below could be used when passing a single argument, or without any argument,
|
||||||
|
* it was developed to support both usages of portYIELD inside of an ISR. Any other usage form
|
||||||
|
* might result in undesired behavior
|
||||||
|
*/
|
||||||
|
#if defined(__cplusplus) && (__cplusplus > 201703L)
|
||||||
|
#define portYIELD_FROM_ISR(...) CHOOSE_MACRO_VA_ARG(_0 __VA_OPT__(,) ##__VA_ARGS__, portYIELD_FROM_ISR_ARG, portYIELD_FROM_ISR_NO_ARG)(__VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define portYIELD_FROM_ISR(...) CHOOSE_MACRO_VA_ARG(_0, ##__VA_ARGS__, portYIELD_FROM_ISR_ARG, portYIELD_FROM_ISR_NO_ARG)(__VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define portEND_SWITCHING_ISR(xSwitchRequired) if(xSwitchRequired) vPortYield()
|
#define portEND_SWITCHING_ISR(xSwitchRequired) if(xSwitchRequired) vPortYield()
|
||||||
/* Yielding within an API call (when interrupts are off), means the yield should be delayed
|
/* Yielding within an API call (when interrupts are off), means the yield should be delayed
|
||||||
until interrupts are re-enabled.
|
until interrupts are re-enabled.
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
#include "soc/spinlock.h"
|
#include "soc/spinlock.h"
|
||||||
#include "hal/cpu_hal.h"
|
#include "hal/cpu_hal.h"
|
||||||
#include "esp_private/crosscore_int.h"
|
#include "esp_private/crosscore_int.h"
|
||||||
|
#include "esp_macro.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
#include "esp_timer.h" /* required for esp_timer_get_time. [refactor-todo] make this common between archs */
|
#include "esp_timer.h" /* required for esp_timer_get_time. [refactor-todo] make this common between archs */
|
||||||
#include "esp_newlib.h" /* required for esp_reent_init() in tasks.c */
|
#include "esp_newlib.h" /* required for esp_reent_init() in tasks.c */
|
||||||
@ -92,7 +93,6 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* --------------------------------------------------- Port Types ------------------------------------------------------
|
/* --------------------------------------------------- Port Types ------------------------------------------------------
|
||||||
* - Port specific types.
|
* - Port specific types.
|
||||||
* - The settings in this file configure FreeRTOS correctly for the given hardware and compiler.
|
* - The settings in this file configure FreeRTOS correctly for the given hardware and compiler.
|
||||||
@ -339,15 +339,6 @@ static inline void __attribute__((always_inline)) vPortExitCriticalSafe(portMUX_
|
|||||||
*/
|
*/
|
||||||
void vPortYield( void );
|
void vPortYield( void );
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief
|
|
||||||
*
|
|
||||||
* @note [refactor-todo] Refactor this to avoid va_args
|
|
||||||
* @param argc
|
|
||||||
* @param ... Variable arguments to allow for IDF prototype without arguments, and vanilla version WITH argument
|
|
||||||
*/
|
|
||||||
void vPortEvaluateYieldFromISR(int argc, ...);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Yields the other core
|
* @brief Yields the other core
|
||||||
*
|
*
|
||||||
@ -517,17 +508,28 @@ static inline void __attribute__((always_inline)) uxPortCompareSetExtram(volatil
|
|||||||
|
|
||||||
#define portYIELD() vPortYield()
|
#define portYIELD() vPortYield()
|
||||||
|
|
||||||
|
extern void _frxt_setup_switch( void ); //Defined in portasm.S
|
||||||
|
|
||||||
|
#define portYIELD_FROM_ISR_NO_ARG() ({ \
|
||||||
|
traceISR_EXIT_TO_SCHEDULER(); \
|
||||||
|
_frxt_setup_switch(); \
|
||||||
|
})
|
||||||
|
#define portYIELD_FROM_ISR_ARG(xHigherPriorityTaskWoken) ({ \
|
||||||
|
if (xHigherPriorityTaskWoken == pdTRUE) { \
|
||||||
|
traceISR_EXIT_TO_SCHEDULER(); \
|
||||||
|
_frxt_setup_switch(); \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @note The macro below could be used when passing a single argument, or without any argument,
|
* @note The macro below could be used when passing a single argument, or without any argument,
|
||||||
* it was developed to support both usages of portYIELD inside of an ISR. Any other usage form
|
* it was developed to support both usages of portYIELD inside of an ISR. Any other usage form
|
||||||
* might result in undesired behavior
|
* might result in undesired behavior
|
||||||
*
|
|
||||||
* @note [refactor-todo] Refactor this to avoid va_args
|
|
||||||
*/
|
*/
|
||||||
#if defined(__cplusplus) && (__cplusplus > 201703L)
|
#if defined(__cplusplus) && (__cplusplus > 201703L)
|
||||||
#define portYIELD_FROM_ISR(...) vPortEvaluateYieldFromISR(portGET_ARGUMENT_COUNT(__VA_ARGS__) __VA_OPT__(,) __VA_ARGS__)
|
#define portYIELD_FROM_ISR(...) CHOOSE_MACRO_VA_ARG(_0 __VA_OPT__(,) ##__VA_ARGS__, portYIELD_FROM_ISR_ARG, portYIELD_FROM_ISR_NO_ARG)(__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define portYIELD_FROM_ISR(...) vPortEvaluateYieldFromISR(portGET_ARGUMENT_COUNT(__VA_ARGS__), ##__VA_ARGS__)
|
#define portYIELD_FROM_ISR(...) CHOOSE_MACRO_VA_ARG(_0, ##__VA_ARGS__, portYIELD_FROM_ISR_ARG, portYIELD_FROM_ISR_NO_ARG)(__VA_ARGS__)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Yielding within an API call (when interrupts are off), means the yield should be delayed
|
/* Yielding within an API call (when interrupts are off), means the yield should be delayed
|
||||||
@ -723,28 +725,6 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS *xMPUSettings, const struct xMEMOR
|
|||||||
void vPortReleaseTaskMPUSettings( xMPU_SETTINGS *xMPUSettings );
|
void vPortReleaseTaskMPUSettings( xMPU_SETTINGS *xMPUSettings );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// -------------------- VA_ARGS Yield ----------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Macro to count number of arguments of a __VA_ARGS__ used to support portYIELD_FROM_ISR with,
|
|
||||||
* or without arguments. The macro counts only 0 or 1 arguments.
|
|
||||||
*
|
|
||||||
* In the future, we want to switch to C++20. We also want to become compatible with clang.
|
|
||||||
* Hence, we provide two versions of the following macros which are using variadic arguments.
|
|
||||||
* The first one is using the GNU extension ##__VA_ARGS__. The second one is using the C++20 feature __VA_OPT__(,).
|
|
||||||
* This allows users to compile their code with standard C++20 enabled instead of the GNU extension.
|
|
||||||
* Below C++20, we haven't found any good alternative to using ##__VA_ARGS__.
|
|
||||||
*/
|
|
||||||
#if defined(__cplusplus) && (__cplusplus > 201703L)
|
|
||||||
#define portGET_ARGUMENT_COUNT(...) portGET_ARGUMENT_COUNT_INNER(0 __VA_OPT__(,) __VA_ARGS__,1,0)
|
|
||||||
#else
|
|
||||||
#define portGET_ARGUMENT_COUNT(...) portGET_ARGUMENT_COUNT_INNER(0, ##__VA_ARGS__,1,0)
|
|
||||||
#endif
|
|
||||||
#define portGET_ARGUMENT_COUNT_INNER(zero, one, count, ...) count
|
|
||||||
|
|
||||||
_Static_assert(portGET_ARGUMENT_COUNT() == 0, "portGET_ARGUMENT_COUNT() result does not match for 0 arguments");
|
|
||||||
_Static_assert(portGET_ARGUMENT_COUNT(1) == 1, "portGET_ARGUMENT_COUNT() result does not match for 1 argument");
|
|
||||||
|
|
||||||
// -------------------- Heap Related -----------------------
|
// -------------------- Heap Related -----------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2017 Amazon.com, Inc. or its affiliates
|
||||||
|
* SPDX-FileCopyrightText: 2015-2019 Cadence Design Systems, Inc.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*
|
||||||
|
* SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*/
|
||||||
/*
|
/*
|
||||||
* FreeRTOS Kernel V10.4.3
|
* FreeRTOS Kernel V10.4.3
|
||||||
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||||
@ -53,7 +61,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
|
||||||
#include <xtensa/config/core.h>
|
#include <xtensa/config/core.h>
|
||||||
#include <xtensa/xtensa_context.h>
|
#include <xtensa/xtensa_context.h>
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
@ -354,32 +361,6 @@ void vPortYieldOtherCore( BaseType_t coreid )
|
|||||||
esp_crosscore_int_send_yield( coreid );
|
esp_crosscore_int_send_yield( coreid );
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void _frxt_setup_switch( void ); //Defined in portasm.S
|
|
||||||
|
|
||||||
void IRAM_ATTR vPortEvaluateYieldFromISR(int argc, ...)
|
|
||||||
{
|
|
||||||
BaseType_t xYield;
|
|
||||||
va_list ap;
|
|
||||||
va_start(ap, argc);
|
|
||||||
|
|
||||||
if (argc) {
|
|
||||||
xYield = (BaseType_t)va_arg(ap, int);
|
|
||||||
va_end(ap);
|
|
||||||
} else {
|
|
||||||
//it is a empty parameter vPortYieldFromISR macro call:
|
|
||||||
va_end(ap);
|
|
||||||
traceISR_EXIT_TO_SCHEDULER();
|
|
||||||
_frxt_setup_switch();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Yield exists, so need evaluate it first then switch:
|
|
||||||
if (xYield == pdTRUE) {
|
|
||||||
traceISR_EXIT_TO_SCHEDULER();
|
|
||||||
_frxt_setup_switch();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------- Hook Functions ----------------------
|
// ------------------- Hook Functions ----------------------
|
||||||
|
|
||||||
void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName )
|
void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, char *pcTaskName )
|
||||||
|
@ -298,7 +298,6 @@ void esp_log_writev(esp_log_level_t level, const char* tag, const char* format,
|
|||||||
|
|
||||||
/// macro to output logs in startup code, before heap allocator and syscalls have been initialized.
|
/// macro to output logs in startup code, before heap allocator and syscalls have been initialized.
|
||||||
/// Log at ``ESP_LOG_ERROR`` level. @see ``printf``,``ESP_LOGE``,``ESP_DRAM_LOGE``
|
/// Log at ``ESP_LOG_ERROR`` level. @see ``printf``,``ESP_LOGE``,``ESP_DRAM_LOGE``
|
||||||
#define portGET_ARGUMENT_COUNT_INNER(zero, one, count, ...) count
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In the future, we want to switch to C++20. We also want to become compatible with clang.
|
* In the future, we want to switch to C++20. We also want to become compatible with clang.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user