#include "os/os.h" #include "os_util.h" #include "task.h" static size_t int_flag; static portMUX_TYPE s_spin_lock = portMUX_INITIALIZER_UNLOCKED; static os_mutex_t s_scheduler_mutex; int os_start(void *heap_mem, size_t heap_size) { extern int os_entry(void *heap, size_t size); return os_entry(heap_mem, heap_size); } void os_int_entry(void) { os_interrupt_disable(); ++int_flag; os_interrupt_enable(); } void os_int_exit(void) { os_interrupt_disable(); int_flag -= !!int_flag; os_interrupt_enable(); } bool os_is_isr_context(void) { return xPortInIsrContext() || (int_flag > 0); } void os_interrupt_disable(void) { portENTER_CRITICAL(&s_spin_lock); } void os_interrupt_enable(void) { portEXIT_CRITICAL(&s_spin_lock); } void os_scheduler_suspend(void) { // 在进入临界区前检查是否在中断上下文中 if (os_is_isr_context()) { OS_ERR("Called in isr"); // 在中断中不要挂起调度器,可能会导致死锁 return; } if (!os_mutex_is_valid(&s_scheduler_mutex)) { os_mutex_create(&s_scheduler_mutex); } os_mutex_lock(&s_scheduler_mutex, OS_WAIT_FOREVER); } void os_scheduler_resume(void) { // 只有在非中断上下文中才恢复调度器 if (!os_is_isr_context()) { os_mutex_unlock(&s_scheduler_mutex); } } bool os_scheduler_is_running(void) { return (bool)(xTaskGetSchedulerState() == taskSCHEDULER_RUNNING); } #ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS void os_sys_print_info(void) { const size_t bytes_per_task = 40; /* see vTaskList description */ char *task_list_buffer = malloc(uxTaskGetNumberOfTasks() * bytes_per_task); if (task_list_buffer == NULL) { OS_LOG(1, "failed to allocate buffer for vTaskList output\r\n"); return; } fputs("Task Name\tStatus\tPrio\tHWM\tTask#", stdout); #ifdef CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID fputs("\tAffinity", stdout); #endif fputs("\n", stdout); vTaskList(task_list_buffer); fputs(task_list_buffer, stdout); free(task_list_buffer); } #else void os_sys_print_info(void) { OS_LOG(1, "os_sys_print_info() not supported, please set configUSE_TRACE_FACILITY to 1\n"); } #endif os_time_t os_get_sys_time(void) { os_time_t ticks_count = xTaskGetTickCount(); return OS_TicksToMSecs(ticks_count); } size_t os_get_sys_ticks(void) { return (size_t)xTaskGetTickCount(); } os_time_t os_calc_ticks_to_msec(size_t ticks) { os_time_t msec; if (ticks == OS_WAIT_FOREVER) { msec = portMAX_DELAY; } else if (ticks == 0) { msec = 0; } else { msec = OS_TicksToMSecs(ticks); if (msec == 0) { msec = 1; } } return msec; } size_t os_calc_msec_to_ticks(os_time_t msec) { size_t tick; if (msec == OS_WAIT_FOREVER) { tick = portMAX_DELAY; } else if (msec == 0) { tick = 0; } else { tick = OS_MSecsToTicks(msec); if (tick == 0) { tick = 1; } } return tick; } size_t os_cpu_usage(void) { return 100; } #if (configUSE_POSIX_ERRNO == 1) extern int FreeRTOS_errno; int os_get_err(void) { return FreeRTOS_errno; } void os_set_err(int err) { FreeRTOS_errno = err; } #elif (configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0) #define OS_ERRNO_LOCATION_IDX 0 int os_get_err(void) { return (int)pvTaskGetThreadLocalStoragePointer(NULL, OS_ERRNO_LOCATION_IDX); } void os_set_err(int err) { vTaskSetThreadLocalStoragePointer(NULL, OS_ERRNO_LOCATION_IDX, (void *)err); } #endif