Embedded RTOS中任务抢占死角的处理

Embedded RTOS中任务抢占死角的处理,embedded,rtos,autosar,Embedded,Rtos,Autosar,假设RTOS中有两个任务:TASKL(低优先级)和TASKH(高优先级)。RTOS遵循基于优先级的抢占调度。TASKL执行三个操作:a)使用可变变量读取传感器值。b) 操纵读取的值(比如乘以10)。c) 将值发送到另一个组件。 现在假设一个场景,其中TASKL执行了语句a,然后被TASKH中断。同时,传感器值也通过中断得到更新。当TASKL恢复时,它会从语句b恢复吗?如果是,则它将具有更新的传感器值还是旧的传感器值?另外,请告诉我如何避免这种情况?这取决于实际代码。您所写的内容提供了以下内容:

假设RTOS中有两个任务:TASKL(低优先级)和TASKH(高优先级)。RTOS遵循基于优先级的抢占调度。TASKL执行三个操作:a)使用可变变量读取传感器值。b) 操纵读取的值(比如乘以10)。c) 将值发送到另一个组件。
现在假设一个场景,其中TASKL执行了语句a,然后被TASKH中断。同时,传感器值也通过中断得到更新。当TASKL恢复时,它会从语句b恢复吗?如果是,则它将具有更新的传感器值还是旧的传感器值?另外,请告诉我如何避免这种情况?

这取决于实际代码。您所写的内容提供了以下内容:

//a
int val = sensor_volatile_val;

//b
val *= 10;

//c
put_into_queue(val);
上面的代码不会出现调度错误,(在大多数平台上),因为易失性读取很可能是原子性的。这可以通过显式原子读取来改进(在大多数平台上):

int val = atomic_read32(sensor_volatile_val);
然而,重要的是,传感器_volatile_val实际上被定义为volatile。(看到它被一个中断更新了。)这个中断给出了潜在的竞争条件。不是日程安排。 调度问题可能发生在语句“c”中。“将价值传递给另一个组件”相当含糊

我的“放入队列”是ofc,一种适当的互斥保护RTOS特性^^ 不过我不知道你的

顺便说一句,回答您的一些问题:不,即使传感器中断触发并更新了传感器值,语句“b”仍将使用之前读取的“旧”值

如果出于某种原因,您不想使用“旧”传感器值。您可以在将值放入队列之前验证该值:

if( old_sensor_val != sensor_volatile_val) goto start;

但在处理普通的“传感器”时,这几乎没有意义。作为一个有趣的小折痕,如果一个不符合
volatile
条件的对象以编译器不期望的方式被修改,gcc有时会表现得非常奇怪。使用选项
-mcpu=cortex-m0-O2
时生成代码臂gcc 10.2.1

unsigned short test(unsigned short *p)
{
  unsigned short temp = *p;
  return temp - (temp >> 15);
}

如果在执行该函数期间,
*p
的值在0xFFFF和0之间变化,则返回0xFFFF,反之亦然,即使该函数只读取一次
*p
,如果
*p
被读取为0xFFFF,则返回0xFFFE;如果
*p
被读取为零,则返回零。

不确定您真正想要实现什么或问题是什么。不要使用volatile(共享)变量本身进行计算,而要使用局部变量从volatile变量获取值。但是,最好将更改后的值从ISR发送到任务,例如使用队列。这可能是计划和优先级分配中的设计缺陷。询问一个真实的问题,而不是一个不太可能的假设问题。设计应确保a)TASKL可以在新值可用之前完成其处理,b TAKSH的执行时间不应过长,以免导致TASKL误期。还发布了真实代码来说明问题——不清楚在这种情况下,volatile的相关性是什么。快速而肮脏的解决方案是将传感器处理封装在互斥或关键部分。