从零开始学硬件<9>demo源码OceanOS-CM0-B7解读
2026/8/3 6:50:40 网站建设 项目流程

B7课程:互斥锁

上一课B6讲的是临界区。临界区的做法比较硬:把调度器锁住,这段时间别的任务插不进来。能解决问题,但代价也明显——锁得时间一长,实时性就差了。

B7换了个思路:任务该阻塞就阻塞,别把整个系统冻住。这就是互斥锁(mutex)。多任务共用一个资源(本例是串口)时,如何保证同一时刻只有一个任务在用。

(图一)

工程跑在APM32Cortex-M0)上,应用层主要看al_main_task.c

main里关掉中断,初始化OS,创建一个优先级为1main_task,然后os_start()。真正干活的逻辑都在al_main_task里:

SysTick1ms)、USART1LED

os_mutex_init(&g_mutex)

再创建两个优先级都是2的任务:task1task2

void al_task1(void *arg)

{

while (1)

{

os_mutex_lock(&g_mutex, OS_PEND_FOREVER);

printf("11111\n");

al_busy_delay(5000*1000);

os_mutex_unlock(&g_mutex);

}

}

void al_task2(void *arg)

{

os_tick_delay(100);

while (1)

{

os_mutex_lock(&g_mutex, OS_PEND_FOREVER);

printf("22222\n");

al_busy_delay(5000*1000);

os_mutex_unlock(&g_mutex);

}

}

共享资源就是串口。printf底层走fputc,一个字符一个字符往USART塞。如果两个任务同时打字,串口输出很容易搅在一起。锁把「打印+ busy delay」包起来,谁拿到锁谁独占这段输出。

task2开头故意os_tick_delay(100),让task1先跑一会儿,现象更直观。两个任务优先级相同,中间那段al_busy_delay是空转,不会主动让出CPU;时间片到了还是可能切走,但因为锁还在手里,另一个任务进不了临界代码,最多在外面干等。

串口里正常应该看到完整的一行行11111 / 22222,不会出现11212...这种穿插。

修改完后,按预期的打印。后期有兴趣可以研究下os_tick.c底层的机制,就会更清晰地了解到为什么会是这个结果了。

(图二)

建议自己改一版对比

把两个任务里的os_mutex_lock/unlock注释掉,重新烧录看串口。大概率输出会糊成一团。再加回锁,现象立刻干净。这一步比只看代码印象深。

也可以试着把al_busy_delay挪到unlock后面,观察两个任务输出切换会不会更密——这能帮你体会「锁住的时间」到底意味着什么。

(图三)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询