在做pic的mcu升级功能时发现mplab居然不能输出bin格式,只好自己用C写了个小工具把hex转成bin,已在pic24和pic32平台下测试过。编译器用的mingw,使用C标准库应该很容易在linux编译使用,不过没有测试过,毕竟mcu的开发环境大部分是windows的。
GenericTypeDefs.h 头文件和hex解析部分用的pic的官方驱动中的代码,虽然速度比较快,但是移植到部分平台上会有大小端的问题。
#ifndef __GENERIC_TYPE_DEFS_H_
#define __GENERIC_TYPE_DEFS_H_
/* Specify an extension for GCC based compilers */
#if defined(__GNUC__)
#define __EXTENSION __extension__
#else
#define __EXTENSION
#endif
/* get compiler defined type definitions (NULL, size_t, etc) */
#include
#define TRUE 1
#define FALSE 0
typedef unsigned char BOOL;
/* INT is processor specific in length may vary in size */
typedef signed int INT;
typedef signed char INT8;
typedef signed short int INT16;
typedef signed long int INT32;
/* MPLAB C Compiler for PIC18 does not support 64-bit integers */
#if !defined(__18CXX)
__EXTENSION typedef signed long long INT64;
#endif
/* UINT is processor specific in length may vary in size */
typedef unsigned int UINT;
typedef unsigned char UINT8;
typedef unsigned short int UINT16;
/* 24-bit type only available on C18 */
#if defined(__18CXX)
typedef unsigned short long UINT24;
#endif
typedef unsigned long int UINT32; /* other name for 32-bit integer */
/* MPLAB C Compiler for PIC18 does not support 64-bit integers */
#if !defined(__18CXX)
__EXTENSION typedef unsigned long long UINT64;
#endif
typedef union
{
UINT8 Val;
struct
{
__EXTENSION UINT8 b0:1;
__EXTENSION UINT8 b1:1;
__EXTENSION UINT8 b2:1;
__EXTENSION UINT8 b3:1;
__EXTENSION UINT8 b4:1;
__EXTENSION UINT8 b5:1;
__EXTENSION UINT8 b6:1;
__EXTENSION UINT8 b7:1;
} bits;
} UINT8_VAL, UINT8_BITS;
typedef union
{
UINT16 Val;
UINT8 v[2];
struct
{
UINT8 LB;
UINT8 HB;
} byte;
struct
{
__EXTENSION UINT8 b0:1;
__EXTENSION UINT8 b1:1;
__EXTENSION UINT8 b2:1;
__EXTENSION UINT8 b3:1;
__EXTENSION UINT8 b4:1;
__EXTENSION UINT8 b5:1;
__EXTENSION UINT8 b6:1;
__EXTENSION UINT8 b7:1;
__EXTENSION UINT8 b8:1;
__EXTENSION UINT8 b9:1;
__EXTENSION UINT8 b10:1;
__EXTENSION UINT8 b11:1;
__EXTENSION UINT8 b12:1;
__EXTENSION UINT8 b13:1;
__EXTENSION UINT8 b14:1;
__EXTENSION UINT8 b15:1;
} bits;
} UINT16_VAL, UINT16_BITS;
/* 24-bit type only available on C18 */
#if defined(__18CXX)
typedef union
{
UINT24 Val;
UINT8 v[3];
struct
{
UINT8 LB;
UINT8 HB;
UINT8 UB;
} byte;
struct
{
__EXTENSION UINT8 b0:1;
__EXTENSION UINT8 b1:1;
__EXTENSION UINT8 b2:1;
__EXTENSION UINT8 b3:1;
__EXTENSION UINT8 b4:1;
__EXTENSION UINT8 b5:1;
__EXTENSION UINT8 b6:1;
__EXTENSION UINT8 b7:1;
__EXTENSION UINT8 b8:1;
__EXTENSION UINT8 b9:1;
__EXTENSION UINT8 b10:1;
__EXTENSION UINT8 b11:1;
__EXTENSION UINT8 b12:1;
__EXTENSION UINT8 b13:1;
__EXTENSION UINT8 b14:1;
__EXTENSION UINT8 b15:1;
__EXTENSION UINT8 b16:1;
__EXTENSION UINT8 b17:1;
__EXTENSION UINT8 b18:1;
__EXTENSION UINT8 b19:1;
__EXTENSION UINT8 b20:1;
__EXTENSION UINT8 b21:1;
__EXTENSION UINT8 b22:1;
__EXTENSION UINT8 b23:1;
} bits;
} UINT24_VAL, UINT24_BITS;
#endif
typedef union
{
UINT32 Val;
UINT16 w[2];
UINT8 v[4];
struct
{
UINT16 LW;
UINT16 HW;
} word;
struct
{
UINT8 LB;
UINT8 HB;
UINT8 UB;
UINT8 MB;
} byte;
struct
{
UINT16_VAL low;
UINT16_VAL high;
}wordUnion;
struct
{
__EXTENSION UINT8 b0:1;
__EXTENSION UINT8 b1:1;
__EXTENSION UINT8 b2:1;
__EXTENSION UINT8 b3:1;
__EXTENSION UINT8 b4:1;
__EXTENSION UINT8 b5:1;
__EXTENSION UINT8 b6:1;
__EXTENSION UINT8 b7:1;
__EXTENSION UINT8 b8:1;
__EXTENSION UINT8 b9:1;
__EXTENSION UINT8 b10:1;
__EXTENSION UINT8 b11:1;
__EXTENSION UINT8 b12:1;
__EXTENSION UINT8 b13:1;
__EXTENSION UINT8 b14:1;
__EXTENSION UINT8 b15:1;
__EXTENSION UINT8 b16:1;
__EXTENSION UINT8 b17:1;
__EXTENSION UINT8 b18:1;
__EXTENSION UINT8 b19:1;
__EXTENSION UINT8 b20:1;
__EXTENSION UINT8 b21:1;
__EXTENSION UINT8 b22:1;
__EXTENSION UINT8 b23:1;
__EXTENSION UINT8 b24:1;
__EXTENSION UINT8 b25:1;
__EXTENSION UINT8 b26:1;
__EXTENSION UINT8 b27:1;
__EXTENSION UINT8 b28:1;
__EXTENSION UINT8 b29:1;
__EXTENSION UINT8 b30:1;
__EXTENSION UINT8 b31:1;
} bits;
} UINT32_VAL;
/* MPLAB C Compiler for PIC18 does not support 64-bit integers */
#if !defined(__18CXX)
typedef union
{
UINT64 Val;
UINT32 d[2];
UINT16 w[4];
UINT8 v[8];
struct
{
UINT32 LD;
UINT32 HD;
} dword;
struct
{
UINT16 LW;
UINT16 HW;
UINT16 UW;
UINT16 MW;
} word;
struct
{
__EXTENSION UINT8 b0:1;
__EXTENSION UINT8 b1:1;
__EXTENSION UINT8 b2:1;
__EXTENSION UINT8 b3:1;
__EXTENSION UINT8 b4:1;
__EXTENSION UINT8 b5:1;
__EXTENSION UINT8 b6:1;
__EXTENSION UINT8 b7:1;
__EXTENSION UINT8 b8:1;
__EXTENSION UINT8 b9:1;
__EXTENSION UINT8 b10:1;
__EXTENSION UINT8 b11:1;
__EXTENSION UINT8 b12:1;
__EXTENSION UINT8 b13:1;
__EXTENSION UINT8 b14:1;
__EXTENSION UINT8 b15:1;
__EXTENSION UINT8 b16:1;
__EXTENSION UINT8 b17:1;
__EXTENSION UINT8 b18:1;
__EXTENSION UINT8 b19:1;
__EXTENSION UINT8 b20:1;
__EXTENSION UINT8 b21:1;
__EXTENSION UINT8 b22:1;
__EXTENSION UINT8 b23:1;
__EXTENSION UINT8 b24:1;
__EXTENSION UINT8 b25:1;
__EXTENSION UINT8 b26:1;
__EXTENSION UINT8 b27:1;
__EXTENSION UINT8 b28:1;
__EXTENSION UINT8 b29:1;
__EXTENSION UINT8 b30:1;
__EXTENSION UINT8 b31:1;
__EXTENSION UINT8 b32:1;
__EXTENSION UINT8 b33:1;
__EXTENSION UINT8 b34:1;
__EXTENSION UINT8 b35:1;
__EXTENSION UINT8 b36:1;
__EXTENSION UINT8 b37:1;
__EXTENSION UINT8 b38:1;
__EXTENSION UINT8 b39:1;
__EXTENSION UINT8 b40:1;
__EXTENSION UINT8 b41:1;
__EXTENSION UINT8 b42:1;
__EXTENSION UINT8 b43:1;
__EXTENSION UINT8 b44:1;
__EXTENSION UINT8 b45:1;
__EXTENSION UINT8 b46:1;
__EXTENSION UINT8 b47:1;
__EXTENSION UINT8 b48:1;
__EXTENSION UINT8 b49:1;
__EXTENSION UINT8 b50:1;
__EXTENSION UINT8 b51:1;
__EXTENSION UINT8 b52:1;
__EXTENSION UINT8 b53:1;
__EXTENSION UINT8 b54:1;
__EXTENSION UINT8 b55:1;
__EXTENSION UINT8 b56:1;
__EXTENSION UINT8 b57:1;
__EXTENSION UINT8 b58:1;
__EXTENSION UINT8 b59:1;
__EXTENSION UINT8 b60:1;
__EXTENSION UINT8 b61:1;
__EXTENSION UINT8 b62:1;
__EXTENSION UINT8 b63:1;
} bits;
} UINT64_VAL;
#endif /* __18CXX */
/***********************************************************************************/
/* Alternate definitions */
typedef void VOID;
typedef char CHAR8;
typedef unsigned char UCHAR8;
typedef unsigned char BYTE; /* 8-bit unsigned */
typedef unsigned short int WORD; /* 16-bit unsigned */
typedef unsigned long DWORD; /* 32-bit unsigned */
/* MPLAB C Compiler for PIC18 does not support 64-bit integers */
#if !defined(__18CXX)
__EXTENSION
typedef unsigned long long QWORD; /* 64-bit unsigned */
#endif /* __18CXX */
typedef signed char CHAR; /* 8-bit signed */
typedef signed short int SHORT; /* 16-bit signed */
typedef signed long LONG; /* 32-bit signed */
/* MPLAB C Compiler for PIC18 does not support 64-bit integers */
#if !defined(__18CXX)
__EXTENSION
typedef signed long long LONGLONG; /* 64-bit signed */
#endif /* __18CXX */
typedef union
{
BYTE Val;
struct
{
__EXTENSION BYTE b0:1;
__EXTENSION BYTE b1:1;
__EXTENSION BYTE b2:1;
__EXTENSION BYTE b3:1;
__EXTENSION BYTE b4:1;
__EXTENSION BYTE b5:1;
__EXTENSION BYTE b6:1;
__EXTENSION BYTE b7:1;
} bits;
} BYTE_VAL, BYTE_BITS;
typedef union
{
WORD Val;
BYTE v[2];
struct
{
BYTE LB;
BYTE HB;
} byte;
struct
{
__EXTENSION BYTE b0:1;
__EXTENSION BYTE b1:1;
__EXTENSION BYTE b2:1;
__EXTENSION BYTE b3:1;
__EXTENSION BYTE b4:1;
__EXTENSION BYTE b5:1;
__EXTENSION BYTE b6:1;
__EXTENSION BYTE b7:1;
__EXTENSION BYTE b8:1;
__EXTENSION BYTE b9:1;
__EXTENSION BYTE b10:1;
__EXTENSION BYTE b11:1;
__EXTENSION BYTE b12:1;
__EXTENSION BYTE b13:1;
__EXTENSION BYTE b14:1;
__EXTENSION BYTE b15:1;
} bits;
} WORD_VAL, WORD_BITS;
typedef union
{
DWORD Val;
WORD w[2];
BYTE v[4];
struct
{
WORD LW;
WORD HW;
} word;
struct
{
BYTE LB;
BYTE HB;
BYTE UB;
BYTE MB;
} byte;
struct
{
WORD_VAL low;
WORD_VAL high;
}wordUnion;
struct
{
__EXTENSION BYTE b0:1;
__EXTENSION BYTE b1:1;
__EXTENSION BYTE b2:1;
__EXTENSION BYTE b3:1;
__EXTENSION BYTE b4:1;
__EXTENSION BYTE b5:1;
__EXTENSION BYTE b6:1;
__EXTENSION BYTE b7:1;
__EXTENSION BYTE b8:1;
__EXTENSION BYTE b9:1;
__EXTENSION BYTE b10:1;
__EXTENSION BYTE b11:1;
__EXTENSION BYTE b12:1;
__EXTENSION BYTE b13:1;
__EXTENSION BYTE b14:1;
__EXTENSION BYTE b15:1;
__EXTENSION BYTE b16:1;
__EXTENSION BYTE b17:1;
__EXTENSION BYTE b18:1;
__EXTENSION BYTE b19:1;
__EXTENSION BYTE b20:1;
__EXTENSION BYTE b21:1;
__EXTENSION BYTE b22:1;
__EXTENSION BYTE b23:1;
__EXTENSION BYTE b24:1;
__EXTENSION BYTE b25:1;
__EXTENSION BYTE b26:1;
__EXTENSION BYTE b27:1;
__EXTENSION BYTE b28:1;
__EXTENSION BYTE b29:1;
__EXTENSION BYTE b30:1;
__EXTENSION BYTE b31:1;
} bits;
} DWORD_VAL;
/* MPLAB C Compiler for PIC18 does not support 64-bit integers */
#if !defined(__18CXX)
typedef union
{
QWORD Val;
DWORD d[2];
WORD w[4];
BYTE v[8];
struct
{
DWORD LD;
DWORD HD;
} dword;
struct
{
WORD LW;
WORD HW;
WORD UW;
WORD MW;
} word;
struct
{
__EXTENSION BYTE b0:1;
__EXTENSION BYTE b1:1;
__EXTENSION BYTE b2:1;
__EXTENSION BYTE b3:1;
__EXTENSION BYTE b4:1;
__EXTENSION BYTE b5:1;
__EXTENSION BYTE b6:1;
__EXTENSION BYTE b7:1;
__EXTENSION BYTE b8:1;
__EXTENSION BYTE b9:1;
__EXTENSION BYTE b10:1;
__EXTENSION BYTE b11:1;
__EXTENSION BYTE b12:1;
__EXTENSION BYTE b13:1;
__EXTENSION BYTE b14:1;
__EXTENSION BYTE b15:1;
__EXTENSION BYTE b16:1;
__EXTENSION BYTE b17:1;
__EXTENSION BYTE b18:1;
__EXTENSION BYTE b19:1;
__EXTENSION BYTE b20:1;
__EXTENSION BYTE b21:1;
__EXTENSION BYTE b22:1;
__EXTENSION BYTE b23:1;
__EXTENSION BYTE b24:1;
__EXTENSION BYTE b25:1;
__EXTENSION BYTE b26:1;
__EXTENSION BYTE b27:1;
__EXTENSION BYTE b28:1;
__EXTENSION BYTE b29:1;
__EXTENSION BYTE b30:1;
__EXTENSION BYTE b31:1;
__EXTENSION BYTE b32:1;
__EXTENSION BYTE b33:1;
__EXTENSION BYTE b34:1;
__EXTENSION BYTE b35:1;
__EXTENSION BYTE b36:1;
__EXTENSION BYTE b37:1;
__EXTENSION BYTE b38:1;
__EXTENSION BYTE b39:1;
__EXTENSION BYTE b40:1;
__EXTENSION BYTE b41:1;
__EXTENSION BYTE b42:1;
__EXTENSION BYTE b43:1;
__EXTENSION BYTE b44:1;
__EXTENSION BYTE b45:1;
__EXTENSION BYTE b46:1;
__EXTENSION BYTE b47:1;
__EXTENSION BYTE b48:1;
__EXTENSION BYTE b49:1;
__EXTENSION BYTE b50:1;
__EXTENSION BYTE b51:1;
__EXTENSION BYTE b52:1;
__EXTENSION BYTE b53:1;
__EXTENSION BYTE b54:1;
__EXTENSION BYTE b55:1;
__EXTENSION BYTE b56:1;
__EXTENSION BYTE b57:1;
__EXTENSION BYTE b58:1;
__EXTENSION BYTE b59:1;
__EXTENSION BYTE b60:1;
__EXTENSION BYTE b61:1;
__EXTENSION BYTE b62:1;
__EXTENSION BYTE b63:1;
} bits;
} QWORD_VAL;
#endif /* __18CXX */
#undef __EXTENSION
#endif /* __GENERIC_TYPE_DEFS_H_ */
main.c 最大支持512K的Flash,代码稍作修改就可以支持1M或以上。
#include
#include
#include
#include "GenericTypeDefs.h"
#if 1
#define DBG_MSG printf
#else
#define DBG_MSG
#endif
#define AsciiToHexByte(m,l) ( (AsciiToHexNibble(m) << 4 ) | AsciiToHexNibble(l) )
#define READ_BUFFER_SIZE 512
// Record buffer array size
#define MAX_RECORD_LENGTH 255 // Max Hex-Record Length (converted)
// Buffer for reading image file data
BYTE ReadBuffer[READ_BUFFER_SIZE];
// This structure holds the translated version of the hex record
typedef struct
{
unsigned char RecordLength; // Length record data payload (adjusted
unsigned int LoadOffset; // 16-bit offset to which the data will
unsigned char RecordType; // Type of data in the record
unsigned char data[MAX_RECORD_LENGTH] __attribute__ ((aligned (4)));
// Record data buffer - needs to be 32-bit aligned so
// that we can read 32-bit words out of it.
unsigned char Checksum; // Checksum of the record
} RECORD_STRUCT; // hexadecimal format data for transfer to aggregator
typedef enum
{
RECORD_START_TOKEN = 0,
RECORD_BYTE_COUNT_NIBBLE_1,
RECORD_BYTE_COUNT_NIBBLE_0,
RECORD_ADDRESS_NIBBLE_3,
RECORD_ADDRESS_NIBBLE_2,
RECORD_ADDRESS_NIBBLE_1,
RECORD_ADDRESS_NIBBLE_0,
RECORD_TYPE_NIBBLE_1,
RECORD_TYPE_NIBBLE_0,
RECORD_DATA,
RECORD_CHECKSUM_NIBBLE_1,
RECORD_CHECKSUM_NIBBLE_0
} RECORD_STATE;
typedef enum
{
RECORD_TYPE_DATA_RECORD = 0x00,
RECORD_TYPE_EOF = 0x01,
RECORD_TYPE_EXTENDED_ADDRESS = 0x04
} RECORD_TYPE;
#define BIN_FILE_MAX_LEN (512*1024) // max 512K
// Stores the information about the current record
RECORD_STRUCT current_record;
RECORD_STATE record_state; // This field specifies which part of the
UINT8 bin_buffer[BIN_FILE_MAX_LEN];
UINT32 bin_size;
UINT32 bin_start_address;
UINT32 bin_end_address;
UINT32 bin_len;
/****************************************************************************
Function:
unsigned char AsciiToHexNibble(unsigned char data)
Description:
Converts an ASCII byte in the range of "0 - 9", "A - F", or "a - f" to a
hex nibble
Precondition:
None
Parameters:
data - char containing the data to convert
Returns:
hex value represented by the input ASCII character (0x00 - 0x0F)
0 for input values out of range.
Remarks:
Example: value = AsciiToHexNibble('A'); // value = 0x0A
***************************************************************************/
unsigned char AsciiToHexNibble(unsigned char data)
{
if (data < '0') // return 0 for an invalid characters
{
return 0;
}
else if (data <= '9') // handle numbers
{
return ( data - '0' );
}
else if (data < 'A')
{
return 0;
}
else if (data <= 'F') // handle uppercase letters
{
return ( data - 'A' + 10 );
}
else if (data < 'a')
{
return 0;
}
else if (data <= 'f') // handle lowercase letters
{
return ( data - 'a' + 10 );
}
else
{
return 0;
}
} // AsciiToHexNibble
int ProgramHexRecord(RECORD_STRUCT* record, UINT32 address)
{
UINT8 *p;
UINT32 i;
if(address+(*record).RecordLength > BIN_FILE_MAX_LEN-1)
{
printf("address over 512K! 0x%lx
", address);
return 0;
}
p = bin_buffer + address;
for(i=0; i<(*record).RecordLength; i++)
{
*p++ = (*record).data[i];
}
if(bin_size < ((*record).RecordLength+address))
{
bin_size = ((*record).RecordLength+address);
}
return 0;
}
int ConvertFile(FILE *fp)
{
// record is currently being read.
unsigned int nRemaining; // Number of bytes remaining to decode
BYTE *p_file_data;
WORD_VAL byteCountASCII;
DWORD_VAL addressASCII;
WORD_VAL recordTypeASCII;
WORD_VAL checksumASCII;
WORD_VAL dataByteASCII;
DWORD_VAL totalAddress;
WORD_VAL extendedAddress;
BYTE calculated_checksum;
BYTE recordDataCounter;
BYTE byteEvenVsOdd;
//Generic loop index. Needs to be a WORD since a record could be 255 bytes
// and in this case written 4 bytes at a time. Thus the counts for that loop
// would be 252 and 256. Since 256 can't be represented in a byte, a loop
// counter of a byte could only count up to 252 bytes.
WORD i;
DWORD numRecordsProcessed;
// Read the file and program it to Flash
nRemaining = 0;
record_state = RECORD_START_TOKEN;
numRecordsProcessed = 0;
//DBG_MSG("Start convert
");
while(feof(fp) != EOF)
{
//Read in a BL_READ_BUFFER_SIZE block of data into the ReadBuffer. This
// data will be processed in the following loop. Record the number of
// bytes actually read into the nRemaining variable. This variable will
// track the number of bytes remaining in the ReadBuffer.
nRemaining = fread(&ReadBuffer[0], 1, READ_BUFFER_SIZE, fp );
if(nRemaining == 0)
{
//We weren't able to read any data from the file for some reason
// even though the file stream indicated that it wasn't at the end
// of the file.
//printf("File error - unable to read data from file even though it was not reported as EOF.
" );
break;
}
//point to the data read from the file
p_file_data = (BYTE*) &ReadBuffer[0];
//process all of the data read so far...
while(nRemaining)
{
switch(record_state)
{
case RECORD_START_TOKEN: //start code
if(*p_file_data == ':')
{
//move to the first state of the byte count
record_state = RECORD_BYTE_COUNT_NIBBLE_1;
}
else
{
//If we didn't see a start code ":" where we expected it, then
//ignore line feeds and line returns
if((*p_file_data != 0x0D) && (*p_file_data != 0x0A))
{
//If there was anything other than a line feed or line return
// then there was an error with the hex file. Abort the
// loading operation.
printf("Start code expected but not found.
" );
return 1;
}
}
//byte read from the buffer. Advance to the next position.
p_file_data++;
break;
case RECORD_BYTE_COUNT_NIBBLE_1: //byte count byte 1
byteCountASCII.v[1] = *p_file_data++;
//move to the next state of the byte count
record_state = RECORD_BYTE_COUNT_NIBBLE_0;
break;
case RECORD_BYTE_COUNT_NIBBLE_0: //byte count byte 2
byteCountASCII.v[0] = *p_file_data++;
current_record.RecordLength = AsciiToHexByte(byteCountASCII.v[1],byteCountASCII.v[0]);
byteEvenVsOdd = 0;
recordDataCounter = 0;
//move to the first state of the address
record_state = RECORD_ADDRESS_NIBBLE_3;
break;
case RECORD_ADDRESS_NIBBLE_3: //address byte 1
addressASCII.v[3] = *p_file_data++;
//move to the next state of the address
record_state = RECORD_ADDRESS_NIBBLE_2;
break;
case RECORD_ADDRESS_NIBBLE_2: //address byte 2
addressASCII.v[2] = *p_file_data++;
//move to the next state of the address
record_state = RECORD_ADDRESS_NIBBLE_1;
break;
case RECORD_ADDRESS_NIBBLE_1: //address byte 3
addressASCII.v[1] = *p_file_data++;
//move to the next state of the address
record_state = RECORD_ADDRESS_NIBBLE_0;
break;
case RECORD_ADDRESS_NIBBLE_0: //address byte 4
addressASCII.v[0] = *p_file_data++;
current_record.LoadOffset = ((AsciiToHexByte(addressASCII.v[3],addressASCII.v[2]))<<8) + AsciiToHexByte(addressASCII.v[1],addressASCII.v[0]);
//move to the first state of the type
record_state = RECORD_TYPE_NIBBLE_1;
break;
case RECORD_TYPE_NIBBLE_1: //record type byte 1
recordTypeASCII.v[1] = *p_file_data++;
//move to the next state of the type
record_state = RECORD_TYPE_NIBBLE_0;
break;
case RECORD_TYPE_NIBBLE_0: //record type byte 2
recordTypeASCII.v[0] = *p_file_data++;
current_record.RecordType = AsciiToHexByte(recordTypeASCII.v[1],recordTypeASCII.v[0]);
if(current_record.RecordLength == 0)
{
//There is no data stage for this record. Proceed to the
// checksum.
record_state = RECORD_CHECKSUM_NIBBLE_1;
}
else
{
//move to the data state
record_state = RECORD_DATA;
}
break;
case RECORD_DATA: //data
if(byteEvenVsOdd == 0)
{
dataByteASCII.v[1] = *p_file_data++;
byteEvenVsOdd = 1;
}
else
{
dataByteASCII.v[0] = *p_file_data++;
current_record.data[recordDataCounter++] = AsciiToHexByte(dataByteASCII.v[1],dataByteASCII.v[0]);
byteEvenVsOdd = 0;
}
//If we have read all of the data, then move to the next state
if(recordDataCounter == current_record.RecordLength)
{
record_state = RECORD_CHECKSUM_NIBBLE_1;
}
break;
case RECORD_CHECKSUM_NIBBLE_1: //checksum byte 1
checksumASCII.v[1] = *p_file_data++;
//move to the next state of the checksum
record_state = RECORD_CHECKSUM_NIBBLE_0;
break;
case RECORD_CHECKSUM_NIBBLE_0: //checksum byte 2
checksumASCII.v[0] = *p_file_data++;
current_record.Checksum = AsciiToHexByte(checksumASCII.v[1],checksumASCII.v[0]);
numRecordsProcessed++;
//Calculate the checksum of the data
calculated_checksum = current_record.RecordLength +
(current_record.LoadOffset&0xFF) +
((current_record.LoadOffset>>8)&0xFF) +
current_record.RecordType;
for(i=0;i= bin_start_address)
{
if(ProgramHexRecord(¤t_record, totalAddress.Val-bin_start_address))
{
printf("USB:There was an error programming the data
");
//There was an error programming the data. The
// error status is already set by the ProgramHexRecord function
// so we just need to close the file and exit here.
return 1;
}
}
else
{
DBG_MSG("hex_address(0x%lx) < start_address(0x%lx), ignored!
", totalAddress.Val, bin_start_address);
//return 1;
}
break;
case RECORD_TYPE_EOF:
//FSfclose( fp );
break;
case RECORD_TYPE_EXTENDED_ADDRESS:
extendedAddress.v[1] = current_record.data[0];
extendedAddress.v[0] = current_record.data[1];
break;
}
//Move to the start token phase. This record is complete.
// Start looking for the next record.
record_state = RECORD_START_TOKEN;
break;
default:
//If for some reason we are not in one of the predetermined
// states, then exit.
printf("Loader state machine in an unknown state.
" );
return 1;
}
//We have finished processing this byte. There is now one less byte
// in the ReadBuffer.
nRemaining--;
}
}
return 0;
}
UINT32 AsciiToHex(char *Strg)
{
UINT8 i;
UINT32 Val=0;
if ((Strg[0] == '0') && ((Strg[1] == 'x')||((Strg[1] == 'X'))))
{
Strg+= 2;
}
for (i=0; Strg[i]; i++)
{
if ((Strg[i] >= '0') && (Strg[i] <= '9'))
{
Val <<= 4;
Val |= (Strg[i] - '0');
}
else if ((Strg[i] >= 'a') && (Strg[i] <= 'f'))
{
Val <<= 4;
Val |= (Strg[i] - 'a' + 10);
}
else if ((Strg[i] >= 'A') && (Strg[i] <= 'F'))
{
Val <<= 4;
Val |= (Strg[i] - 'A' + 10);
}
else
{
break;
}
}
return Val;
}
int main(int argc, char *argv[])
{
#define HEX_FILE_NAME argv[1]
FILE *fp_hex;
FILE *fp_bin;
char *bin_file_name;
int bin_file_name_len;
if(argc < 2)
{
printf("too few arguments: hex2bin.exe xxx.hex [start] [end]
");
return 1;
}
// get bin file name
bin_file_name_len = strlen(HEX_FILE_NAME);
bin_file_name = (char *)malloc(bin_file_name_len+1);
if(bin_file_name == NULL)
{
printf("can't malloc bin_file_name
");
return 1;
}
strcpy(bin_file_name, HEX_FILE_NAME);
if((bin_file_name[bin_file_name_len-3] != 'h') ||
(bin_file_name[bin_file_name_len-2] != 'e') ||
(bin_file_name[bin_file_name_len-1] != 'x'))
{
printf("hex2bin.exe xxx.hex [start] [end]
");
return 1;
}
bin_file_name[bin_file_name_len-3] = 'b';
bin_file_name[bin_file_name_len-2] = 'i';
bin_file_name[bin_file_name_len-1] = 'n';
if((fp_hex=fopen(HEX_FILE_NAME, "r"))==NULL)
{
printf("Can't open %s!
", HEX_FILE_NAME);
free(bin_file_name);
return 1;
}
// convert
bin_size = 0;
bin_start_address = 0;
bin_end_address = BIN_FILE_MAX_LEN-1;
if(argc > 2)
bin_start_address = AsciiToHex(argv[2]);
if(argc > 3)
bin_end_address = AsciiToHex(argv[3]);
memset(bin_buffer, 0xFF, sizeof(bin_buffer));
if(ConvertFile(fp_hex))
{
printf("Convert hex file failed!
");
fclose(fp_hex);
free(bin_file_name);
return 1;
}
if((bin_end_address-bin_start_address) < bin_size)
bin_size = (bin_end_address-bin_start_address);
// save to bin file
if((fp_bin=fopen(bin_file_name, "wb"))==NULL)
{
printf("Cannot open %s!
", bin_file_name);
fclose(fp_hex);
free(bin_file_name);
return 1;
}
bin_len = bin_size;
DBG_MSG("%s
", bin_file_name);
DBG_MSG("start: 0x%lx
", bin_start_address);
DBG_MSG("end: 0x%lx
", bin_size);
DBG_MSG("length: 0x%lx, %ldK
", bin_len, bin_len/1024);
if(fwrite(&bin_buffer[0], 1, bin_len, fp_bin) != bin_len)
{
printf("Write %s failed!
", bin_file_name);
}
fclose(fp_hex);
fclose(fp_bin);
free(bin_file_name);
return 0;
}
biuld.bat 类似makefile功能的脚本,偷懒用的
,安装目录自己根据需要修改。
@echo off
set install_dir=D:"Program Files"hex2bin
:start
echo m: make
echo i: install
echo c: clear
echo x: exit
set /p cho=input:
if /i "%cho%"=="m" goto make
if /i "%cho%"=="i" goto install
if /i "%cho%"=="x" goto out
if /i "%cho%"=="c" goto clear
echo Invalid input!
echo.
goto start
:make
gcc -Wall main.c -o hex2bin
echo.
goto start
:install
if not exist %install_dir% mkdir %install_dir%
if not exist hex2bin.exe gcc -Wall main.c -o hex2bin
if exist hex2bin.exe copy hex2bin.exe %install_dir%
echo Install successed!
echo.
goto start
:clear
if exist hex2bin.exe del hex2bin.exe
if exist %install_dir% rd /s /q %install_dir%
echo.
goto start
:out
exit
creatbin.bat hex2bin.exe最少需要2个参数,转换的文件名和起始地址,第3个参数结束地址可选。编译安装完hex2bin之后,在mplab等mcu开发工具中直接调用此脚本就可以了。
@echo off
D:"Program Files"hex2binhex2bin.exe mcu123.hex D000 2A800
pause