资讯详情

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

bin2srec.c

/*  BIN2SREC  - Convert binary to Motorola S-Record file  Copyright (C) 1998-2012  Anthony Goffart   This program is free software: you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the 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 of  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  along 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 Xh\r", address);    this_line = min(line_length, (max_addr - address)   1);   byte_count = (addr_bytes   this_line   1);   printf("S%dX", addr_bytes - 1, byte_count);    checksum = byte_count;    for (i = addr_bytes - 1; i >= 0; i--)   {    c = (address >> (i << 3)) & 0xff;    printf("X", c);    checksum  = c;   }    fread(buf, 1, this_line, infile);    for (i = 0; i < this_line; i  )   {    printf("X", buf[i]);    checksum  = buf[i];   }    printf("X\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("S604XX\n", record_count, 255 - checksum);   }   else   {    checksum = 3   (record_count & 0xff)   ((record_count >> 8) & 0xff);    printf("S503XX\n", record_count, 255 - checksum);   }    byte_count = (addr_bytes   1);   printf("S%dX", 11 - addr_bytes, byte_count);    checksum = byte_count;    for (i = addr_bytes - 1; i >= 0; i--)   {    c = (addr_offset >> (i << 3)) & 0xff;    printf("X", c);    checksum  = c;   }   printf("X\n", 255 - checksum);  }   if (verbose)   fprintf(stderr, "Processing complete \n"); }  /***************************************************************************/  int main(int argc, char *argv[]) {  int i;  uint32_t size;  int offset_speified = 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);
		else
			end_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 bin2srec
	Copyright (C) 1998-2012  Anthony Goffart

	This file is part of SREC2BIN and BIN2SREC

	BIN2SREC and SREC2BIN are free software: you can redistribute them
	and/or modify them under the terms of the GNU General Public License
	as published by the Free Software Foundation, either version 3
	of the License, or (at your option) any later version.

	BIN2SREC and SREC2BIN are distributed in the hope that they will be
	useful, but WITHOUT ANY WARRANTY; without even the implied warranty
	of 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 along
	with 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);
	else
		return(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段开始所有字节的总和)。

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

标签: s503热继电器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台