1 /* 2 * SPDX-FileCopyrightText: 2017 Amazon.com, Inc. or its affiliates 3 * SPDX-FileCopyrightText: 2015-2019 Cadence Design Systems, Inc. 4 * 5 * SPDX-License-Identifier: MIT 6 * 7 * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD 8 */ 9 /* 10 * FreeRTOS Kernel V10.6.2 11 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 12 * 13 * Permission is hereby granted, free of charge, to any person obtaining a copy of 14 * this software and associated documentation files (the "Software"), to deal in 15 * the Software without restriction, including without limitation the rights to 16 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 17 * the Software, and to permit persons to whom the Software is furnished to do so, 18 * subject to the following conditions: 19 * 20 * The above copyright notice and this permission notice shall be included in all 21 * copies or substantial portions of the Software. If you wish to use our Amazon 22 * FreeRTOS name, please do so in a fair use way that does not cause confusion. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 26 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 27 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 28 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 * 31 * https://www.FreeRTOS.org 32 * https://github.com/FreeRTOS 33 * 34 * 1 tab == 4 spaces! 35 */ 36 37 /* 38 * Copyright (c) 2015-2019 Cadence Design Systems, Inc. 39 * 40 * Permission is hereby granted, free of charge, to any person obtaining 41 * a copy of this software and associated documentation files (the 42 * "Software"), to deal in the Software without restriction, including 43 * without limitation the rights to use, copy, modify, merge, publish, 44 * distribute, sublicense, and/or sell copies of the Software, and to 45 * permit persons to whom the Software is furnished to do so, subject to 46 * the following conditions: 47 * 48 * The above copyright notice and this permission notice shall be included 49 * in all copies or substantial portions of the Software. 50 * 51 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 52 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 53 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 54 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 55 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 56 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 57 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 58 */ 59 60 #ifndef PORTMACRO_H 61 #define PORTMACRO_H 62 63 /* *INDENT-OFF* */ 64 #ifdef __cplusplus 65 extern "C" { 66 #endif 67 /* *INDENT-ON* */ 68 69 #ifndef __ASSEMBLER__ 70 71 #include <stdint.h> 72 73 #include <xtensa/hal.h> 74 #include <xtensa/config/core.h> 75 #include <xtensa/config/system.h> /* required for XSHAL_CLIB */ 76 #include <xtensa/xtruntime.h> 77 #include "soc/spinlock.h" 78 #include "esp_timer.h" /* required for FreeRTOS run time stats */ 79 #include "esp_system.h" 80 #include "esp_idf_version.h" 81 #include "esp_heap_caps.h" 82 83 /* TODO: Resolve build warnings generated due to this header inclusion */ 84 #include "hal/cpu_hal.h" 85 86 /* TODO: These includes are not directly used in this file. They are kept into to prevent a breaking change. Remove these. */ 87 #include <limits.h> 88 #include <xtensa/xtensa_api.h> 89 90 #include "soc/cpu.h" 91 #include "soc/soc_memory_layout.h" 92 #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)) 93 #include "soc/compare_set.h" 94 #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */ 95 96 /*#include "xtensa_context.h" */ 97 98 /*----------------------------------------------------------- 99 * Port specific definitions. 100 * 101 * The settings in this file configure FreeRTOS correctly for the 102 * given hardware and compiler. 103 * 104 * These settings should not be altered. 105 *----------------------------------------------------------- 106 */ 107 108 /* Type definitions. */ 109 110 #define portCHAR int8_t 111 #define portFLOAT float 112 #define portDOUBLE double 113 #define portLONG int32_t 114 #define portSHORT int16_t 115 #define portSTACK_TYPE uint8_t 116 #define portBASE_TYPE int 117 118 typedef portSTACK_TYPE StackType_t; 119 typedef portBASE_TYPE BaseType_t; 120 typedef unsigned portBASE_TYPE UBaseType_t; 121 122 #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) 123 typedef uint16_t TickType_t; 124 #define portMAX_DELAY ( TickType_t ) 0xffff 125 #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) 126 typedef uint32_t TickType_t; 127 #define portMAX_DELAY ( TickType_t ) 0xffffffffUL 128 #else 129 #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. 130 #endif 131 /*-----------------------------------------------------------*/ 132 133 /* portbenchmark */ 134 #include "portbenchmark.h" 135 136 #include "sdkconfig.h" 137 #include "esp_attr.h" 138 139 /* "mux" data structure (spinlock) */ 140 typedef spinlock_t portMUX_TYPE; /**< Spinlock type used by FreeRTOS critical sections */ 141 #define portMUX_INITIALIZER_UNLOCKED SPINLOCK_INITIALIZER /**< Spinlock initializer */ 142 #define portMUX_FREE_VAL SPINLOCK_FREE /**< Spinlock is free. [refactor-todo] check if this is still required */ 143 #define portMUX_NO_TIMEOUT SPINLOCK_WAIT_FOREVER /**< When passed for 'timeout_cycles', spin forever if necessary. [refactor-todo] check if this is still required */ 144 #define portMUX_TRY_LOCK SPINLOCK_NO_WAIT /**< Try to acquire the spinlock a single time only. [refactor-todo] check if this is still required */ 145 #define portMUX_INITIALIZE(mux) spinlock_initialize(mux) /*< Initialize a spinlock to its unlocked state */ 146 147 #define portCRITICAL_NESTING_IN_TCB 1 148 149 /* 150 * Modifications to portENTER_CRITICAL. 151 * 152 * For an introduction, see "Critical Sections & Disabling Interrupts" in docs/api-guides/freertos-smp.rst 153 * 154 * The original portENTER_CRITICAL only disabled the ISRs. This is enough for single-CPU operation: by 155 * disabling the interrupts, there is no task switch so no other tasks can meddle in the data, and because 156 * interrupts are disabled, ISRs can't corrupt data structures either. 157 * 158 * For multiprocessing, things get a bit more hairy. First of all, disabling the interrupts doesn't stop 159 * the tasks or ISRs on the other processors meddling with our CPU. For tasks, this is solved by adding 160 * a spinlock to the portENTER_CRITICAL macro. A task running on the other CPU accessing the same data will 161 * spinlock in the portENTER_CRITICAL code until the first CPU is done. 162 * 163 * For ISRs, we now also need muxes: while portENTER_CRITICAL disabling interrupts will stop ISRs on the same 164 * CPU from meddling with the data, it does not stop interrupts on the other cores from interfering with the 165 * data. For this, we also use a spinlock in the routines called by the ISR, but these spinlocks 166 * do not disable the interrupts (because they already are). 167 * 168 * This all assumes that interrupts are either entirely disabled or enabled. Interrupt priority levels 169 * will break this scheme. 170 * 171 * Remark: For the ESP32, portENTER_CRITICAL and portENTER_CRITICAL_ISR both alias vPortEnterCritical, meaning 172 * that either function can be called both from ISR as well as task context. This is not standard FreeRTOS 173 * behaviour; please keep this in mind if you need any compatibility with other FreeRTOS implementations. 174 */ 175 void vPortCPUInitializeMutex( portMUX_TYPE * mux ); 176 #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG 177 #error CONFIG_FREERTOS_PORTMUX_DEBUG not supported in Amazon FreeRTOS 178 #endif 179 180 void vTaskExitCritical(); 181 void vTaskEnterCritical(); vPortConsumeSpinlockArg(int unused,...)182 static inline void vPortConsumeSpinlockArg( int unused, 183 ... ) 184 { 185 } 186 187 /** @brief Acquire a portmux spinlock with a timeout 188 * 189 * @param mux Pointer to portmux to acquire. 190 * @param timeout_cycles Timeout to spin, in CPU cycles. Pass portMUX_NO_TIMEOUT to wait forever, 191 * portMUX_TRY_LOCK to try a single time to acquire the lock. 192 * 193 * @return true if mutex is successfully acquired, false on timeout. 194 */ 195 bool vPortCPUAcquireMutexTimeout( portMUX_TYPE * mux, 196 int timeout_cycles ); 197 void vPortCPUReleaseMutex( portMUX_TYPE * mux ); 198 199 #define portENTER_CRITICAL( ... ) do { vTaskEnterCritical(); vPortConsumeSpinlockArg( 0, ## __VA_ARGS__ ); } while( 0 ) 200 #define portEXIT_CRITICAL( ... ) do { vTaskExitCritical(); vPortConsumeSpinlockArg( 0, ## __VA_ARGS__ ); } while( 0 ) 201 202 203 #define portENTER_CRITICAL_ISR( mux ) vPortCPUAcquireMutexTimeout( mux, portMUX_NO_TIMEOUT ) 204 #define portEXIT_CRITICAL_ISR( mux ) vPortCPUReleaseMutex( mux ) 205 206 #define portENTER_CRITICAL_SAFE( mux ) \ 207 do { \ 208 if( xPortInIsrContext() ) { \ 209 portENTER_CRITICAL_ISR( mux ); \ 210 } \ 211 else { \ 212 portENTER_CRITICAL( mux ); \ 213 } \ 214 } while( 0 ) 215 216 #define portEXIT_CRITICAL_SAFE( mux ) \ 217 do { \ 218 if( xPortInIsrContext() ) { \ 219 portEXIT_CRITICAL_ISR( mux ); \ 220 } \ 221 else { \ 222 portEXIT_CRITICAL( mux ); \ 223 } \ 224 } while( 0 ) 225 226 #define portASSERT_IF_IN_ISR() vPortAssertIfInISR() 227 void vPortAssertIfInISR(void); 228 229 /* Critical section management. NW-TODO: replace XTOS_SET_INTLEVEL with more efficient version, if any? */ 230 /* These cannot be nested. They should be used with a lot of care and cannot be called from interrupt level. */ 231 /* */ 232 /* Only applies to one CPU. See notes above & below for reasons not to use these. */ 233 #define portDISABLE_INTERRUPTS() do { XTOS_SET_INTLEVEL( XCHAL_EXCM_LEVEL ); portbenchmarkINTERRUPT_DISABLE(); } while( 0 ) 234 #define portENABLE_INTERRUPTS() do { portbenchmarkINTERRUPT_RESTORE( 0 ); XTOS_SET_INTLEVEL( 0 ); } while( 0 ) 235 236 /* Cleaner solution allows nested interrupts disabling and restoring via local registers or stack. */ 237 /* They can be called from interrupts too. */ 238 /* WARNING: Only applies to current CPU. See notes above. */ xPortSetInterruptMaskFromISR(void)239 static inline UBaseType_t __attribute__( ( always_inline ) ) xPortSetInterruptMaskFromISR( void ) 240 { 241 UBaseType_t prev_int_level = XTOS_SET_INTLEVEL( XCHAL_EXCM_LEVEL ); 242 portbenchmarkINTERRUPT_DISABLE(); 243 return prev_int_level; 244 } 245 vPortClearInterruptMaskFromISR(UBaseType_t prev_level)246 static inline void __attribute__( ( always_inline ) ) vPortClearInterruptMaskFromISR( UBaseType_t prev_level ) 247 { 248 portbenchmarkINTERRUPT_RESTORE( prev_level ); 249 XTOS_RESTORE_JUST_INTLEVEL( prev_level ); 250 } 251 252 /* These FreeRTOS versions are similar to the nested versions above */ 253 #define portSET_INTERRUPT_MASK_FROM_ISR() xPortSetInterruptMaskFromISR() 254 #define portCLEAR_INTERRUPT_MASK_FROM_ISR( prev_level ) vPortClearInterruptMaskFromISR( prev_level ) 255 256 /*Because the ROM routines don't necessarily handle a stack in external RAM correctly, we force */ 257 /*the stack memory to always be internal. */ 258 #define portTcbMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT) 259 #define portStackMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT) 260 261 #define pvPortMallocTcbMem(size) heap_caps_malloc(size, portTcbMemoryCaps) 262 #define pvPortMallocStackMem(size) heap_caps_malloc(size, portStackMemoryCaps) 263 264 /*xTaskCreateStatic uses these functions to check incoming memory. */ 265 #define portVALID_TCB_MEM( ptr ) ( esp_ptr_internal( ptr ) && esp_ptr_byte_accessible( ptr ) ) 266 #ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY 267 #define portVALID_STACK_MEM( ptr ) esp_ptr_byte_accessible( ptr ) 268 #else 269 #define portVALID_STACK_MEM( ptr ) ( esp_ptr_internal( ptr ) && esp_ptr_byte_accessible( ptr ) ) 270 #endif 271 272 /* 273 * Wrapper for the Xtensa compare-and-set instruction. This subroutine will atomically compare 274 * *addr to 'compare'. If *addr == compare, *addr is set to *set. *set is updated with the previous 275 * value of *addr (either 'compare' or some other value.) 276 * 277 * Warning: From the ISA docs: in some (unspecified) cases, the s32c1i instruction may return the 278 * *bitwise inverse* of the old mem if the mem wasn't written. This doesn't seem to happen on the 279 * ESP32 (portMUX assertions would fail). 280 */ uxPortCompareSet(volatile uint32_t * addr,uint32_t compare,uint32_t * set)281 static inline void uxPortCompareSet( volatile uint32_t * addr, 282 uint32_t compare, 283 uint32_t * set ) 284 { 285 #if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0)) 286 __asm__ __volatile__ ( 287 "WSR %2,SCOMPARE1 \n" 288 "S32C1I %0, %1, 0 \n" 289 : "=r" ( *set ) 290 : "r" ( addr ), "r" ( compare ), "0" ( *set ) 291 ); 292 #else 293 #if ( XCHAL_HAVE_S32C1I > 0 ) 294 __asm__ __volatile__ ( 295 "WSR %2,SCOMPARE1 \n" 296 "S32C1I %0, %1, 0 \n" 297 : "=r" ( *set ) 298 : "r" ( addr ), "r" ( compare ), "0" ( *set ) 299 ); 300 #else 301 /* No S32C1I, so do this by disabling and re-enabling interrupts (slower) */ 302 uint32_t intlevel, old_value; 303 __asm__ __volatile__ ( "rsil %0, " XTSTR( XCHAL_EXCM_LEVEL ) "\n" 304 : "=r" ( intlevel ) ); 305 306 old_value = *addr; 307 308 if( old_value == compare ) 309 { 310 *addr = *set; 311 } 312 313 __asm__ __volatile__ ( "memw \n" 314 "wsr %0, ps\n" 315 : : "r" ( intlevel ) ); 316 317 *set = old_value; 318 #endif /* if ( XCHAL_HAVE_S32C1I > 0 ) */ 319 #endif /* #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)) */ 320 } 321 322 #if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0)) 323 void uxPortCompareSetExtram( volatile uint32_t * addr, 324 uint32_t compare, 325 uint32_t * set ); 326 #else uxPortCompareSetExtram(volatile uint32_t * addr,uint32_t compare,uint32_t * set)327 static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set) 328 { 329 #if defined(CONFIG_SPIRAM) 330 compare_and_set_extram(addr, compare, set); 331 #endif 332 } 333 #endif 334 335 /*-----------------------------------------------------------*/ 336 337 /* Architecture specifics. */ 338 #define portSTACK_GROWTH ( -1 ) 339 #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) 340 #define portBYTE_ALIGNMENT 4 341 #define portNOP() XT_NOP() 342 /*-----------------------------------------------------------*/ 343 344 /* Fine resolution time */ 345 #define portGET_RUN_TIME_COUNTER_VALUE() xthal_get_ccount() 346 /*ccount or esp_timer are initialized elsewhere */ 347 #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() 348 349 #ifdef CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER 350 /* Coarse resolution time (us) */ 351 #define portALT_GET_RUN_TIME_COUNTER_VALUE( x ) do { x = ( uint32_t )esp_timer_get_time(); } while( 0 ) 352 #endif 353 354 355 356 /* Kernel utilities. */ 357 void vPortYield( void ); 358 void vPortEvaluateYieldFromISR( int argc, ... ); 359 void _frxt_setup_switch( void ); 360 /* Macro to count number of arguments of a __VA_ARGS__ used to support portYIELD_FROM_ISR with, 361 * or without arguments. The macro counts only 0 or 1 arguments. 362 * 363 * In the future, we want to switch to C++20. We also want to become compatible with clang. 364 * Hence, we provide two versions of the following macros which are using variadic arguments. 365 * The first one is using the GNU extension ##__VA_ARGS__. The second one is using the C++20 feature __VA_OPT__(,). 366 * This allows users to compile their code with standard C++20 enabled instead of the GNU extension. 367 * Below C++20, we haven't found any good alternative to using ##__VA_ARGS__. 368 */ 369 #if defined( __cplusplus ) && ( __cplusplus > 201703L ) 370 #define portGET_ARGUMENT_COUNT(...) portGET_ARGUMENT_COUNT_INNER( 0 __VA_OPT__(,) __VA_ARGS__, 1 , 0 ) 371 #else 372 #define portGET_ARGUMENT_COUNT(...) portGET_ARGUMENT_COUNT_INNER( 0, ##__VA_ARGS__, 1, 0 ) 373 #endif 374 #define portGET_ARGUMENT_COUNT_INNER( zero, one, count, ... ) count 375 376 _Static_assert( portGET_ARGUMENT_COUNT() == 0, "portGET_ARGUMENT_COUNT() result does not match for 0 arguments" ); 377 _Static_assert( portGET_ARGUMENT_COUNT( 1 ) == 1, "portGET_ARGUMENT_COUNT() result does not match for 1 argument" ); 378 379 #define portYIELD() vPortYield() 380 381 /* The macro below could be used when passing a single argument, or without any argument, 382 * it was developed to support both usages of portYIELD inside of an ISR. Any other usage form 383 * might result in undesired behaviour 384 */ 385 #if defined( __cplusplus ) && ( __cplusplus > 201703L ) 386 #define portYIELD_FROM_ISR(...) vPortEvaluateYieldFromISR( portGET_ARGUMENT_COUNT( __VA_ARGS__ ) __VA_OPT__( , ) __VA_ARGS__ ) 387 #else 388 #define portYIELD_FROM_ISR(...) vPortEvaluateYieldFromISR( portGET_ARGUMENT_COUNT( __VA_ARGS__ ), ##__VA_ARGS__ ) 389 #endif 390 391 static inline BaseType_t xPortGetCoreID(); 392 393 /*-----------------------------------------------------------*/ 394 395 /* Task function macros as described on the FreeRTOS.org WEB site. */ 396 #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) 397 #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) 398 399 /* When coprocessors are defined, we to maintain a pointer to coprocessors area. */ 400 /* We currently use a hack: redefine field xMPU_SETTINGS in TCB block as a structure that can hold: */ 401 /* MPU wrappers, coprocessor area pointer, trace code structure, and more if needed. */ 402 /* The field is normally used for memory protection. FreeRTOS should create another general purpose field. */ 403 typedef struct 404 { 405 #if XCHAL_CP_NUM > 0 406 volatile StackType_t * coproc_area; /* Pointer to coprocessor save area; MUST BE FIRST */ 407 #endif 408 409 #if portUSING_MPU_WRAPPERS 410 /* Define here mpu_settings, which is port dependent */ 411 int mpu_setting; /* Just a dummy example here; MPU not ported to Xtensa yet */ 412 #endif 413 414 #if configUSE_TRACE_FACILITY_2 415 struct 416 { 417 /* Cf. porttraceStamp() */ 418 int taskstamp; /* Stamp from inside task to see where we are */ 419 int taskstampcount; /* A counter usually incremented when we restart the task's loop */ 420 } porttrace; 421 #endif 422 } xMPU_SETTINGS; 423 424 /* Main hack to use MPU_wrappers even when no MPU is defined (warning: mpu_setting should not be accessed; otherwise move this above xMPU_SETTINGS) */ 425 #if ( XCHAL_CP_NUM > 0 || configUSE_TRACE_FACILITY_2 ) && !portUSING_MPU_WRAPPERS /* If MPU wrappers not used, we still need to allocate coproc area */ 426 #undef portUSING_MPU_WRAPPERS 427 #define portUSING_MPU_WRAPPERS 1 /* Enable it to allocate coproc area */ 428 #define MPU_WRAPPERS_H /* Override mpu_wrapper.h to disable unwanted code */ 429 #define PRIVILEGED_FUNCTION 430 #define PRIVILEGED_DATA 431 #endif 432 433 void vApplicationSleep( TickType_t xExpectedIdleTime ); 434 435 #define portSUPPRESS_TICKS_AND_SLEEP( idleTime ) vApplicationSleep( idleTime ) 436 437 void _xt_coproc_release( volatile void * coproc_sa_base ); 438 439 /*-----------------------------------------------------------*/ 440 441 #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)) 442 /* Architecture specific optimisations. */ 443 444 #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 445 446 /* Check the configuration. */ 447 #if( configMAX_PRIORITIES > 32 ) 448 #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. 449 #endif 450 451 /* Store/clear the ready priorities in a bit map. */ 452 #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) 453 #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) 454 455 /*-----------------------------------------------------------*/ 456 457 #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( ( uxReadyPriorities ) ) ) 458 459 #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ 460 461 #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */ 462 463 /*-----------------------------------------------------------*/ 464 465 /* 466 * Map to the memory management routines required for the port. 467 * 468 * Note that libc standard malloc/free are also available for 469 * non-FreeRTOS-specific code, and behave the same as 470 * pvPortMalloc()/vPortFree(). 471 */ 472 #define pvPortMalloc heap_caps_malloc_default 473 #define vPortFree heap_caps_free 474 #define xPortGetFreeHeapSize esp_get_free_heap_size 475 #define xPortGetMinimumEverFreeHeapSize esp_get_minimum_free_heap_size 476 477 #if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0)) 478 /* 479 * Send an interrupt to another core in order to make the task running 480 * on it yield for a higher-priority task. 481 */ 482 483 void vPortYieldOtherCore( BaseType_t coreid ) PRIVILEGED_FUNCTION; 484 485 #endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0) */ 486 487 /* 488 * Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack 489 * watchpoint around. 490 */ 491 void vPortSetStackWatchpoint( void * pxStackStart ); 492 493 /* 494 * Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs 495 * aren't detected here, but they normally cannot call C code, so that should not be an issue anyway. 496 */ 497 BaseType_t xPortInIsrContext(); 498 499 500 /* 501 * This function will be called in High prio ISRs. Returns true if the current core was in ISR context 502 * before calling into high prio ISR context. 503 */ 504 BaseType_t xPortInterruptedFromISRContext(); 505 506 /* 507 * The structures and methods of manipulating the MPU are contained within the 508 * port layer. 509 * 510 * Fills the xMPUSettings structure with the memory region information 511 * contained in xRegions. 512 */ 513 #if ( portUSING_MPU_WRAPPERS == 1 ) 514 struct xMEMORY_REGION; 515 void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, 516 const struct xMEMORY_REGION * const xRegions, 517 StackType_t * pxBottomOfStack, 518 uint32_t usStackDepth ) PRIVILEGED_FUNCTION; 519 void vPortReleaseTaskMPUSettings( xMPU_SETTINGS * xMPUSettings ); 520 #endif 521 522 /* Multi-core: get current core ID */ xPortGetCoreID()523 static inline BaseType_t IRAM_ATTR xPortGetCoreID() 524 { 525 return ( uint32_t )cpu_hal_get_core_id(); 526 } 527 528 /* Get tick rate per second */ 529 uint32_t xPortGetTickRateHz( void ); 530 xPortCanYield(void)531 static inline bool IRAM_ATTR xPortCanYield(void) 532 { 533 uint32_t ps_reg = 0; 534 535 //Get the current value of PS (processor status) register 536 RSR(PS, ps_reg); 537 538 /* 539 * intlevel = (ps_reg & 0xf); 540 * excm = (ps_reg >> 4) & 0x1; 541 * CINTLEVEL is max(excm * EXCMLEVEL, INTLEVEL), where EXCMLEVEL is 3. 542 * However, just return true, only intlevel is zero. 543 */ 544 545 return ((ps_reg & PS_INTLEVEL_MASK) == 0); 546 } 547 548 /* porttrace */ 549 #if configUSE_TRACE_FACILITY_2 550 #include "porttrace.h" 551 #endif 552 553 /* configASSERT_2 if requested */ 554 #if configASSERT_2 555 #include <stdio.h> 556 void exit( int ); 557 #define configASSERT( x ) if( !( x ) ) { porttracePrint( -1 ); printf( "\nAssertion failed in %s:%d\n", __FILE__, __LINE__ ); exit( -1 ); } 558 #endif 559 560 /* Barriers */ 561 #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) 562 563 564 #endif // __ASSEMBLER__ 565 566 /* *INDENT-OFF* */ 567 #ifdef __cplusplus 568 } 569 #endif 570 /* *INDENT-ON* */ 571 572 #endif /* PORTMACRO_H */ 573