2019-01-05 11:36:35 whik1194 阅读数 1453
  • 《C语言/C++学习指南》加密解密篇(安全相关算法)

    本套视频教程介绍加密解密相关的常见算法,指出每种算法的应用场景,并给出使用示例。具体包含: (1) 数据转换(HEX和base64) (2) 对称加密 (DES, 3DES, AES) (3) 校验 CRC, MD5摘要, SHA1摘要 (4) 数字签名(HMAC-SHA1) , 并介绍了crypto++这个算法库的使用方法。

    25316 人正在学习 去看看 邵发

前言

上一篇文章介绍了使用Keil下载单独的Hex文件到单片机内,本篇文章介绍,如何使用SEGGER官方软件JFlash来进行程序的下载,支持Hex和Bin文件。

JFlash的下载和安装

首先,安装JFlash软件,安装完成后,会默认安装JLink驱动程序,主要包含以下几个工具:

  • JFlash,主要用于程序下载和读取。
  • JFlashLite,JFlash的Mini版
  • JFlashSPI,用于给SPI存储器下载程序,如W25Q128。
  • JLinkGDBServer,用于第三方软件的调试器,如使用Eclipse搭建STM32开发环境时,就要使用GDB Server来进行调试。
  • JLink Command,命令操作窗口,输入指令执行连接,擦除、下载、运行等操作。

软件准备

  • Jlink软件
  • Hex文件或者Bin文件
  • Jlink调试器,如Jlink V9

1.打开JFlash

打开JFlash

2.创建新工程

点击 File->NewProject

3.选择芯片的型号

这里支持很多ARM Cortex内核的芯片,选择对应的芯片,我这里选择的是STM32F103RE系列。

4.连接芯片

如果选择的是SWD模式,就要连接SWDIO、SWCLK、GND这三根线,连接好之后,点击Target->Connect,如果连接成功,在下面的LOG窗口会显示连接成功。

5.打开烧写文件

JLink支持Hex、Bin等多种文件类型,

这里如果选择的是Bin文件,还需要指定烧写的起始地址,因为Bin文件是不包含烧写地址的,而Hex文件是包含的,具体的区别可以查看之前发的一篇文章:BIN、HEX、AXF、ELF文件格式有什么区别

6.开始烧写

打开Hex文件之后,点击Target->Producion Programming,或者使用快捷键F7,等待几秒之后,程序就下载进去了,下载成功后,会在底部窗口显示烧写成功。

7.开始运行

烧写成功之后,此时程序还没有运行,点击Target->Manual Programming->Start Application,或者按快捷键F9,程序才开始运行,或者按复位键也可以让程序运行。

8.工程配置为自动运行

如果想让每次下载完成后,程序自动运行,而不用复位。可以使用工程配置下的自动运行选项。打开Option->Project Setting,切换到Production选项,勾选Start Application,就可以让程序自动运行。

可以把当前工程的配置存为一个文件,如STM32F103RE.jflash,下次需要下载时,直接打开这个工程就可以了。

JLink软件的下载

公众号后台回复“JLINK”,可获得JLink_Windows_V614b.exe软件下载链接。


Jlink使用技巧系列文章:


欢迎大家关注我的个人博客

或微信扫码关注我的公众号

2018-08-10 16:45:22 CSDN4646 阅读数 262
  • 《C语言/C++学习指南》加密解密篇(安全相关算法)

    本套视频教程介绍加密解密相关的常见算法,指出每种算法的应用场景,并给出使用示例。具体包含: (1) 数据转换(HEX和base64) (2) 对称加密 (DES, 3DES, AES) (3) 校验 CRC, MD5摘要, SHA1摘要 (4) 数字签名(HMAC-SHA1) , 并介绍了crypto++这个算法库的使用方法。

    25316 人正在学习 去看看 邵发

                                    如何从单片机中读出hex文件 

注意:本教程只在单片机程序未加密的情况下验证有效,其他未知!

网址:https://wenku.baidu.com/view/00320a5b8bd63186bdebbc90.html


 以C8051F020为例: 
1.下载C8051F编程器(可百度自行搜索)。通过搜索网络上有几个版本,比如新华龙电子的V6.00版本,以及鸿翼电子的V1.1版本与V2.1版本,我用的时候用的“鸿翼电子C8051F编程器V1.1”,因为新华龙电子的V6.00版本总是出现找不到设备的错误,鸿翼电子V2.1版本读出操作失败,各编程器界面如下图所示。

C8051F单片机hex文件读取:

具体的操作步骤如下:
1. 将仿真器与目标板以及计算机进行连接。打开下载的软件,选择编程接口形式,我用的JTAG口,所以选择JTAG,然后点击“连接目标芯片”

2. 连接成功后,会出现目标单片机的型号,如图所示

3. 连接成功后点击“读出”,等待片刻会跳出窗口,选择保存位置以及名字后,就完成了Hex文件的读取。

(1)出现正在读出…界面

(2)出现保存窗口

(4)保存成功后,出现“读出程序已保存至myhex.hex”。

4. 至此完成hex文件的读取

5. 若想直接将hex文件烧写到单片机内,连接成功后,选择“打开编辑文件”,选择你要烧写的文件,然后选择“写入”即可。

6. 为了验证读出程序的有效性,将单片机程序擦除后,将读出的hex文件烧写入其中,经验证有效。

2019-08-27 22:56:35 qq_43600271 阅读数 54
  • 《C语言/C++学习指南》加密解密篇(安全相关算法)

    本套视频教程介绍加密解密相关的常见算法,指出每种算法的应用场景,并给出使用示例。具体包含: (1) 数据转换(HEX和base64) (2) 对称加密 (DES, 3DES, AES) (3) 校验 CRC, MD5摘要, SHA1摘要 (4) 数字签名(HMAC-SHA1) , 并介绍了crypto++这个算法库的使用方法。

    25316 人正在学习 去看看 邵发

咚咚咚————【Matlab】单片机读取摄像头回传的RGB数组绘制图片

(一)效果展示

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

(二)源码分享

(Excel部分函数)

=HEX2BIN(A1,8)&HEX2BIN(B1,8)	//将两个字节的十六进制数据转换成二进制,并在单元格C1显示
=BIN2DEC(MID(C1,1,5))*8	//分离RGB565中的red部分并填充0转成RGB888的red数据
=BIN2DEC(MID(C1,6,6))*4	//分离RGB565中的green部分并填充0转成RGB888的green数据
=BIN2DEC(MID(C1,12,5))*8	//分离RGB565中的blue部分并填充0转成RGB888的blue数据

(Matlab部分函数)

image = zeros(480,480,3);		%申请图片变量空间;
image = uint8(image);				 %强制转换成uint8格式
R = reshape(CH1,480,480);	%转换R数组行列(像素大小480*480)
G = reshape(CH2,480,480);	%转换G数组行列
B = reshape(CH3,480,480);	%转换B数组行列
image(:,:,1)= R;				%红色赋值
image(:,:,2)= G;				%绿色赋值
image(:,:,3)= B;				%蓝色赋值
imshow(image)					%绘制图片

(三)需要改进的地方及不足

后期会把Excel部分的函数移植到Matlab中处理,这样子剩下了操作步骤。

2019-09-13 21:32:39 Maple_Leaf_15 阅读数 134
  • 《C语言/C++学习指南》加密解密篇(安全相关算法)

    本套视频教程介绍加密解密相关的常见算法,指出每种算法的应用场景,并给出使用示例。具体包含: (1) 数据转换(HEX和base64) (2) 对称加密 (DES, 3DES, AES) (3) 校验 CRC, MD5摘要, SHA1摘要 (4) 数字签名(HMAC-SHA1) , 并介绍了crypto++这个算法库的使用方法。

    25316 人正在学习 去看看 邵发

背景

从学习单片机以来,在Keil下的烧写都是把.hex文件烧写到单片机内部Flash,对于.hex文件的格式和烧写流程都没有深究。直到需要了解IAP(In Application Programming,即脱离JLink等烧写器进行在线升级)的时候,才发现.hex文件不能作为被直接下载的文件格式,只能用.bin文件代替。下面简单说下这两个文件之间的关联。

Hex文件的样子

这里参考了另一篇文章的内容。
Hex文件打开后每一行称为一个“记录(record)”,每行记录按照同样的结构包含了5个域(且每行以冒号开头):
记录的域的结构
每个域的含义
类型域的说明
根据以上图片知道,一个hex文件最后一行中的记录类型应该是’01’、表示文件结束。
为此写了个简单的程序并用VSCode打开生成的hex:
只有简单的几个常量数组
在这里插入图片描述
可以看到最后一行的记录类型域是’01’、表示文件结束。

这里插一句:第一行的记录类型域是’04’,表示“扩展线性地址记录”;倒数第二行的’05’表示“线性地址开始记录”,现在还不懂是什么意思…
在这里插入图片描述

Bin文件的样子

bin文件是最干净、没有地址信息等额外信息的文件,直接就是可以跑在单片机中机器码(包括程序和数据)。从下面可以看到C源码中**“A char string for see how ASCII char stored in hex and bin”**和另外的字符串被直接放在bin文件的最后(左边白色是bin文件的数据、右边是部分对应的ASCII码,其中控制字符和非ASCII码都显示为"."):
对应的bin文件

两个文件大小对比

hex比bin大
这个简单的程序生成的hex比bin大一倍多(3KB vs 1KB)。
因为hex包含很多额外信息(从截图来看,一行记录最多只能包含16字节的有效数据,也就是hex文件要给bin文件中每16字节增加5字节的信息和1字节的冒号…咦?那不至于两倍多?可能还有别的占存储空间的地方?不清楚…)。
编译另外一个程序得到的结果也是如此(22KB vs 8KB):
在这里插入图片描述
对于hex比bin大很多的原因,这篇文章提到(但这个理解是错误的!):
在这里插入图片描述
该作者的意思是“hex文件把C源码中的每个十六进制数的都当做字符串来处理”——但实际并不是如此,下图可以看出我C源码中的int数组,每个int元素都直接存进了hex文件,它们并没有转化为这些数字对应的ASCII码(如’23’对应的ASCII码应该是’32 33’)
int数组
hex文件的实际数据
bin文件的实际数据

什么时候用hex什么时候用bin呢?

还是引用这里的描述

Hex文件和Bin文件的存在价值:
从上面的介绍中,我们发现Hex文件中每行的内容,就像我们发送串口数据的数据帧,并且最后一行还指示出文件结束了。我们得出hex文件的两个优点:

1. 使用ASCII文本保存固件信息,方便查看一些固件内容;
2. 通过文件每行的校验和与最后一行的文件结束标志,在文件的传输与保存过程中能够发现固件是否完整。

Hex文件有更好的可读性,最重要的是hex文件能够保证固件在保存与传输时的完整性。因此hex文件更适用于保存与传输。而Bin文件是纯二进制文件,内部只包含程序编译后的机器码和变量数据。当文件损坏时,我们也无法知道文件已损坏。不过Bin文件作为固件的最终形式,在使用串口下载程序或者远程升级时,是不可替代的。

最后有一个很好的问题:既然hex和bin在内容上相差了一些额外的信息、而且bin的数据才是单片机最终可见的数据,那hex的额外信息什么时候去掉的呢?
答案是:是在使用JLink或者SWD烧录器给烧录代码时。烧录器上的程序把这些信息去除的。那么可以这样说:烧录hex文件仅在有烧录器的情况使用,否则如果是通过串口或普通的通讯接口,则只能使用bin文件。

2019-01-23 14:34:11 qq_41256212 阅读数 953
  • 《C语言/C++学习指南》加密解密篇(安全相关算法)

    本套视频教程介绍加密解密相关的常见算法,指出每种算法的应用场景,并给出使用示例。具体包含: (1) 数据转换(HEX和base64) (2) 对称加密 (DES, 3DES, AES) (3) 校验 CRC, MD5摘要, SHA1摘要 (4) 数字签名(HMAC-SHA1) , 并介绍了crypto++这个算法库的使用方法。

    25316 人正在学习 去看看 邵发

微处理器一般又称单片机,其可以根据人们编写的代码执行相关的逻辑操作。程序员将产品的逻辑操作抽象为C代码,然后通过编译器的编译和链接,生成微处理器可执行的机器码。通常编译器封装的不带调试信息的机器码有3种格式,分别为bin、motorola、hex,下面将分别介绍其特点:

1、Bin格式:

       Bin文件是二进制文件,是编译器生成的机器码文件,烧录工具可以直接读取该文件的内容而不用解析,然后通过烧录口直接烧录到微处理器的程序空间,但烧录前要指定程序存储空间的起始地址。由于Bin文件不带文件内容校验功能,因此要注意其文件内容的破坏。

2、Motorola格式:

       Motorola格式记录文件是ASCII格式的文件,又称SREC、S19,其是对机器码的一种封装描述。Motolora格式的文件相对于Bin文件来说,其带有程序的地址信息和数据校验功能,其Wiki的详细解说网址如下所示:

https://en.wikipedia.org/wiki/SREC_(file_format)

 

其数据组织方式为:

Record type

Byte count

Address

Data

Checksum

 

Record type:

       Record type为2个字节ASCII字符,第一个字符为‘S’,第二个字符为ASCII数字的‘0’~‘9’,下面将介绍其区别:

记录

类型

记录

目的

地址域

数据域

描述

S0

头说明

16位,默认值为“0000”

本记录为供应商特定的ASCII字符串信息,通常该值默认为“HDR”。

S1

数据

16位地址

本记录包含了数据内容和其16位地址信息,适用于8位单片机。

S2

数据

24位地址

本记录包含了数据内容和其24位地址信息。

S3

数据

32位地址

本记录包含了数据内容和其32位地址信息,适用于32位芯片。

S4

保留

N/A

N/A

本记录保留,未定义

S5

计数

16位计数

本记录为可选记录,记录S1/S2/S3计数,当计数值大于0xFFFF,S6记录被使用

S6

计数

24位计数

本记录为可选记录,记录S1/S2/S3计数,当计数值小于0xFFFF,S5记录被使用

S7

起始地址或结束

32位地址

本记录用于定义32位可执行起始地址,也用于S3记录结束的标志。当SREC文件只是用于内存编程,则忽略起始地址。

S8

起始地址或结束

24位地址

本记录用于定义24位可执行起始地址,也用于S2记录结束的标志。当SREC文件只是用于内存编程,则忽略起始地址。

S9

起始地址或结束

16位地址

本记录用于定义16位可执行起始地址,也用于S1记录结束的标志。当SREC文件只是用于内存编程,则忽略起始地址。

        对不同宽度的地址,其使用S19记录类型也不一样,对16位宽度的地址而言,其使用S0、S1、S5、S9类型的数据记录;对24位宽度的地址而言,其使用S0、S2、S5、S8类型的数据记录;对32位宽度的地址而言,其使用 S0、S3、S5、S7类型的数据记录。

 

Byte count:

       Byte count为2个16进制的ASCII数字,定义了Address + Data + Checksum域字节总数目。

 

Address:

       Address为4/6/8个16进制的ASCII数字,该个数取决于Record type的类型,用于表示数据的起始绝对地址,其数据格式为大端模式(即低地址为高字节数据)。

 

Data:

       Data为2*n个16进制的ASCII数字(n字节数据)。

 

Checksum:

       Checksum为2个16进制的ASCII数字,用于校验该行数据的完整性。该校验算法为将Byte count、Address、Data域的值进行相加,取低8位的和,然后取和的反值作为校验值,比如某S19文件中某记录为 S1090170E002FA050000A4,其数据和为:

09 + 01 + 70 + E0 + 02 + FA + 05 + 00 + 00 = 5B,5B的反值为A4,因此该行数据记录的校验值为A4。

 

S19数据记录以 行结束符 作为记录的结束,对不同的操作系统而言其行结束符是不一样的,比如对于Windows操作系统而言,其行结束符为CR LF(0x0D 0x0A)(‘\r’ ‘\n’),对于Linux操作系统而言,其行结束符为LF。

 

 

3、Hex格式:

       Hex文件是ASCII格式的文件,其也是对机器码的一种封装描述。Hex格式的文件相对于Bin文件来说,其也是带有程序的地址信息和数据校验功能,其Wiki的解说网址如下所示:

https://en.wikipedia.org/wiki/Intel_HEX

 

其数据组织方式为:

 

Start code

 

Byte Count

Address

Record type

Data

Checksum

 

Start code:

       Start code为1个ASCII字符’:’,用于标志一行Hex记录的开始。

 

Byte count:

       Byte count为2个16进制的ASCII数字,定义Data域字节数目。

 

Address:

       Address为4个16进制的ASCII数字,用于表示数据的偏移地址,其数据格式为大端模式(即低地址为高字节数据)。

 

Record type:

       Record type为2个16进制的ASCII数字,其值范围为00 ~05,用于定义记录的类型。

 

Hex code

Record type

Description

Example

00

数据(Data)

包含了数据内容和其偏移地址

:087DD00000A24A0400000000BB

本记录定义了偏移地址为0x7DD0的8个字节数据,分别为00,A2,4A,04,00,00,00,00

 

01

文件结束(End Of File)

该记录为Hex文件的最后一个记录,用于标志Hex文件记录的结束,该记录的固定格式为::00000001FF

:00000001FF

本记录用于标志Hex文件记录的结束。

02

扩展分片地址(Extended Segment Address)

该记录数据域定义了分片的基础地址,地址域为0x0000

:020000021200EA

03

分片起始地址(Start Segment Address)

该行数据域定义了分片的起始地址,地址域为0x0000

:0400000300003800C1

04

扩展线性地址(Extended Linear Address)

该行数据域定义了随后分片数据地址的高16位地址,使用00 和 02数据记录可以计算出分片数据的绝对地址,该地址域为0x0000

:02000004FFFFFC

05

起始线性地址(Start Linear Address)

该数据域定义了起始线性地址,该地址域为0x0000

:04000005080060EDA2

对使用不同宽度地址而言,其使用Hex记录类型也不一样,对16位宽度的地址而言,其使用00和01类型的数据记录;对20位宽度的地址而言,其使用00、01、02、03类型的数据记录;对32位宽度的地址而言,其使用 00、01、04、05类型的数据记录。

 

Data:

       Data为2*n个16进制的ASCII数字(n字节数据)。

Checksum:

       Checksum为2个16进制的ASCII数字,用于校验该行数据的完整性。该校验算法为将Byte count、Address、Record type、Data域的值进行相加,取低8位的和,然后取和的互补值(取反加1)作为校验值,比如hex文件中某hex记录为 :020000040800F2,其数据和为:02 + 00 + 00 + 04 + 08 + 00 = 0E,0E的互补值为F2,因此该行数据记录的校验值为F2。

 

HEX数据记录以 行结束符 作为记录的结束,对不同的操作系统而言其行结束符是不一样的,比如对于Windows操作系统而言,其行结束符为CR LF(0x0D 0x0A)(‘\r’ ‘\n’),对于Linux操作系统而言,其行结束符为LF。

 

 

4、区别:

Bin格式、Motorola格式、Hex格式的区别如下表所示:

 

Bin格式

Motorola格式

Hex格式

文件格式

二进制

ASCII

ASCII

文件大小

是否带有地址信息

程序地址格式

绝对地址

相对地址

内容校验

 

 

5、格式解析代码:

    motorola和hex解析头文件为ProgramFileDecode.h,其内容如下所示:

#ifndef __PROGRAM_FILE_DECODE_H
#define __PROGRAM_FILE_DECODE_H


#define PROGRAM_ARGUMENT_ERROR        (-1)
#define PROGRAM_UNKNOWN_CONTENT        (-2)
#define PROGRAM_S19_RECORD_UNKNOWN_ERROR    (-3)
#define PROGRAM_S19_RECORD_CHECKSUM_ERROR   (-4)
#define PROGRAM_HEX_RECORD_UNKNOWN_ERROR    (-3)
#define PROGRAM_HEX_RECORD_CHECKSUM_ERROR   (-4)
#define PROGRAM_ADDRESS_OVERLAP_ERROR        (-5)

#define SUPPORT_MAX_SEGMENT    (100)
#define SUPPORT_SEGMENT_SIZE    (0xFFFF)
typedef struct
{
    uint8_t* data[SUPPORT_MAX_SEGMENT];
    int dataLen[SUPPORT_MAX_SEGMENT];
    uint32_t address[SUPPORT_MAX_SEGMENT];
    int segmentNum;
}ProgramSegment;

typedef enum
{
    START_OUT_END_OUT=0,
    START_OUT_END_IN,
    START_IN_END_IN,
    START_IN_END_OUT,
    START_OUT_END_OUT1
}ADDR_STATE;

extern ProgramSegment gProgramSegment;

int ProgramFileDecode(char *program,int programLen,uint32_t startAddress,uint32_t endAddress,ProgramSegment *segment);

#endif

其C文件内容如下所示:

#include <ansi_c.h>
#include "ProgramFileDecode.h"

int gS4_Error = 0;
uint8_t gU1_ProgramData[SUPPORT_MAX_SEGMENT * SUPPORT_SEGMENT_SIZE];
uint32_t gU4_ProgramDataUsedCnt = 0;//用于计数gU1_ProgramData的使用数目

   
char gU1_RecordArray[512]; 
uint32_t gU4_RecordArrayLen=0;
uint8_t gU1_RecordArrayBinValue[256]; 
uint8_t gU1_RecordData[256];
uint8_t gU1_RecordType=0,gU1_ByteCount = 0,gU1_DataLen = 0;
uint32_t gU4_AddressStart=0;
uint32_t gU4_AddressEnd=0;
uint32_t gU4_AddressEndLast=0; 

ADDR_STATE addressState = START_OUT_END_OUT; 
uint32_t gU4_IgnoreByteCnt=0;
uint32_t gU4_PaddingByteLen=0;
uint32_t gU4_ValidDataLen = 0;
uint32_t gU4_ProgramDataLen=0;
uint8_t gU1_MemoryBusWith = 1;

int gS4_AddressWidth = 1;
int gS4_EndLineCharType = 0;
int gS4_PaddingSwitch = 0;
int gU1_PaddingValue = 0xFF;

ProgramSegment gProgramSegment; 

void ProgramDecodeModeSet(int addressWidth,int endLineCharType,int paddingSwitch,uint8_t paddingValue)
{
    gS4_AddressWidth = addressWidth;
    gS4_EndLineCharType = endLineCharType;
    gS4_PaddingSwitch = paddingSwitch;
    gU1_PaddingValue = paddingValue;    
}
char *getARecord(char *str,char *record,unsigned int *recordLen)
{
    char *pLF,*pCR;
    size_t len=0;
    
    if(((*str) == 'S') || ((*str) == ':'))
    {
        pLF = strchr(str,10);
        pCR = pLF-1;
        if((*pCR) == 13)
        {
            //Windows system
            len = (size_t)(pCR - str);
            strncpy(record,str,len);
        }
        else
        {
            //Linux system
            len = (size_t)(pLF - str);
            strncpy(record,str,len);
        }
        record[len]=0;
        *recordLen = len;
        return (++pLF);
    }
    else
        return 0;
}
uint32_t getValueFromArray(uint8_t *data,int len)
{
    int i;
    uint32_t value=0;
    if(len > 4)
        return 0;
    
    value = 0;
    for(i=0;i<len;i++)
    {
        value =    value * 256 + data[i];    
    }
    return value;
}

int getBinValueFromHexAsciiArray(char *str,int len,uint8_t *data)
{
    int i,j,byteCnt;
    uint8_t hexValue=0;
        
    byteCnt=len / 2;//字符串的长度必须为2的整数倍
    hexValue=0;
    for(j=0;j<byteCnt;j++)
    {
        hexValue = 0;
        for(i=j*2;i<j*2+2;i++)
        {
            if(str[i] >= '0' && str[i] <= '9')
            {
                hexValue=hexValue * 16 + (str[i] - '0');    
            }
            else if(str[i] >= 'a' && str[i] <= 'f')
            {
                hexValue=hexValue * 16 + (10 + str[i] - 'a');
            }
            else if(str[i] >= 'A' && str[i] <= 'F')
            {
                hexValue=hexValue * 16 + (10 + str[i] - 'A');       
            }
        }
        data[j]= hexValue;
    }
    return byteCnt;
}
int getMotorolaRecordInfo(char *record,int recordLen,uint8_t *recordType,uint8_t *byteCount,uint32_t *address,uint8_t *data,uint8_t *dataLen)
{
    uint8_t type=0,byteCountTemp=0,addressAndCountLen=0;
    uint8_t checkSumOrigion = 0,checkSumCal = 0;  
    uint8_t binValueArrayLen = 0;
    int i;
    
    if(record[0] == 'S')
    {
        type = record[1] - '0';
        if(type > 9)
            return PROGRAM_S19_RECORD_UNKNOWN_ERROR;
        *recordType = type;
    
        binValueArrayLen = (uint8_t)getBinValueFromHexAsciiArray(&record[2],recordLen - 2,gU1_RecordArrayBinValue);
        byteCountTemp = gU1_RecordArrayBinValue[0];
        if(byteCountTemp < 3)
            return PROGRAM_S19_RECORD_UNKNOWN_ERROR;
        *byteCount = byteCountTemp;    
        checkSumOrigion = (uint8_t)getValueFromArray(&gU1_RecordArrayBinValue[1 + byteCountTemp - 1],1); 
        checkSumCal = 0;
        for(i=0;i<byteCountTemp;i++)
        {
            checkSumCal = checkSumCal + gU1_RecordArrayBinValue[i];         
        }
        checkSumCal = ~checkSumCal;
        if(checkSumCal != checkSumOrigion)
            return PROGRAM_S19_RECORD_CHECKSUM_ERROR;
        
        switch(type)
        {
            case 0:
                addressAndCountLen = 2;     
                break;
            case 1:
                addressAndCountLen = 2; 
                break;
            case 2:
                addressAndCountLen = 3; 
                break;
            case 3:
                addressAndCountLen = 4; 
                break;
            case 4:
                //TODO return
                break;
            case 5:
                addressAndCountLen = 2;
                break;
            case 6:
                addressAndCountLen = 3;
                break;
            case 7:
                addressAndCountLen = 4;
                break;
            case 8:
                addressAndCountLen = 3; 
                break;
            case 9:
                addressAndCountLen = 2;
                break;
            default:
                //TODO return
                return PROGRAM_S19_RECORD_UNKNOWN_ERROR;  
                break;
        }
        *address = getValueFromArray(&gU1_RecordArrayBinValue[1],addressAndCountLen);
        memcpy(data,&gU1_RecordArrayBinValue[1 + addressAndCountLen],byteCountTemp - addressAndCountLen -1);
        *dataLen = binValueArrayLen - 2 - addressAndCountLen; 
        return 0;    
    }
    else
    {
        return PROGRAM_S19_RECORD_UNKNOWN_ERROR;
    }
}
int getHexRecordInfo(char *record,int recordLen,uint8_t *byteCount,uint32_t *address,uint8_t *recordType,uint8_t *data,uint8_t *dataLen)
{
    uint8_t byteCountTemp=0;
    uint8_t checkSumOrigion = 0,checkSumCal = 0;  
    int i;
    
    if(record[0] == ':')   
    {
        getBinValueFromHexAsciiArray(&record[1],recordLen - 1,gU1_RecordArrayBinValue);
        byteCountTemp = (uint8_t)getValueFromArray(gU1_RecordArrayBinValue,1);
        checkSumOrigion = (uint8_t)getValueFromArray(&gU1_RecordArrayBinValue[4 + byteCountTemp],1); 
        checkSumCal = 0;
        for(i=0;i<(byteCountTemp + 4);i++)
        {
            checkSumCal = checkSumCal + gU1_RecordArrayBinValue[i];         
        }
        checkSumCal = ~checkSumCal + 1; 
        if( checkSumCal != checkSumOrigion)
            return PROGRAM_HEX_RECORD_CHECKSUM_ERROR; 
        
        *byteCount = byteCountTemp;
        *dataLen =  byteCountTemp;
        *address = getValueFromArray(&gU1_RecordArrayBinValue[1],2);
        *recordType = (uint8_t)getValueFromArray(&gU1_RecordArrayBinValue[3],1);
        if(*recordType > 5)
            return PROGRAM_HEX_RECORD_UNKNOWN_ERROR;
        memcpy(data,&gU1_RecordArrayBinValue[4],byteCountTemp);
        return 0;
    }
    else
    {
        return PROGRAM_HEX_RECORD_UNKNOWN_ERROR;    
    }
}
int ProgramFileDecode(char *program,int programLen,uint32_t startAddress,uint32_t endAddress,ProgramSegment *segment)
{
    char *pNextRecord;
    char *pEndRecord;
    uint8_t *programData = NULL;
    uint32_t programSegmentLen = 0;
    uint32_t extendedLinearAddr = 0;
    
    gS4_Error = 0;
    if((program == NULL) || (startAddress >= endAddress) || (segment == NULL))
    {
        gS4_Error = PROGRAM_ARGUMENT_ERROR;
        return gS4_Error;    
    }
    
    pNextRecord = program;
    pEndRecord  = &program[programLen];
    gU4_ProgramDataLen =0;
    gU4_AddressEndLast = 0;
    gU4_ValidDataLen = 0;
    gU4_IgnoreByteCnt = 0;
    extendedLinearAddr = 0;
    
    while(pNextRecord < pEndRecord)
    {
        pNextRecord = getARecord(pNextRecord,gU1_RecordArray,&gU4_RecordArrayLen);
        if(pNextRecord == 0)
        {
            break;
        }
        if(gU1_RecordArray[0] == 'S')
        {
            gS4_Error = getMotorolaRecordInfo(gU1_RecordArray,gU4_RecordArrayLen,&gU1_RecordType,&gU1_ByteCount,&gU4_AddressStart,gU1_RecordData,&gU1_DataLen);    
            if(gS4_Error < 0)
            {
                //Some error happend
                return gS4_Error;    
            }
            gU1_DataLen = gU1_DataLen / gU1_MemoryBusWith;
            gU4_AddressEnd =gU4_AddressStart + gU1_DataLen - 1; 
            //Program data
            switch(gU1_RecordType)
            {
                //Header
                case 0:
                    break;
                //Data
                case 1:
                case 2:
                case 3:
                    if(gU4_AddressStart < startAddress)
                    {
                        if(gU4_AddressEnd < startAddress)
                            addressState = START_OUT_END_OUT;
                        else
                            addressState = START_OUT_END_IN;
                    }
                    else if(gU4_AddressStart <= endAddress)
                    {
                        if(gU4_AddressEnd <= endAddress)
                            addressState = START_IN_END_IN;
                        else
                            addressState = START_IN_END_OUT;    
                    }
                    else if(gU4_AddressStart > endAddress)
                    {
                        addressState = START_OUT_END_OUT1;
                    }
            
                    switch(addressState)
                    {
                        case START_OUT_END_OUT:
                            gU4_IgnoreByteCnt = gU4_IgnoreByteCnt + gU1_DataLen;
                            break;
                        case START_OUT_END_IN:
                            gU4_ProgramDataUsedCnt = 0;
                            programSegmentLen = 0;
                            segment->segmentNum = 1;
                            segment->address[segment->segmentNum - 1] = startAddress; 
                            segment->data[segment->segmentNum - 1] = &gU1_ProgramData[0];
                            programData = segment->data[segment->segmentNum - 1]; 
                            
                            gU4_ValidDataLen = gU4_AddressEnd - startAddress + 1;
                             memcpy(&programData[0],&gU1_RecordData[(gU1_DataLen - gU4_ValidDataLen) * gU1_MemoryBusWith],gU4_ValidDataLen*gU1_MemoryBusWith);
                            programSegmentLen = gU4_ValidDataLen * gU1_MemoryBusWith;
                            segment->dataLen[segment->segmentNum - 1] = programSegmentLen;
                            gU4_AddressEndLast = gU4_AddressEnd;
                            break;
                        case START_IN_END_IN:
                            if(gU4_AddressEndLast == 0)//首个分片 
                            {
                                gU4_ProgramDataUsedCnt = 0;
                                programSegmentLen = 0;
                                segment->segmentNum = 1;
                                segment->address[segment->segmentNum - 1] = startAddress; 
                                segment->data[segment->segmentNum - 1] = &gU1_ProgramData[0];
                                programData = segment->data[segment->segmentNum - 1];
                                
                            }
                            else if((gU4_AddressEndLast + 1) < gU4_AddressStart)//出现新的程序分片
                            {
                                gU4_ProgramDataUsedCnt = gU4_ProgramDataUsedCnt + programSegmentLen; 
                                programSegmentLen = 0;
                                segment->segmentNum++;
                                segment->address[segment->segmentNum - 1] = gU4_AddressStart; 
                                segment->data[segment->segmentNum - 1] = &gU1_ProgramData[gU4_ProgramDataUsedCnt];
                                programData = segment->data[segment->segmentNum - 1];
                            }
                            else if((gU4_AddressEndLast + 1) == gU4_AddressStart)//地址连续
                            {
                                    
                            }
                            else//出现错误,地址冲突
                            {
                                gS4_Error = PROGRAM_ADDRESS_OVERLAP_ERROR;
                                return gS4_Error;
                            }
                            gU4_ValidDataLen = gU1_DataLen;
                             memcpy(&programData[programSegmentLen],&gU1_RecordData[0],gU4_ValidDataLen*gU1_MemoryBusWith);
                            programSegmentLen = programSegmentLen + gU4_ValidDataLen * gU1_MemoryBusWith;
                            segment->dataLen[segment->segmentNum - 1] = programSegmentLen;
                            gU4_AddressEndLast = gU4_AddressEnd; 
                            break;
                        case START_IN_END_OUT:
                            if(gU4_AddressEndLast == 0)//首个分片 
                            {
                                gU4_ProgramDataUsedCnt = 0;
                                programSegmentLen = 0;
                                segment->segmentNum = 1;
                                segment->address[segment->segmentNum - 1] = startAddress; 
                                segment->data[segment->segmentNum - 1] = &gU1_ProgramData[0];
                                programData = segment->data[segment->segmentNum - 1];
                                
                            }
                            else if((gU4_AddressEndLast + 1) < gU4_AddressStart)//出现新的程序分片
                            {
                                gU4_ProgramDataUsedCnt = gU4_ProgramDataUsedCnt + segment->dataLen[segment->segmentNum - 1]; 
                                programSegmentLen = 0;
                                segment->segmentNum++;
                                segment->address[segment->segmentNum - 1] = gU4_AddressStart; 
                                segment->data[segment->segmentNum - 1] = &gU1_ProgramData[gU4_ProgramDataUsedCnt];
                                programData = segment->data[segment->segmentNum - 1];
                            }
                            else if((gU4_AddressEndLast + 1) == gU4_AddressStart)//地址连续
                            {
                                    
                            }
                            else//出现错误,地址冲突
                            {
                                gS4_Error = PROGRAM_ADDRESS_OVERLAP_ERROR;
                                return gS4_Error;
                            }
                            
                            gU4_ValidDataLen = endAddress - gU4_AddressStart + 1;
                             memcpy(&programData[programSegmentLen],&gU1_RecordData[0],gU4_ValidDataLen*gU1_MemoryBusWith);
                            programSegmentLen = programSegmentLen + gU4_ValidDataLen * gU1_MemoryBusWith;
                            segment->dataLen[segment->segmentNum - 1] = programSegmentLen;
                            gU4_ProgramDataUsedCnt = gU4_ProgramDataUsedCnt + programSegmentLen; 
                            gU4_AddressEndLast = gU4_AddressEnd; 
                            
                            break;
                        case START_OUT_END_OUT1:
                            break;
                        default:
                            ;
                            break;
                    
                    }
                    break;
                //Reserve
                case 4:
                    break;
                //Count
                case 5:
                case 6:
                    break;
                //End flag
                case 7:
                case 8:
                case 9:
                    
                    break;
                default:
                    ;
            }
        }
        else if(gU1_RecordArray[0] == ':')
        {
            gS4_Error = getHexRecordInfo(gU1_RecordArray,gU4_RecordArrayLen,&gU1_ByteCount,&gU4_AddressStart,&gU1_RecordType,gU1_RecordData,&gU1_DataLen);
            if(gS4_Error < 0)
            {
                return gS4_Error;
            }
            switch(gU1_RecordType)
            {
                //Data
                case 0:
                    
                    gU4_AddressStart = gU4_AddressStart + extendedLinearAddr;
                    gU1_DataLen = gU1_DataLen / gU1_MemoryBusWith;
                    gU4_AddressEnd =gU4_AddressStart + gU1_DataLen - 1;
                    
                    if(gU4_AddressStart < startAddress)
                    {
                        if(gU4_AddressEnd < startAddress)
                            addressState = START_OUT_END_OUT;
                        else
                            addressState = START_OUT_END_IN;
                    }
                    else if(gU4_AddressStart <= endAddress)
                    {
                        if(gU4_AddressEnd <= endAddress)
                            addressState = START_IN_END_IN;
                        else
                            addressState = START_IN_END_OUT;    
                    }
                    else if(gU4_AddressStart > endAddress)
                    {
                        addressState = START_OUT_END_OUT1;
                    }
            
                    switch(addressState)
                    {
                        case START_OUT_END_OUT:
                            gU4_IgnoreByteCnt = gU4_IgnoreByteCnt + gU1_DataLen;
                            break;
                        case START_OUT_END_IN:
                            gU4_ProgramDataUsedCnt = 0;
                            programSegmentLen = 0;
                            segment->segmentNum = 1;
                            segment->address[segment->segmentNum - 1] = startAddress; 
                            segment->data[segment->segmentNum - 1] = &gU1_ProgramData[0];
                            programData = segment->data[segment->segmentNum - 1]; 
                            
                            gU4_ValidDataLen = gU4_AddressEnd - startAddress + 1;
                             memcpy(&programData[0],&gU1_RecordData[(gU1_DataLen - gU4_ValidDataLen) * gU1_MemoryBusWith],gU4_ValidDataLen*gU1_MemoryBusWith);
                            programSegmentLen = gU4_ValidDataLen * gU1_MemoryBusWith;
                            segment->dataLen[segment->segmentNum - 1] = programSegmentLen;
                            gU4_AddressEndLast = gU4_AddressEnd;
                            break;
                        case START_IN_END_IN:
                            if(gU4_AddressEndLast == 0)//首个分片 
                            {
                                gU4_ProgramDataUsedCnt = 0;
                                programSegmentLen = 0;
                                segment->segmentNum = 1;
                                segment->address[segment->segmentNum - 1] = startAddress; 
                                segment->data[segment->segmentNum - 1] = &gU1_ProgramData[0];
                                programData = segment->data[segment->segmentNum - 1];
                                
                            }
                            else if((gU4_AddressEndLast + 1) < gU4_AddressStart)//出现新的程序分片
                            {
                                gU4_ProgramDataUsedCnt = gU4_ProgramDataUsedCnt + segment->dataLen[segment->segmentNum - 1]; 
                                programSegmentLen = 0;
                                segment->segmentNum++;
                                segment->address[segment->segmentNum - 1] = gU4_AddressStart; 
                                segment->data[segment->segmentNum - 1] = &gU1_ProgramData[gU4_ProgramDataUsedCnt];
                                programData = segment->data[segment->segmentNum - 1];
                            }
                            else if((gU4_AddressEndLast + 1) == gU4_AddressStart)//地址连续
                            {
                                    
                            }
                            else//出现错误,地址冲突
                            {
                                gS4_Error = PROGRAM_ADDRESS_OVERLAP_ERROR;
                                return gS4_Error;
                            }
                            gU4_ValidDataLen = gU1_DataLen;
                             memcpy(&programData[programSegmentLen],&gU1_RecordData[0],gU4_ValidDataLen*gU1_MemoryBusWith);
                            programSegmentLen = programSegmentLen + gU4_ValidDataLen * gU1_MemoryBusWith;
                            segment->dataLen[segment->segmentNum - 1] = programSegmentLen;
                            gU4_AddressEndLast = gU4_AddressEnd; 
                            break;
                        case START_IN_END_OUT:
                            if(gU4_AddressEndLast == 0)//首个分片 
                            {
                                gU4_ProgramDataUsedCnt = 0;
                                programSegmentLen = 0;
                                segment->segmentNum = 1;
                                segment->address[segment->segmentNum - 1] = startAddress; 
                                segment->data[segment->segmentNum - 1] = &gU1_ProgramData[0];
                                programData = segment->data[segment->segmentNum - 1];
                                
                            }
                            else if((gU4_AddressEndLast + 1) < gU4_AddressStart)//出现新的程序分片
                            {
                                gU4_ProgramDataUsedCnt = gU4_ProgramDataUsedCnt + segment->dataLen[segment->segmentNum - 1]; 
                                programSegmentLen = 0;
                                segment->segmentNum++;
                                segment->address[segment->segmentNum - 1] = gU4_AddressStart; 
                                segment->data[segment->segmentNum - 1] = &gU1_ProgramData[gU4_ProgramDataUsedCnt];
                                programData = segment->data[segment->segmentNum - 1];
                            }
                            else if((gU4_AddressEndLast + 1) == gU4_AddressStart)//地址连续
                            {
                                    
                            }
                            else//出现错误,地址冲突
                            {
                                gS4_Error = PROGRAM_ADDRESS_OVERLAP_ERROR;
                                return gS4_Error;
                            }
                            
                            gU4_ValidDataLen = endAddress - gU4_AddressStart + 1;
                             memcpy(&programData[programSegmentLen],&gU1_RecordData[0],gU4_ValidDataLen*gU1_MemoryBusWith);
                            programSegmentLen = programSegmentLen + gU4_ValidDataLen * gU1_MemoryBusWith;
                            segment->dataLen[segment->segmentNum - 1] = programSegmentLen;
                            gU4_AddressEndLast = gU4_AddressEnd; 
                            
                            break;
                        case START_OUT_END_OUT1:
                            break;
                        default:
                            ;
                            break;
                    
                    }
                    break;
                //End of file
                case 1:
                    
                    break;
                //Extended segment address
                case 2:
                    
                    break;
                //Start segment address
                case 3:
                    
                    break;
                //Extended linear address
                case 4:
                    extendedLinearAddr = ((gU1_RecordData[0] << 8) & 0xFF00) | (gU1_RecordData[1]);
                    extendedLinearAddr = (extendedLinearAddr << 16) & 0xFFFF0000;
                    
                    break;
                //Start linear address
                case 5:
                    
                    break;
                default:
                    ;
            }
        }
        else
        {
            gS4_Error = PROGRAM_UNKNOWN_CONTENT;
            return gS4_Error;
        }
    }
    return 0;    
}

代码讲解:

    Motorola和Hex程序文件解析函数入口为ProgramFileDecode,其函数原型如下所示:

int ProgramFileDecode(char *program,int programLen,uint32_t startAddress,uint32_t endAddress,ProgramSegment *segment);
    其中program为从程序文件中读取出来的文件内容,programLen为文件内容的长度,startAddress为需要截取程序的起始地址,endAddress为需要截取程序的终止地址,segment为起始地址和结束地址之间的程序分片。当调用ProgramFileDecode函数成功后,需要将segment分片的内容打包发给微处理器的Bootloader以更新程序。

代码举例:

    

int ProgramFileProcess(void)
{
    int n;
    ssize_t size;
    int fileHandle = 0;
    int ret = 0;
    int k = 0;

    n = GetFileInfo(programFilePath,&size);
    fileHandle = OpenFile(programFilePath,VAL_READ_ONLY,VAL_OPEN_AS_IS,VAL_BINARY );
    ret = ReadFile(fileHandle,hexFileContent,size);
    if(ret != size)
    {
        DebugInfo(LEVEL_ERROR,"Read program file failed\r\n");    
    }
    ProgramFileDecode(hexFileContent,size,gU4_FlashStartAddr,gU4_FlashEndAddr,&gProgramSegment);
    
    GetPageAddress(gProgramSegment.address[0],gU4_FlashPageSize,&gU4_ProgramStartPageAddress);
    GetPageAddress(gProgramSegment.address[gProgramSegment.segmentNum - 1] + gProgramSegment.dataLen[gProgramSegment.segmentNum - 1],gU4_FlashPageSize,&gU4_ProgramEndPageAddress);
    gU4_ProgramEndPageAddress = gU4_ProgramEndPageAddress + gU4_FlashPageSize - 1;
    
    //DebugInfo(LEVEL_NORMAL,"StartPageAddress = 0x%X,EndPageAddress =  0x%X\r\n",gU4_ProgramStartPageAddress,gU4_ProgramEndPageAddress);
    
    if(gProgramSegment.address[0] != gU4_ProgramStartPageAddress)
    {
        DebugInfo(LEVEL_WARNING,"Attention!.Program start address is not page address.\r\n");    
    }
    
    ProgramUpgrade1(&programUpgradeCancel);
    
    return 0;
}

 

 

 

 

 

没有更多推荐了,返回首页