diff --git a/components/freertos/include/freertos/portmacro.h b/components/freertos/include/freertos/portmacro.h index f55eeefe0c..336737de94 100644 --- a/components/freertos/include/freertos/portmacro.h +++ b/components/freertos/include/freertos/portmacro.h @@ -199,8 +199,6 @@ void vPortCPUInitializeMutex(portMUX_TYPE *mux); #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG void vPortCPUAcquireMutex(portMUX_TYPE *mux, const char *function, int line); portBASE_TYPE vPortCPUReleaseMutex(portMUX_TYPE *mux, const char *function, int line); -void vPortCPUAcquireMutexIntsDisabled(portMUX_TYPE *mux, const char *function, int line); -portBASE_TYPE vPortCPUReleaseMutexIntsDisabled(portMUX_TYPE *mux, const char *function, int line); void vTaskEnterCritical( portMUX_TYPE *mux, const char *function, int line ); void vTaskExitCritical( portMUX_TYPE *mux, const char *function, int line ); #define portENTER_CRITICAL(mux) vTaskEnterCritical(mux, __FUNCTION__, __LINE__) @@ -212,8 +210,6 @@ void vTaskExitCritical( portMUX_TYPE *mux ); void vTaskEnterCritical( portMUX_TYPE *mux ); void vPortCPUAcquireMutex(portMUX_TYPE *mux); void vPortCPUReleaseMutex(portMUX_TYPE *mux); -void vPortCPUAcquireMutexIntsDisabled(portMUX_TYPE *mux); -void vPortCPUReleaseMutexIntsDisabled(portMUX_TYPE *mux); #define portENTER_CRITICAL(mux) vTaskEnterCritical(mux) #define portEXIT_CRITICAL(mux) vTaskExitCritical(mux) diff --git a/components/freertos/port.c b/components/freertos/port.c index fda5ed6cfd..3d0fd192e6 100644 --- a/components/freertos/port.c +++ b/components/freertos/port.c @@ -307,6 +307,7 @@ void vPortCPUInitializeMutex(portMUX_TYPE *mux) { mux->count=0; } +#include "portmux_impl.h" /* * For kernel use: Acquire a per-CPU mux. Spinlocks, so don't hold on to these muxes for too long. @@ -325,72 +326,6 @@ void vPortCPUAcquireMutex(portMUX_TYPE *mux) { } #endif -/* XOR one core ID with this value to get the other core ID */ -#define CORE_ID_XOR_SWAP (CORE_ID_PRO ^ CORE_ID_APP) - -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG -void vPortCPUAcquireMutexIntsDisabled(portMUX_TYPE *mux, const char *fnName, int line) { -#else -void vPortCPUAcquireMutexIntsDisabled(portMUX_TYPE *mux) { -#endif -#if !CONFIG_FREERTOS_UNICORE - uint32_t res; - portBASE_TYPE coreID, otherCoreID; -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG - uint32_t timeout=(1<<16); - uint32_t owner = mux->owner; - if (owner != portMUX_FREE_VAL && owner != CORE_ID_PRO && owner != CORE_ID_APP) { - ets_printf("ERROR: vPortCPUAcquireMutex: mux %p is uninitialized (0x%X)! Called from %s line %d.\n", mux, owner, fnName, line); - mux->owner=portMUX_FREE_VAL; - } -#endif - - /* Spin until we own the core */ - - RSR(PRID, coreID); - /* Note: coreID is the full 32 bit core ID (CORE_ID_PRO/CORE_ID_APP), - not the 0/1 value returned by xPortGetCoreID() - */ - otherCoreID = CORE_ID_XOR_SWAP ^ coreID; - do { - /* mux->owner should be one of portMUX_FREE_VAL, CORE_ID_PRO, - CORE_ID_APP: - - - If portMUX_FREE_VAL, we want to atomically set to 'coreID'. - - If "our" coreID, we can drop through immediately. - - If "otherCoreID", we spin here. - */ - res = coreID; - uxPortCompareSet(&mux->owner, portMUX_FREE_VAL, &res); - -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG - timeout--; - if (timeout == 0) { - ets_printf("Timeout on mux! last non-recursive lock %s line %d, curr %s line %d\n", mux->lastLockedFn, mux->lastLockedLine, fnName, line); - ets_printf("Owner 0x%x count %d\n", mux->owner, mux->count); - } -#endif - } while (res == otherCoreID); - - assert(res == coreID || res == portMUX_FREE_VAL); /* any other value implies memory corruption or uninitialized mux */ - assert((res == portMUX_FREE_VAL) == (mux->count == 0)); /* we're first to lock iff count is zero */ - assert(mux->count < 0xFF); /* Bad count value implies memory corruption */ - - /* now we own it, we can increment the refcount */ - mux->count++; - - -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG - if (res==portMUX_FREE_VAL) { //initial lock - mux->lastLockedFn=fnName; - mux->lastLockedLine=line; - } else { - ets_printf("Recursive lock: count=%d last non-recursive lock %s line %d, curr %s line %d\n", mux->count-1, - mux->lastLockedFn, mux->lastLockedLine, fnName, line); - } -#endif -#endif -} /* * For kernel use: Release a per-CPU mux @@ -411,58 +346,12 @@ void vPortCPUReleaseMutex(portMUX_TYPE *mux) { } #endif -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG -void vPortCPUReleaseMutexIntsDisabled(portMUX_TYPE *mux, const char *fnName, int line) { -#else -void vPortCPUReleaseMutexIntsDisabled(portMUX_TYPE *mux) { -#endif -#if !CONFIG_FREERTOS_UNICORE - portBASE_TYPE coreID; -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG - const char *lastLockedFn=mux->lastLockedFn; - int lastLockedLine=mux->lastLockedLine; - mux->lastLockedFn=fnName; - mux->lastLockedLine=line; - uint32_t owner = mux->owner; - if (owner != portMUX_FREE_VAL && owner != CORE_ID_PRO && owner != CORE_ID_APP) { - ets_printf("ERROR: vPortCPUReleaseMutex: mux %p is invalid (0x%x)!\n", mux, mux->owner); - } -#endif - -#if CONFIG_FREERTOS_PORTMUX_DEBUG || !defined(NDEBUG) - RSR(PRID, coreID); -#endif - -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG - if (coreID != mux->owner) { - ets_printf("ERROR: vPortCPUReleaseMutex: mux %p was already unlocked!\n", mux); - ets_printf("Last non-recursive unlock %s line %d, curr unlock %s line %d\n", lastLockedFn, lastLockedLine, fnName, line); - } -#endif - - assert(coreID == mux->owner); // This is a mutex we didn't lock, or it's corrupt - assert(mux->count > 0); // Indicates memory corruption - assert(mux->count < 0x100); // Indicates memory corruption - - mux->count--; - if(mux->count == 0) { - mux->owner = portMUX_FREE_VAL; - } -#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG_RECURSIVE - else { - ets_printf("Recursive unlock: count=%d last locked %s line %d, curr %s line %d\n", mux->count, lastLockedFn, lastLockedLine, fnName, line); - } -#endif -#endif //!CONFIG_FREERTOS_UNICORE -} - #if CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG void vPortFirstTaskHook(TaskFunction_t function) { esp_set_breakpoint_if_jtag(function); } #endif - void vPortSetStackWatchpoint( void* pxStackStart ) { //Set watchpoint 1 to watch the last 32 bytes of the stack. //Unfortunately, the Xtensa watchpoints can't set a watchpoint on a random [base - base+n] region because diff --git a/components/freertos/portmux_impl.h b/components/freertos/portmux_impl.h new file mode 100644 index 0000000000..fece3aa389 --- /dev/null +++ b/components/freertos/portmux_impl.h @@ -0,0 +1,147 @@ +/* + Copyright (C) 2016-2017 Espressif Shanghai PTE LTD + Copyright (C) 2015 Real Time Engineers Ltd. + + All rights reserved + + 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 +*/ + +/* This header exists for performance reasons, in order to inline the + implementation of vPortCPUAcquireMutexIntsDisabled and + vPortCPUReleaseMutexIntsDisabled into the + vTaskEnterCritical/vTaskExitCritical functions as well as the + vPortCPUAcquireMutex/vPortCPUReleaseMutex implementations. + + Normally this kind of performance hack is over the top, but these + functions get used a great deal by FreeRTOS internals. + + It should be #included by freertos port.c or tasks.c, in esp-idf. +*/ +#include "soc/cpu.h" + +/* XOR one core ID with this value to get the other core ID */ +#define CORE_ID_XOR_SWAP (CORE_ID_PRO ^ CORE_ID_APP) + +#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG +static inline void vPortCPUAcquireMutexIntsDisabled(portMUX_TYPE *mux, const char *fnName, int line) { +#else +static inline void vPortCPUAcquireMutexIntsDisabled(portMUX_TYPE *mux) { +#endif +#if !CONFIG_FREERTOS_UNICORE + uint32_t res; + portBASE_TYPE coreID, otherCoreID; +#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG + uint32_t timeout=(1<<16); + uint32_t owner = mux->owner; + if (owner != portMUX_FREE_VAL && owner != CORE_ID_PRO && owner != CORE_ID_APP) { + ets_printf("ERROR: vPortCPUAcquireMutex: mux %p is uninitialized (0x%X)! Called from %s line %d.\n", mux, owner, fnName, line); + mux->owner=portMUX_FREE_VAL; + } +#endif + + /* Spin until we own the core */ + + RSR(PRID, coreID); + /* Note: coreID is the full 32 bit core ID (CORE_ID_PRO/CORE_ID_APP), + not the 0/1 value returned by xPortGetCoreID() + */ + otherCoreID = CORE_ID_XOR_SWAP ^ coreID; + do { + /* mux->owner should be one of portMUX_FREE_VAL, CORE_ID_PRO, + CORE_ID_APP: + + - If portMUX_FREE_VAL, we want to atomically set to 'coreID'. + - If "our" coreID, we can drop through immediately. + - If "otherCoreID", we spin here. + */ + res = coreID; + uxPortCompareSet(&mux->owner, portMUX_FREE_VAL, &res); + +#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG + timeout--; + if (timeout == 0) { + ets_printf("Timeout on mux! last non-recursive lock %s line %d, curr %s line %d\n", mux->lastLockedFn, mux->lastLockedLine, fnName, line); + ets_printf("Owner 0x%x count %d\n", mux->owner, mux->count); + } +#endif + } while (res == otherCoreID); + + assert(res == coreID || res == portMUX_FREE_VAL); /* any other value implies memory corruption or uninitialized mux */ + assert((res == portMUX_FREE_VAL) == (mux->count == 0)); /* we're first to lock iff count is zero */ + assert(mux->count < 0xFF); /* Bad count value implies memory corruption */ + + /* now we own it, we can increment the refcount */ + mux->count++; + + +#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG + if (res==portMUX_FREE_VAL) { //initial lock + mux->lastLockedFn=fnName; + mux->lastLockedLine=line; + } else { + ets_printf("Recursive lock: count=%d last non-recursive lock %s line %d, curr %s line %d\n", mux->count-1, + mux->lastLockedFn, mux->lastLockedLine, fnName, line); + } +#endif +#endif +} + +#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG +static inline void vPortCPUReleaseMutexIntsDisabled(portMUX_TYPE *mux, const char *fnName, int line) { +#else +static inline void vPortCPUReleaseMutexIntsDisabled(portMUX_TYPE *mux) { +#endif +#if !CONFIG_FREERTOS_UNICORE + portBASE_TYPE coreID; +#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG + const char *lastLockedFn=mux->lastLockedFn; + int lastLockedLine=mux->lastLockedLine; + mux->lastLockedFn=fnName; + mux->lastLockedLine=line; + uint32_t owner = mux->owner; + if (owner != portMUX_FREE_VAL && owner != CORE_ID_PRO && owner != CORE_ID_APP) { + ets_printf("ERROR: vPortCPUReleaseMutex: mux %p is invalid (0x%x)!\n", mux, mux->owner); + } +#endif + +#if CONFIG_FREERTOS_PORTMUX_DEBUG || !defined(NDEBUG) + RSR(PRID, coreID); +#endif + +#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG + if (coreID != mux->owner) { + ets_printf("ERROR: vPortCPUReleaseMutex: mux %p was already unlocked!\n", mux); + ets_printf("Last non-recursive unlock %s line %d, curr unlock %s line %d\n", lastLockedFn, lastLockedLine, fnName, line); + } +#endif + + assert(coreID == mux->owner); // This is a mutex we didn't lock, or it's corrupt + assert(mux->count > 0); // Indicates memory corruption + assert(mux->count < 0x100); // Indicates memory corruption + + mux->count--; + if(mux->count == 0) { + mux->owner = portMUX_FREE_VAL; + } +#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG_RECURSIVE + else { + ets_printf("Recursive unlock: count=%d last locked %s line %d, curr %s line %d\n", mux->count, lastLockedFn, lastLockedLine, fnName, line); + } +#endif +#endif //!CONFIG_FREERTOS_UNICORE +} diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 74dec7fbde..7101c5a18f 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -4103,6 +4103,7 @@ For ESP32 FreeRTOS, vTaskEnterCritical implements both portENTER_CRITICAL and po #if ( portCRITICAL_NESTING_IN_TCB == 1 ) +#include "portmux_impl.h" #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG void vTaskEnterCritical( portMUX_TYPE *mux, const char *function, int line )