为什么要进行临界资源处理
当多个运行空间同时访问共享资源时会导致数据冲突和系统不稳定。
未加保护的临界区可能导致不可预测的行为,如数据损坏、中断丢失和系统崩溃,
影响系统的实时性和可靠性。
01. 临界区与临界资源的理解
临界区: 访问临界资源的代码段
临界资源: 可能会被多个运行空间同时访问的共享资源,比如内存、外设I/O等
02. 临界区处理有什么要求
1)临界区需要不可分割地处理,即原子操作
2) 临界区尽快能短,否则会影响系统的实时性,甚至出现数据丢失的问题
03. UCOS-III保护临界区的几种方式
3.1 关中断
这种方式比较简单粗暴,可以用在任何场景,也是大家最常用的方式。
void YourFunction (void)
{
CPU_SR_ALLOC();
CPU_CRITICAL_ENTER();
Access the resource;
CPU_CRITICAL_EXIT();
}
不过这种方式会导致其他中断的延迟响应,甚至可能会丢失中断。
上图中,在中断处理前有多个中断,中断也只挂起了一次。
3.2 关闭系统调度
只能用在任务间的临界资源保护,这种方式会破坏系统的实时性。
void YourFunction (void)
{
OS_ERR err;
OSSchedLock(&err);
Access the resource;
OSSchedUnlock(&err);
}
3.3 使用信号量
可以用在任务间的临界资源保护,这种方式可能会导致任务优先级反转的问题。也可以用在某些场景的ISR与任务间的临界资源保护。
SSemCreate() Create a semaphore.
OSSemPend() Wait on a semaphore.
OSSemPost() Release or signal a semaphore.
3.4 使用互斥锁
只能用在任务间的临界资源保护
OSMutexCreate() Create a mutex.
OSMutexPend() Wait on a mutex.
OSMutexPost() Release a mutex.
OS_MUTEX MyMutex;
SOME_STRUCT MySharedResource;
void MyTask (void *p_arg)
{
OS_ERR err;
CPU_TS ts;
:
while (DEF_ON) {
OSMutexPend((OS_MUTEX *)&MyMutex,
(OS_TICK )0,
(OS_OPT )OS_OPT_PEND_BLOCKING,
(CPU_TS *)&ts,
(OS_ERR *)&err);
/* Check "err" */
/* Acquire shared resource if no error */
MyLibFunction();
OSMutexPost((OS_MUTEX *)&MyMutex,
(OS_OPT )OS_OPT_POST_NONE,
(OS_ERR *)&err);
/* Check "err" */
}
}
void MyLibFunction (void)
{
OS_ERR err;
CPU_TS ts;
OSMutexPend((OS_MUTEX *)&MyMutex,
(OS_TICK )0,
(OS_OPT )OS_OPT_PEND_BLOCKING,
(CPU_TS *)&ts,
(OS_ERR *)&err);
/* Check "err" */
/* Access shared resource if no error */
OSMutexPost((OS_MUTEX *)&MyMutex,
(OS_OPT )OS_OPT_POST_NONE,
(OS_ERR *)&err);
/* Check "err" */
}