本帖最后由 9pin 于 2018-12-22 14:36 编辑
有人看再更新实现。添加附件
app.rar
(606.1 KB)
boot.rar
(661.69 KB)
core.rar
(2.04 MB)
4.0 程序架构设计.pdf
(498.6 KB)
程序架构设计够用的硬件
能用的代码
实用的教程
屋脊雀工作室编撰 -201800906
官网:www.wujique.com
github:https://github.com/wujique/stm32f407
资料下载:https://pan.baidu.com/s/1bHUVe6X6tymktUHk_z91cA
如果你认真看了前面的文档,会发现一个我们的教程跟其他教程的不同点:其他教程都是在教你如何用这个设备,我们说的是,如何给这个设备写驱动。其中,我们一直在强调的一点是,要提供良好的接口给应用使用。
为什么呢?因为,一个复杂项目,底层通常是跟应用分开的。
为了应付复杂的程序,通常需要一个大概的程序架构设计。下面,我们一起学习一种常见的程序架构设计。
为什么
为什么需要架构设计呢?
固件更新
到目前为止,下载程序,我们有两种方法: - 通过串口下载,在下载过程中,需要控制boot管脚。
- 通过JTAG(SW)调试口下载。
在真实产品开发中,调试口只存在于PCB上,预留测试点。没见过有产品外露调试口的。
有外露串口的,也有用牙签顶住一个小洞就能更新固件的,少,很少。
产品需要支持其他方式更新固件,例如U盘、USB、无线OTA更新方式。
怎么做? 当前芯片基本上都支持IAP功能。
简单的说,就是,在运行程序时,可以通过程序擦写FLASH,写新的程序到FLASH上。
那么我们可以通过IAP在应用更新固件。
应用和驱动分离
功能复杂,程序就大,人就多。
遇到问题就扯皮。
有的公司,会将底层打包为库,丢给应用使用,应用将自己的程序跟底层库一起打包编译。
这样的方式,并不能解决问题。
除了扯皮,也有实际问题。 - 多应用
有很多行业,一个设备,会卖给不同的客户,不同的客户就有不同的需求,就需要不同的程序。
如果底层已一个BUG,需要修改,那么就需要发布N个程序。 - 升级压力
如果程序比较大,例如驱动有200K,应用有200K,一起400K,那么,OTA就要传输400K。
如果两者分开,只有一个修改的时候,只需要OTA 200K。 - 促进发展
如果将底层和APP分离,务必就有一套标准的接口。
如何做?
牵涉以下问题: - 空间分配
驱动跟应用分离,意思是,驱动一个工程,单独编译。应用是另外一个工程,单独编译。
那么FLASH和RAM空间就需要分开,通过分散加载文件实现。
RAM,分开的是全局变量空间。临时变量用的是栈,不需要分开。 - 时间片
如果驱动没有时间片需求,那么驱动,就类似一堆库函数。应用只要调用就行了。
如果驱动有要轮询的任务呢?
- 可以放在一个低优先级的定时器中轮询。-----不建议
- 去不放在一个函数中,让应用带着跑--------如果应用是小循环模式,带着跑很不方便。
- 上RTOS,驱动掌控RTOS,应用做为一个RTOS的一个任务----------强烈建议用这个方法。
- 接口
应用如何调用底层接口呢?
CPU执行一个函数,就是将PC指针指向函数。
写程序时,我们经常会用函数指针。
APP和驱动的沟通,就是通过函数指针来实现。 - 分离的缺陷
驱动和应用都会链接标准库,代码会大一点。
常见架构
我们常见的架构方式是:3段式框架。
如下图: 戏称三权分立 - BOOT
最先启动的代码,负责固件更新,并包含最基础的固件下载功能。
启动后,跳到CORE运行位置,丢失控制权。 - CORE
通常包含驱动,测试程序。可能会支持更多的固件下载方式。
部分软件模块也放在CORE。例如文件系统等软件模块。
所有给应用使用的接口,放在固定位置,以便APP调用。
如果没有使用RTOS,右边就不是获取,而是跳到APP任务,一单跳过去,CPU控制器就归APP了。 - 应用程序
实现应用逻辑,通过调用底层接口控制硬件设备。
关键流程
BOOT启动,校验固件,跳转还是更新。
CORE运行,环境初始化,驱动APP任务。
APP,其实就是一个函数。
实现
只讨论基于RTOS的情况。
硬件基于STM32F407。
只讨论关键技术。
分散加载文件划分
BOOT跳到CORE
CORE启动APP任务
驱动接口的定义
IAP
end
|