Motorola S19(S-record)格式解析

news/2025/3/17 1:41:13/

S-record格式文件是Freescale CodeWarrior编译器生成的后缀名为.S19的程序文件,是一段直接烧写进MCU的ASCII码,英文全称问Motorola format for EEPROM programming。

1.格式

S-record 每行最大78字节,156个字符,由5部分组成

Image srec_motorola_1.png

Stype 1byte描述记录的类型((S0,S1,S2,S3,S5,S6,S7,S8,S9)。
Record Length1byte剩余此行后续数据 byte数,16进制
Address

2byte

3byte

4byte

记录数据地址信息,地址长度由载入地址的byte数决定
Data0-64byte代表内存载入数据或者描述信息16进制数
CheckSum1byteRecord length 、address、data 16进制数据相加求和,只保留最低byte 0xNN,CheckSum =0xFF - 0xNN 

stype描述
s0

Address没有被用,用零置位(0x0000)。数据场中的信息被划分为以下四个子域:

      name(名称):20个字符,用来编码单元名称

      ver(版本):2个字符,用来编码版本号

      rev(修订版本):2个字符,用来编码修订版本号

      description(描述):0-36个字符,用来编码文本注释

此行表示程序的开始,不需烧入memory。

s1Address 用2 byte 表示
s2Address 用3 byte 表示
s3Address 用4 byte 表示
s5Address 用 2byte 表示,包含之前的 s1,s2,s3 记录的计数,没有Data部分
s7Address 用4byte表示,包含了开始执行地址,没有Data 部分,表示程序结束,不需要烧写memory
s8Address 用3byte表示,包含了开始执行地址,没有Data 部分,表示程序结束,不需要烧写memory
s9Address 用2byte表示,包含了开始执行地址,没有Data 部分,表示程序结束,不需要烧写memory
s6Address 用 3byte 表示,包含之前的 s1,s2,s3 记录的计数,没有Data部分

2.实例

3.格式转换工具

SRecord 1.65

4.bin 转s19功能实现

/*BIN2SREC  - Convert binary to Motorola S-Record fileCopyright (C) 1998-2015  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 <stdbool.h>#include "common.h"#define HEADER1 "\nBIN2SREC " SREC_VER " - Convert binary to Motorola S-Record file.\n"char *infilename;
char *outfilename;
FILE *infile, *outfile;uint32_t addr_offset = 0;
uint32_t begin_addr;
uint32_t end_addr;
uint32_t addr_bytes = 2;
bool do_headers = true;
bool verbose = true;
uint32_t line_length = 32;
char *head_char;
bool have_header=false;
uint8_t headhex[255];
uint32_t end_flag =0;//end frame flag /***************************************************************************/void syntax(void)
{fprintf(stderr, HEADER1);fprintf(stderr, HEADER2);fprintf(stderr, "Syntax: BIN2SREC <options> INFILE > OUTFILE\n\n");fprintf(stderr, "-h               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,if have -s ,not add header records.default  add header records\n");fprintf(stderr, "-n               Add S0 note ,default none\n");fprintf(stderr, "-q               Quiet mode - no output except S-Record.\n");fprintf(stderr, "-f <end flag>            have S7 S8 S9 frame  0--nothave  1 --have  default =0\n ");
}/***************************************************************************/void process(void)
{int i;uint32_t max_addr, address;uint32_t byte_count, this_line;uint8_t checksum;uint32_t c;int record_count = 0;uint32_t head_count = 0;uint32_t head_checksum = 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((outfile = fopen(outfilename, "wb")) != NULL){}else{fprintf(stderr, "Can't create output file %s.\n", outfilename);//return(1);return;}if (verbose){fprintf(stderr, HEADER1);fprintf(stderr, HEADER2);fprintf(stderr, "Input binary file: %s\n", infilename);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   = %u\n", addr_bytes);}if(do_headers){if(have_header){head_count = strlen(head_char);fprintf(outfile,"S0%02X0000",head_count+3);head_checksum = head_count+3;for(i=0;i<head_count;i++){//headhex[i] = char_to_uint8(head_char[i]);fprintf(outfile,"%02X",head_char[i]);head_checksum +=(uint8_t)head_char[i];}checksum = 0xFF - head_checksum&0xFF;fprintf(outfile,"%02X\n",checksum);		}else{fprintf(outfile,"S00600004844521B\n");}}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);fprintf(outfile,"S%u%02X", addr_bytes - 1, byte_count);checksum = byte_count;for (i = addr_bytes - 1; i >= 0; i--){c = (address >> (i << 3)) & 0xff;fprintf(outfile,"%02X", c);checksum += c;}if(fread(buf, 1, this_line, infile)) {}for (i = 0; i < this_line; i++){fprintf(outfile,"%02X", buf[i]);checksum += buf[i];}fprintf(outfile,"%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 (1){#if 0if (record_count > 0xffff){checksum = 4 + (record_count & 0xff) + ((record_count >> 8) & 0xff) + ((record_count >> 16) & 0xff);fprintf(outfile,"S604%06X%02X\n", record_count, 255 - checksum);}else{checksum = 3 + (record_count & 0xff) + ((record_count >> 8) & 0xff);fprintf(outfile,"S503%04X%02X\n", record_count, 255 - checksum);}#endif byte_count = (addr_bytes + 1);if(end_flag==1){fprintf(outfile,"S%u%02X", 11 - addr_bytes, byte_count);}checksum = byte_count;for (i = addr_bytes - 1; i >= 0; i--){c = (addr_offset >> (i << 3)) & 0xff;fprintf(outfile,"%02X", c);checksum += c;}fprintf(outfile,"%02X\n", 255 - checksum);}if (verbose)//fprintf(stderr, "byte count %d\n",byte_count);fprintf(stderr, "Processing complete \n");
}/***************************************************************************/int main(int argc, char *argv[])
{int i;uint32_t size;bool offset_specified = false;bool 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_addr -= 1;end_specified = true;continue;}else if (!strcmp(argv[i], "-a")){sscanf(argv[++i], "%u", &addr_bytes);addr_bytes = max(2, addr_bytes);addr_bytes = min(4, addr_bytes);continue;}else if (!strcmp(argv[i], "-l")){sscanf(argv[++i], "%u", &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],"-f")){sscanf(argv[++i], "%u", &end_flag);//fprintf(stderr, "end flag %u\n",end_flag);}else if(!strcmp(argv[i],"-n")){have_header  = true;head_char = argv[++i];if(head_char == NULL){fprintf(stderr, "\n** No  head note specified\n");return(1);}}else if (!strcmp(argv[i], "-q")){verbose = false;continue;}else if (!strncmp(argv[i], "-h", 2))		 /* -h or -help */{syntax();return(0);}else{infilename = argv[i];outfilename = argv[++i];}}if (infilename == NULL){syntax();fprintf(stderr, "\n** No input infilename specified\n");return(1);}if (outfilename == NULL){//syntax();fprintf(stderr, "\n** No output infilename specified\n");return(1);}if ((infile = fopen(infilename, "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", infilename);return(2);}
}/***************************************************************************/

5.s19转bin 实现


#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>#include "common.h"#define HEADER1 "\nSREC2BIN " SREC_VER " - Convert Motorola S-Record to binary file.\n"#define LINE_LEN 1024char *infilename;
char *outfilename;
FILE *infile, *outfile;uint32_t max_addr = 0;
uint32_t min_addr = 0;uint8_t filler = 0xff;
bool verbose = true;/***************************************************************************/void syntax(void)
{fprintf(stderr, HEADER1);fprintf(stderr, HEADER2);fprintf(stderr, "Syntax: SREC2BIN <options> INFILE OUTFILE\n\n");fprintf(stderr, "-help            Show this help.\n");fprintf(stderr, "-o <offset>      Start address offset (hex), default = 0.\n");fprintf(stderr, "-a <addrsize>    Minimum binary file size (hex), default = 0.\n");fprintf(stderr, "-f <fillbyte>    Filler byte (hex), default = FF.\n");fprintf(stderr, "-q               Quiet mode\n");
}/***************************************************************************/void parse(int scan, uint32_t *max, uint32_t *min)
{int i, j;char line[LINE_LEN] = "";uint32_t address;uint32_t rec_type, addr_bytes, byte_count;char c;uint8_t buf[256];do{if(fgets(line, LINE_LEN, infile)) {}if (line[0] == 'S')								/* an S-record */{rec_type = line[1] - '0';if ((rec_type >= 1) && (rec_type <= 3))		/* data record */{address = 0;addr_bytes = rec_type + 1;for (i = 4; i < (addr_bytes * 2) + 4; i++){c = line[i];address <<= 4;address += char_to_uint8(c);}byte_count = (char_to_uint8(line[2]) << 4) + char_to_uint8(line[3]);byte_count -= (addr_bytes + 1);if (scan){if (*min > address)*min = address;if (*max < (address + (byte_count - 1)))*max = address + (byte_count - 1);}else{address -= min_addr;if (verbose)fprintf(stderr, "Writing %3u bytes at %08X\r", byte_count, address);j = 0;for (i = (addr_bytes * 2) + 4; i < (addr_bytes * 2) + (byte_count * 2) + 4; i += 2){buf[j] = (char_to_uint8(line[i]) << 4) + char_to_uint8(line[i+1]);j++;}fseek(outfile, address, SEEK_SET);fwrite(buf, 1, byte_count, outfile);}}}}while(!feof(infile));rewind(infile);
}/***************************************************************************/
#define BLOCK_SIZE 512int process(void)
{uint32_t i;uint32_t blocks, remain;uint32_t pmax = 0;uint32_t pmin = 0xffffffff;uint8_t buf[BLOCK_SIZE];if (verbose){fprintf(stderr, HEADER1);fprintf(stderr, HEADER2);fprintf(stderr, "Input Motorola S-Record file: %s\n", infilename);fprintf(stderr, "Output binary file: %s\n", outfilename);}parse(true, &pmax, &pmin);min_addr = min(min_addr, pmin);max_addr = max(pmax, min_addr + max_addr);blocks = (max_addr - min_addr + 1) / BLOCK_SIZE;remain = (max_addr - min_addr + 1) % BLOCK_SIZE;if (verbose){fprintf(stderr, "Minimum address  = %Xh\n", min_addr);fprintf(stderr, "Maximum address  = %Xh\n", max_addr);i = max_addr - min_addr + 1;fprintf(stderr, "Binary file size = %u (%Xh) bytes.\n", i, i);}if ((outfile = fopen(outfilename, "wb")) != NULL){for (i = 0; i < BLOCK_SIZE; i++)buf[i] = filler;for (i = 0; i < blocks; i++)fwrite(buf, 1, BLOCK_SIZE, outfile);fwrite(buf, 1, remain, outfile);parse(false, &pmax, &pmin);fclose(outfile);}else{fprintf(stderr, "Can't create output file %s.\n", outfilename);return(1);}if (verbose)fprintf(stderr, "Processing complete          \n");return(0);
}/***************************************************************************/int main(int argc, char *argv[])
{int i;int result = 0;for (i = 1; i < argc; i++){if (!strcmp(argv[i], "-q"))verbose = false;else if (!strcmp(argv[i], "-a"))max_addr = str_to_uint32(argv[++i]) - 1;else if (!strcmp(argv[i], "-o"))min_addr = str_to_uint32(argv[++i]);else if (!strcmp(argv[i], "-f"))filler = str_to_uint32(argv[++i]) & 0xff;else if (!strncmp(argv[i], "-h", 2))			/* -h or -help */{syntax();return(0);}else{infilename = argv[i];outfilename = argv[++i];}}if (infilename == NULL){syntax();fprintf(stderr, "\n** No input filename specified\n");return(1);}if (outfilename == NULL){syntax();fprintf(stderr, "\n** No output filename specified\n");return(1);}if ((infile = fopen(infilename, "rb")) != NULL){result = process();fclose(infile);return(result);}else{printf("Input file %s not found\n", infilename);return(2);}
}

参考

1.http://srecord.sourceforge.net/man/man5/srec_motorola.html

2.S19格式文件详解(S-record) 分享-lantianyu520-ChinaUnix博客


http://www.ppmy.cn/news/178709.html

相关文章

S19文件格式简述

转自&#xff1a;http://blog.csdn.net/finewind/article/details/5483554 1.概述 为了在不同的计算机平台之间传输程序代码和数据&#xff0c;摩托罗拉将程序和数据文件以一种可打印的格式(ASCII格式)编码成s格式文件。s格式文件是Freescale推荐使用的标准文件传送格式。编译…

hex、s19文件烧录

S19 格式定义及含义 S-record每行最大是78个字节&#xff0c;156个字符 S-record format type count address data checksum type(类型)&#xff1a;2个字符。用来描述记录的类型 (S0&#xff0c;S1&#xff0c;S2&#xff0c;S3&#xff0c;S5&#xff0c;S7&#xf…

NVR –D款设备如何将4路拓展成6路?

Q&#xff1a;NVR –D款设备如何将4路拓展成6路&#xff1f; A&#xff1a; 人机界面路径&#xff1a; 【系统配置】--->【基本配置】-->【路数扩展】 6.Q&#xff1a;NVR添加相机提示“通道IP不合法” A&#xff1a;地址冲突导致&#xff0c;修改摄像机IP地址重新添…

DV con 分析

test 2021年&#xff1a;保护膝盖不用跪求&#xff0c;DVCon2021论文合集和PPT全部内容我们都给你-面包板社区 2017年、2018年&#xff1a;DVCon相关论文 – 路科验证

display:grid;网格布局

网格布局是二维面&#xff0c;像坐标系的x轴、y轴一样。 grid-area为每个网格区域取别名&#xff1b; grid-template-columns设置网格有多少列&#xff0c;可以设置固定像素也可以设置比例&#xff0c;比例为fr单位&#xff1b; &#xff08;eg&#xff1a;grid-template-co…

DVWA 安装配置

1. 下载并安装phpStudy&#xff0c;官网地址&#xff1a;http://www.phpstudy.net 该程序包集成了Apache、php、MySQL等&#xff0c;安装之后无需配置即可使用&#xff0c;非常方便。单击图中切换版本处&#xff0c;就可以选择自己需要的版本了。 2. 下载并解压缩DVWA安装包&am…

DVWA安装手册

dvwa安装详解 一、下载软件 下载运行环境 本文使用 PhpStudy。下载链接https://www.xp.cn/ 下载DVWA。下载链接&#xff1a; https://codeload.github.com/digininja/DVWA/zip/refs/heads/master 二、启动运行环境 2.1PhpStudy安装完成后启动Apache和Mysql 2.2修改或查看数据…

dvwa最新安装教程

DVWA&#xff08;Damn Vulnerable Web Application&#xff09;是一个用来进行安全脆弱性鉴定的PHP/MySQL Web应用&#xff0c;旨在为安全专业人员测试自己的专业技能和工具提供合法的环境&#xff0c;帮助web开发者更好的理解web应用安全防范的过程。 一共有十个模块&#xf…