查看: 17027|回复: 57

[分享] 飞思卡尔基于串口升级教程(Boot & Reboot)

  [复制链接]

该用户从未签到

7

主题

25

帖子

0

注册会员

Rank: 2

积分
126
最后登录
2021-4-8
发表于 2015-5-4 15:14:02 | 显示全部楼层 |阅读模式
本帖最后由 梁子 于 2015-5-5 09:45 编辑

网页看着不方便,可以下载PDF,如果文章有问题,可以跟帖或私信!

序:
关于系统的讲解飞思卡尔升级的文章,比较少,也比较零碎,对于新手来说,可能整了半天还一头雾水,还不知道错在哪里,几年前我就是这样,用了一周多的时间,终于搞定了,现在在坛子里还有人问我一些关于升级的问题,时间有限,没办法及时答复,甚至选择了不回复。
为了坛子,为了新手,为了抛砖引玉,这里抽时间写一下本例程。

一、关于升级
    本文以MCF51JM128芯片,对飞思卡尔(专家系统)实现基于串口的升级方法(Boot数据包大小为1K字节,串口配置96N81)。
    也是最近要做的东西,因此边做边整理,以供大家学习参考,少走弯路,尽快掌握Boot程序编程方法和主程序的注意事项。
    因为飞思卡尔芯片的继承性比较好,因此本文讲述的内容,差不多可以应用、移植到飞思卡尔全系列芯片。
    同时大家不要认为基于串口升级的程序,不能作为基于CAN等方式的升级程序,基于串口只是其中一条路,完全可以在此基础上做成基于CAN、SPI、I2C、甚至是1BUS的Boot程序。
二、硬件平台
    MCF51JM128VLD,串口1(串口2也可以,本文以串口1为例);
三、软件平台
    CodeWarriorfor ColdFire V6.3(V6.2也可,V10.x也可)
四、S19文件格式详解(原文来自网络,这里为方便查看,进行了一定的整理)
    做为下位机程序员来说,如果你有一个好的上位机软件,对S19文件则不需要过多的理解和掌握,上位机软件会先对S19文件进行整理,再发给下位机,上、下位机两人搞明白各自的工作即可,但你将永远都是普通程序员了,呵呵;
    对于S19文件,可以先略过,当看完下一节时,再回头看这段,印象会更深刻!也可现用现看,记忆力好的就另说了。
S-record格式文件是Freescale CodeWarrior编译器生成的后缀名为.S19的程序文件,是一段直接烧写进MCU的ASCII码,英文全称问Motorolaformat for EEPROM programming。
上面“是一段直接烧写进MCU的ASCII码”,这样说可能会误导初学者,因为并不是直接将ASCII码写进MCU,写进MCU前还要对S19文件进行一个解析,把有用的机器代码分解出来,然后再进行写入,写入的也不是ASCII而是二进制码。
1、格式定义及含义
S-record每行最大是78个字节,156个字符
S-record 格式:
  
Type
  
Count
Address
Data
Checksum
1)、Type(类型):2个字符。用来描述记录的类型(S0,S1,S2,S3,S5,S7,S8,S9)。
S0 Record记录类型是“S0” (0x5330)。地址场没有被用,用零置位(0x0000)。此行表示程序的开始,不需烧入memory。
数据场中的信息被划分为以下四个子域:
  
Name
  
Ver
Rev
Description
Name(名称):20个字符,用来编码单元名称;
Ver(版本):2个字符,用来编码版本号;
Rev(修订版本):2个字符,用来编码修订版本号;
Description(描述):0-36个字符,用来编码文本注释;
S1 Record记录类型是“S1” (0x5331)。地址场由2个字节地址来说明。数据场由可载入的数据组成。
S2 Record记录类型是“S2” (0x5332)。地址场由3个字节地址来说明。数据场由可载入的数据组成。
S3 Record记录类型是“S3” (0x5333)。地址场由4个字节地址来说明。数据场由可载入的数据组成。
S5 Record记录类型是“S5” (0x5335)。地址场由2字节的值说明,包含了先前传输的S1、S2、S3记录的计数。没有数据场。
S7 Record记录类型是“S7” (0x5337)。地址场由4字节的地址说明,包含了开始执行地址。没有数据场。此行表示程序的结束,不需烧入memory。
S8 Record记录类型是“S8” (0x5338)。地址场由3字节的地址说明,包含了开始执行地址。没有数据场。此行表示程序的结束,不需烧入memory。
S9 Record记录类型是“S9” (0x5339)。地址场由2字节的地址说明,包含了开始执行地址。没有数据场。此行表示程序的结束,不需烧入memory。
根据不同的描述信息,在以上三种不同的结束行中选择一种使用。

2)、Count(计数):2个字符。 用来组成和说明了一个16进制的值,显示了在记录中剩余成对字符的计数。
3)、Address(地址):4或6或8个字节。用来组成和说明了一个16进制的值,显示了数据应该装载的地址, 这部分的长度取决于载入地址的字节数。2个字节的地址占用4个字符,3个字节的地址占用6个字符,4个字节的地址占用8个字符。
4)、Data(数据):0—64字符。用来组成和说明一个代表了内存载入数据或者描述信息的16进制的值。
5)、Checksum(校验和):2个字符。这些字符当被配对并换算成16进制数据的时候形成了一个最低有效字符节,该字符节用来表达作为补充数据,地址和数据库的字符对所代表的(字节的)补码的byte总和。即计数值、地址场和数据场的若干字符以两个字符为一对,将它们相加求和,和的溢出部分不计,只保留最低两位字符NN,checksum =0xFF-0xNN。
2、EXAMPLE
1)、 ExampleI
S19文件首行:S021000036384B50524F47202020313143524541544544204259204541535936384B6D
首行翻译信息: S0 0000 6 8 K P R O G    1 1C R E A T E D  B Y  E A S Y 6 8 K
色块图例:module name   version number  revision number   checksum
Checksum的算法:
0x21+0x00+0x00+0x36+0x38+0x4B+0x50+0x52+0x4F+0x47+0x20+0x20+0x20+0x31+0x31+0x43+0x52+0x45+0x41+0x54+0x45+0x44+0x20+0x42+0x59+0x20+0x45+0x41+0x53+0x59+0x36+0x38+0x4B=0x792
checksum=0xFF-0x92=6D
注意:EASy68K总是用S8 record作为结束行。
2)、ExampleII
S123C000CF1400790011CC09395B105A124A8046304A8000300001C01BCB73140007340027
色块图例:type   count   address   data   checksum
3)、ExampleIII
S224308000C61E877C1516C6197B151ACE04C07E15187A153EC74A90F9301D026A01C6017BF0
色块图例:type   count   address   data   checksum

五、Boot程序部分
先从程序流程图开始吧!
1.png
图一、Boot程序流程图
1、串口通讯部分:
在串口函数中要解决的事情有:数据接收、指令回复、数据校验、数据解析。
一般做Boot这类程序都要用一个握手包,我使用的是“版本号询问”,大家可以根据自己的情况使用“开始升级”,或者自己定义一个握手包。
    也可以对软件自行“加花”,我自己对“增加一些可有可无,有则更好,没有也可的程序”叫“加花”,可增加“波特率调整指令及代码”,提高一点软件升级的通讯速度。
2、FLASH的擦写操作:
    擦Flash:
for(i=0;i<120;i++)
{
Flag =IFsh1_EraseSector((IFsh1_TAddress)(i * 1024 + 0x2000));//(主程序空间范围8K-128K)
}
我使用了专家系统下的IFsh1模块,因此擦、写Flash就这几行代码,主程序空间范围8K-128K,因为代码空间充裕,128K的零头都留给了Boot使用,大家可以自行根据自己的Boot代码的大小,灵活调整。
写Flash:
if(FlashAddr > 0x1FFF)//写地址>0x1FFF(8K以后才是主程序)
{
Flag =IFsh1_NonDestructiveUnsecureWrite((IFsh1_TAddress)&Uart_rBuffer[10],FlashAddr, Packet.DataLong);//待写入数据的起始地址,Flash的写入起始起址,数据长度(字节)
}
擦写操作都有了,Boot程序还没完,还有一个很重要的事情,Boot空间分配!
3、Boot程序的Flash空间分配及程序入口代码:本文的重点了!

工程默认空间分配

工程默认空间分配
图二、专家系统建立工程后,默认的Flash空间配置
我在专家系统下对Flash空间进行如下的分配,如图三:

Boot空间分配

Boot空间分配
图三、为Boot程序更改FLASH空间分配
ROM/RAM segments中的Segment0从430开始,长度1BD0,因此Flash的前8K都属于Boot程序,所以在升级时擦Flash时就擦8K以后的空间。
有人可能眼力好,看到了ROM/RAM segments中的Segment0从410变成了430,多出的这点空间用于存放了Boot和主程序的入口地址。用于实现Boot程序和主程序的相互跳转。
并在Boot程序中增加下如代码
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//此xxx分隔线中间的代码,不得更改.
/*-----------------------------------------------------------
/ 函数名称 : void  (* const_BootEntry2[])()@(BOOT_ENTRY_ADDRESS+4)
/ 函数功能 : Boot段指针入口
/ 说   明 : 目的:主程序工作状态下,可重新进入Boot模式,进行必要的升级等工作.
/-----------------------------------------------------------*/
extern asm void _startup(void);
#define BOOT_ENTRY_ADDRESS    0x00000410 //Boot程序入口
#define MAIN_ENTRY_ADDRESS    0x00002410 // 主 程序入口(主程序入口为什么是2410和Boot程序入口为什么410一样,这里做了一个间接跳转;也可以查看中断相量表,写成直接跳转,这里推荐间接跳转)
//下面这两个小函数编译后合到一起的机器代码的意思是:“一次空操作后,立即跳到程序的启动代码处(_startup)”
const byte _BootEntry[] @ GMBOOT_ENTRY_ADDRESS=
{
  0x4E,0x71, 0x4E,0xF9           //asm NOP(0x4E71), asmJMP(0x4EF9)
};
void  (* const _BootEntry2[])()@(GMBOOT_ENTRY_ADDRESS+4)=
{
  _startup
};
/*-----------------------------------------------------------
/ 函数名称 : void EnterMain(void)
/ 函数功能 : 主程序入口
/ 说   明 :在Boot程序适当位置写出asm (JMP MAIN_ENTRY_ADDRESS);即可,为本文说明方便,单独拿出来写个函数.
/-----------------------------------------------------------*/
void EnterMain(void)
{
  asm (JMPMAIN_ENTRY_ADDRESS);//跳入主程序入口
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
至此,Boot程序已经完成了(串口、Flash的擦写、Flash空间分配及程序入口代码)。
因为串口比较简单没有详细说,这里补充的是,数据包一定要有一个合理的格式(包头、包尾、长度、校验)。

六、主程序部分
在讲Boot的时候,特意用倒序的方法说的;到了主程序,就得先从空间分配上开始了(讲是这么讲,当你自己做程序的时候,就随意了,要活学活用);
1、主程序空间分配:

工程默认空间分配-1

工程默认空间分配-1
图四、专家系统建立工程后,默认的Flash空间配置
图二、图四是一样的,我都是用专家系统建立的工程、做程序,从接触飞思卡尔开始,一直在用专家系统,仅发现几个小问题,基本都可以不改专家系统生成的底层代码就可以搞定。
将主程序工程默认的空间进行更改,如图五:

主程序空间分配

主程序空间分配
图五、主程序空间分配
ROM/RAMsegments:
Segment0:主程序代码空间
Segment1:主程序RAM空间
Segment2:中断向量的代码段
Segment3:中断向量的RAM段
中断向量的代码段中的内容,要在程序初始化之前,复制到RAM中,不然程序没有中断向量表,是不会正常执行的。或许有更好的办法(比如更改中断向量的指针),由于工作关系,没有大块时间细抠,希望本文抛砖引玉,能找到更好的方法。
空间分配完成后,在进入主程序的第一件事儿就是中断向量表的复制,代码如下:
  dword *pdst,*psrc;
  word i;

  asm (move.l  #0x00800000,d0);
  asm (movec   d0,vbr);

  pdst=(dword*)0x00800000;
  psrc=(dword*)0x00003000;

  for(i=0;i<=0x6E;i++)//0x6E中断向量数量(双字)
  {
    *pdst++ = *psrc++;
  }
//此行以后,就是PE_low_level_init();

2、主程序的入口代码和Reboot功能
现在主程序代码,可以在Boot代码之后运行了;为了主程序具有Reboot功能,为了Boot程序能跳转到主程序,还需要增加如下代码;
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
// 此xxx分隔线中间的代码,不得更改.
/*-----------------------------------------------------------
/ 说    明 : 1. 主程序入口地址
/           2.主程序状态下,重新进入Boot模式,进行必要的升级等工作.
/-----------------------------------------------------------*/
extern asm void _startup(void);

#define  BOOT_ENTRY_ADDRESS    0x00000410 //Boot程序入口
#define  MAIN_ENTRY_ADDRESS    0x00002410 // 主 程序入口

const byte _UserEntry[] @ MAIN_ENTRY_ADDRESS=
{
  0x4E, 0x71, 0x4E,0xF9           //asm NOP(0x4E71), asmJMP(0x4EF9)
};
void  (* const_UserEntry2[])()@(MAIN_ENTRY_ADDRESS+4)=
{
  _startup
};
/*-----------------------------------------------------------
/ 函数名称 : void EnterBoot (void)
/ 函数功能 : 主程序入口
/ 说    明 :在Boot程序适当位置写出asm (JMP BOOT_ENTRY_ADDRESS);即可,为本文说明方便,单独拿出来写个函数.
/-----------------------------------------------------------*/
void EnterBoot(void)
{
  asm (JMP BOOT_ENTRY_ADDRESS);//跳入主程序入口
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
七、其他
本文用了半天的时间写的,有可能有一些错误、或者不当之处,希望各位提出指正!



作者:梁子

2015/5/5

Bug1:20150505,图五错误,更换图片(重新上传PDF文档).

飞思卡尔专家系统-基于串口升级教程20150505.pdf

410.25 KB, 下载次数: 345, 下载积分: 威望 1

飞思卡尔基于串口升级教程

回复

使用道具 举报

该用户从未签到

7

主题

25

帖子

0

注册会员

Rank: 2

积分
126
最后登录
2021-4-8
 楼主| 发表于 2015-5-4 15:14:44 | 显示全部楼层
留楼备用!
回复

使用道具 举报

  • TA的每日心情
    开心
    2021-12-10 16:14
  • 签到天数: 1442 天

    [LV.10]以坛为家III

    17

    主题

    3862

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    8291
    最后登录
    2021-12-10
    发表于 2015-5-4 17:51:53 | 显示全部楼层
    很不错的经验分享,顶一个
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    郁闷
    2022-4-4 11:28
  • 签到天数: 351 天

    [LV.8]以坛为家I

    141

    主题

    8054

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    5740
    最后登录
    2022-4-4
    发表于 2015-5-4 20:59:46 | 显示全部楼层
    学习,谢谢分享
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2017-5-3 11:19
  • 签到天数: 10 天

    [LV.3]偶尔看看II

    50

    主题

    1万

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    14090
    最后登录
    2024-4-19
    发表于 2015-5-4 21:12:12 | 显示全部楼层
    这个是好东西。。。 nothing.png nothing.png nothing.png nothing.png nothing.png nothing.png nothing.png nothing.png nothing.png nothing.png
    该会员没有填写今日想说内容.
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    慵懒
    2017-4-27 10:34
  • 签到天数: 3 天

    [LV.2]偶尔看看I

    36

    主题

    507

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    1450
    最后登录
    2020-8-3
    发表于 2015-5-5 13:57:24 | 显示全部楼层
    很不错的贴!
    哎...今天够累的,签到来了1...
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    0

    主题

    15

    帖子

    0

    新手上路

    Rank: 1

    积分
    48
    最后登录
    2018-7-24
    发表于 2015-5-6 11:07:16 | 显示全部楼层
    如果出厂有预烧写的IAP或ISP的固件就更加棒了,是不是
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    0

    主题

    50

    帖子

    0

    注册会员

    Rank: 2

    积分
    126
    最后登录
    1970-1-1
    发表于 2015-5-6 13:50:47 | 显示全部楼层
    kanbudong...
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2017-1-24 09:50
  • 签到天数: 2 天

    [LV.1]初来乍到

    654

    主题

    3262

    帖子

    0

    金牌会员

    Rank: 6Rank: 6

    积分
    11246
    最后登录
    2019-1-27
    发表于 2015-5-8 10:01:13 | 显示全部楼层
    楼主的这个帖子很不错!
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    2

    主题

    16

    帖子

    0

    注册会员

    Rank: 2

    积分
    123
    最后登录
    2020-11-11
    发表于 2015-5-8 10:04:52 | 显示全部楼层
    好贴必顶
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-5-14 12:00 , Processed in 0.458968 second(s), 27 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

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