本文主要是介绍临界区保护,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
1. 临界区的保护实际应用中可能需要的场合:
调用公共函数的代码(不可重入函数)
读取或者修改变量(全局变量)
使用硬件资源(MCU的ram、flash、uart、spi、adc等)
对时序有精准要求的操作(I2C通讯)
某些用户不想被打断的代码(比如 printf 打印),串口接收的状态、接收中断重新开启等操作
2. 临界区保护方法:
在实时操作系统(RTOS)中操作I2C通常涉及到多任务/中断环境,因此需要确保I2C的使用是线程安全的。关闭中断和使用互斥量是两种常见的方法来确保线程安全。RT-Thread中提供了多种保护临界区的方法,具体分为以下几类
(1) 禁用系统调度器 ,中断可以响应
rt_enter_critical(); //将线程调度器上锁,此时线程调度器仅能响应中断
/* 以下进入临界区 */. . . .
/*临界区执行完成*/
rt_exit_critical(); //调度器解锁
(2)禁用中断
关闭中断通常用于确保在执行I2C传输时不会被其他中断打断。但是,这种方法应谨慎使用,因为它会影响系统的实时性。
rt_base_t level; //创建变量以使用中断关闭和中断开启函数
level = rt_hw_interrupt_disable(); //中断关闭函数
/* 以下是临界区*/
. . . .
rt_hw_interrupt_enable(level); 中断开启函数
(3)互斥量(Mutex)
是一种更灵活的同步机制,可以在保持系统实时性的同时提供更细粒度的同步。如果你的RTOS支持互斥量,并且你希望避免关闭中断带来的潜在问题,那么使用互斥量会是更好的选择。
3. 临界区具体场合的操作方法
(1)在任务中对全局变量先判断后赋值,而中断代码、高优先级任务中也会对该全局变量操作,这种情况需在任务中对其临界区保护。
(2)串口协议发送装帧代码(全局变量的复制)也需临界区保护,防止中断代码、高优先级任务对全局变量修改,比如装帧时复制了ADC值的一半部分后发生中断修改了该值,返回后继续复制后半部分,则装帧错误。
(3)串口接收的状态、接收中断重新开启等操作,也不希望被中断打断,导致出错,也需临界区保护。如果在串口中断接收中也有这段代码,如果串口优先级最高(所有访问该临界区的任务、中断等)因为优先级已经最高了,则不需要再保护了。
(3)串口、Timer等中断服务程序中,对同一全局变量有操作的代码段(临界区),需临界区保护。
函数 taskENTER_CRITICAL_FROM_ISR()和 taskEXIT_CRITICAL_FROM_ISR()中断级别临界段代码保护,是用在中断服务程序中的。
低优先级的中断被屏蔽了:优先级低于、等于configMAX_SYSCALL_INTERRUPT_PRIORITY
高优先级的中断可以产生:优先级高于configMAX_SYSCALL_INTERRUPT_PRIORITY
这篇关于临界区保护的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!