| 
									
										
										
										
											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 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * 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"
 | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | #include "riscv/riscv_interrupts.h"
 | 
					
						
							|  |  |  | #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"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ---------------------------------------------------- Variables ------------------------------------------------------
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ------------------------------------------------------------------------------------------------------------------ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const char *TAG = "cpu_start"; // [refactor-todo]: might be appropriate to change in the future, but
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | BaseType_t uxSchedulerRunning = 0; | 
					
						
							|  |  |  | UBaseType_t uxInterruptNesting = 0; | 
					
						
							| 
									
										
										
										
											2020-11-04 18:34:47 -03:00
										 |  |  | BaseType_t xPortSwitchFlag = 0; | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | __attribute__((aligned(16))) static StackType_t xIsrStack[configISR_STACK_SIZE]; | 
					
						
							|  |  |  | StackType_t *xIsrStackTop = &xIsrStack[0] + (configISR_STACK_SIZE & (~((portPOINTER_SIZE_TYPE)portBYTE_ALIGNMENT_MASK))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 -------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern void esprv_intc_int_set_threshold(int); // FIXME, this function is in ROM only
 | 
					
						
							|  |  |  | BaseType_t xPortStartScheduler(void) | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  |     uxInterruptNesting = 0; | 
					
						
							|  |  |  |     uxCriticalNesting = 0; | 
					
						
							|  |  |  |     uxSchedulerRunning = 0; | 
					
						
							| 
									
										
										
										
											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 */ | 
					
						
							|  |  |  |     riscv_global_interrupts_enable(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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-01-27 12:06:30 +03:00
										 |  |  | __attribute__((noreturn)) static void _prvTaskExitError(void) | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | { | 
					
						
							|  |  |  |     /* A function that implements a task must not exit or attempt to return to
 | 
					
						
							|  |  |  |     its caller as there is nothing to return to.  If a task wants to exit it | 
					
						
							|  |  |  |     should instead call vTaskDelete( NULL ). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Artificially force an assert() to be triggered if configASSERT() is | 
					
						
							|  |  |  |     defined, then stop here so application writers can catch the error. */ | 
					
						
							|  |  |  |     configASSERT(uxCriticalNesting == ~0UL); | 
					
						
							|  |  |  |     portDISABLE_INTERRUPTS(); | 
					
						
							| 
									
										
										
										
											2020-12-29 12:31:54 +08:00
										 |  |  |     abort(); | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-27 12:06:30 +03:00
										 |  |  | __attribute__((naked)) static void prvTaskExitError(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     asm volatile(".option push\n" \ | 
					
						
							|  |  |  |                 ".option norvc\n" \ | 
					
						
							|  |  |  |                 "nop\n" \ | 
					
						
							|  |  |  |                 ".option pop"); | 
					
						
							| 
									
										
										
										
											2022-02-02 22:27:13 +03:00
										 |  |  |     /* Task entry's RA will point here. Shifting RA into prvTaskExitError is necessary
 | 
					
						
							|  |  |  |        to make GDB backtrace ending inside that function. | 
					
						
							|  |  |  |        Otherwise backtrace will end in the function laying just before prvTaskExitError in address space. */ | 
					
						
							| 
									
										
										
										
											2022-01-27 12:06:30 +03:00
										 |  |  |     _prvTaskExitError(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     extern uint32_t __global_pointer$; | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  |     uint8_t *task_thread_local_start; | 
					
						
							|  |  |  |     uint8_t *threadptr; | 
					
						
							| 
									
										
										
										
											2021-04-21 11:49:58 +02:00
										 |  |  |     extern char _thread_local_start, _thread_local_end, _flash_rodata_start; | 
					
						
							| 
									
										
										
										
											2020-12-24 01:56:20 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Byte pointer, so that subsequent calculations don't depend on sizeof(StackType_t). */ | 
					
						
							| 
									
										
										
										
											2021-04-02 12:41:21 +08:00
										 |  |  |     uint8_t *sp = (uint8_t *) pxTopOfStack; | 
					
						
							| 
									
										
										
										
											2020-12-24 01:56:20 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-21 11:49:58 +02:00
										 |  |  |     /* Set up TLS area.
 | 
					
						
							|  |  |  |      * The following diagram illustrates the layout of link-time and run-time | 
					
						
							|  |  |  |      * TLS sections. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      *          +-------------+ | 
					
						
							|  |  |  |      *          |Section:     |      Linker symbols: | 
					
						
							|  |  |  |      *          |.flash.rodata|      --------------- | 
					
						
							|  |  |  |      *       0x0+-------------+ <-- _flash_rodata_start | 
					
						
							|  |  |  |      *        ^ |             | | 
					
						
							|  |  |  |      *        | | Other data  | | 
					
						
							|  |  |  |      *        | |     ...     | | 
					
						
							|  |  |  |      *        | +-------------+ <-- _thread_local_start | 
					
						
							|  |  |  |      *        | |.tbss        | ^ | 
					
						
							|  |  |  |      *        v |             | | | 
					
						
							|  |  |  |      *    0xNNNN|int example; | | (thread_local_size) | 
					
						
							|  |  |  |      *          |.tdata       | v | 
					
						
							|  |  |  |      *          +-------------+ <-- _thread_local_end | 
					
						
							|  |  |  |      *          | Other data  | | 
					
						
							|  |  |  |      *          |     ...     | | 
					
						
							|  |  |  |      *          |             | | 
					
						
							|  |  |  |      *          +-------------+ | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      *                                Local variables of | 
					
						
							|  |  |  |      *                              pxPortInitialiseStack | 
					
						
							|  |  |  |      *                             ----------------------- | 
					
						
							|  |  |  |      *          +-------------+ <-- pxTopOfStack | 
					
						
							|  |  |  |      *          |.tdata (*)   |  ^ | 
					
						
							|  |  |  |      *        ^ |int example; |  |(thread_local_size | 
					
						
							|  |  |  |      *        | |             |  | | 
					
						
							|  |  |  |      *        | |.tbss (*)    |  v | 
					
						
							|  |  |  |      *        | +-------------+ <-- task_thread_local_start | 
					
						
							|  |  |  |      * 0xNNNN | |             |  ^ | 
					
						
							|  |  |  |      *        | |             |  | | 
					
						
							|  |  |  |      *        | |             |  |_thread_local_start - _rodata_start | 
					
						
							|  |  |  |      *        | |             |  | | 
					
						
							|  |  |  |      *        | |             |  v | 
					
						
							|  |  |  |      *        v +-------------+ <-- threadptr | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      *   (*) The stack grows downward! | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-24 01:56:20 +01:00
										 |  |  |     uint32_t thread_local_sz = (uint32_t) (&_thread_local_end - &_thread_local_start); | 
					
						
							|  |  |  |     thread_local_sz = ALIGNUP(0x10, thread_local_sz); | 
					
						
							|  |  |  |     sp -= thread_local_sz; | 
					
						
							|  |  |  |     task_thread_local_start = sp; | 
					
						
							|  |  |  |     memcpy(task_thread_local_start, &_thread_local_start, thread_local_sz); | 
					
						
							| 
									
										
										
										
											2021-04-21 11:49:58 +02:00
										 |  |  |     threadptr = task_thread_local_start - (&_thread_local_start - &_flash_rodata_start); | 
					
						
							| 
									
										
										
										
											2020-12-24 01:56:20 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* Simulate the stack frame as it would be created by a context switch interrupt. */ | 
					
						
							|  |  |  |     sp -= RV_STK_FRMSZ; | 
					
						
							|  |  |  |     RvExcFrame *frame = (RvExcFrame *)sp; | 
					
						
							|  |  |  |     memset(frame, 0, sizeof(*frame)); | 
					
						
							| 
									
										
										
										
											2022-01-27 12:06:30 +03:00
										 |  |  |     /* Shifting RA into prvTaskExitError is necessary to make GDB backtrace ending inside that function.
 | 
					
						
							|  |  |  |        Otherwise backtrace will end in the function laying just before prvTaskExitError in address space. */ | 
					
						
							| 
									
										
										
										
											2022-02-02 22:27:13 +03:00
										 |  |  |     frame->ra = (UBaseType_t)prvTaskExitError + 4/*size of the nop insruction at the beginning of prvTaskExitError*/; | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  |     frame->mepc = (UBaseType_t)pxCode; | 
					
						
							|  |  |  |     frame->a0 = (UBaseType_t)pvParameters; | 
					
						
							|  |  |  |     frame->gp = (UBaseType_t)&__global_pointer$; | 
					
						
							| 
									
										
										
										
											2020-12-24 01:56:20 +01:00
										 |  |  |     frame->tp = (UBaseType_t)threadptr; | 
					
						
							| 
									
										
										
										
											2020-11-13 16:03:50 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  |     //TODO: IDF-2393
 | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  |     return (StackType_t *)frame; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ---------------------------------------------- Port Implementations -------------------------------------------------
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ------------------------------------------------------------------------------------------------------------------ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // --------------------- Interrupts ------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | BaseType_t xPortInIsrContext(void) | 
					
						
							| 
									
										
										
										
											2020-12-29 12:31:54 +08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-24 16:56:45 +08:00
										 |  |  |     return uxInterruptNesting; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											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 */ | 
					
						
							|  |  |  |     return uxInterruptNesting; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											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 --------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ---------------------- Yielding -------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int vPortSetInterruptMask(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int ret; | 
					
						
							|  |  |  |     unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE); | 
					
						
							|  |  |  |     ret = REG_READ(INTERRUPT_CORE0_CPU_INT_THRESH_REG); | 
					
						
							|  |  |  |     REG_WRITE(INTERRUPT_CORE0_CPU_INT_THRESH_REG, RVHAL_EXCM_LEVEL); | 
					
						
							|  |  |  |     RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE); | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * 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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 -------------------------------------------------
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ------------------------------------------------------------------------------------------------------------------ */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // --------------------- App Start-up ----------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* [refactor-todo]: See if we can include this through a header */ | 
					
						
							| 
									
										
										
										
											2020-11-06 15:03:21 +11:00
										 |  |  | extern void esp_startup_start_app_common(void); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void esp_startup_start_app(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     esp_startup_start_app_common(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ESP_LOGI(TAG, "Starting scheduler."); | 
					
						
							|  |  |  |     vTaskStartScheduler(); | 
					
						
							|  |  |  | } |