烧录文件bin、Motorola、hex格式介绍及解析

微处理器一般又称单片机,其可以根据人们编写的代码执行相关的逻辑操作。程序员将产品的逻辑操作抽象为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;
}

 

 

 

 

 

  • 4
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值