Skip to content

Commit

Permalink
Merge branch 'feature/freertos_plus_posix_SMP' into 'master'
Browse files Browse the repository at this point in the history
[FreeRTOS/Linux] POSIX/Linux and SMP

Closes IDF-6087

See merge request espressif/esp-idf!21818
  • Loading branch information
0xjakob committed Apr 25, 2023
2 parents a8b6a70 + d6fe302 commit af2d326
Show file tree
Hide file tree
Showing 39 changed files with 3,427 additions and 22 deletions.
16 changes: 9 additions & 7 deletions components/freertos/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -42,31 +42,33 @@ set(include_dirs
# or #include "esp_private/freertos_idf_additions_priv.h"
"esp_additions/arch/${arch}/include") # For #include "freertos/FreeRTOSConfig_arch.h"

if(CONFIG_FREERTOS_SMP)
list(APPEND include_dirs "${kernel_dir}/portable/${arch}/include/freertos") # Xtensa headers via #include "xx.h"
endif()

set(private_include_dirs
"${kernel_dir}/portable/${arch}/include/freertos"
"${kernel_dir}/portable/${arch}"
"${kernel_dir}/include/freertos" # FreeRTOS headers via #include "xxx.h"
"esp_additions" # For include "freertos_tasks_c_additions.h"
.)

set(private_requirements "")

if(${target} STREQUAL "linux")
list(APPEND srcs
"${kernel_dir}/portable/${arch}/port_idf.c"
"${kernel_dir}/portable/${arch}/utils/wait_for_event.c")
list(APPEND srcs "${kernel_dir}/portable/${arch}/utils/wait_for_event.c")
if(NOT CONFIG_FREERTOS_SMP)
list(APPEND srcs "${kernel_dir}/portable/${arch}/port_idf.c")
endif()
else()
list(APPEND srcs
"app_startup.c"
"FreeRTOS-openocd.c"
"port_common.c"
"${kernel_dir}/portable/${arch}/portasm.S")

list(APPEND private_include_dirs
"esp_additions") # For #include "freertos_tasks_c_additions.h"

if(CONFIG_FREERTOS_SMP)
set(ldfragments linker_smp.lf linker_common.lf)
list(APPEND include_dirs "${kernel_dir}/portable/${arch}/include/freertos") # Xtensa headers via #include "xx.h"
else()
list(APPEND srcs
"${kernel_dir}/portable/port_systick.c"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,10 @@
#endif

#ifdef configNEWLIB_REENTRANT_IS_DYNAMIC
#if ( configUSE_NEWLIB_REENTRANT != 1 )
#error configUSE_NEWLIB_REENTRANT must be defined to 1 to enable configNEWLIB_REENTRANT_IS_DYNAMIC
#if configNEWLIB_REENTRANT_IS_DYNAMIC == 1
#if ( configUSE_NEWLIB_REENTRANT != 1 )
#error configUSE_NEWLIB_REENTRANT must be defined to 1 to enable configNEWLIB_REENTRANT_IS_DYNAMIC
#endif
#endif
#else /* configNEWLIB_REENTRANT_IS_DYNAMIC */
#define configNEWLIB_REENTRANT_IS_DYNAMIC 0
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,320 @@
/*
* FreeRTOS Kernel V10.4.3
* Copyright 2020 Cambridge Consultants Ltd.
*
* SPDX-FileCopyrightText: 2020 Cambridge Consultants Ltd.
*
* SPDX-License-Identifier: MIT
*
* SPDX-FileContributor: 2023 Espressif Systems (Shanghai) CO LTD
*
* 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

#include <limits.h>
#include <stdint.h>
#include "esp_macros.h"
#include "spinlock.h"

#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 before first as they are used further down the file
* ------------------------------------------------------------------------------------------------------------------ */

/* Type definitions. */
#define portCHAR char
#define portFLOAT float
#define portDOUBLE double
#define portLONG long
#define portSHORT short
#define portSTACK_TYPE unsigned long
#define portBASE_TYPE long
#define portPOINTER_SIZE_TYPE intptr_t

typedef portSTACK_TYPE StackType_t;
typedef portBASE_TYPE BaseType_t;
typedef unsigned long UBaseType_t;

typedef unsigned long TickType_t;
#define portMAX_DELAY ( TickType_t ) ULONG_MAX

#define portTICK_TYPE_IS_ATOMIC 1

/* 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 )
/*-----------------------------------------------------------*/

/* ----------------------------------------------- Port Configurations -------------------------------------------------
* - Configurations values supplied by each port
* - Required by FreeRTOS
* ------------------------------------------------------------------------------------------------------------------ */

#define portCRITICAL_NESTING_IN_TCB 1
#define portSTACK_GROWTH ( -1 )
#define portHAS_STACK_OVERFLOW_CHECKING ( 1 ) // Set in non-SMP POSIX port
#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
#define portTICK_RATE_MICROSECONDS ( ( TickType_t ) 1000000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 8
#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
* ------------------------------------------------------------------------------------------------------------------ */

// ---------------------- Spinlocks ------------------------

typedef spinlock_t portMUX_TYPE; /**< Spinlock type used by FreeRTOS critical sections */
/**< Spinlock initializer */
#define portMUX_INITIALIZER_UNLOCKED SPINLOCK_INITIALIZER /**< Spinlock initializer */
#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) spinlock_initialize(mux) /*< Initialize a spinlock to its unlocked state */

// ----------------------- Memory --------------------------

// --------------------- Interrupts ------------------------

BaseType_t xPortCheckIfInISR(void);

// ------------------ Critical Sections --------------------

/*
These are always called with interrupts already disabled. We simply need to get/release the spinlocks
*/

extern portMUX_TYPE port_xTaskLock;
extern portMUX_TYPE port_xISRLock;

void vPortTakeLock( portMUX_TYPE *lock );
void vPortReleaseLock( portMUX_TYPE *lock );

// ---------------------- Yielding -------------------------

void vPortYield( void );
extern void vPortYieldFromISR( void );

#define portYIELD_FROM_ISR_CHECK(x) ({ \
if ( (x) == pdTRUE ) { \
vPortYieldFromISR(); \
} \
})
#define portYIELD_FROM_ISR_NO_CHECK() vPortYieldFromISR()

// ----------------------- System --------------------------

static inline BaseType_t __attribute__((always_inline)) xPortGetCoreID( void );

// ----------------------- TCB Cleanup --------------------------

void vPortCleanUpTCB ( void *pxTCB );

/* ----------------------------------------- FreeRTOS SMP Porting Interface --------------------------------------------
* - Contains all the mappings of the macros required by FreeRTOS SMP
* - Must come after forward declare as some porting macros map to declared functions
* ------------------------------------------------------------------------------------------------------------------ */

// ----------------------- Memory --------------------------

// --------------------- Interrupts ------------------------

#define portDISABLE_INTERRUPTS() xPortSetInterruptMask()
#define portENABLE_INTERRUPTS() vPortClearInterruptMask(0)
#define portRESTORE_INTERRUPTS(x) vPortClearInterruptMask(x)

// ------------------ Critical Sections --------------------

#define portGET_TASK_LOCK() vPortTakeLock(&port_xTaskLock)
#define portRELEASE_TASK_LOCK() vPortReleaseLock(&port_xTaskLock)
#define portGET_ISR_LOCK() vPortTakeLock(&port_xISRLock)
#define portRELEASE_ISR_LOCK() vPortReleaseLock(&port_xISRLock)

//Critical sections used by FreeRTOS SMP
extern void vTaskEnterCritical( void );
extern void vTaskExitCritical( void );
#define portENTER_CRITICAL_SMP() vTaskEnterCritical();
#define portEXIT_CRITICAL_SMP() vTaskExitCritical();

#if defined(__cplusplus) && (__cplusplus > 201703L)
#define portENTER_CRITICAL(...) CHOOSE_MACRO_VA_ARG(portENTER_CRITICAL_IDF, portENTER_CRITICAL_SMP __VA_OPT__(,) __VA_ARGS__)(__VA_ARGS__)
#define portEXIT_CRITICAL(...) CHOOSE_MACRO_VA_ARG(portEXIT_CRITICAL_IDF, portEXIT_CRITICAL_SMP __VA_OPT__(,) __VA_ARGS__)(__VA_ARGS__)
#else
#define portENTER_CRITICAL(...) CHOOSE_MACRO_VA_ARG(portENTER_CRITICAL_IDF, portENTER_CRITICAL_SMP, ##__VA_ARGS__)(__VA_ARGS__)
#define portEXIT_CRITICAL(...) CHOOSE_MACRO_VA_ARG(portEXIT_CRITICAL_IDF, portEXIT_CRITICAL_SMP, ##__VA_ARGS__)(__VA_ARGS__)
#endif

extern portBASE_TYPE xPortSetInterruptMask( void );
extern void vPortClearInterruptMask( portBASE_TYPE xMask );

#define portSET_INTERRUPT_MASK_FROM_ISR() ({ \
portBASE_TYPE cur_level; \
cur_level = xPortSetInterruptMask(); \
vTaskEnterCritical(); \
cur_level; \
})
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) ({ \
vTaskExitCritical(); \
vPortClearInterruptMask(x); \
})

// ---------------------- Yielding -------------------------

#define portYIELD() vPortYield()
#if defined(__cplusplus) && (__cplusplus > 201703L)
#define portYIELD_FROM_ISR(...) CHOOSE_MACRO_VA_ARG(portYIELD_FROM_ISR_CHECK, portYIELD_FROM_ISR_NO_CHECK __VA_OPT__(,) __VA_ARGS__)(__VA_ARGS__)
#else
#define portYIELD_FROM_ISR(...) CHOOSE_MACRO_VA_ARG(portYIELD_FROM_ISR_CHECK, portYIELD_FROM_ISR_NO_CHECK, ##__VA_ARGS__)(__VA_ARGS__)
#endif
// Note that the Linux port does not provide portYIELD_CORE(x) because purely single core for now.

// ----------------------- System --------------------------

#define portGET_CORE_ID() xPortGetCoreID()
#define portCHECK_IF_IN_ISR() xPortCheckIfInISR()

// ------------------- Run Time Stats ----------------------

extern unsigned long ulPortGetRunTime( void );
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() /* no-op */
#define portGET_RUN_TIME_COUNTER_VALUE() ulPortGetRunTime()
// TODO IDF-5723: no esp_timer implementation

// ------------------- TCB Cleanup ----------------------

#define portCLEAN_UP_TCB( pxTCB ) vPortCleanUpTCB( pxTCB )

/* --------------------------------------------- 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
* ------------------------------------------------------------------------------------------------------------------ */

// --------------------- Interrupts ------------------------

// ------------------ Critical Sections --------------------

// ---------------------- Yielding -------------------------

// NOTE: vPortYieldCore( BaseType_t xCoreID ) is currently not implemented as the simulator is single core

// ----------------------- System --------------------------
/**
* @brief Get the current core's ID
*
* @note dummy function for freertos simulator, always returns 0.
@ return BaseType_t 0
*/
static inline BaseType_t xPortGetCoreID(void)
{
return (BaseType_t) 0; // POSIX simulator is only single-core at the moment
}

/* ------------------------------------------------ IDF Compatibility --------------------------------------------------
* - These macros and functions need to be defined for IDF to compile
* ------------------------------------------------------------------------------------------------------------------ */

// --------------------- Interrupts ------------------------

static inline BaseType_t xPortInIsrContext(void)
{
//Just call the FreeRTOS port interface version
return xPortCheckIfInISR();
}

// xPortInterruptedFromISRContext() is only used in panic handler and core dump,
// both probably not relevant on POSIX sim.
//BaseType_t xPortInterruptedFromISRContext(void);

// Following functions seem to not be used in SMP:
//static inline UBaseType_t xPortSetInterruptMaskFromISR(void)
//static inline void vPortClearInterruptMaskFromISR(UBaseType_t prev_level)

// Following functions should have been removed according to
// docs/en/migration-guides/release-5.x/5.0/system.rst
//static inline bool __attribute__((always_inline)) vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout)
//static inline void __attribute__((always_inline)) vPortCPUReleaseMutex(portMUX_TYPE *mux)

// ------------------ Critical Sections --------------------

void vPortEnterCriticalIDF(void);
void vPortExitCriticalIDF(void);

// We ignore the lock and timeout argument on POSIX simulator since it is single core

//IDF task critical sections
#define portTRY_ENTER_CRITICAL(lock, timeout) ({(void) lock; (void) timeout; vPortEnterCriticalIDF(); pdPASS;})
#define portENTER_CRITICAL_IDF(lock) ({(void) lock; vPortEnterCriticalIDF();})
#define portEXIT_CRITICAL_IDF(lock) ({(void) lock; vPortExitCriticalIDF();})
//IDF ISR critical sections
#define portTRY_ENTER_CRITICAL_ISR(lock, timeout) ({(void) lock; (void) timeout; vPortEnterCriticalIDF(); pdPASS;})
#define portENTER_CRITICAL_ISR(lock) ({(void) lock; vPortEnterCriticalIDF();})
#define portEXIT_CRITICAL_ISR(lock) ({(void) lock; vPortExitCriticalIDF();})
//IDF safe critical sections (they're the same)
#define portENTER_CRITICAL_SAFE(lock) ({(void) lock; vPortEnterCriticalIDF();})
#define portEXIT_CRITICAL_SAFE(lock) ({(void) lock; vPortExitCriticalIDF();})

// ---------------------- Yielding -------------------------

// Added for backward compatibility with IDF
#define portYIELD_WITHIN_API() vTaskYieldWithinAPI()

// ----------------------- System --------------------------

bool portVALID_TCB_MEM(const void *ptr);
bool portVALID_STACK_MEM(const void *ptr);

/*-----------------------------------------------------------*/

/* POSIX-specific port functions */

extern void vPortThreadDying( void *pxTaskToDelete, volatile BaseType_t *pxPendYield );
extern void vPortCancelThread( void *pxTaskToDelete );
#define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxPendYield ) vPortThreadDying( ( pvTaskToDelete ), ( pxPendYield ) )
/*-----------------------------------------------------------*/

/*
* Tasks run in their own pthreads and context switches between them
* are always a full memory barrier. ISRs are emulated as signals
* which also imply a full memory barrier.
*
* Thus, only a compilier barrier is needed to prevent the compiler
* reordering.
*/
#define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" )

#ifdef __cplusplus
}
#endif

#endif /* PORTMACRO_H */
Loading

0 comments on commit af2d326

Please sign in to comment.