| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2022-01-29 16:49:56 +08:00
										 |  |  |  * SPDX-FileCopyrightText: 2020 Amazon.com, Inc. or its affiliates | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * SPDX-License-Identifier: MIT | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  |  * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD | 
					
						
							| 
									
										
										
										
											2022-01-29 16:49:56 +08:00
										 |  |  |  */ | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * FreeRTOS Kernel V10.4.3 | 
					
						
							|  |  |  |  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 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
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 1 tab == 4 spaces! | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*-----------------------------------------------------------------------
 | 
					
						
							|  |  |  |  * Implementation of functions defined in portable.h for the RISC-V port. | 
					
						
							|  |  |  |  *----------------------------------------------------------------------*/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:03:50 -03:00
										 |  |  | #include "sdkconfig.h"
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2021-01-28 11:32:51 +08:00
										 |  |  | #include "soc/soc_caps.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | #include "soc/periph_defs.h"
 | 
					
						
							|  |  |  | #include "soc/system_reg.h"
 | 
					
						
							|  |  |  | #include "hal/systimer_hal.h"
 | 
					
						
							|  |  |  | #include "hal/systimer_ll.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:03:50 -03:00
										 |  |  | #include "riscv/rvruntime-frames.h"
 | 
					
						
							| 
									
										
										
										
											2022-07-26 22:07:58 +08:00
										 |  |  | #include "riscv/rv_utils.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | #include "riscv/interrupt.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:03:50 -03:00
										 |  |  | #include "esp_private/crosscore_int.h"
 | 
					
						
							|  |  |  | #include "esp_attr.h"
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | #include "esp_system.h"
 | 
					
						
							|  |  |  | #include "esp_intr_alloc.h"
 | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | #include "esp_log.h"
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | #include "FreeRTOS.h"       /* This pulls in portmacro.h */
 | 
					
						
							|  |  |  | #include "task.h"
 | 
					
						
							|  |  |  | #include "portmacro.h"
 | 
					
						
							|  |  |  | #include "port_systick.h"
 | 
					
						
							| 
									
										
										
										
											2022-07-21 19:14:41 +08:00
										 |  |  | #include "esp_memory_utils.h"
 | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | #if CONFIG_IDF_TARGET_ESP32P4
 | 
					
						
							|  |  |  | //TODO: IDF-7566
 | 
					
						
							|  |  |  | #include "soc/hp_system_reg.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-11 15:00:42 +08:00
										 |  |  | _Static_assert(portBYTE_ALIGNMENT == 16, "portBYTE_ALIGNMENT must be set to 16"); | 
					
						
							| 
									
										
										
										
											2023-05-04 17:31:31 +02:00
										 |  |  | #if CONFIG_ESP_SYSTEM_HW_STACK_GUARD
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * offsetof() can not be used in asm code. Then we need make sure that | 
					
						
							|  |  |  |  * PORT_OFFSET_PX_STACK and PORT_OFFSET_PX_END_OF_STACK have expected values. | 
					
						
							|  |  |  |  * Macro used in the portasm.S instead of variables to save at least 4 instruction calls | 
					
						
							|  |  |  |  * which accessing DRAM memory. This optimization saves CPU time in the interrupt handling. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | _Static_assert(offsetof( StaticTask_t, pxDummy6 ) == PORT_OFFSET_PX_STACK); | 
					
						
							|  |  |  | _Static_assert(offsetof( StaticTask_t, pxDummy8 ) == PORT_OFFSET_PX_END_OF_STACK); | 
					
						
							|  |  |  | #endif // CONFIG_ESP_SYSTEM_HW_STACK_GUARD
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* ---------------------------------------------------- Variables ------------------------------------------------------
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ------------------------------------------------------------------------------------------------------------------ */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | //TODO: IDF-7566
 | 
					
						
							|  |  |  | #if !CONFIG_IDF_TARGET_ESP32P4
 | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @brief A variable is used to keep track of the critical section nesting. | 
					
						
							|  |  |  |  * @note This variable has to be stored as part of the task context and must be initialized to a non zero value | 
					
						
							|  |  |  |  *       to ensure interrupts don't inadvertently become unmasked before the scheduler starts. | 
					
						
							|  |  |  |  *       As it is stored as part of the task context it will automatically be set to 0 when the first task is started. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2020-12-29 12:31:54 +08:00
										 |  |  | static UBaseType_t uxCriticalNesting = 0; | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | static UBaseType_t uxSavedInterruptState = 0; | 
					
						
							| 
									
										
										
										
											2022-11-24 22:20:50 +08:00
										 |  |  | BaseType_t uxSchedulerRunning = 0;  // Duplicate of xSchedulerRunning, accessible to port files
 | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | UBaseType_t uxInterruptNesting = 0; | 
					
						
							| 
									
										
										
										
											2020-11-04 18:34:47 -03:00
										 |  |  | BaseType_t xPortSwitchFlag = 0; | 
					
						
							| 
									
										
										
										
											2023-05-04 17:31:31 +02:00
										 |  |  | __attribute__((aligned(16))) StackType_t xIsrStack[configISR_STACK_SIZE]; | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | StackType_t *xIsrStackTop = &xIsrStack[0] + (configISR_STACK_SIZE & (~((portPOINTER_SIZE_TYPE)portBYTE_ALIGNMENT_MASK))); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | #else
 | 
					
						
							|  |  |  | /* uxCriticalNesting will be increased by 1 each time one processor is entering a critical section
 | 
					
						
							|  |  |  |  * and will be decreased by 1 each time one processor is exiting a critical section | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | volatile UBaseType_t uxCriticalNesting[portNUM_PROCESSORS] = {0}; | 
					
						
							|  |  |  | volatile UBaseType_t uxSavedInterruptState[portNUM_PROCESSORS] = {0}; | 
					
						
							|  |  |  | volatile BaseType_t uxSchedulerRunning[portNUM_PROCESSORS] = {0}; | 
					
						
							|  |  |  | volatile UBaseType_t uxInterruptNesting[portNUM_PROCESSORS] = {0}; | 
					
						
							|  |  |  | volatile BaseType_t xPortSwitchFlag[portNUM_PROCESSORS] = {0}; | 
					
						
							|  |  |  | /* core0 interrupt stack space */ | 
					
						
							|  |  |  | __attribute__((aligned(16))) static StackType_t xIsrStack[configISR_STACK_SIZE]; | 
					
						
							|  |  |  | /* core1 interrupt stack space */ | 
					
						
							|  |  |  | __attribute__((aligned(16))) static StackType_t xIsrStack1[configISR_STACK_SIZE]; | 
					
						
							|  |  |  | /* core0 interrupt stack top, passed to sp */ | 
					
						
							|  |  |  | StackType_t *xIsrStackTop = &xIsrStack[0] + (configISR_STACK_SIZE & (~((portPOINTER_SIZE_TYPE)portBYTE_ALIGNMENT_MASK))); | 
					
						
							|  |  |  | /* core1 interrupt stack top, passed to sp */ | 
					
						
							|  |  |  | StackType_t *xIsrStackTop1 = &xIsrStack1[0] + (configISR_STACK_SIZE & (~((portPOINTER_SIZE_TYPE)portBYTE_ALIGNMENT_MASK))); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | /* ------------------------------------------------ FreeRTOS Portable --------------------------------------------------
 | 
					
						
							|  |  |  |  * - Provides implementation for functions required by FreeRTOS | 
					
						
							|  |  |  |  * - Declared in portable.h | 
					
						
							|  |  |  |  * ------------------------------------------------------------------------------------------------------------------ */ | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | // ----------------- Scheduler Start/End -------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | //TODO: IDF-7566
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | BaseType_t xPortStartScheduler(void) | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | #if !CONFIG_IDF_TARGET_ESP32P4
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  |     uxInterruptNesting = 0; | 
					
						
							|  |  |  |     uxCriticalNesting = 0; | 
					
						
							|  |  |  |     uxSchedulerRunning = 0; | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | #else
 | 
					
						
							|  |  |  |     BaseType_t coreID = xPortGetCoreID(); | 
					
						
							|  |  |  |     uxInterruptNesting[coreID] = 0; | 
					
						
							|  |  |  |     uxCriticalNesting[coreID] = 0; | 
					
						
							|  |  |  |     uxSchedulerRunning[coreID] = 0; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  |     /* Setup the hardware to generate the tick. */ | 
					
						
							|  |  |  |     vPortSetupTimer(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     esprv_intc_int_set_threshold(1); /* set global INTC masking level */ | 
					
						
							| 
									
										
										
										
											2022-07-26 22:07:58 +08:00
										 |  |  |     rv_utils_intr_global_enable(); | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     vPortYield(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*Should not get here*/ | 
					
						
							|  |  |  |     return pdFALSE; | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | void vPortEndScheduler(void) | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  |     /* very unlikely this function will be called, so just trap here */ | 
					
						
							|  |  |  |     abort(); | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | // ------------------------ Stack --------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 18:17:13 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @brief Align stack pointer in a downward growing stack | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This macro is used to round a stack pointer downwards to the nearest n-byte boundary, where n is a power of 2. | 
					
						
							|  |  |  |  * This macro is generally used when allocating aligned areas on a downward growing stack. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #define STACKPTR_ALIGN_DOWN(n, ptr)     ((ptr) & (~((n)-1)))
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |  * @brief Allocate and initialize GCC TLS area | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This function allocates and initializes the area on the stack used to store GCC TLS (Thread Local Storage) variables. | 
					
						
							|  |  |  |  * - The area's size is derived from the TLS section's linker variables, and rounded up to a multiple of 16 bytes | 
					
						
							|  |  |  |  * - The allocated area is aligned to a 16-byte aligned address | 
					
						
							|  |  |  |  * - The TLS variables in the area are then initialized | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Each task access the TLS variables using the THREADPTR register plus an offset to obtain the address of the variable. | 
					
						
							|  |  |  |  * The value for the THREADPTR register is also calculated by this function, and that value should be use to initialize | 
					
						
							|  |  |  |  * the THREADPTR register. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param[in] uxStackPointer Current stack pointer address | 
					
						
							|  |  |  |  * @param[out] ret_threadptr_reg_init Calculated THREADPTR register initialization value | 
					
						
							|  |  |  |  * @return Stack pointer that points to the TLS area | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, uint32_t *ret_threadptr_reg_init) | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2022-09-27 18:17:13 +08:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |     TLS layout at link-time, where 0xNNN is the offset that the linker calculates to a particular TLS variable. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     LOW ADDRESS | 
					
						
							|  |  |  |             |---------------------------|   Linker Symbols | 
					
						
							|  |  |  |             | Section                   |   -------------- | 
					
						
							|  |  |  |             | .flash.rodata             | | 
					
						
							|  |  |  |          0x0|---------------------------| <- _flash_rodata_start | 
					
						
							|  |  |  |           ^ | Other Data                | | 
					
						
							|  |  |  |           | |---------------------------| <- _thread_local_start | 
					
						
							|  |  |  |           | | .tbss                     | ^ | 
					
						
							|  |  |  |           V |                           | | | 
					
						
							|  |  |  |       0xNNN | int example;              | | tls_area_size | 
					
						
							|  |  |  |             |                           | | | 
					
						
							|  |  |  |             | .tdata                    | V | 
					
						
							|  |  |  |             |---------------------------| <- _thread_local_end | 
					
						
							|  |  |  |             | Other data                | | 
					
						
							|  |  |  |             | ...                       | | 
					
						
							|  |  |  |             |---------------------------| | 
					
						
							|  |  |  |     HIGH ADDRESS | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     // Calculate TLS area size and round up to multiple of 16 bytes.
 | 
					
						
							| 
									
										
										
										
											2021-04-21 11:49:58 +02:00
										 |  |  |     extern char _thread_local_start, _thread_local_end, _flash_rodata_start; | 
					
						
							| 
									
										
										
										
											2022-09-27 18:17:13 +08:00
										 |  |  |     const uint32_t tls_area_size = ALIGNUP(16, (uint32_t)&_thread_local_end - (uint32_t)&_thread_local_start); | 
					
						
							|  |  |  |     // TODO: check that TLS area fits the stack
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Allocate space for the TLS area on the stack. The area must be aligned to 16-bytes
 | 
					
						
							|  |  |  |     uxStackPointer = STACKPTR_ALIGN_DOWN(16, uxStackPointer - (UBaseType_t)tls_area_size); | 
					
						
							|  |  |  |     // Initialize the TLS area with the initialization values of each TLS variable
 | 
					
						
							|  |  |  |     memcpy((void *)uxStackPointer, &_thread_local_start, tls_area_size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |     Calculate the THREADPTR register's initialization value based on the link-time offset and the TLS area allocated on | 
					
						
							|  |  |  |     the stack. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     HIGH ADDRESS | 
					
						
							|  |  |  |             |---------------------------| | 
					
						
							|  |  |  |             | .tdata (*)                | | 
					
						
							|  |  |  |           ^ | int example;              | | 
					
						
							|  |  |  |           | |                           | | 
					
						
							|  |  |  |           | | .tbss (*)                 | | 
					
						
							|  |  |  |           | |---------------------------| <- uxStackPointer (start of TLS area) | 
					
						
							|  |  |  |     0xNNN | |                           | ^ | 
					
						
							|  |  |  |           | |                           | | | 
					
						
							|  |  |  |           |             ...               | _thread_local_start - _rodata_start | 
					
						
							|  |  |  |           | |                           | | | 
					
						
							|  |  |  |           | |                           | V | 
					
						
							|  |  |  |           V |                           | <- threadptr register's value | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     LOW ADDRESS | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     *ret_threadptr_reg_init = (uint32_t)uxStackPointer - ((uint32_t)&_thread_local_start - (uint32_t)&_flash_rodata_start); | 
					
						
							|  |  |  |     return uxStackPointer; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-12-24 01:56:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-27 18:41:19 +08:00
										 |  |  | #if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
 | 
					
						
							| 
									
										
										
										
											2023-02-02 01:17:28 +07:00
										 |  |  | static void vPortTaskWrapper(TaskFunction_t pxCode, void *pvParameters) | 
					
						
							| 
									
										
										
										
											2022-10-27 18:41:19 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-02-02 01:17:28 +07:00
										 |  |  |     __asm__ volatile(".cfi_undefined ra");  // tell to debugger that it's outermost (inital) frame
 | 
					
						
							| 
									
										
										
										
											2022-10-27 18:41:19 +08:00
										 |  |  |     extern void __attribute__((noreturn)) panic_abort(const char *details); | 
					
						
							|  |  |  |     static char DRAM_ATTR msg[80] = "FreeRTOS: FreeRTOS Task \"\0"; | 
					
						
							|  |  |  |     pxCode(pvParameters); | 
					
						
							| 
									
										
										
										
											2023-02-02 01:17:28 +07:00
										 |  |  |     /* FreeRTOS tasks should not return. Log the task name and abort. */ | 
					
						
							| 
									
										
										
										
											2022-10-27 18:41:19 +08:00
										 |  |  |     /* We cannot use s(n)printf because it is in flash */ | 
					
						
							| 
									
										
										
										
											2023-02-02 01:17:28 +07:00
										 |  |  |     strcat(msg, pcTaskGetName(NULL)); | 
					
						
							| 
									
										
										
										
											2022-10-27 18:41:19 +08:00
										 |  |  |     strcat(msg, "\" should not return, Aborting now!"); | 
					
						
							|  |  |  |     panic_abort(msg); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif // CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 18:17:13 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @brief Initialize the task's starting interrupt stack frame | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This function initializes the task's starting interrupt stack frame. The dispatcher will use this stack frame in a | 
					
						
							|  |  |  |  * context restore routine. Therefore, the starting stack frame must be initialized as if the task was interrupted right | 
					
						
							|  |  |  |  * before its first instruction is called. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * - The stack frame is allocated to a 16-byte aligned address | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param[in] uxStackPointer Current stack pointer address | 
					
						
							|  |  |  |  * @param[in] pxCode Task function | 
					
						
							|  |  |  |  * @param[in] pvParameters Task function's parameter | 
					
						
							|  |  |  |  * @param[in] threadptr_reg_init THREADPTR register initialization value | 
					
						
							|  |  |  |  * @return Stack pointer that points to the stack frame | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackFrame(UBaseType_t uxStackPointer, TaskFunction_t pxCode, void *pvParameters, uint32_t threadptr_reg_init) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /*
 | 
					
						
							|  |  |  |     Allocate space for the task's starting interrupt stack frame. | 
					
						
							|  |  |  |     - The stack frame must be allocated to a 16-byte aligned address. | 
					
						
							|  |  |  |     - We use XT_STK_FRMSZ (instead of sizeof(XtExcFrame)) as it rounds up the total size to a multiple of 16. | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     uxStackPointer = STACKPTR_ALIGN_DOWN(16, uxStackPointer - RV_STK_FRMSZ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Clear the entire interrupt stack frame
 | 
					
						
							|  |  |  |     RvExcFrame *frame = (RvExcFrame *)uxStackPointer; | 
					
						
							|  |  |  |     memset(frame, 0, sizeof(RvExcFrame)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-27 18:41:19 +08:00
										 |  |  |     /* Initialize the stack frame. */ | 
					
						
							| 
									
										
										
										
											2022-09-27 18:17:13 +08:00
										 |  |  |     extern uint32_t __global_pointer$; | 
					
						
							| 
									
										
										
										
											2022-10-27 18:41:19 +08:00
										 |  |  |     #if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
 | 
					
						
							|  |  |  |         frame->mepc = (UBaseType_t)vPortTaskWrapper; | 
					
						
							|  |  |  |         frame->a0 = (UBaseType_t)pxCode; | 
					
						
							|  |  |  |         frame->a1 = (UBaseType_t)pvParameters; | 
					
						
							|  |  |  |     #else
 | 
					
						
							|  |  |  |         frame->mepc = (UBaseType_t)pxCode; | 
					
						
							|  |  |  |         frame->a0 = (UBaseType_t)pvParameters; | 
					
						
							|  |  |  |     #endif // CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
 | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  |     frame->gp = (UBaseType_t)&__global_pointer$; | 
					
						
							| 
									
										
										
										
											2022-09-27 18:17:13 +08:00
										 |  |  |     frame->tp = (UBaseType_t)threadptr_reg_init; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return uxStackPointer; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-11-13 16:03:50 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 18:17:13 +08:00
										 |  |  | StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-12-13 19:02:42 +08:00
										 |  |  | #ifdef __clang_analyzer__
 | 
					
						
							|  |  |  |     // Teach clang-tidy that pxTopOfStack cannot be a pointer to const
 | 
					
						
							|  |  |  |     volatile StackType_t * pxTemp = pxTopOfStack; | 
					
						
							|  |  |  |     pxTopOfStack = pxTemp; | 
					
						
							|  |  |  | #endif /*__clang_analyzer__ */
 | 
					
						
							| 
									
										
										
										
											2022-09-27 18:17:13 +08:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |     HIGH ADDRESS | 
					
						
							|  |  |  |     |---------------------------| <- pxTopOfStack on entry | 
					
						
							|  |  |  |     | TLS Variables             | | 
					
						
							|  |  |  |     | ------------------------- | <- Start of useable stack | 
					
						
							|  |  |  |     | Starting stack frame      | | 
					
						
							|  |  |  |     | ------------------------- | <- pxTopOfStack on return (which is the tasks current SP) | 
					
						
							|  |  |  |     |             |             | | 
					
						
							|  |  |  |     |             |             | | 
					
						
							|  |  |  |     |             V             | | 
					
						
							|  |  |  |     ----------------------------- <- Bottom of stack | 
					
						
							|  |  |  |     LOW ADDRESS | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     - All stack areas are aligned to 16 byte boundary | 
					
						
							|  |  |  |     - We use UBaseType_t for all of stack area initialization functions for more convenient pointer arithmetic | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     UBaseType_t uxStackPointer = (UBaseType_t)pxTopOfStack; | 
					
						
							| 
									
										
										
										
											2022-11-11 15:00:42 +08:00
										 |  |  |     configASSERT((uxStackPointer & portBYTE_ALIGNMENT_MASK) == 0); | 
					
						
							| 
									
										
										
										
											2022-09-27 18:17:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Initialize GCC TLS area
 | 
					
						
							|  |  |  |     uint32_t threadptr_reg_init; | 
					
						
							|  |  |  |     uxStackPointer = uxInitialiseStackTLS(uxStackPointer, &threadptr_reg_init); | 
					
						
							| 
									
										
										
										
											2022-11-11 15:00:42 +08:00
										 |  |  |     configASSERT((uxStackPointer & portBYTE_ALIGNMENT_MASK) == 0); | 
					
						
							| 
									
										
										
										
											2022-09-27 18:17:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Initialize the starting interrupt stack frame
 | 
					
						
							|  |  |  |     uxStackPointer = uxInitialiseStackFrame(uxStackPointer, pxCode, pvParameters, threadptr_reg_init); | 
					
						
							| 
									
										
										
										
											2022-11-11 15:00:42 +08:00
										 |  |  |     configASSERT((uxStackPointer & portBYTE_ALIGNMENT_MASK) == 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-27 18:17:13 +08:00
										 |  |  |     // Return the task's current stack pointer address which should point to the starting interrupt stack frame
 | 
					
						
							|  |  |  |     return (StackType_t *)uxStackPointer; | 
					
						
							| 
									
										
										
										
											2020-11-13 16:03:50 -03:00
										 |  |  |     //TODO: IDF-2393
 | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ---------------------------------------------- Port Implementations -------------------------------------------------
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ------------------------------------------------------------------------------------------------------------------ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // --------------------- Interrupts ------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | //TODO: IDF-7566
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | BaseType_t xPortInIsrContext(void) | 
					
						
							| 
									
										
										
										
											2020-12-29 12:31:54 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | #if !CONFIG_IDF_TARGET_ESP32P4
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  |     return uxInterruptNesting; | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | #else
 | 
					
						
							|  |  |  |     BaseType_t coreID = xPortGetCoreID(); | 
					
						
							|  |  |  |     return uxInterruptNesting[coreID]; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-11-13 16:03:50 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     /* For single core, this can be the same as xPortInIsrContext() because reading it is atomic */ | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | #if !CONFIG_IDF_TARGET_ESP32P4
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  |     return uxInterruptNesting; | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | #else
 | 
					
						
							|  |  |  |     BaseType_t coreID = xPortGetCoreID(); | 
					
						
							|  |  |  |     return uxInterruptNesting[coreID]; | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-11-13 16:03:50 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | // ---------------------- Spinlocks ------------------------
 | 
					
						
							| 
									
										
										
										
											2020-12-29 12:31:54 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | // ------------------ Critical Sections --------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | //TODO: IDF-7566
 | 
					
						
							|  |  |  | #if !CONFIG_IDF_TARGET_ESP32P4
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | void vPortEnterCritical(void) | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-10-16 00:14:27 +08:00
										 |  |  |     BaseType_t state = portSET_INTERRUPT_MASK_FROM_ISR(); | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  |     uxCriticalNesting++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (uxCriticalNesting == 1) { | 
					
						
							|  |  |  |         uxSavedInterruptState = state; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void vPortExitCritical(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (uxCriticalNesting > 0) { | 
					
						
							|  |  |  |         uxCriticalNesting--; | 
					
						
							|  |  |  |         if (uxCriticalNesting == 0) { | 
					
						
							| 
									
										
										
										
											2021-10-16 00:14:27 +08:00
										 |  |  |             portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptState); | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | #else
 | 
					
						
							|  |  |  | void vPortEnterCritical(portMUX_TYPE *mux) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BaseType_t coreID = xPortGetCoreID(); | 
					
						
							|  |  |  |     BaseType_t state = portSET_INTERRUPT_MASK_FROM_ISR(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     spinlock_acquire((spinlock_t *)mux, SPINLOCK_WAIT_FOREVER); | 
					
						
							|  |  |  |     uxCriticalNesting[coreID]++; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (uxCriticalNesting[coreID] == 1) { | 
					
						
							|  |  |  |         uxSavedInterruptState[coreID] = state; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void vPortExitCritical(portMUX_TYPE *mux) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     spinlock_release((spinlock_t *)mux); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BaseType_t coreID = xPortGetCoreID(); | 
					
						
							|  |  |  |     if (uxCriticalNesting[coreID] > 0) { | 
					
						
							|  |  |  |         uxCriticalNesting[coreID]--; | 
					
						
							|  |  |  |         if (uxCriticalNesting[coreID] == 0) { | 
					
						
							|  |  |  |             portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptState[coreID]); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | // ---------------------- Yielding -------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | //TODO: IDF-7566
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | int vPortSetInterruptMask(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret; | 
					
						
							|  |  |  |     unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE); | 
					
						
							|  |  |  |     ret = REG_READ(INTERRUPT_CORE0_CPU_INT_THRESH_REG); | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if !CONFIG_IDF_TARGET_ESP32P4
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  |     REG_WRITE(INTERRUPT_CORE0_CPU_INT_THRESH_REG, RVHAL_EXCM_LEVEL); | 
					
						
							|  |  |  |     RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE); | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | #else
 | 
					
						
							|  |  |  |     #define RVHAL_EXCM_THRESHOLD_VALUE   (((RVHAL_EXCM_LEVEL << (8 - NLBITS)) | 0x1f) << CLIC_CPU_INT_THRESH_S)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     REG_WRITE(INTERRUPT_CORE0_CPU_INT_THRESH_REG, RVHAL_EXCM_THRESHOLD_VALUE); | 
					
						
							| 
									
										
										
										
											2023-07-18 14:38:41 +08:00
										 |  |  |     /**
 | 
					
						
							|  |  |  |      * TODO: IDF-7898 | 
					
						
							|  |  |  |      * Here is an issue that, | 
					
						
							|  |  |  |      * 1. Set the CLIC_INT_THRESH_REG to mask off interrupts whose level is lower than `intlevel`. | 
					
						
							|  |  |  |      * 2. Set MSTATUS_MIE (global interrupt), then program may jump to interrupt vector. | 
					
						
							|  |  |  |      * 3. The register value change in Step 1 may happen during Step 2. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * To prevent this, here a fence is used | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     rv_utils_memory_barrier(); | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  |     RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  |     /**
 | 
					
						
							|  |  |  |      * In theory, this function should not return immediately as there is a | 
					
						
							|  |  |  |      * delay between the moment we mask the interrupt threshold register and | 
					
						
							|  |  |  |      * the moment a potential lower-priority interrupt is triggered (as said | 
					
						
							|  |  |  |      * above), it should have a delay of 2 machine cycles/instructions. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * However, in practice, this function has an epilogue of one instruction, | 
					
						
							|  |  |  |      * thus the instruction masking the interrupt threshold register is | 
					
						
							|  |  |  |      * followed by two instructions: `ret` and `csrrs` (RV_SET_CSR). | 
					
						
							|  |  |  |      * That's why we don't need any additional nop instructions here. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void vPortClearInterruptMask(int mask) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     REG_WRITE(INTERRUPT_CORE0_CPU_INT_THRESH_REG, mask); | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * The delay between the moment we unmask the interrupt threshold register | 
					
						
							|  |  |  |      * and the moment the potential requested interrupt is triggered is not | 
					
						
							|  |  |  |      * null: up to three machine cycles/instructions can be executed. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * When compilation size optimization is enabled, this function and its | 
					
						
							|  |  |  |      * callers returning void will have NO epilogue, thus the instruction | 
					
						
							|  |  |  |      * following these calls will be executed. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * If the requested interrupt is a context switch to a higher priority | 
					
						
							|  |  |  |      * task then the one currently running, we MUST NOT execute any instruction | 
					
						
							|  |  |  |      * before the interrupt effectively happens. | 
					
						
							|  |  |  |      * In order to prevent this, force this routine to have a 3-instruction | 
					
						
							|  |  |  |      * delay before exiting. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     asm volatile ( "nop" ); | 
					
						
							|  |  |  |     asm volatile ( "nop" ); | 
					
						
							|  |  |  |     asm volatile ( "nop" ); | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | //TODO: IDF-7566
 | 
					
						
							|  |  |  | #if !CONFIG_IDF_TARGET_ESP32P4
 | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | void vPortYield(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (uxInterruptNesting) { | 
					
						
							|  |  |  |         vPortYieldFromISR(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-29 12:31:54 +08:00
										 |  |  |         esp_crosscore_int_send_yield(0); | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  |         /* There are 3-4 instructions of latency between triggering the software
 | 
					
						
							|  |  |  |            interrupt and the CPU interrupt happening. Make sure it happened before | 
					
						
							|  |  |  |            we return, otherwise vTaskDelay() may return and execute 1-2 | 
					
						
							|  |  |  |            instructions before the delay actually happens. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            (We could use the WFI instruction here, but there is a chance that | 
					
						
							|  |  |  |            the interrupt will happen while evaluating the other two conditions | 
					
						
							|  |  |  |            for an instant yield, and if that happens then the WFI would be | 
					
						
							|  |  |  |            waiting for the next interrupt to occur...) | 
					
						
							|  |  |  |         */ | 
					
						
							| 
									
										
										
										
											2020-12-29 12:31:54 +08:00
										 |  |  |         while (uxSchedulerRunning && uxCriticalNesting == 0 && REG_READ(SYSTEM_CPU_INTR_FROM_CPU_0_REG) != 0) {} | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | void vPortYieldFromISR( void ) | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  |     traceISR_EXIT_TO_SCHEDULER(); | 
					
						
							|  |  |  |     uxSchedulerRunning = 1; | 
					
						
							|  |  |  |     xPortSwitchFlag = 1; | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-18 16:21:15 +08:00
										 |  |  | #else
 | 
					
						
							|  |  |  | void vPortYield(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BaseType_t coreID = xPortGetCoreID(); | 
					
						
							|  |  |  |     if (uxInterruptNesting[coreID]) { | 
					
						
							|  |  |  |         vPortYieldFromISR(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         esp_crosscore_int_send_yield(coreID); | 
					
						
							|  |  |  |         /* There are 3-4 instructions of latency between triggering the software
 | 
					
						
							|  |  |  |            interrupt and the CPU interrupt happening. Make sure it happened before | 
					
						
							|  |  |  |            we return, otherwise vTaskDelay() may return and execute 1-2 | 
					
						
							|  |  |  |            instructions before the delay actually happens. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |            (We could use the WFI instruction here, but there is a chance that | 
					
						
							|  |  |  |            the interrupt will happen while evaluating the other two conditions | 
					
						
							|  |  |  |            for an instant yield, and if that happens then the WFI would be | 
					
						
							|  |  |  |            waiting for the next interrupt to occur...) | 
					
						
							|  |  |  |         */ | 
					
						
							|  |  |  |         while (uxSchedulerRunning[coreID] && uxCriticalNesting[coreID] == 0 && REG_READ(HP_SYSTEM_CPU_INT_FROM_CPU_0_REG + 4*coreID) != 0) {} | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void vPortYieldFromISR( void ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     traceISR_EXIT_TO_SCHEDULER(); | 
					
						
							|  |  |  |     BaseType_t coreID = xPortGetCoreID(); | 
					
						
							|  |  |  |     uxSchedulerRunning[coreID] = 1; | 
					
						
							|  |  |  |     xPortSwitchFlag[coreID] = 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | void vPortYieldOtherCore(BaseType_t coreid) | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  |     esp_crosscore_int_send_yield(coreid); | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | // ------------------- Hook Functions ----------------------
 | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | void __attribute__((weak)) vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #define ERR_STR1 "***ERROR*** A stack overflow in task "
 | 
					
						
							|  |  |  | #define ERR_STR2 " has been detected."
 | 
					
						
							|  |  |  |     const char *str[] = {ERR_STR1, pcTaskName, ERR_STR2}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     char buf[sizeof(ERR_STR1) + CONFIG_FREERTOS_MAX_TASK_NAME_LEN + sizeof(ERR_STR2) + 1 /* null char */] = {0}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     char *dest = buf; | 
					
						
							|  |  |  |     for (int i = 0; i < sizeof(str) / sizeof(str[0]); i++) { | 
					
						
							|  |  |  |         dest = strcat(dest, str[i]); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     esp_system_abort(buf); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | // ----------------------- System --------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | uint32_t xPortGetTickRateHz(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return (uint32_t)configTICK_RATE_HZ; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define STACK_WATCH_AREA_SIZE 32
 | 
					
						
							|  |  |  | #define STACK_WATCH_POINT_NUMBER (SOC_CPU_WATCHPOINTS_NUM - 1)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void vPortSetStackWatchpoint(void *pxStackStart) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     uint32_t addr = (uint32_t)pxStackStart; | 
					
						
							|  |  |  |     addr = (addr + (STACK_WATCH_AREA_SIZE - 1)) & (~(STACK_WATCH_AREA_SIZE - 1)); | 
					
						
							| 
									
										
										
										
											2021-12-14 10:08:15 +05:30
										 |  |  |     esp_cpu_set_watchpoint(STACK_WATCH_POINT_NUMBER, (char *)addr, STACK_WATCH_AREA_SIZE, ESP_CPU_WATCHPOINT_STORE); | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ---------------------------------------------- Misc Implementations -------------------------------------------------
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ------------------------------------------------------------------------------------------------------------------ */ |