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