基于 RTOS 的问题
在本节中,我们将探讨开发人员在使用 RTOS 时遇到的一些常见问题,并展示如何检测和纠正这些问题。
堆栈溢出:
在基于内核的应用程序中,每个任务都需要自己的堆栈。任务所需的堆栈大小是特定于应用程序的。 如果使堆栈大于任务所需,则会浪费内存。如果堆栈太小,您的应用程序很可能会覆盖应用程序变量或另一个任务的堆栈。堆栈区域外的任何写入都称为堆栈溢出。当然,在这两种选择之间,为堆栈过度分配内存比分配不足要好。因此,您可以通过过度分配内存来减少堆栈溢出的机会。但是,通常只需要 25-50% 的额外堆栈空间。一些 CPU,例如基于 ARMv8M 架构的 CPU,具有内置的堆栈溢出检测功能。但是,该功能无助于确定正确的堆栈大小。它只是防止堆栈溢出的负面后果。
参考文献[1]解释了如何确定每个任务堆栈的大小。简而言之,您通过为任务堆栈过度分配空间来开始您的设计,然后在已知的最坏情况下运行您的应用程序,同时监控实际的堆栈使用情况。
下图是 μC/Probe 对一个测试应用的内核感知的截图。Stack Usage列显示每个任务在任何给定时间的最大堆栈使用量的条形图。虽然截取了屏幕截图,但 μC/Probe 会实时更新并显示此信息,因此您无需停止目标即可查看此信息,因为它正在更新。
绿色表示最大堆栈使用率一直保持在 70% 以下。
黄色表示堆栈使用率介于 70% 和 90% 之间。
红色表示堆栈使用率已超过 90%。
显然,应该增加使用 92% 的任务的堆栈,使其回到 70% 范围以下。黄色的任务堆栈是空闲任务,在 77% 的情况下,它通常不会成为问题,除非您将代码添加到空闲任务回调函数(这取决于您使用的 RTOS)。
中断响应:
在操作内部数据结构(即临界区)时,RTOS 和应用程序代码通常必须禁用中断。RTOS 开发人员尽一切努力减少中断禁用时间,因为它会影响系统对事件的响应。
一些 RTOS 实际上基于每个任务测量最坏情况下的中断禁用时间,如下面的 μC/Probe 屏幕截图所示。如果您试图满足实时截止日期,则此信息非常宝贵。
中断被禁用的时间很大程度上取决于 CPU、它的时钟频率、您的应用程序和被调用的 RTOS 服务。禁用中断时间最长的任务以红色突出显示。这使您可以快速识别潜在的异常值,尤其是在大型和复杂的应用程序中。
如果最大的中断禁用时间是由 RTOS 引起的,那么您可能无能为力,除非:
查找中断禁用时间较短的备用 RTOS API。例如,如果您只是向任务发出信号以指示事件发生,那么您可以简单地挂起/恢复任务,而不是使用信号量或事件标志。换句话说,等待事件的任务会自行挂起,而发出事件信号的 ISR 会恢复任务。
提高 CPU 的时钟频率。不幸的是,这很少是一种选择,因为其他因素可能已经决定了理想的 CPU 时钟频率。
使用非内核感知中断来处理对时间高度敏感的代码。
优先级反转:
当低优先级任务拥有高优先级任务所需的资源时,就会发生优先级反转。当中等优先级任务抢占低优先级任务同时持有资源时,问题会更加严重。术语“优先级倒置”指的是低优先级任务的行为就好像它比高优先级任务具有更高的优先级,至少在共享该资源时是这样。
优先级反转是实时系统中的一个问题,并且在使用基于优先级的抢占式内核时会发生(大多数 RTOS 都是抢占式的)。如下图所示,SystemView 用于说明优先级倒置的场景。
App HPT(High Priority Task)优先级最高
App MPT (Medium Priority Task) 具有中等优先级
App LPT (低优先级任务)的优先级最低
1 - LPT 是唯一可以运行的任务,因此它获取 CPU 并获取信号量以访问共享资源。
2 -为了模拟优先级反转的发生,LPT 使 HPT 准备好运行,因此 RTOS 上下文切换到 HPT。
3 - HPT 使 MPT 准备好运行但继续执行,因为 HPT 仍然具有更高的优先级。
4 - HPT 需要访问共享资源并尝试获取信号量。但是,由于信号量归 LPT 所有,HPT 无法继续执行,因此 RTOS 切换到 MPT。
5 - MPT 一直执行,直到它需要等待其事件再次发生,以便 RTOS 切换回 LPT。
6 - LPT 完成对共享资源的使用,因此它释放信号量。此时,RTOS 注意到 HPT 正在等待资源,因此将信号量提供给 HPT 并使其准备好运行。HPT 恢复执行并执行它需要对共享资源执行的任何操作。
7 - 一旦 HPT 完成对资源的访问,它就会释放信号量,然后等待其事件再次发生(在这种情况下,我们通过自挂起模拟了这一点)。
8 - LPT 恢复执行,因为其他两个任务都没有准备好运行。
9 -发生优先级反转是因为 LPT 拥有 HPT 需要的资源。但是,当中等优先级任务进一步延迟 LPT 释放信号量时,问题会变得更糟。
您可以通过使用称为 Mutex(互斥信号量)的特殊 RTOS 机制来解决上述优先级反转问题。下图显示了相同的场景,除了这里 LPT 和 HPT 都使用互斥锁而不是信号量来访问共享资源。
1 - LPT 是唯一可以运行的任务,因此它获取 CPU 并获取互斥体以访问共享资源。
2 - 为了模拟优先级反转的发生,LPT 使 HPT 准备好运行,因此 RTOS 上下文切换到 HPT。
3 - HPT 使 MPT 准备好运行但继续执行,因为 HPT 仍然具有更高的优先级。
4 - HPT 需要访问共享资源并尝试获取互斥锁。但是,由于互斥锁归 LPT 所有,因此 HPT 无法继续执行。但是,由于使用了互斥体,RTOS 会将 LPT 的优先级提高到 HPT 的优先级,以防止它被中等优先级抢占。
5 - 然后 RTOS 切换到 LPT,它现在以与 HPT 相同的优先级运行。
6 - LPT 完成对共享资源的使用,因此它释放互斥锁。RTOS 将 LPT 的优先级降低回其原始(较低)优先级,并将互斥锁分配给 HPT。
7 - RTOS 切换回 HPT,因为它正在等待释放互斥锁。一旦完成,HPT 就会释放互斥锁。
8 - 一旦 HPT 完成其工作的执行,它就会等待它正在等待的事件的再次发生。
9 - RTOS 切换到在就绪队列中等待的 MPT。
10 -当 MPT 完成它的工作时,它还挂起将导致该任务再次执行的事件。
11 - LPT 现在可以恢复执行。
优先级反转现在受限于 LPT 访问共享资源所需的时间量。如果没有像 SystemView 这样的工具,优先级反转将很难识别和纠正。
请注意,如果 LPT 仅比 HPT 低一个优先级,则可以使用信号量。在这种情况下,信号量是首选,因为它比互斥锁更快,因为 RTOS 不需要更改 LPT 的优先级。
审核编辑:郭婷
-
cpu
+关注
关注
68文章
10873浏览量
212062 -
API
+关注
关注
2文章
1502浏览量
62125 -
RTOS
+关注
关注
22文章
815浏览量
119705
发布评论请先 登录
相关推荐
评论