#include #include "os_port.h" #include "os_critical.h" #include "os_rdy_list.h" #include "os_yield_list.h" #include "os_idle.h" #include "os_isr.h" volatile os_task_t* g_os_sched_current_task_p; volatile os_size_t g_os_sched_pending_cnt; static volatile os_task_t* p_curr_task; static volatile os_task_t* p_next_task; static os_bool_t s_os_sched_wip_flag; /* ------------------------------------------------------------------------------------------------------------------ */ /* */ void os_sched_init(void){ g_os_sched_current_task_p = 0; g_os_sched_pending_cnt = 0; s_os_sched_wip_flag = OS_FALSE; } void os_sched_in_isr(void){ os_critical_enter_in_isr(); if(s_os_sched_wip_flag == OS_TRUE){ // 调度正在进行中,返回 os_critical_leave_in_isr(); return; } s_os_sched_wip_flag = OS_TRUE; if(g_os_isr_nesting_cnt>0){ // 中断嵌套 g_os_sched_pending_cnt++; s_os_sched_wip_flag = OS_FALSE; os_critical_leave_in_isr(); return; } if(g_os_sched_current_task_p && g_os_sched_current_task_p->state == kOsTaskState_Running){ // 当前任务还在运行,返回 s_os_sched_wip_flag = OS_FALSE; os_critical_leave_in_isr(); return; } p_curr_task = g_os_sched_current_task_p; // 获取下一个任务 os_priority_t priority = os_priority_get_highest(); os_rdy_list_t* p_rdy_list = os_rdy_list_get(priority); os_list_node_t* p_node = p_rdy_list->head.next; p_next_task = os_list_member_of(p_node, os_task_t, node); if(!os_idle_is_idle_task((os_task_t*)p_next_task)){ os_rdy_list_remove((os_task_t*)p_next_task); } // yield 的任务加入就绪表 for(p_node = g_os_yield_list.next; p_node!=&g_os_yield_list; ){ os_task_t* p_task = os_list_member_of(p_node, os_task_t, node); p_node = p_node->next; os_yield_list_remove(p_task); if(!os_idle_is_idle_task(p_task)) { os_rdy_list_insert(p_task); } } // 下个任务就是当前任务, 获得一次运行的机会 if(p_next_task==p_curr_task){ p_next_task->state = kOsTaskState_Running; p_next_task->remain_ticks = p_next_task->init_ticks; s_os_sched_wip_flag = OS_FALSE; os_critical_leave_in_isr(); return; } s_os_sched_wip_flag = OS_FALSE; os_critical_leave_in_isr(); // 执行上下文切换 os_port_context_switch((void*)(p_curr_task?&p_curr_task->stack.sp:0), (void*)&p_next_task->stack.sp); }