下载 FreeRTOS
 

出色的 RTOS & 嵌入式软件

内核
最新资讯
简化任何设备的身份验证云连接。
利用 CoAP 设计节能型云连接 IoT 解决方案。
11.0.0 版 FreeRTOS 内核简介:
FreeRTOS 路线图和代码贡献流程。
使用 FreeRTOS 实现 OPC-UA over TSN。

解决方案 #3
减少 RAM 利用率


<<< | >>>

注意:自 FreeRTOS V4.0.0 引入以来,这些页面一直没有更新。 V4.0.0 引入了协程的概念, 可为本教程所介绍的设计提供另一种新颖解决方案。 更多信息,请参阅任务和协程文档 。

概要

解决方案 #2 充分利用了 RTOS。 这使得设计干净,但只能在具有充足 RAM 和处理资源的嵌入式计算机上使用。 解决方案 #3 试图通过将功能分区更改为任务来减少 RAM 使用量。


实现


解决方案 #3 函数任务和优先级

我们之前已经看到如何将假设应用程序的时间要求 分为三类:

  1. 严格定时 - 设备控制

    如前所述,创建高优先级任务来为关键控制功能提供服务。

  2. 仅限截止日期定时 - 人机界面

    解决方案 #3 将 RS232、键扫描和 LED 功能分组为一个中等优先级任务。

    由于前面所述的原因, 嵌入式 Web 服务器任务可以较低优先级操作。 不是专门为 Web 服务器创建任务, 而是实现空闲任务挂钩,以将 Web 服务器功能添加到空闲任务中。 必须写入 Web 服务器 以确保它永远不会阻塞!

  3. 灵活定时 - LED

    LED 功能太简单,如果 RAM 处于高级状态,则无法保证自己的任务。 为了演示,此示例 将 LED 功能包含在单个中等优先级任务中。 当然,它可以通过多种方式实现(例如, 从外围定时器)。

空闲任务以外的任务将阻塞,直到事件指示需要处理。 事件可以是外部事件(如 按下的键),或内部事件(如定时器即将过期)。


操作理念

将功能分组到中等优先级任务有三个重要优势, 相比于解决方案 #1 中提出的无限循环实现:
  1. 使用队列允许中等优先级任务阻塞,直到事件导致数据可用 - 然后 立即跳转到相关函数以处理事件。 这可以防止浪费处理器周期 - 与无限 循环实现相反,无限循环实现只有在循环周期到适当的处理程序时才会处理事件。

  2. 使用实时内核消除了在应用程序源代码中显式考虑时间关键型任务的调度的要求 。

  3. 从循环中删除嵌入式 Web 服务器函数使执行时间更加可预测。
此外,已分组为单个任务的功能来自以前具有相同优先级的多个任务 (除了 LED 函数)。 此优先级代码的执行频率不会改变, 不论是在单个任务还是多个任务中。

设备控制任务作为最高优先级的任务,保证在需要时分配处理时间。 必要时,它将抢占低优先级和中等优先级的任务。 每当两个应用程序任务都被阻塞时,空闲任务就会执行。 空闲任务可以选择将处理器置于节能模式。


调度器配置

调度器配置为抢占式操作。 内核滴答频率应设置为 提供所需时间粒度的最慢值。


评估

只创建两个应用程序任务,因此使用的 RAM 少于解决方案 #2。
处理器利用率在最迫切需要的基础上自动从一个任务切换到另一个任务。
有效地利用空闲任务可以创建三个应用程序任务优先级,开销仅为两个。
设计仍然简单,但中等优先级任务中函数的执行时间 可能会引入定时问题。 嵌入式 Web 服务器任务的分离降低了这种风险,并且在任何情况下, 任何此类问题都不会影响设备控制任务。
如果空闲任务将 CPU 置于省电(睡眠)模式,则可以降低功耗,但也可能会 浪费,因为滴答中断有时会不必要地唤醒 CPU。
RTOS 功能将使用处理资源。 其程度将取决于所选的内核 滴答频率。
如果应用程序变得太大,设计可能无法扩展。


结论

这对于 RAM 有限的系统来说可能是一个很好的解决方案,但它仍然是处理器密集型的。 应检查系统内的剩余容量,以便将来扩展。


示例

此示例是先前介绍的假设应用程序的部分实现。 使用 FreeRTOS API。


设备控制任务

设备控制任务与解决方案 #2 中描述的相同。


嵌入式 Web 服务器

这只是从空闲任务调用并运行到完成的函数。


中等优先级任务

中等优先级任务可由以下伪代码表示。
#define DELAY_PERIOD 4
#define FLASH_RATE 1000

void MediumPriorityTask( void *pvParameters )
{
xQueueItem Data;
TickType_t FlashTime;

    InitialiseQueue();
    FlashTime = xTaskGetTickCount();
    
    for( ;; )
    {
        do
        {
            // A
            if( xQueueReceive( xCommsQueue, &Data, DELAY_PERIOD ) )
            {
                ProcessRS232Characters( Data.Value );
            }
            
          // B
        } while ( uxQueueMessagesWaiting( xCommsQueue ) );
        
        // C
        if( ScanKeypad() )
        {
            UpdateLCD();
        }
        
        // D
        if( ( xTaskGetTickCount() - FlashTime ) >= FLASH_RATE )
        {
            FlashTime = xTaskGetTickCount();
            UpdateLED();
        }
    }

    // Should never get here.
    return 0;
}
请参阅上面代码片段内的标签:
  1. 该任务首先阻塞等待通信事件。 阻塞时间相对较短。

  2. do-while 循环将执行,直到队列中没有剩余数据为止。 必须修改此实现, 如果数据到达太快,以至于队列永远无法完全为空。

  3. 队列已清空所有数据,或者在指定的阻塞期间内没有数据到达。 阻塞等待数据的最长时间 足够短,以确保键盘扫描频率足够高,满足指定的定时限制。

  4. 检查是否是时候闪烁 LED。 这条线执行的频率会有一些抖动, 但 LED 定时要求足够灵活,可以通过此实现来满足。


下一步 >>> 解决方案 #4: 减少处理器开销





Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.