从零开始学硬件<7>demo源码OceanOS-CM0-B5解读

📅 2026/7/1 1:35:42
从零开始学硬件<7>demo源码OceanOS-CM0-B5解读
B5课程时间片调度B4优先级问题处理的是谁更急谁先跑。B5换一个问题优先级一样的时候怎么办这就是时间片调度。代码改动不大烧进去以后串口输出会和B4完全不同。示例在干什么图一main_task还是老样子初始化串口和LED亮500ms、灭500ms。优先级仍是1。这次创建了两个子任务task1和task2优先级都是2os_task_create(al_task1,NULL,task1,g_task1_tcb,g_task1_stack,AL_TASK1_STACK_SIZE,2);os_task_create(al_task2,NULL,task2,g_task2_tcb,g_task2_stack,AL_TASK2_STACK_SIZE,2);两个任务的循环也几乎一样只是打印内容不同voidal_task1(void*arg){while(1){printf(11111\r\n);}}voidal_task2(void*arg){while(1){printf(22222\r\n);}}这次有两个同优先级的任务在抢烧录后打开串口通常会看到11111和22222交替出现如图二所示图二时间片从哪来OceanOS里每个TCB有个tick_slice字段。注释写得很直白0xFF表示这个任务独占CPU0表示时间片用完了。默认时间片长度在os_config.h里#defineOS_TASK_TICK_SLICE_DEFAULT44个tick也就是4msSysTick配的是1ms一次。调度器选下一个任务时会看同优先级队列里还有没有别的任务g_os_tcb_upcoming-tick_slice(g_os_tcb_upcoming-next_tcb)?OS_TASK_TICK_SLICE_DEFAULT:OS_TASK_TICK_SLICE_CLOSE;有「邻居」——同优先级下还有别的任务——就分配4个tick开启时间片轮转。队列里只有自己——就设成0xFF关时间片独占CPU和B4里高优先级独占的情况一样。时间片怎么转每个SysTick进os_tick_beat()如果当前任务在运行、且时间片开着计数就减1。减到0时内核会做一件事把这个任务从就绪表当前位置摘下来挂到同优先级队列末尾状态改回就绪等下次调度再轮上来。if(g_os_tcb_current-tick_slice0){if(g_os_tcb_current-next_tcb){os_tcb_table_remove(g_os_ready_tcb_table,g_os_tcb_current);os_tcb_table_insert(g_os_ready_tcb_table,g_os_tcb_current);g_os_tcb_current-task_statusOS_TASK_STATUS_READY;}}同优先级队列是双向链表先来先服务时间片用完就排到队尾。task1跑4mstask2上task2跑4ms再换回task1——串口上11111和22222就这样交错出来。如果同优先级只有一个任务时间片关闭可以一直占着CPU直到更高优先级任务就绪或者自己阻塞。B4的task1就是这种情况优先级0队列里只有它一个又从不阻塞所以低优先级的main_task几乎没机会跑。B4和B5放在一起看B4教的是「等级」数字越小越优先高等级可以压着低等级跑。那个实验有点极端但极端才看得清楚。B5教的是「公平」等级相同不能永远让先创建的那个霸占CPU。时间片像发牌每人摸几张摸完轮到下家。实际项目里两种机制一起用紧急任务给高优先级同级别的采集、通信、日志打印靠时间片轮流跑避免某一个把CPU吃死。B5的小结B5的demo阐述的问题一样重要时怎么分。log打印的11111和22222的比例不一定严格1:1。printf本身耗时、上下文切换开销、调度时机都会让某一边偶尔多打几行。这是正常的不是