到手一块新的开发板,是不是总想赶紧跑上一段代码试试?但是板子芯片没有适配驱动的情况时有发生,本文将带领大家一起全流程操作基于STM32芯片的OneOS驱动适配工作,希望在各位小伙伴遇到此类问题时能有所帮助~
本文使用的软件版本为:OneOS-v2.3.0
适配的芯片型号为:STM32L073_RZT6芯片
一、工程建立
Step1 生成工程模板
首先,在git工程中的project目录下,打开OneOS-Cube工具,通过执行project命令进入芯片型号选择界面,根据项目需要适配的芯片来生成默认的工程模板。
Step2 配置MCU工作频率
适配驱动之前需要确认用户需求,工作频率一般越低整体功耗就越低。具体配置参数在CubeMX中根据修改相关分频系数来改变MCU工作频率。
基础功能配置需要工程创建初期就确定下来,否则修改后会影响各个模块功能,导致全部需要重新验证。
Step3 编译优化等级
针对Flash资源紧张,在Keil中选择AC6编译器,优化级别选择-Oz可以提供尽可能小的代码量,减少Flash占用资源。
使用-Oz最高优化等级存在风险,没法预期优化后程序运行是否存在问题,需要把功能全覆盖验证才能确定。
编译优化需要在项目创建初期确定,否则影响后续功能验证。
修改template.uvprojx文件中的编译器为AC6默认版本和对应的优化级别。
选择优化级别-Oz,减少资源占用。
Step4 配置BootLoader
在生成的芯片模板工程目录下,通过OneOS-Cube执行menuconfig命令来配置BootLoader。
首先根据需求是否需要加载BootLoader,配置使能与否。
然后配置Flash起始地址。若不使用BootLoader,根据STM32L0x3芯片参考手册的Flash起始地址从0x08000000 开始,则对应配置为OneOS启动起始地址。
在OneOS-Cube中text section size选项代表烧录程序占用的Flash大小,data section size选项代表芯片的RAM大小,根据芯片手册设置成对应的参数。
本示例中的STM32L073_RZT6芯片Flash是192K,即192*1024转换为16进制即0x00030000。
RAM是20K,即20*1024转换为16进制即0x00005000。
若需要加载BootLoader,根据BootLoader分配的APP起始地址分区,修改text section addr增加相应的地址偏移量,text section size做相应的减少。
二、驱动适配
根据项目具体需求适配需要使用的驱动,裁剪未用到的驱动文件。详细的操作配置可以参考OneOS开发文档中驱动一栏,链接:https://os.iot.10086.cn/oneos-doc-2.0/
流程大体为CubeMX配置驱动基本属性,OneOS-Cube工具执行menuconfig命令使能驱动。
2.1 Serial
Step1 通用串口配置
首先根据项目需求,在CubeMX中使能相应配置引脚的UART。
芯片与其他模组通过串口通讯数据量较大时,应配置为DMA循环模式,从而减少丢包情况。
在CubeMX中可以不配置串口波特率,停止位等参数,采用默认即可。后续再使用串口时,通过os_device_control接口来设置对应参数。
根据实际需求在串口驱动中配置收/发的buffer长度,该功能会统一修改所有串口的buffer长度,暂不支持单独设置各个串口。
Step2 标准输出终端
os_kprintf()函数(为减少对栈的使用,此函数不支持浮点数)用于打印调试,使用方法同printf。在CubeMX中配置对应的串口为标准输出终端,属性设置为:波特率115200,数据位8,停止位1,奇偶校验位NONE。
在OneOS-Cube驱动选项中使能控制台功能。配置的串口名需要严格按照小写规则映射,如USART1对应uart1,LPUART1对应lpuart1等。
Step3 Shell工具
Shell工具通过控制台命令行交互。常用命令有help查看注册的测试示例代码,device查看加载的设备驱动信息,show_mem查看RAM使用情况。
使用Shell控制台时遇到提示hard fault in task:shell崩溃的问题,则一般情况为Shell任务栈溢出导致,需要增大配置的栈空间。
MCU串口发送数据正常,但是接收不到数据的问题,可能是串口引脚被其他功能模块占用。本例程中被SN功能占用,导致Shell控制台无法正常接收数据,需要禁能SN配置功能。
2.2 GPIO
GPIO驱动不需要在CubeMX中单独配置每个功能引脚,只需要在使用时,调用GET_PIN()获取引脚值即可。本例程中STM32l073_RZT6引脚映射的规则从PA0(索引数值为0)开始以此递增,具体实现见drv_gpio.h文件。
使能GPIO驱动需要打开Drivers->MISC 下的 "Using push button device drivers" 和"Using led device drivers"两个选项。
2.3 Watchdog
首先在CubeMX中具体配置参考下图
看门狗时间计算:T = Prescaler * Reload / 37K
PS: IWDG所用计时时钟是不稳定的(35-60KHz),通常取40KHz计算。本例子配置的是37KHz。
若按照下列所示参数配置,则看门狗复位时间约为:
T = Prescaler * Reload / 37K = 64 * 4096 / 37000 = 7.0849 秒
看门狗测试验证方法:
在工程中增加对应的wdg_test.c文件,路径OneOS\demos\driver\xxx.c
本示例配置Prescaler参数为16,测试效果如下:
os_device_control()设置超时函数失败,不支持设置API设置超时时间,根据配置的参数来决定复位时间。
2.4 Flash
本示例中操作的是片内Flash。根据芯片的参考手册,查看Flash起始地址和大小区间。
可以在BootLoader划分后的app分区内,根据业务需求划分。例如在APP末尾的一段分区划分出作为日志持久化存储区域。
通过read/write/erase 等基本API来对Flash进行相关操作。
修改以下2个文件划分APP使用的Flash分区。擦除最小单元按照配置的block_size来确定,根据对应的芯片手册本示例为128字节。
写操作的最小单元以page_size来确定,最小写入单位4字节对齐操作。
三、功能裁剪
给用户预留Flash和ram使用的空间,需要裁剪未使用到的驱动和组件。
根据project.map文件查看编译代码占用的资源。双击工程名字可以快捷打开该文件。
PS:若双击不能打开,则需要进编译选项中的Listing选项卡界面,把Select Folder for Listings重新指定到project.map路径即可。
map文件分析
Code:代码空间,本质是ARM指令(Flash)。
RO-data:即 Read Only-data, 表示程序定义的常量,如 const 类型(Flash)。
RW-data:即 Read Write-data, 非0初始化的全局和静态变量占用的RAM大小,同时还要占用等量的ROM大小用于存放这些非0变量的初值(Flash+RAM)。
ZI-data:即 Zero Init-data, 0初始化的内存区的大小(该区域3个用途:0初始化的全局和静态变量+堆区+栈区)(RAM)。
程序占用Flash=Code + RO-data + RW-data 即map文件中ROM size。
程序占用RAM = RW-data + ZI-data 即map文件中RW size。
RW-data即占用Flash又占用RAM空间。由前文知道RAM掉电数据会丢失,RW-data是非0初始化的数据,已初始化的数据需要被存储在掉电不会丢失的Flash中,上电后会从Flash搬移到RAM中。
映像文件image的内容包含这三个Code 、 RO-data 和 RW-data。不包含ZI-data。
因为ZI-data数据是0,没必要包含,只要在程序运行前把ZI数据区域一律清零即可,包含进去反而浪费Flash存储空间。
堆栈大小在stm32的启动文件,例如本工程是在startup_stm32l073xx_arm.s里面设置。
如果没有用到标准库的malloc,Heap Size值可以设置为0。
四、总结
OneOS系统提供了丰富的基础驱动支持,驱动部分通过对底层代码和厂家 SDK 的统一封装,以 device 设备的方式对外提供统一的接口和较为全面的协议支持,更便于客户上手开发。OneOS 在各类外设的基础上抽象出了设备驱动模型,有效提高了代码可复用性、可移植性,模块分层解耦,降低了各层的开发难度。设备驱动框架设计遵循以下原则:
1.下层向上层提供统一的访问接口;
2.分层设计,屏蔽硬件差异;
3.每一层只跟其相邻的层建立联系;
更多OneOS驱动资料请参考:
https://os.iot.10086.cn/v2/doc/detailPage/documentHtml?proId=2000000000&proName=OneOS&idss=41&versionName=v2.4.0&versionId=3000000000