/* * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ /* * This file contains most of the code located in the demo application in the * upstream FreeRTOS repository. It is put here so that IDF applications can * seamlessly switch between Linux and chip targets without the need to provide * or implement additional functionality if the target is the Linux target. */ #include #include #include #include #include #include /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" #include "utils/wait_for_event.h" #include "esp_log.h" static const char *TAG = "port"; static volatile UBaseType_t uxInterruptNesting = 0; /* When configSUPPORT_STATIC_ALLOCATION is set to 1 the application writer can * use a callback function to optionally provide the memory required by the idle * and timer tasks. This is the stack that will be used by the timer task. It is * declared here, as a global, so it can be checked by a test that is implemented * in a different file. */ StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; BaseType_t xPortCheckIfInISR(void) { return uxInterruptNesting; } void app_main(void); static void main_task(void* args) { app_main(); vTaskDelete(NULL); } int main(int argc, const char **argv) { // This makes sure that stdio is flushed after each '\n' so that idf.py monitor // reads the program output on time. setvbuf(stdout, NULL, _IOLBF, 0); usleep(1000); BaseType_t res = xTaskCreatePinnedToCore(&main_task, "main", ESP_TASK_MAIN_STACK, NULL, ESP_TASK_MAIN_PRIO, NULL, ESP_TASK_MAIN_CORE); assert(res == pdTRUE); (void)res; ESP_LOGI(TAG, "Starting scheduler."); vTaskStartScheduler(); // This line should never be reached assert(false); } void esp_vApplicationIdleHook(void) { /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set * to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle * task. It is essential that code added to this hook function never attempts * to block in any way (for example, call xQueueReceive() with a block time * specified, or call vTaskDelay()). If application tasks make use of the * vTaskDelete() API function to delete themselves then it is also important * that vApplicationIdleHook() is permitted to return to its calling function, * because it is the responsibility of the idle task to clean up memory * allocated by the kernel to any task that has since deleted itself. */ usleep( 15000 ); } void esp_vApplicationTickHook( void ) { } #if ( configUSE_TICK_HOOK > 0 ) void vApplicationTickHook( void ) { esp_vApplicationTickHook(); } #endif void vPortYieldOtherCore( BaseType_t coreid ) { } // trying to skip for now #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) /* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an * implementation of vApplicationGetIdleTaskMemory() to provide the memory that is * used by the Idle task. */ void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer, StackType_t ** ppxIdleTaskStackBuffer, uint32_t * pulIdleTaskStackSize ) { /* If the buffers to be provided to the Idle task are declared inside this * function then they must be declared static - otherwise they will be allocated on * the stack and so not exists after this function exits. */ static StaticTask_t xIdleTaskTCB; static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; /* Pass out a pointer to the StaticTask_t structure in which the Idle task's * state will be stored. */ *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; /* Pass out the array that will be used as the Idle task's stack. */ *ppxIdleTaskStackBuffer = uxIdleTaskStack; /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. * Note that, as the array is necessarily of type StackType_t, * configMINIMAL_STACK_SIZE is specified in words, not bytes. */ *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; } #endif // configSUPPORT_STATIC_ALLOCATION == 1 /*-----------------------------------------------------------*/ #if ( configSUPPORT_STATIC_ALLOCATION == 1 ) /* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the * application must provide an implementation of vApplicationGetTimerTaskMemory() * to provide the memory that is used by the Timer service task. */ void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer, StackType_t ** ppxTimerTaskStackBuffer, uint32_t * pulTimerTaskStackSize ) { /* If the buffers to be provided to the Timer task are declared inside this * function then they must be declared static - otherwise they will be allocated on * the stack and so not exists after this function exits. */ static StaticTask_t xTimerTaskTCB; /* Pass out a pointer to the StaticTask_t structure in which the Timer * task's state will be stored. */ *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; /* Pass out the array that will be used as the Timer task's stack. */ *ppxTimerTaskStackBuffer = uxTimerTaskStack; /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. * Note that, as the array is necessarily of type StackType_t, * configMINIMAL_STACK_SIZE is specified in words, not bytes. */ *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; } #endif // configSUPPORT_STATIC_ALLOCATION == 1 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]); } printf("%s\n", buf); abort(); }