APP下载

基于STM32的mbed OS移植与低功耗研究

2020-05-12杨东升

小型微型计算机系统 2020年3期
关键词:看门狗开发板低功耗

张 翔,杨东升

1(中国科学院 沈阳计算技术研究所有限公司,沈阳 110168)

2(中国科学院大学,北京 100049)

E-mail:492490817@qq.com

1 引 言

物联网操作系统的概念,最先来自于无线传感器操作系统,知名的有TinyOS 和Contiki.与传统的嵌入式设备相比,物联网感知层具有更小的设备、更低的功耗、更高的安全性和更灵活的联网能力;物联网通信层需要支持各种通信协议和协议转换;应用层需要云计算能力;在软件方面,支持物联网设备的软件比传统的嵌入式设备软件更加复杂[1].于是就有了物联网操作系统IoT OS,简而言之,IoT OS就是具备物联网需求的嵌入式操作系统.从2014年至今,陆续出现了支持不同厂商的MCU设备的IoT OS,ARM mbed OS正是其中突出的一员.

物联网技术现已被广泛应用于智能电网、智能交通、环境监测等各种领域[2,3],为了适应新的物联网时代的变化,ARM提供了一个全新的开发方式,Arm mbed将物联网的所有基本组件(包括安全性,通信和设备管理)集成到一整套软件中,以协助开发低功耗、产品级的物联网设备和并优化生产流程.mbed包括了云服务、客户端、mbed OS等几大部分.在mbed 上可以使用mbed TSL实现网络安全协议,也可以实现CoAP 这样的物联网协议,支持访问Restful API来接入中国移动的OneNet物联网云端服务[4].Arm 公司希望mbed成为物联网领域的android,在mbed OS 中注入了大量的最新技术.本文正是在此背景下,针对mbed OS的功能需求进行研究,由于mbed OS目前仅支持受限的开发板型号,提出了一套mbed OS的移植流程,并在STM32设备上验证,并提出了低功耗优化方案,增加了低功耗看门狗功能,测试了系统功耗水平.

2 mbed OS概述

mbed不仅仅指一个嵌入式系统,也是一个面向ARM处理器的设备开发平台,Arm mbed提供高效,安全,快速开发下一个物联网产品所需的操作系统,工具和云服务,内容涉及从硬件到软件、从物端到云端等,功能包括安全、通信传输、设备管理等方面,为实现物联网从原型、开发到生产的快速便捷.

mbed OS为免费的开源物联网操作系统,面向Cortex-M系列处理器,它通过mbed web complier在线编译,代替了传统的离线编译器,使整个开发在浏览器中完成,使用它编译程序而不必安装或设置任何东西,为了省去用户开发环境搭建的麻烦,用户只要上网就可以开发[5].mbed将硬件相关程序使用中间件封装,因此基于mbed OS的开发只用专注于编写调用硬件功能接口的C/C++应用程序,而不需要关心底层驱动,极大限度地降低了嵌入式开发的难度,简化了软件开发流程,缩短了开发中的学习过程[6].同时mbed OS搭载CMSIS框架,CMSIS专为Cortex-M而设计,是独立于供应商的硬件抽象层[7].它屏蔽了微处理器之间的差异,使得基于mbed的用户可以轻松地替换来自不同制造商的ARM微处理器,而不用更改工程代码.

对于嵌入式开发,mbed OS最大的帮助就是提供了许多有用的组件,它提供的强大的API功能几乎包含控制器内部各种模块的使用,如串行通信、中断、模拟/数字信号、网络接口等,使用mbed编写简单的应用程序只需要短短的几行代码[8].它的Libraries提供了各种硬件、传感器的库,使得设备接入更加快捷.mbed OS与Arduino非常相似,Arduino具有便捷灵活、方便上手的特点,在嵌入式程序中非常流行[9].同样的,它们易于使用,直观的编程和设计,降低了开发门槛,使得初学者也能快速获得足以创造具有某种技术水平的新产品的能力[10],但是mbed的功能更加强大,应用领域更广.

3 mbed在STM32上的移植

mbed采用网页编译方式,通过在线选择mbed支持的开发板型号,从而屏蔽掉硬件驱动部分,在方便的同时却存在芯片的局限性,也存在无法调试等问题.目前mbed已经逐步支持200多种芯片,但是想让mbed OS支持其他型号的MCU需要移植.mbed OS作为软件层面的系统支持,移植则是必要任务.

3.1 mbed代码目录

图1为mbed的代码层次结构,它包括以下内容:

drivers:drivers目录中存放的是用户需要调用的mbed相关的.h头文件;

events:事件框架;

features:支持的功能,包括BLE、LWIP、TLS等;

hal:mbed OS定义的API函数,依赖于TARGETS目录提供的硬件适配支持;

RTOS:mbed实时操作系统文件;

CMSIS:MCU与外设之间的软件接口标准及启动链接文件;

targets:特定开发板实现hal需要的接口、连接脚本文件、使用的CMSIS头文件.

其中drivers、events、features、hal、RTOS为MCU无关层,CMSIS、targets为MCU有关层.

图1 mbed OS代码目录

3.2 mbed OS移植方案

本次移植在编译环境Keil uvision 5上进行,通过导出mbed工程源码,通过更改底层参数配置、部分代码、芯片库文件等方式,通过移植mbed OS到STM32L100R8T6及STM3-2F103RET6中,验证了移植流程.

3.2.1 导出工程源码

为了更快速地建立Keil工程,选择在mbed在线编译器中导出工程源码.在mbed compiler中点击Add Board,界面中展示的是mbed支持的开发板型号,使用这些开发板可以直接使用网页编译工程,并直接烧录进mbed中,而其他芯片目前并没有mbed支持,如需要移植mbed到STM32L100R8T6时选择NUCLEO-L152RE开发板,因为该开发板搭载STM32L152RE,与STM32L100R8T6同属于L系列,都搭载有Cortex-M3内核,是相同内核、相似型号的开发板,同理移植mbed到STM32F103RET6中时,可以选择NUCLEO-F103RB开发板,同属于F系列,都搭载有Cortex-M3内核.工程建立后右键 Export Program,toolchain 选择 uvision5,导出后解压并打开,即可得到一份 mbed OS的Keil uvision 5离线工程文件.

3.2.2 适配芯片型号

由于得到的工程文件是适配其他型号芯片的mbed OS工程,所以需要修改Keil配置以及工程中针对芯片型号的代码文件.

1)在uvision 5的 Options for Target选项中点击device,进入芯片型号选择,将原本的芯片型号改为新的芯片型号.

2)更改头文件stm32l1xx.h文件,文件可在工程中直接找到,也可在存放的文件夹目录 targetsTARGET_STM TARGET_STM32L1TARGET_NUCLEO_L152REdevice中找到,(类似地,如STM32F103移植则修改stm32f1xx.h)

原代码包含以下两行(不连续):

#define STM32L152xE

/* #define STM32L100xBA */

第一行为原芯片型号,注释掉第一行,并取消注释掉第二行,第二行为移植的目标型号.这一步是更改了代码中芯片的宏定义.

3.2.3 修改配置文件

1)更改启动文件和库头文件

mbed使用STM32 HAL库,需从官方重新下载对应头启动文件和库文件,删除原工程中该部分文件并从新导出.

STM32L152re启动头件为startup_stm32l152xe.S(目标目录targetsTARGET_STMTARGET_STM32L1TARGET_NUCLEO_L152REdeviceTOOLCHAIN_ARM_STD)

库头文件为stm32l152xe.h(目标目录 targetsTARGET_STMTARGET_STM32L1TARGET_NUCLEO_L152REdevice)

例如,使用 stm32l100xb.h 替换掉了 stm32l152xe.h,startup_stm32l100xba.S替换startup_stm32l152xe.S,则该步骤完成.

2)PeripheralNames.h、PeripheralPins.c及PinNames.h引脚文件修改.

因为芯片差异,该部分需要对应芯片编程手册,更改配置文件,引脚功能定义图一般在芯片手册的Table 8.

PeripheralNames.h文件中,对ADC、DAC、UART、SPI、I2C、PWM功能进行了初始化,例:

typedef enum {

UART_1=(int)UART1_BASE,

UART_2=(int)UART2_BASE,

UART_3=(int)UART3_BASE,

UART_4=(int)UART4_BASE,

UART_5=(int)UART5_BASE,

} UARTName;

初始化了5个通用异步串口,而STM32L100R8T6中,只有三个UART串口,所以删除或注释掉UART_4和UART_5两行.

PeripheralPins.c中是对具有ADC、DAC、UART、SPI、I2C、PWM功能的管脚一一对应,进行功能初始化,仍然以UART为例,如图2所示,同样注释掉UART4和UART5两行.

图2 PeripheralPins.c部分代码

同时,需要修改其他行,UART串口号与指定功能管脚一一对应,该文件中其他代码如SPI、DAC等同理.

PinNames.h中对所有GPIO管脚初始化,对部分功能管脚进出了宏定义,如:

LED1 =PA_5,

I2C_SCL =PB_8,

I2C_SDA =PB_9,

也可按需修改.

3)us_ticker_data.h

us_ticker_data.h中是对CPU定时器的相关配置文件(目标目录targetsTARGET_STMTARGET_STM32L1TARGET_NUCLEO_L152REdevice.

文件中部分代码为:

#define TIM_MST TIM5

#define TIM_MST_IRQ TIM5_IRQn

#define TIM_MST_RCC __TIM5_CLK_ENABLE()

#define TIM_MST_DBGMCU_FREEZE __HAL_DBGMCU_FREEZE_TIM5()

由于STM32L100R8T6并不存在TIM5,则修改为可用定时器TIM4,然后修改定时器位数:

#define TIM_MST_BIT_WIDTH 32 // 16 or 32

原芯片中为32位定时器,是原芯片型号L152RE中特有,L100R8T6不存在32位定时器,则TIM4为16位定时器,则改为16;

4)修改mbed_config.h文件

该文件位置主目录中,在该文件中有包括较多的数值参数,例波特率等,按照工程需求对应修改.

编译程序,如编译成功,则得到了一份mbed OS在Keil uvision 5上的离线移植程序.

3.2.4 实验测试

mbed OS提供了比较多功能的API,此时我们将移植板与计算机通过UART串口连接,由于在移植过程中,引脚的几个文件已经对UART等引脚标识并初始化,如果移植成功,则电脑与开发板间可以正常通讯.

使用以下代码,使用定时器,通过串口使用计算机屏幕返回一次通讯成功所需要的运行时间.

#include "mbed.h"

Timer t; //定义定时器t

Serial pc(USBTX,USBRX);

int main(){

t.start(); //启动定时器

pc.printf("The time taken was");//在屏幕上显示

t.stop();//停止定时器

pc.printf("%f seconds ",t.read());

}

如图3所示为计算机串口调试界面结果,至此表示mbed OS移植成功,并显示了一次通讯时间为0.017秒.

图3 串口通讯程序结果

4 低功耗模式设计

mbed OS通过void sleep()调用睡眠功能,它选择最合适的睡眠模式,mbed OS有两种可用的睡眠模式:1)睡眠模式,核心的系统时钟停止,直到发生复位或中断.这消除了处理器,存储器系统和总线使用的动态功率.此模式保持处理器,外设和存储器状态,外设继续工作并可产生中断,可以通过任何内部外设中断或外部引脚中断唤醒处理器.这时所有线程都处于等待状态.2)深度睡眠模式,此模式类似于睡眠但节省更多功率并具有更长的唤醒时间,它通过关闭高速时钟节省了额外的电力.因此,只有在不使用高速时钟的外设时才能进入该模式.在大多数情况下,只要系统空闲,mbed OS就会自动进入合适的睡眠模式.

4.1 低功耗模式优化

为实现最大限度的功耗优化,提出了可行性方案:

1)覆盖空闲循环任务:空闲循环是后台系统线程,当没有其他线程准备好运行时,调度程序执行.当应用程序等待事件发生时,会在后台执行空闲循环任务.空闲循环任务为最低优先级进程,一旦有更高优先级进程进入就绪态时,空闲任务会立即切换至新任务,空闲任务处理时,会调用处理器入睡眠模式,是一种自动低功耗方法,所以可以通过定制空闲任务功能,系统会在每次空闲时低能耗执行该任务,是可行的省电方案.

2)创建异步回调任务:许多mbed库依赖于某种I/O事务.无论是切换引脚,I2C,SPI还是串行传输,甚至是其他东西,他们都有一个共同点:它们往往需要执行时间.由于总线速度通常远低于核心运行的频率,因此这些库往往会引入大量类似的等待代码.由于这只是在没有做任何有用的情况下燃烧CPU周期,设置一个异步的回调函数来实现传输,在程序流中调用,将他们发给外设执行,并在传输完成时获得回调状态,以来解放CPU,在回调执行期间可以做更多的其他操作或是让CPU进入睡眠状态以节省大量功耗.

event_callback_t functionpointer;//回调函数

void handler(int events){

//在此处理事件,events参数表示事件标志

}

void init_fp(){

//设置functionpointer对象以指向此对象上的′handler′方法

functionpointer.attach(handler);

}

3)利用超时和断续中断:超时表示在外部事件发生后按计划时间以后触发中断,使用timeout函数实现,触发一个延迟事件是一种常见的需求;断续表示建立一个循环中断,周期性调用ticker断续函数,例如让LED每隔几秒闪烁一次,在嵌入式系统中创建一个周期性的事件也是最自然和常见的需求.然而上述两种需求如果使用延迟函数wait()去实现,比如在循环中使用wait()创建时间周期达到周期性触发事件的效果,该方法占用CPU,使CPU无法完成其他的任务,而使用超时和断续,释放CPU去做任何需要的事情,而测量变化时间的任务交给定时器硬件在后台完成,从而在计划时间触发中断,调用某一任务,而调用的频率由程序决定,不限制所创建的装置的数量.

在程序流中使用超时代替延迟函数是一种功耗的优化,它避免了CPU在等待延迟函数wait()到期时的阻塞状态,还有一种低功耗超时方法,LowPowerTimer继承自Timer类.在这种情况下,计时器即使在深度睡眠模式下也继续运行.它依赖于lp_ticker,这是低功率的计时器,测量精度在毫秒左右,在某些精度要求低的情况下可以使用它创建超时.同时超时也可以以回调的方式运行,我们通过创建超时任务,并设计一个回调函数标记超时进行状态,并开始睡眠直到超时结束,采用异步的方式,将睡眠程序包装在超时状态的while循环中,超时结束后继续执行后续的程序,这种方式避免的以同步方式触发睡眠的安全性问题,同时优化了功耗.例当我们希望停止程序流半秒时,使用低功耗计时器创建一个超时任务.

LowPowerTimeout Response;

bool flag=false; //回调状态

void callback(void){

flag=true;

}

void main(void){

Response.attach(callback,0.5f);

//确保我们只在超时到期后继续执行程序流程.

while(!flag)sleep();

.... //后续程序流程

}

4.2 看门狗实现

看门狗程序作为嵌入式设备的常用手段,保证设备的正常运行,看门狗定时器作为独立的定时器,需要不断的重启计时,俗称喂狗,如果没有及时喂狗,则定时器溢出,看门狗程序判定为系统崩溃,会复位重启系统[11].mbed OS中没有实现看门狗功能,本文实现了在mbed OS中启动看门狗任务,并同时提出了其在低功耗睡眠模式下的运行方法.

本文导入HAL库的IWDG函数实现看门狗程序编写并在mbed OS中启动,已知的看门狗唤醒时间公式为:溢出时间=预分频系数*重装载值/40,单位为ms,HAL库中IWDG_PRESCALER_表示预分频系数,如预分频系数采用64,重装载值采用625,则可按公式计算出1000ms即1s的溢出时间,那么需要在溢出时间内1s内实行喂狗,否则系统会复位重启.参考设置例程如下:

voidwatchdog(void){

hiwdg.Instance=IWDG;

hiwdg.Init.Prescaler=IWDG_PRESCALER_64

hiwdg.Init.Reload=625;

HAL_IWDG_Init(&hiwdg);

}

在喂狗时调用HAL_IWDG_Refresh(&hiwdg)函数实现喂狗,如在mbed中设置好watchdog函数后实现LED闪烁的喂狗程序如下:

while(true){

led1=!led1;

HAL_IWDG_Refresh(&hiwdg);

wait(0.5);

}

LED灯与喂狗程序同处于延迟0.5s的循环中,每0.5s LED闪烁一次并实行一次喂狗操作,如果系统未正常运行,那么看门狗溢出,系统复位.

看门狗是为了检测和解决由软件错误引起的故障,然而在低功耗模式下CPU休眠,无法进行正常的喂狗程序,而看门狗定时器作为独立的振荡器存在,开启后无法被关闭,在sleep模式下如果不进行喂狗操作,则整个系统会频发复位.针对该情况,本文提出了采用超时唤醒的方式实行喂狗操作,设置一个超时中断作为闹钟,设置一个标识标记中断的触发状态,在中断函数中实行喂狗操作和中断触发状态标记,如设置一个5秒钟的超时中断,当超时到期时,唤醒CPU,并标记中断触发,判定中断标识后执行喂狗操作并再次进入sleep()模式,如果CPU未成功唤醒,看门狗溢出,或CPU由其他未知错误导致唤醒,由于中断触发状态标识未更新,不会进行喂狗操作,同样导致看门狗溢出.其具体流程如图4所示.

图4 低功耗看门狗流程图

4.3 低功耗性能测试

1)硬件环境:本实验基于实验室自主研发开发板,带有M3内核的STM32L100RB芯片.

存储记录仪,用于测量板件程序运行时电压变化情况,根据终端的电阻大小,通过公式I=U/R,得到运行电流.

2)实验方案:通过对将mbed OS移植适配到该板件后编写简单的LED灯闪烁程序,测量在正常运行状态下功耗情况,然后通过创建空闲循环任务实现LED闪烁的低功耗方案,使系统切换到低功耗模式下,观测并记录低功耗下功耗变化.选用μC/OS-II系统做功耗对比,μC/OS-II是知名的开源实时操作系统,它代码结构清晰明了,可裁剪,系统短小精悍,是研究与学习实时操作系统的首选[12].同样的,将功耗与无操作系统情况下和移植μC/OS-II操作系统做对比,同样测量正常运行和低功耗情况下功耗情况,对比实验结果.

图5 电压变化图

如图5为存储记录仪中显示mbed的电压变化情况,总的实验数据结果如表1所示.

表1 功耗测试实验数据表

Table 1 Power test experimental data sheet

操作系统模式平均电压电阻平均电流-正常25mV10Ω2.5mA-低功耗6mV10Ω0.6mAμC/OS-II正常70mV10Ω7mAμC/OS-II低功耗20mV10Ω2mAmbed正常40mV10Ω4mAmbed低功耗12mV10Ω1.2mA

如上所示,可以得出结论,在无操作系统的情况下,裸板在运行和低功耗模式下功耗是最低的,嵌入式操作系统因为其更多功能的支持,功耗有所增加.但在在低功耗和正常运行情况下,mbed功耗仍相当可观,相较于μC/OS-II操作系统,功耗均接近于其的二分之一.

5 结束语

本文基于mbed OS,根据其在物联网中的参考架构,对其中的关键技术进行探讨,基于本文提出的移植方案可以突破mbed OS芯片局限,使其支持更多的MCU设备,基于本文设计的低功耗终端、传感器设备等可用于实际物联网场景.实践表明mbed确实代码简约、功能强大,极大程度地降低了开发难度和成本,在能耗上也完全符合物联网低功耗的需求,具有实用价值.

猜你喜欢

看门狗开发板低功耗
一种高速低功耗比较器设计
复合材料结构的低功耗冲击区域监测方法
基于STM32H7的FDCAN通信系统设计与实现∗
基于时钟芯片的硬件看门狗电路设计与实现
把他叫醒
核芯互联发布高性能ADC模数转换器
一种宽带低功耗四合一接收机设计
开发板在单片机原理及接口技术课程教学中的应用
ARM宣布mbed Enabled Freescale FRDM—K64F开发板通过微软认证
把它叫醒