BIN 转化为 S19 格式及 S19 格式解析

来源:互联网 发布:淘宝链接怎么做的 编辑:程序博客网 时间:2024/05/19 18:42

bin2srec.c

/*BIN2SREC  - Convert binary to Motorola S-Record fileCopyright (C) 1998-2012  Anthony GoffartThis program is free software: you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation, either version 3 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program.  If not, see <http://www.gnu.org/licenses/>.*/#include <stdio.h>#include <string.h>#include <stdint.h>#include "common.h"#define HEADER1 "\nBIN2SREC " SREC_VER " - Convert binary to Motorola S-Record file.\n"char *filename;FILE *infile;uint32_t addr_offset = 0;uint32_t begin_addr;uint32_t end_addr;int addr_bytes = 2;int do_headers = TRUE;int verbose = TRUE;int line_length = 32;/***************************************************************************/void syntax(void){fprintf(stderr, HEADER1);fprintf(stderr, HEADER2);fprintf(stderr, "Syntax: BIN2SREC <options> INFILE > OUTFILE\n\n");fprintf(stderr, "-help            Show this help.\n");fprintf(stderr, "-b <begin>       Address to begin at in binary file (hex), default = 0.\n");fprintf(stderr, "-e <end>         Address to end at in binary file (hex), default = end of file.\n");fprintf(stderr, "-o <offset>      Generated address offset (hex), default = begin address.\n");fprintf(stderr, "-a <addrsize>    Number of bytes used for address (2-4),\n");fprintf(stderr, "                  default = minimum needed for maximum address.\n");fprintf(stderr, "-l <linelength>  Number of bytes per line (8-32), default = 32.\n");fprintf(stderr, "-s               Suppress header and footer records.\n");fprintf(stderr, "-q               Quiet mode - no output except S-Record.\n");}/***************************************************************************/void process(void){int i;uint32_t max_addr, address;int byte_count, this_line;unsigned char checksum;uint32_t c;int record_count = 0;unsigned char buf[32];max_addr = addr_offset + (end_addr - begin_addr);fseek(infile, begin_addr, SEEK_SET);if ((max_addr > 0xffffl) && (addr_bytes < 3))addr_bytes = 3;if ((max_addr > 0xffffffl) && (addr_bytes < 4))addr_bytes = 4;if (verbose){fprintf(stderr, HEADER1);fprintf(stderr, HEADER2);fprintf(stderr, "Input binary file: %s\n", filename);fprintf(stderr, "Begin address   = %Xh\n", begin_addr);fprintf(stderr, "End address     = %Xh\n", end_addr);fprintf(stderr, "Address offset  = %Xh\n", addr_offset);fprintf(stderr, "Maximum address = %Xh\n", max_addr);fprintf(stderr, "Address bytes   = %d\n", addr_bytes);}if (do_headers)printf("S00600004844521B\n");/* Header record */address = addr_offset;for (;;){if (verbose)fprintf(stderr, "Processing %08Xh\r", address);this_line = min(line_length, (max_addr - address) + 1);byte_count = (addr_bytes + this_line + 1);printf("S%d%02X", addr_bytes - 1, byte_count);checksum = byte_count;for (i = addr_bytes - 1; i >= 0; i--){c = (address >> (i << 3)) & 0xff;printf("%02X", c);checksum += c;}fread(buf, 1, this_line, infile);for (i = 0; i < this_line; i++){printf("%02X", buf[i]);checksum += buf[i];}printf("%02X\n", 255 - checksum);record_count++;/* check before adding to allow for finishing at 0xffffffff */if ((address - 1 + line_length) >= max_addr)break;address += line_length;}if (do_headers){if (record_count > 0xffff){checksum = 4 + (record_count & 0xff) + ((record_count >> 8) & 0xff) + ((record_count >> 16) & 0xff);printf("S604%06X%02X\n", record_count, 255 - checksum);}else{checksum = 3 + (record_count & 0xff) + ((record_count >> 8) & 0xff);printf("S503%04X%02X\n", record_count, 255 - checksum);}byte_count = (addr_bytes + 1);printf("S%d%02X", 11 - addr_bytes, byte_count);checksum = byte_count;for (i = addr_bytes - 1; i >= 0; i--){c = (addr_offset >> (i << 3)) & 0xff;printf("%02X", c);checksum += c;}printf("%02X\n", 255 - checksum);}if (verbose)fprintf(stderr, "Processing complete \n");}/***************************************************************************/int main(int argc, char *argv[]){int i;uint32_t size;int offset_specified = FALSE;int end_specified = FALSE;for (i = 1; i < argc; i++){if (!strcmp(argv[i], "-o")){addr_offset = str_to_uint32(argv[++i]);offset_specified = TRUE;continue;}else if (!strcmp(argv[i], "-b")){begin_addr = str_to_uint32(argv[++i]);continue;}else if (!strcmp(argv[i], "-e")){end_addr = str_to_uint32(argv[++i]);end_specified = TRUE;continue;}else if (!strcmp(argv[i], "-a")){sscanf(argv[++i], "%d", &addr_bytes);addr_bytes = max(2, addr_bytes);addr_bytes = min(4, addr_bytes);continue;}else if (!strcmp(argv[i], "-l")){sscanf(argv[++i], "%d", &line_length);line_length = max(8, line_length);line_length = min(32, line_length);continue;}else if (!strcmp(argv[i], "-s")){do_headers = FALSE;continue;}else if (!strcmp(argv[i], "-q")){verbose = FALSE;continue;}else if (!strncmp(argv[i], "-h", 2)) /* -h or -help */{syntax();return(0);}else{filename = argv[i];}}if (filename == NULL){syntax();fprintf(stderr, "\n** No input filename specified\n");return(1);}if ((infile = fopen(filename, "rb")) != NULL){size = file_size(infile) - 1;if (end_specified)end_addr = min(size, end_addr);elseend_addr = size;if (begin_addr > size){fprintf(stderr, "Begin address %Xh is greater than file size %Xh\n", begin_addr, size);return(3);}if (end_addr < begin_addr){fprintf(stderr, "End address %Xh is less than begin address %Xh\n", end_addr, begin_addr);return(3);}if (!offset_specified)addr_offset = begin_addr;process();fclose(infile);return(0);}else{fprintf(stderr, "Input file %s not found\n", filename);return(2);}}/***************************************************************************/

common.c

/*common.c - Common functions for both srec2bin and bin2srecCopyright (C) 1998-2012  Anthony GoffartThis file is part of SREC2BIN and BIN2SRECBIN2SREC and SREC2BIN are free software: you can redistribute themand/or modify them under the terms of the GNU General Public Licenseas published by the Free Software Foundation, either version 3of the License, or (at your option) any later version.BIN2SREC and SREC2BIN are distributed in the hope that they will beuseful, but WITHOUT ANY WARRANTY; without even the implied warrantyof MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU General Public License for more details.You should have received a copy of the GNU General Public License alongwith BIN2SREC and SREC2BIN. If not, see <http://www.gnu.org/licenses/>.*/#include <sys/stat.h>#include "common.h"/***************************************************************************/unsigned int char_to_uint(char c){int res = 0;if (c >= '0' && c <= '9')res = (c - '0');else if (c >= 'A' && c <= 'F')res = (c - 'A' + 10);else if (c >= 'a' && c <= 'f')res = (c - 'a' + 10);return(res);}/***************************************************************************/uint32_t str_to_uint32(char *s){int i;char c;uint32_t res = 0;for (i = 0; (i < 8) && (s[i] != '\0'); i++){c = s[i];res <<= 4;res += char_to_uint(c);}return(res);}/***************************************************************************/uint32_t file_size(FILE *f){struct stat info;if (!fstat(fileno(f), &info))return((uint32_t)info.st_size);elsereturn(0);}/***************************************************************************/

common.h

#ifndef COMMON_H#define COMMON_H#define SREC_VER "1.43"#define HEADER2 "Copyright (c) 2000-2014 Ant Goffart - http://www.s-record.com/\n\n"#include <stdio.h>#include <stdint.h>#ifndef FALSE#define FALSE (0)#endif#ifndef TRUE#define TRUE (~FALSE)#endif#define max(a,b) (((a)>(b))?(a):(b))#define min(a,b) (((a)<(b))?(a):(b))unsigned int char_to_uint(char s);uint32_t str_to_uint32(char *s);uint32_t file_size(FILE *f);#endif

Motorola S-records 16进制文件格式是嵌入式中除intel hex之外很常见的格式,下面是它的格式:
+-------------------//------------------//-----------------------+
| type(hex1) | count(hex 1) |  address | data | checksum(从count累加到checksum,总和为0xFF) |
+-------------------//------------------//-----------------------+
  S0    :标识记录,地址域长度为2个字节,并用0000填充,数据区记录了一些模块名称和版本之类的信息
  S1    :数据记录,地址域长度为2个字节,数据区域为数据内容。
  S2    :数据记录,地址域长度为3个字节,数据区域为数据内容。
  S3    :数据记录,地址域长度为4个字节,数据区域为数据内容。
  S5    :统计记录,地址域长度为2个字节,内容是之前数据记录(S1,S2,S3)的个数,数据区域空。
  S7    : 运行记录,地址域长度为4个字节,内容是程序启动的地址,数据域空。
  S8    :运行记录,地址域长度为3个字节,内容是程序启动的地址,数据域空。
  S9    :运行记录,地址域长度为2个字节,内容是程序启动的地址,数据域空。
下面是一个例子,大家看看:
S02B0000433A5C446F63756D656E747320616E642053657474696E67735C7A6F75642E4143434F554E54535C7D
S208010000FFFFFFFFFA
S30800020000000000F5
S5030002FA
S9030000FC
第一行:没什么,开个头而已。
第二行:地址0x10000有4个0xFF
第三行:地址0x20000有3个0x00
第四行:标明之前有两条数据记录
第五行:程序从0x0000地址开始运行
关于checksum的算法和intel hex不太一样,
checksum = 0xFF - (从count段开始所有字节的总和)。


更快学习的动力来源于适当的压力。

0 0
原创粉丝点击