3段式程序架构设计(更新实现方式说明和例子)

2019-07-20 05:38发布

本帖最后由 屋脊雀 于 2018-9-14 16:45 编辑


在STM32上实现了最简单的例子,请见附件。
具体如何实现的,在附件文档有说明。

欢迎大家继续讨论。

三段式程序架构设计.rar (3.61 MB, 下载次数: 177) 2018-9-14 16:44 上传 点击文件名下载附件

屋脊雀工作室编撰



如果你认真看了前面的文档,会发现一个我们的教程跟其他教程的不同点:其他教程都是在教你如何用这个设备,我们说的是,如何给这个设备写驱动。其中,我们一直在强调的一点是,要提供良好的接口给应用使用。
为什么呢?因为,一个复杂项目,底层通常是跟应用分开的。
为了应付复杂的程序,通常需要一个大概的程序架构设计。下面,我们一起学习一种常见的程序架构设计。

为什么

为什么需要架构设计呢?
固件更新
到目前为止,下载程序,我们有两种方法:
  • 通过串口下载,在下载过程中,需要控制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


友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。