FinSH控制台
在计算机发展的早期,图形系统出现之前,没有鼠标,甚至没有键盘。那时候人们如何与计算机交互呢?最早期的计算机使用打孔的纸条向计算机输入命令,编写程序。
后来随着计算机的不断发展,显示器、键盘成为计算机的标准配置,但此时的操作系统还不支持图形界面,计算机先驱们开发了一种软件,**它接受用户输入的命令,解释之后,传递给操作系统,并将操作系统执行的结果返回给用户。**这个程序像一层外壳包裹在操作系统的外面,所以它被称为shell。
嵌入式设备通常需要将开发板与PC机连接起来通讯,常见连接方式包括:串口、USB、以太网、WiFi等。一个灵活的shell也应该支持在多种连接方式上工作。
有了shell,就像在开发者和计算机之间架起了一座沟通的桥梁,开发者能很方便的获取系统的运行情况,并通过命令控制系统的运行。特别是在调试阶段,有了shell,开发者除了能更快的定位到问题之外,也能利用shell调用测试函数,改变测试函数的参数,减少代码的烧录次数,缩减项目的开发时间。
FinSH是RT-Thread的命令行组件(shell)。
FinSH简介
FinSH是RT-Thread的命令行组件,提供一套供用户在命令行调用的操作接口,主要用于调试或查看系统信息。它可以使用串口/以太网/USB等与PC机进行通信。
用户在控制终端输入命令,控制终端通过串口、USB、网络等方式将命令传给设备里的FinSH,FinSH会读取设备输入命令,解析并自动扫描内部函数表,寻找对应函数名,执行函数后输出回应,回应通过原路返回,将结果显示在控制终端上。
当使用串口连接设备与控制终端时,FinSH命令的执行流程,如图所示:
ulog简介
日志的定义:日志是将软件运行的状态,过程等信息,输出到不同的介质中(例如:文件、控制台、显示屏等),并进行显示和保存。为软件调试、维护过程中的问题追溯、性能分析、系统监控、故障预警等功能,提供参考依据。
可以说,日志的使用,几乎占用软件生命周期的80%。
日志的重要性:对于操作系统而言,由于其软件的复杂度非常大,单步调试在一些场景下并不适合,所以日志组件在操作系统上几乎都是标配。完善的日志系统也能让操作系统的调试事半功倍。
ulog的起源:RT-Thread一直缺少小巧、实用的日志组件,而ulog的诞生补全了这块的短板。它将作为RT-Thread的基础组件被开源出来,让开发者也能用上简洁易用的日志系统,提高开发效率。
ulog是一个非常简洁、易用的C/C++日志组件,第一个字母u代表微型,它能做到最低ROM<1K,RAM<0.2K的资源占用。
ulog不仅有小巧体积,同样也有非常全面的功能,其设计理念参考的另外一款C/C++开源日志库:EasyLogger(简称elog),并在功能和性能等方面做了非常多的改进。主要特性如下:
- 日志输出的后端多样化,可支持例如:串口、网络、文件,闪存等后端形式。
- 日志输出被设计为线程安全的方式,并支持异步输出模式。
- 日志系统高可靠,在中断 ISR 、Hardfault 等复杂环境下依旧可用。
- 日志支持运行期 / 编译期设置输出级别。
- 日志内容支持按关键词及标签方式进行全局过滤。
- API 和日志格式可兼容 linux syslog。
- 支持以 hex 格式 dump 调试数据到日志中。
- 兼容 rtdbg (RTT 早期的日志头文件)及 EasyLogger 的日志输出 API。
电源管理
嵌入式系统低功耗管理的目的在于满足用户对性能需求的前提下,尽可能降低系统能耗以延长设备待机时间。
高性能与有限的电池能量在嵌入式系统中矛盾最为突出,硬件低功耗设计与软件低功耗管理的联合应用称为解决矛盾的有效手段。
现在的各种MCU都或多或少的在低功耗方面提供了管理接口。比如对主控时钟频率的调整、工作电压的改变、总线频率的调整甚至关闭、外围工作时钟的关闭等。
有了硬件上的支持,合理的软件设计就成为节能的关键,一般可以把低功耗管理分为三个类别:
- 处理器电源管理主要实现方式:对CPU频率的动态管理,以及系统空闲时对工作模式的调整。
- 设备电源管理:关闭个别闲置设备。
- 系统平台电源管理:针对特定系统平台的非常见设备具体定制。
随着物联网(IoT)的兴起,产品对功耗的需求越来越强烈。
作为数据采集的传感器节点通常需要在电池供电时长期工作,而作为联网的SOC也需要有快速的响应功能和较低的功能。
在产品开发的起始阶段,首先考虑是尽快完成产品的功能开发。
在产品功能逐步完善之后,就需要加入电源管理功能。为了适应IoT的这种需求,提供电源管理组件。
PM组件介绍
对PM组件采用分层设计思想,分离架构和芯片相关的部分,提取公共部分作为核心。
在对上层提供通用的接口同时,也让底层驱动对组件的适配变得更加简单。
- 基于模式来管理功耗,空闲时动态调整工作模式,支持多个等级的休眠。
- 对应用透明,组件在底层自动完成电源管理。
- 支持运行模式下动态变频,根据模式自动更新设备的频率配置,确保在不同的运行模式都可以正常工作。
- 支持设备电源管理,根据模式自动管理设备的挂起和恢复,确保在不同的休眠模式下可以正确的挂起和恢复。
- 支持可选的休眠时间补充,让依赖OS Tick的应用可以透明使用。
- 向上层提供设备接口,如果打开了 devfs 组件,那么也可以通过文件系统接口访问。
工作原理
低功耗的本质是在系统空闲时CPU停止工作,中断或事件唤醒后继续工作。
在RTOS中,通常包含一个IDLE 任务,该任务的优先级最低且一直保持就绪状态,当高优先级任务未就绪时,OS 执行 IDLE 任务。
一般地,未进行低功耗处理时,CPU在IDLE任务中循环执行空指令。
RT-Thread的电源管理组件在IDLE任务中,通过对CPU、时钟和设备等进行管理,从而有效降低系统的功耗。
在上图所示,当高优先级任务运行结束或被挂起时,系统将进入 IDLE 任务中。
在IDLE任务执行后,它将判断系统是否可以进入到休眠状态(以节省功耗)。如果可以进入休眠,将根据芯片情况关闭部分硬件模块,OS Tick也非常有可能进入暂停状态。此时电源管理框架会根据系统定时器情况,计算出下一个超时时间点,并设置低功耗定时器,让设备能够在这个时刻点唤醒,并进行后续的工作。
当系统被唤醒后,系统也需要知道睡眠长度是多少,并对OS Tick进行补充,让系统的OS TICK值调整为一个正确的值。
设计架构
在RT-Thread PM组件中,外设或应用通过投票机制对所需的功耗模式进行投票,当系统空闲时,根据投票测量决策出合适的功耗模式,调用抽象接口,控制芯片会进入低功耗状态,从而降低系统功耗。
当未进行任何投票时,会以默认模式进入(通常为空闲模式)。
与应用不同,某些外设可能在进入低功耗状态时执行特定操作,退出低功耗时采取措施恢复,此时可以通过注册PM设备来实现。
通过注册PM设备,在进入低功耗状态之前,会触发注册设备的suspend回调,开发者可在回调里执行自己的操作;类似地,从低功耗状态退出时,也会触发resume回调。
低功耗状态和模式
RM组件将系统划分为两种状态:运行状态(RUN)和休眠状态(Sleep)。
运行状态控制CPU的频率,适用于变频场景;休眠状态根据SOC特性实现休眠CPU,以降低功耗。
两种状态分别使用不同的API接口,独立控制。
休眠状态就是低功耗状态,通过关闭外设,执行SOC电源管理接口,降低系统功耗。
休眠状态又分为留个模式,呈现为金字塔的形式。随着模式增加,功耗逐级递减的特点。
运行状态通常用于改变CPU的运行频率,独立于休眠模式。当前运行状态划分了四个等级:高速、正常、中速、低速。
模式的请求和释放
在PM组件里,上层应用可以通过请求和释放休眠模式主动参与功耗管理。应用可以根据场景请求不同的休眠模式,并在处理完毕后释放,只要有任意一个应用或设备请求高等级的功耗模式,就不会切换到比它更低的模式。因此,休眠模式的请求和释放的操作通常成对出现,可用于对某个阶段进行保护,如外设的 DMA 传输过程。
调用流程
首先应用设置进出休眠状态的回调函数,然后调用rt_pm_request请求休眠模式,触发休眠操作;PM组件在系统空闲时检查休眠模式计数,根据投票数给出推荐的模式;接着 PM 组件调用 notfiy 通知应用,告知即将进入休眠模式;然后对注册的 PM 设备执行挂起操作,返回 OK 后执行 SOC 实现的的休眠模式,系统进入休眠状态(如果使能时间补偿,休眠之前会先启动低功耗定时器)。此时 CPU 停止工作,等待事件或者中断唤醒。当系统被唤醒后,由于全局中断为关闭状态,系统继续从该处执行,获取睡眠时间补偿系统的心跳,依次唤醒设备,通知应用从休眠模式退出。如此一个周期执行完毕,退出,等待系统下次空闲。