搜索
bottom↓
回复: 93

[分享]一个小技巧在SMT32程序HEX文件中加入固件版本信息

  [复制链接]

出0入0汤圆

发表于 2020-6-28 13:10:41 | 显示全部楼层 |阅读模式
本帖最后由 icode 于 2020-6-28 17:01 编辑

分享一个小技巧,使用MDK编译器,让STM32程序HEX文件中加入固件版本信息,估计很多老手都已经在使用(你有好的方法欢迎分享,希望我的砖能引来你的玉),该方法献给新手或初学者。
代码如下:(已更新!!! 根据5楼坛友 wudicgi 建议更新, 之前没想到常量字符串还可以这样连接...^|^...),使用的一些细节问题见 [14楼]
  1. //------------------------------------------------------------------------------
  2. #include <absacc.h>

  3. //------------------------------------------------------------------------------
  4. #define VERINFO_ADDR_BASE   (0x8009F00) // 版本信息在FLASH中的存放地址
  5. const char Hardware_Ver[] __attribute__((at(VERINFO_ADDR_BASE + 0x00)))  = "Hardware: 1.0.0";
  6. const char Firmware_Ver[] __attribute__((at(VERINFO_ADDR_BASE + 0x20)))  = "Firmware: 1.0.0";
  7. const char Compiler_Date[] __attribute__((at(VERINFO_ADDR_BASE + 0x40))) = "Date: "__DATE__;
  8. const char Compiler_Time[] __attribute__((at(VERINFO_ADDR_BASE + 0x60))) = "Time: "__TIME__;

  9. //------------------------------------------------------------------------------
复制代码


选项配置中:Flash地址与大小不用做任何修改!


HEX文件:


串口打印输出:





本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入12汤圆

发表于 2020-11-14 22:23:05 | 显示全部楼层
谢谢分享,正要用到

出0入0汤圆

发表于 2020-11-14 18:06:59 | 显示全部楼层
很实用,先收藏

出0入0汤圆

发表于 2020-8-26 15:13:16 | 显示全部楼层
icode 发表于 2020-8-26 14:35
用J-Flash,STVP,WinHex等等,任何一个烧写工具都可以,左边显示HEX值,右侧显示的ASCII字符,这样就能 ...

好的 谢谢    另外问一下   boot里面读固件信息   直接读那个指定地址的数据就行了  是吧

出0入0汤圆

 楼主| 发表于 2020-8-26 14:35:50 | 显示全部楼层
Years丶 发表于 2020-8-26 14:21
编译完的hex是用 winhex查看的嘛?  为啥我这看不到定义的版本信息

用J-Flash,STVP,WinHex等等,任何一个烧写工具都可以,左边显示HEX值,右侧显示的ASCII字符,这样就能比较直观的看到HEX文件具体信息了

出0入0汤圆

发表于 2020-8-26 14:21:45 | 显示全部楼层
编译完的hex是用 winhex查看的嘛?  为啥我这看不到定义的版本信息

出0入0汤圆

发表于 2020-7-23 16:15:08 | 显示全部楼层
楼主这办法真香,感谢分享。

出0入0汤圆

发表于 2020-7-21 21:02:13 | 显示全部楼层
很实用,谢谢分享

出0入0汤圆

发表于 2020-7-18 22:04:27 | 显示全部楼层
收藏,感谢分享

出0入0汤圆

发表于 2020-7-17 16:29:06 | 显示全部楼层
很好的功能呀

出0入0汤圆

发表于 2020-7-16 12:15:40 | 显示全部楼层
我们也是这样子的,只是没有固定地址,在程序中定义一个固定字符串,在IAP升级软件中,搜索固定字符串,并修改为IAP升级的时间,这样子,就可以加入实时的IAP升级时间。

出50入0汤圆

发表于 2020-7-16 09:03:56 来自手机 | 显示全部楼层
学习下,谢谢分享!

出0入0汤圆

发表于 2020-7-16 08:16:00 | 显示全部楼层
很实用,谢谢分享

出0入0汤圆

发表于 2020-7-16 00:04:21 | 显示全部楼层
很实用,先收藏

出0入0汤圆

发表于 2020-7-10 11:01:09 | 显示全部楼层
多谢分享。

出0入8汤圆

发表于 2020-7-10 08:48:59 | 显示全部楼层
以前都有用,只能固定一个位置或者不固定,一直没法自动在后面加,看看有没有更好的办法

出0入0汤圆

发表于 2020-7-9 08:58:57 来自手机 | 显示全部楼层
不错!学习了!

出0入0汤圆

发表于 2020-7-9 08:15:27 | 显示全部楼层
这种固定编译,如果放在程序的前面一点,会比较占空间~

出0入0汤圆

发表于 2020-7-8 17:56:56 | 显示全部楼层
收藏一下,有空测试一下

出0入4汤圆

发表于 2020-7-8 14:07:07 | 显示全部楼层
严重搜藏,感谢!

出0入0汤圆

 楼主| 发表于 2020-7-1 11:10:43 | 显示全部楼层
252514251 发表于 2020-7-1 10:56
主要是怕自己给的地址不合适
不给固定地址,只能加特征值,用的时候从hex文件中搜索出来 ...

只要你不放在最最最...前面把中断向量的地址给占了,一般没什么问题, 如果还是不放心:可以让它紧跟在程序使用空间的后面(这个地址要自己算一下)  或者 放在FLASH空间的末尾处。

出0入0汤圆

发表于 2020-7-1 10:56:06 | 显示全部楼层
icode 发表于 2020-6-30 22:25
使用指定地址与让编译器自动分配本质没什么太大的区别, 但指定地址会更加方便一,比如:
1) 一打开HEX文 ...

主要是怕自己给的地址不合适
不给固定地址,只能加特征值,用的时候从hex文件中搜索出来

出0入0汤圆

发表于 2020-7-1 08:08:47 | 显示全部楼层
固件版本信息还能这么用啊,感谢

出0入0汤圆

发表于 2020-7-1 06:34:15 来自手机 | 显示全部楼层
干货实用

出0入0汤圆

发表于 2020-7-1 06:34:15 来自手机 | 显示全部楼层
干货实用

出0入0汤圆

发表于 2020-6-30 22:54:26 来自手机 | 显示全部楼层
谢谢分享

出0入0汤圆

 楼主| 发表于 2020-6-30 22:25:18 | 显示全部楼层
252514251 发表于 2020-6-30 17:04
固定位置感觉不是很好,我喜欢做个特征值由编译器分配到flash,使用的时候搜索出来 ...

使用指定地址与让编译器自动分配本质没什么太大的区别, 但指定地址会更加方便一,比如:
1) 一打开HEX文件就能很方便的看到程序的版本信息。
2) 使用工具会很方便的识别到HEX的版本信息(比如用自己的下载工具,一些加密处理的HEX)。
3) 一些带IAP功能的程序,在boot程序中也可以很方便的去读取FLASH中当前APP的版本信息。


出0入0汤圆

发表于 2020-6-30 17:04:27 | 显示全部楼层
本帖最后由 252514251 于 2020-6-30 17:06 编辑

固定位置感觉不是很好,我喜欢做个特征值由编译器分配到flash,使用的时候搜索出来

出0入0汤圆

发表于 2020-6-30 17:01:55 | 显示全部楼层
这个不错,不用手动输入。

出0入0汤圆

发表于 2020-6-30 14:29:58 | 显示全部楼层
看了大家的讨论,又学习了。先前也用到了__DATE__ 和 __TIME__,但没有放到指定位置。如果需要在boot中去读取版本信息,还是放在固定位置,并且在程序文件头的位置还是很/方便的。
INT32U year = ((__DATE__[7]-'0')*1000 + (__DATE__[8]-'0')*100 + (__DATE__[9]-'0')*10 + (__DATE__[10]-'0'));
INT32U month = ((MONTH_IS_JAN) ? 1 :(MONTH_IS_FEB) ? 2 :(MONTH_IS_MAR) ? 3 :(MONTH_IS_APR) ? 4 :(MONTH_IS_MAY) ? 5 :(MONTH_IS_JUN) ? 6 :(MONTH_IS_JUL) ? 7 :\
                (MONTH_IS_AUG) ? 8 :(MONTH_IS_SEP) ? 9 :(MONTH_IS_OCT) ? 10 :(MONTH_IS_NOV) ? 11 :(MONTH_IS_DEC) ? 12 : 0);
INT32U day = (((__DATE__[4]>'0')?__DATE__[4]:'0')-'0')*10 + (__DATE__[5]-'0');
char* time = __TIME__;
time = time;
char* date = __DATE__;
date = date;
char strDatetime[32];
sprintf(strDatetime, "XXX:" __DATE__ " " __TIME__ "");

出0入4汤圆

发表于 2020-6-30 10:26:35 | 显示全部楼层
可以放在前面,但是不能最前面,比如stm32 最开始就是堆栈位置和中断向量表。 可以在起始位置+0x400之类的(偏移1K)样子。比如#define VERINFO_ADDR_BASE   (0x8000400) // 版本信息在FLASH中的存放地址,编译器会自动利用和剩余空间。也不会扩大bin文件。

出0入0汤圆

发表于 2020-6-29 22:44:49 | 显示全部楼层
实用好方法,谢谢分享

出0入0汤圆

发表于 2020-6-29 22:35:31 来自手机 | 显示全部楼层
真很实用,谢谢分享

出0入0汤圆

发表于 2020-6-29 22:11:44 来自手机 | 显示全部楼层
感谢楼主分享

出0入0汤圆

发表于 2020-6-29 21:27:58 | 显示全部楼层
谢谢,收藏了,这个很好

出0入0汤圆

发表于 2020-6-29 21:12:27 | 显示全部楼层
谢谢,收藏了,这个很好

出0入0汤圆

发表于 2020-6-29 19:23:19 | 显示全部楼层
打个记号,学习一下

出0入0汤圆

发表于 2020-6-29 15:52:42 | 显示全部楼层
扔一个IAR的吧,作为备注


  1. /** IAR **/
  2. #define VERINFO_ADDR_BASE   (0x8009F00) // 版本信息在FLASH中的存放地址

  3. // 在最後一頁的首字節寫入FLASH截至數據
  4. __root  char Hardware_Ver[]@(VERINFO_ADDR_BASE + 0x00)  = "Hardware: 1.0.0";;
  5. __root  char Firmware_Ver[]@(VERINFO_ADDR_BASE + 0x20)  = "Firmware: 1.0.0";
  6. __root  char Compiler_Date[]@(VERINFO_ADDR_BASE + 0x40) = "Date: "__DATE__;
  7. __root  char Compiler_Time[]@(VERINFO_ADDR_BASE + 0x60) = "Time: "__TIME__;
复制代码

出0入0汤圆

发表于 2020-6-29 15:46:45 | 显示全部楼层
xiaomu 发表于 2020-6-28 15:59
不是hex文件, 是bin 文件,烧录器烧录一般都是把hex文件解析成bin文件再烧录的,
只要有数据放到最后, ...

懂了,所以还是放在开始,偏移1K的位置

出0入34汤圆

发表于 2020-6-29 14:43:59 | 显示全部楼层
楼主的这个好,早期只会用那 Date 与 Time 的,而版本号直接给放入 const 内让程序调用,可以由使用者操作显示出当前版本号就好,看了看貌似放入指定的实体位址是更方便些。

出0入0汤圆

发表于 2020-6-29 14:33:28 | 显示全部楼层
学习了,谢谢分享

出0入8汤圆

发表于 2020-6-29 14:08:05 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2020-6-29 13:33:22 | 显示全部楼层
学习了,以后写代码可以加上去

出0入0汤圆

发表于 2020-6-29 13:28:43 | 显示全部楼层
不错,收藏一下

出0入8汤圆

发表于 2020-6-29 10:43:26 | 显示全部楼层
单独写成一个C文件,然后编辑分散加载文件。这样可能更好。

出0入0汤圆

发表于 2020-6-29 10:38:22 | 显示全部楼层
chensi007 发表于 2020-6-28 14:04
楼主这个好。
我也做过类似的。我只是把编译日期和时间放了进去。且位置不固定要用WINHEX去搜

也是做电动工具的哦

出0入0汤圆

发表于 2020-6-29 10:23:49 | 显示全部楼层
谢谢分享。。。

出0入4汤圆

发表于 2020-6-29 09:19:59 | 显示全部楼层
时间 版本号还是很有必要的

出0入0汤圆

发表于 2020-6-29 09:05:12 | 显示全部楼层
可以printf()直接输出,办法不错。

出0入0汤圆

发表于 2020-6-29 09:04:04 | 显示全部楼层
arris9 发表于 2020-6-28 21:55
这里面可以加时间吗

cortex内核的MCU就空了,16BYTES的空间,自己发挥,

出0入0汤圆

发表于 2020-6-29 09:02:31 | 显示全部楼层
vjcmain 发表于 2020-6-28 20:54
如何能放到最前面? 这样用外部工具就可以读取bin格式固件的信息了。

不用放在最前面,bin文件偏移28就是版本信息。

出0入0汤圆

发表于 2020-6-29 09:00:34 | 显示全部楼层
icode 发表于 2020-6-28 22:37
看了一下你这个本质应该是差不多的, (uint32_t)Image$$ER_IROM1$$RO$$Base)+28,通过Linker把地址算好的 ...


一般通过boot升级时,都是用的bin文件, bin文件偏移28就是版本信息所在的位置

出1310入193汤圆

发表于 2020-6-29 08:12:05 | 显示全部楼层
c标准指令   在c51时代就有这么干的

出0入0汤圆

发表于 2020-6-29 07:49:53 | 显示全部楼层
icode 发表于 2020-6-28 15:26
是的, 程序末尾 到 VERINFO_ADDR_BASE地址这一段会被填充成0x00, 根据需要可以修改 VERINFO_ADDR_BASE  ...

不强制指定地址,  由编译器自动分配,如果想这样,请问怎么操作

出0入0汤圆

 楼主| 发表于 2020-6-28 22:37:36 | 显示全部楼层
jjj 发表于 2020-6-28 17:34
砸场子的来了,
startup_stm32xxx.s 中这个位置修改如下:
__Vectors       DCD     __initial_sp          ...

看了一下你这个本质应该是差不多的, (uint32_t)Image$$ER_IROM1$$RO$$Base)+28,通过Linker把地址算好的, 与直接指定地址是差不多的
同理:要在boot获取当前APP的版本信息, 直接去读取FLASH中指定位置的版本信息即可

出0入0汤圆

发表于 2020-6-28 22:25:37 | 显示全部楼层
m学习了  实用

出0入0汤圆

 楼主| 发表于 2020-6-28 21:58:05 | 显示全部楼层
arris9 发表于 2020-6-28 21:50
如何确保你写的地址不会被编译的程序覆盖

这个是放在FLASH中指定位置的常量,编译器会自动避开的

出0入0汤圆

发表于 2020-6-28 21:55:11 | 显示全部楼层
jjj 发表于 2020-6-28 17:34
砸场子的来了,
startup_stm32xxx.s 中这个位置修改如下:
__Vectors       DCD     __initial_sp          ...

这里面可以加时间吗

出0入0汤圆

发表于 2020-6-28 21:50:57 | 显示全部楼层
如何确保你写的地址不会被编译的程序覆盖

出0入0汤圆

 楼主| 发表于 2020-6-28 21:38:56 | 显示全部楼层
vjcmain 发表于 2020-6-28 20:54
如何能放到最前面? 这样用外部工具就可以读取bin格式固件的信息了。

你把 VERINFO_ADDR_BASE 设置到前面的地址即可,例如:0x8000200 // 注意不要占用中断向量地址!!!

出0入0汤圆

发表于 2020-6-28 21:27:48 | 显示全部楼层
学习了,非常实用。

出0入0汤圆

发表于 2020-6-28 21:09:50 | 显示全部楼层
学习了,一直没有好的方法来处理这问题

出0入0汤圆

发表于 2020-6-28 20:54:45 | 显示全部楼层
如何能放到最前面? 这样用外部工具就可以读取bin格式固件的信息了。

出0入0汤圆

发表于 2020-6-28 20:35:05 | 显示全部楼层
jjj 发表于 2020-6-28 17:34
砸场子的来了,
startup_stm32xxx.s 中这个位置修改如下:
__Vectors       DCD     __initial_sp          ...

丢进去编译会报错哦,
../Application/main.c(13): error: use of undeclared identifier 'Image$$ER_IROM1$$RO$$Base'
uint32_t * p_ver=(uint32_t*)(((uint32_t)Image$$ER_IROM1$$RO$$Base)+28);
                                        ^
../Application/main.c(14): error: initializer element is not a compile-time constant
        float        ver_hard=(*p_ver>>16)/1000.0f;
                              ~~~~~~~~~~~~^~~~~~~~
../Application/main.c(15): error: initializer element is not a compile-time constant

出0入0汤圆

发表于 2020-6-28 20:16:29 | 显示全部楼层
很不错哦,谢谢楼主,实用

出0入0汤圆

发表于 2020-6-28 17:53:44 | 显示全部楼层
这个技巧不错啊,学习了,感谢楼主的分享

出0入0汤圆

发表于 2020-6-28 17:34:05 | 显示全部楼层
本帖最后由 jjj 于 2020-6-28 18:51 编辑

砸场子的来了,
startup_stm32xxx.s 中这个位置修改如下:
__Vectors       DCD     __initial_sp               ; Top of Stack
                DCD     Reset_Handler              ; Reset Handler
                DCD     NMI_Handler                ; NMI Handler
                DCD     HardFault_Handler          ; Hard Fault Handler
                DCD     MemManage_Handler          ; MPU Fault Handler
                DCD     BusFault_Handler           ; Bus Fault Handler
                DCD     UsageFault_Handler         ; Usage Fault Handler
                DCD     0x03E803E9                          ; Reserved soft version
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved
                DCD     0                          ; Reserved

应用程序中增加如下:
        uint32 * p_ver=(uint32*)(((uint32_t)Image$$ER_IROM1$$RO$$Base)+28);
        float        ver_hard=(*p_ver>>16)/1000.0f;
        float        ver_soft=(*p_ver&0x0000FFFF)/1000.0f;
        printf("HARD VER:        V%.3f\r\nSOFT VER:        V%.3f \r\n", ver_hard , ver_soft); //打印版本信息

这样做的好处是在boot中也能轻易的获得APP的版本。

出0入4汤圆

发表于 2020-6-28 17:25:17 | 显示全部楼层
又学了一招 ,下次试试

出0入0汤圆

 楼主| 发表于 2020-6-28 17:13:52 | 显示全部楼层
shiva_shiva 发表于 2020-6-28 17:06
这样岂不是编译一次crc变一下

只要这个几版本常量所在的文件没变动过 或者 程序没有 build all, 编译的日期时间标识符就不会变化


出0入0汤圆

发表于 2020-6-28 17:06:42 | 显示全部楼层
这样岂不是编译一次crc变一下

出0入0汤圆

 楼主| 发表于 2020-6-28 16:58:25 | 显示全部楼层
hall 发表于 2020-6-28 16:50
有没有办法把这些信息放到前面的?不用必须最前面,但是最好一打开hex文件在第一页就能看到的。 ...

可以的,但是不能去把中断向量的那部分地址给占了哈

  

出0入0汤圆

 楼主| 发表于 2020-6-28 16:51:05 | 显示全部楼层
meirenai 发表于 2020-6-28 16:48
我一般都是把git的版本信息自动添加到bin文件里面

这方法也不错, 不过可能要使用工具或者脚本程序了

出110入12汤圆

发表于 2020-6-28 16:50:13 | 显示全部楼层
有没有办法把这些信息放到前面的?不用必须最前面,但是最好一打开hex文件在第一页就能看到的。

出0入0汤圆

发表于 2020-6-28 16:48:07 | 显示全部楼层
我一般都是把git的版本信息自动添加到bin文件里面

出0入0汤圆

发表于 2020-6-28 16:46:01 | 显示全部楼层
之前用过code的,把它放在全局变量前面,还是这个好

出0入0汤圆

发表于 2020-6-28 16:24:15 | 显示全部楼层
不错,多谢楼主分享,非常实用。

出0入0汤圆

 楼主| 发表于 2020-6-28 16:16:56 | 显示全部楼层

IAR没有试过,不过应该是可以的,方法思路是差不多的。

出0入0汤圆

发表于 2020-6-28 16:07:09 | 显示全部楼层
IAR可以吗?

出0入0汤圆

发表于 2020-6-28 15:59:41 | 显示全部楼层
icode 发表于 2020-6-28 15:26
是的, 程序末尾 到 VERINFO_ADDR_BASE地址这一段会被填充成0x00, 根据需要可以修改 VERINFO_ADDR_BASE  ...

不是hex文件, 是bin 文件,烧录器烧录一般都是把hex文件解析成bin文件再烧录的,
只要有数据放到最后,就会生成最大的bin文件,这样不管中间你空多少空间,烧录器都会按照最大的地址空间写入。

出0入42汤圆

发表于 2020-6-28 15:46:25 | 显示全部楼层
不错!,谢谢分享

出0入0汤圆

 楼主| 发表于 2020-6-28 15:39:54 | 显示全部楼层
wudicgi 发表于 2020-6-28 15:17
现在 LZ 位的代码有点问题,少空格了
另外这么放一块的话,printf() 输出的时候貌似就比较别扭了

LZ位上更新的代码复制粘贴上去的,应该没问题的(测试过了的)
大佬分享的这个不错哈

出0入0汤圆

 楼主| 发表于 2020-6-28 15:26:04 | 显示全部楼层
本帖最后由 icode 于 2020-6-28 16:14 编辑
xiaomu 发表于 2020-6-28 14:58
这样可以, 但是有一个缺点,就是生成的bin文件都是满flash大小的, 造成每次烧录都是整个flash读写。

其 ...

是的, 程序末尾 到 VERINFO_ADDR_BASE地址这一段会被填充成0x00, 根据需要可以修改 VERINFO_ADDR_BASE 减小地址 或者说 不强制指定地址,  由编译器自动分配, 但这样就要去找相应的版本标识字符串了。
不想前面这一段被大量填充0x00,让HEX文件体积小一点的话, 可以把选项配置中Flash的Size改小一点,把VERINFO_ADDR_BASE设置成从FlashSize后面的空间开始,这样生成的HEX文件就小了,且未用空间就不会被大量填充0x00了。
方法如下:




本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2020-6-28 15:17:06 | 显示全部楼层
icode 发表于 2020-6-28 14:55
感谢你的分享, 之前没想到常量字符串还可以这样连接

现在 LZ 位的代码有点问题,少空格了
另外这么放一块的话,printf() 输出的时候貌似就比较别扭了

觉得 __DATE__ 的格式不好的话,还可以像下面这个代码一样,自己重新组合其中的字符
https://github.com/Samsung/mTower/blob/master/tools/fwinfogen.c

  1. /* Pre-processor Definitions. */
  2. #define BUILD_MONTH_IS_JAN (__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n')
  3. #define BUILD_MONTH_IS_FEB (__DATE__[0] == 'F')
  4. #define BUILD_MONTH_IS_MAR (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r')
  5. #define BUILD_MONTH_IS_APR (__DATE__[0] == 'A' && __DATE__[1] == 'p')
  6. #define BUILD_MONTH_IS_MAY (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y')
  7. #define BUILD_MONTH_IS_JUN (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n')
  8. #define BUILD_MONTH_IS_JUL (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l')
  9. #define BUILD_MONTH_IS_AUG (__DATE__[0] == 'A' && __DATE__[1] == 'u')
  10. #define BUILD_MONTH_IS_SEP (__DATE__[0] == 'S')
  11. #define BUILD_MONTH_IS_OCT (__DATE__[0] == 'O')
  12. #define BUILD_MONTH_IS_NOV (__DATE__[0] == 'N')
  13. #define BUILD_MONTH_IS_DEC (__DATE__[0] == 'D')

  14. #define BUILD_MONTH \
  15.     ( \
  16.         (BUILD_MONTH_IS_JAN) ? 1 : \
  17.         (BUILD_MONTH_IS_FEB) ? 2 : \
  18.         (BUILD_MONTH_IS_MAR) ? 3 : \
  19.         (BUILD_MONTH_IS_APR) ? 4 : \
  20.         (BUILD_MONTH_IS_MAY) ? 5 : \
  21.         (BUILD_MONTH_IS_JUN) ? 6 : \
  22.         (BUILD_MONTH_IS_JUL) ? 7 : \
  23.         (BUILD_MONTH_IS_AUG) ? 8 : \
  24.         (BUILD_MONTH_IS_SEP) ? 9 : \
  25.         (BUILD_MONTH_IS_OCT) ? 16 : \
  26.         (BUILD_MONTH_IS_NOV) ? 17 : \
  27.         (BUILD_MONTH_IS_DEC) ? 18 : \
  28.         /* error default */    0 \
  29.     )

  30. #define BUILD_DAY_CH0 ((__DATE__[4] >= '0') ? (__DATE__[4]) : '0')
  31. #define BUILD_DAY_CH1 (__DATE__[ 5])

  32. #define DATE_COMPILE  (((__DATE__[7] - '0') << 28) \
  33.     | (((unsigned int)(__DATE__[8] - '0')) << 24) \
  34.     | (((unsigned int)(__DATE__[9] - '0')) << 20) \
  35.     | (((unsigned int)(__DATE__[10] - '0')) << 16) \
  36.     | (((unsigned int)(BUILD_MONTH)) << 8) \
  37.     | (((unsigned int)(((__DATE__[4] >= '0') ? (__DATE__[4]) : '0') - '0')) << 4) \
  38. | (((unsigned int)__DATE__[5] - '0')))
复制代码

出0入0汤圆

发表于 2020-6-28 14:58:01 | 显示全部楼层
这样可以, 但是有一个缺点,就是生成的bin文件都是满flash大小的, 造成每次烧录都是整个flash读写。

其实这个可以把存放地址放到前面,比如偏移1K的地方,都不用改指定地址

出20入25汤圆

发表于 2020-6-28 14:57:31 | 显示全部楼层
chensi007 发表于 2020-6-28 14:04
楼主这个好。
我也做过类似的。我只是把编译日期和时间放了进去。且位置不固定要用WINHEX去搜

曾经我想把日期加到FPGA里,怎么都没找到,现在有方法嘛,Xlinx的FPGA

出0入0汤圆

 楼主| 发表于 2020-6-28 14:55:15 | 显示全部楼层
wudicgi 发表于 2020-6-28 14:19
"Date: " __DATE__ 就可以了,字符串常量编译时可以连接

感谢你的分享, 之前没想到常量字符串还可以这样连接



出0入0汤圆

发表于 2020-6-28 14:49:34 | 显示全部楼层
以前我们是直接手动在文件尾部加

出0入13汤圆

发表于 2020-6-28 14:43:44 | 显示全部楼层
真的很实用,谢谢分享

出0入0汤圆

发表于 2020-6-28 14:35:26 | 显示全部楼层
这个很好,很实用,可以用一用

出0入0汤圆

发表于 2020-6-28 14:21:29 | 显示全部楼层
非常实用,又学了一招

出0入0汤圆

发表于 2020-6-28 14:19:13 | 显示全部楼层
"Date: " __DATE__ 就可以了,字符串常量编译时可以连接

出0入12汤圆

发表于 2020-6-28 14:10:20 | 显示全部楼层
这个不错,很实用~~~!

出0入0汤圆

发表于 2020-6-28 14:04:19 | 显示全部楼层
楼主这个好。
我也做过类似的。我只是把编译日期和时间放了进去。且位置不固定要用WINHEX去搜

    volatile unsigned char const DataStr[]=__DATE__;
    volatile unsigned char const TimeStr[]=__TIME__;
      
   #if (TOOL_TYPE == WRENCH)
         # warning "这时候编译的是电扳手!!!!"
    volatile unsigned char const ToolTypeStr[]="WRENCH" ;

出0入0汤圆

发表于 2020-6-28 13:23:17 | 显示全部楼层
这个不错,很实用~~~!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 16:16

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表