1 前言

开发完 MCU 软件后,通常都会生成 hex 文件或者 bin 文件,用来做固件烧录或者升级,如果用来做产品开发,就涉及到固件版本的问题,初学者通常采用固件文件重命名来区分版本。

如果需要将版本写入固件中,就需要通过一定的方式去实现,实现的方式有很多。


2 介绍

下面介绍一个自动打包单片机固件的脚本软件,主要实现以下功能:

  • 基于 Windows 平台的单片机 MCU 固件脚本打包工具
  • 支持 hex 文件的裁剪和 hex 文件的合并
  • 可以为 hex 固件添加版本信息、Git Commit 分支和提交记录等
  • 按照版本信息命名hex固件,可生成 bin 文件等
  • 以上均可通过 ini 配置文件设置参数对 hex 文件进行操作

3 实现步骤

下面以 MDK + STM32 开发为例介绍。

3.1 __attribute__ 机制

首先了解一下__attribute__机制,它是个编译器指令,告诉编译器声明的特性,或者让编译器进行更多的错误检查和高级优化。
GUN C中可以使用__attribute__()给变量、函数和类型设置各种属性,而__attribute__的section选项可以改变段的特性;

其中__attribute__((section("section_name")))的作用是将该定义的函数或数据变量放入指定名为”section_name”段中。

无论是 GNU 还是 ARM 的编译器, 都支持__attribute__所指定的编译属性。

打开keil的options…,取消勾选下图所示,然后点击“Edit…”。

自动弹出“*.sct”文件(先编译通过再操作),下面就是 Keil 中 STM32 的链接文件,编译器会根据链接文件和__attribute__的section选项(可以自己添加一个段,分配地址和大小)等分配函数和数据变量在程序固件中的地址。

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; ************************************************************* LR_IROM1 0x08000000 0x00010000 { ; load region size_region
ER_IROM1 0x08000000 0x00010000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
}
RW_IRAM1 0x20000000 0x00005000 { ; RW data
.ANY (+RW +ZI)
}
}

这里不做过多介绍了,下面介绍的方式不需要自己修改“*.sct”文件,还是采用__attribute__的section选项,只不过在section选项中指定位置即可。

__attribute__ ((section(".ARM.__at_0x08000020")))

3.2 代码实现

1. 定义一个结构体,里面定义一些软件版本相关的信息

typedef struct
{
char szVersion[32]; // 软件版本
char szBuildDate[32]; // 程序编译日期
char szBuildTime[32]; // 程序编译时间
char szCommitId[32]; // git commit id
}AppInfo_t;

2. 通过__attribute__定义一个只读结构体变量(只读的目的:防止程序改变、节约RAM),赋初值(其中__DATE___TIME__是C语言中的内置宏,分别是当前的编译日期和编译时间)。

const AppInfo_t __attribute__ ((section(".ARM.__at_0x08002000"))) sg_tAppInfo =
{
"STM32_TEST",
__DATE__,
__TIME__,
""
};

注:STM32的代码起始地址是从0x08000000开始的,且存储中断向量表信息,因此在选择程序地址的时候一定要绕开,也不能太靠后,不然生成的bin文件超出了实际的代码固件大小,在实现bin文件升级的时候就会耗时太长。

3. 通过串口打印出来

int main(void)
{
FML_USART_Init(); USART_Printf(0, "Version : %s\r\n", sg_tAppInfo.szVersion);
USART_Printf(0, "buildTime: %s\r\n", sg_tAppInfo.szBuildDate);
USART_Printf(0, "buildTime: %s\r\n", sg_tAppInfo.szBuildTime);
USART_Printf(0, "commitId: %s\r\n\r\n", sg_tAppInfo.szCommitId); while(1);
}

4. 提交git编译后,可以看的 git commit id 值(通过 git commit 可以迅速定位是什么时候的源码进行编译的)

3.3 固件打包

下载固件打包脚本,根据配置设置后,双击 bat 即可完成固件打包,然后点击下载验证即可。

需要通过 J-LINK 工具包或者 ST-Link 工具打开生成的固件进行烧录(通过Keil编译直接下载的没有用,我这里用的是 ST-Link 工具)。


4 配置文件内容

下面列举配置文件中的选项

; 文中的路径可采用绝对路径或者相对路径(相对于固件打包bat文件而言)
; 版本信息 Flash 起始地址 预留大小 前缀字符串
[version]
addr=0x08002000
size=32
strPrefix= ; Git 信息 Flash 起始地址 预留大小
[git_commit]
addr=0x08002060
size=32 [boot_file]
; Boot Hex 文件路径 文件名称
hexFilePath=.\
hexFileName=test_boot [file]
; Hex 文件路径 文件名称
hexFilePath=.\
hexFileName=test ; 裁剪起始地址 保留大小
hexFileAddr=0x08000000
hexFileSize=0xFFFF ; 打包文件的输出路径
outputPath=.\output [option]
; 是否合并boot固件
isMergeBootHexFile=0 ; 是否生成 Bin 文件
isGenerateBin=1 ; 是否裁剪 Hex 文件,根据(hexFileAddr hexFileSize)
isCropHexFile=1 ; 是否添加 Git Commit 信息
isAddGitCommit=0 ; 打包成功后是否清除临时文件
isClearTmpFile=1

5 下载地址

MCU固件打包脚本

单片机 MCU 固件打包脚本软件的更多相关文章

  1. 机械臂——arduino、marlin固件、printrun软件【转】

    最近了解到,在市面上大多数机械臂控制都采用的arduino这个开源硬件来控制的,而我发现既然会单片机,就没有必要采用arduino来控制了,arduino只是一种为了简化编程而开发一种软硬件控制平台, ...

  2. ADAS处理器集成功能安全单片机MCU

    ADAS处理器集成功能安全单片机MCU ADAS processors integrate functional safety MCU 拉斯维加斯-德州仪器公司引进了ADAS和网关处理器TDA4VM和 ...

  3. xcode8.3 shell 自动打包脚本 记录

    题记 xcode升级8.3后发现之前所用的xcode自动打包基本无法使用,因此在网上零碎找到些资料,将之前的脚本简化.此次脚本是基于xcode证书配置进行打包(之前是指定描述文件.相对繁琐).因此代码 ...

  4. Linux下Maven+SVN自动打包脚本

        公司的开发环境每次部署项目都很麻烦,需要手动打包并上传上去.这个太麻烦了,所以就准备搞个自动打包的脚本.脚本自动从svn代码库里面更新最新的代码下来,然后maven打包,最后把war包丢到to ...

  5. 安全模式下卸载windows installer打包的软件(转)

    安全模式下卸载windows installer打包的软件 起因: 主机系统MAC,虚拟软件Parallels Desktop, 虚拟系统 Win 7. 今天在虚拟机WIN7里面安装了某个软件导致重启 ...

  6. assetBundle打包脚本与LUA

    AssetBundles与脚本 所有Unity的AssetBundle,无论是从本地获取 还是www,或者打包整个场景.物体上的脚本都不会被编译.所以AssetBundle打包的时候即使物体上有脚本. ...

  7. React Native开发中自动打包脚本

    React Native开发中自动打包脚本 在日常的RN开发中,我们避免不了需要将我们编写的代码编译成安装包,然后生成二维码,供需要测试的人员扫描下载.但是对于非原生的开发人员来说,可能不知如何使用X ...

  8. xcode8.3 shell 自动打包脚本

    题记 xcode升级8.3后发现之前所用的xcode自动打包基本无法使用,因此在网上零碎找到些资料,将之前的脚本简化.此次脚本是基于xcode证书配置进行打包(之前是指定描述文件.相对繁琐).因此代码 ...

  9. TPM:dTPM(硬件)和fTPM(固件模拟的软件模块)

    转:Bitlocker.TPM和系统安全 自从微软在Windows Vista首次引入Bitlocker以来,它已经越来越多的出现在我们的周围.尤其是企业用户,Bitlocker的保护已经变得不可缺少 ...

随机推荐

  1. 【面试普通人VS高手系列】HashMap是怎么解决哈希冲突的?

    常用数据结构基本上是面试必问的问题,比如HashMap.LinkList.ConcurrentHashMap等. 关于HashMap,有个学员私信了我一个面试题说: "HashMap是怎么解 ...

  2. java class 文件格式解析

    前言 大约5年前,想研究javaassistant,cglib等字节码操作的相关类库,来对class进行增强,当要到要操作字节码的时候,发现无法继续下去了,只能放弃. 学习jvm字码,需要理解clas ...

  3. 接口测试框架实战(一) | Requests 与接口请求构造

    1080×388 33.4 KB Requests 是一个优雅而简单的 Python HTTP 库,其实 Python 内置了用于访问网络的资源模块,比如urllib,但是它远不如 Requests ...

  4. 记一次MySQL数据迁移到SQLServer全过程

    为什么要做迁移? 由于系统版本.数据库的升级,导致测试流程阻塞,为了保证数据及系统版本的一致性,我又迫切需要想用这套环境做性能测试,所以和领导.开发请示,得到批准后,便有了这次学习的机会,所以特此来记 ...

  5. 基于Koa与umi实现服务端(SSR)渲染

    工具: umijs:react前端应用框架. koa:基于 Node.js 平台的web 开发框架. 介绍: 本文主要是简单介绍,利用umi开发前端页面,打包成服务端渲染工程包.由Koa实现服务端渲染 ...

  6. 《手把手教你》系列基础篇(九十六)-java+ selenium自动化测试-框架之设计篇-跨浏览器(详解教程)

    1.简介 从这一篇开始介绍和分享Java+Selenium+POM的简单自动化测试框架设计.第一个设计点,就是支持跨浏览器测试. 宏哥自己认为的支持跨浏览器测试就是:同一个测试用例,支持用不同浏览器去 ...

  7. Kubernetes容器之间的通信浅谈

    公众号关注 「开源Linux」 回复「学习」,有我为您特别筛选的学习资料~ 作者: Matt Zand 和 Jim Sullivan 译者: 穿过生命散发芬芳F Kubernetes是一个容器化的解决 ...

  8. 详谈:pNFS增强文件系统架构

    点击上方"开源Linux",选择"设为星标" 回复"学习"获取独家整理的学习资料! 通过 NFS(由服务器.客户机软件和两者之间的协议组成) ...

  9. 干货 | LVM快照学习

    一个执着于技术的公众号 前言 在上一章节,我们学习了LVM逻辑卷管理技术,知道了LVM能够通过增减PE的数量来弹性调整文件系统的大小.除此之外,LVM还有另一个重要功能「LVM快照技术」,也就是可以给 ...

  10. 使用NFS作为Glance存储后端

    NFS服务介绍 NFS网络文件系统提供了一种在类UNIX系统上共享文件的方法.目前NFS有3个版本:NFSv2.NFSv3.NFSv4.CentOS7默认使用NFSv4提供服务,优点是提供了有状态的连 ...