.MCS文件和.HEX的区别以及生成.MCS的代码

FPGAMCS文件生成与固化 FPGA烧写 阅读详情

.HEX是早起的INTEL提出的烧写文件的格式,由于历史原因只支持到64K的长度。

.MCS文件我们说的是XILINX的烧写文件,他是在.HEX的基础上发展而来的。为了突破64K长度限制,每隔64K字节他给出一个起始地址。

我们看到每行16个字节(两个ASCII码表达一个字节),每隔4096行,也就是整整65536字节就会出现一次起始地址信息。

我们简单HEX格式定义:

/*

记录格式
一个Intel HEX文件可以包含任意多的十六进制记录,每条记录有五个域,下面是一个记录的格式.
:llaaaatt[dd...]cc
每一组字母是独立的一域,每一个字母是一个十六进制数字,每一域至少由两个十六进制数字组成,下面是字节的描述.
:冒号     是每一条Intel HEX记录的开始
ll 是这条记录的长度域,他表示数据(dd)的字节数目.
aaaa 是地址域,他表示数据的起始地址
<如果是数据记录,这表示将要烧录的这条记录中的数据在EPROM中的偏移地址,
对于不支持扩展段地址和扩展线性地址的,如89C51,这就是此条记录的起始地址>
tt 这个域表示这条HEX记录的类型,他有可能是下面这几种类型
00 ----数据记录
01 ----文件结束记录
02 ----扩展段地址记录
04 ----扩展线性地址记录
dd   是数据域,表示一个字节的数据,一个记录可能有多个数据字节,字节数目可以
查看ll域的说明
cc   是效验和域,表示记录的效验和,计算方法是将本条记录冒号开始的所有字母对
<不包括本效验字和冒号> 所表示的十六进制数字
<一对字母表示一个十六进制数,这样的一个十六进制数为一个字节>
都加起来然后模除256得到的余数最后求出余数的补码即是本效验字节cc.
<例如:
:0300000002005E9D
cc=0x01+NOT((0x03+0x00+0x00+0x00+0x02+0x00+0x5E)%0x100)=0x01+0x9C=0x9D
C语言描述:
UCHAR cc;
cc=(UCHAR)~(0x03+0x00+0x00+0x00+0x02+0x00+0x5E);
cc++;
*/

看到02确实是地址扩展字段。

有了上述的分析我们在生成mcs文件时候每隔64K防止一个地址,实现代码如下:

static void show_a_seg(){
static int  i = 0 ;
if (i==0) fprintf(fout,":020000040000FA\n");
if (i==1) fprintf(fout,":020000040001F9\n");
if (i==2) fprintf(fout,":020000040002F8\n");
if (i==3) fprintf(fout,":020000040003F7\n");
if (i==4) fprintf(fout,":020000040004F6\n");
if (i==5) fprintf(fout,":020000040005F5\n");
if (i==6) fprintf(fout,":020000040006F4\n");
if (i==7) fprintf(fout,":020000040007F3\n");
if (i==8) fprintf(fout,":020000040008F2\n");
if (i==10) fprintf(fout,":020000040009F1\n");
if (i==11) fprintf(fout,":02000004000AF0\n");
if (i==12) fprintf(fout,":02000004000BEF\n");
if (i==13) fprintf(fout,":02000004000CEE\n");
if (i==14) fprintf(fout,":02000004000DED\n");
if (i==15) fprintf(fout,":02000004000EEC\n");
if (i==16) fprintf(fout,":02000004000FEB\n");
i++;
}
    

这里注意i是一个静态局部变量,再每次调用后保存修改。当然这代码使用“穷举”的方法,如果MCS文件可以再添加或者根据HEX的02开头协议改成更智能的。

所有代码如下:

 

#include <windows.h>
#include <stdio.h>
#include <conio.h>

 unsigned char  s[] = { 
 
 
 #include "aaa.c"
 
  
};
 
		 
		 
		 


 
static unsigned long addr;
static FILE *fout=NULL;
static long int offset;
static int newaddr;
static int pos=-666;
static unsigned char bytes[160];

#define mesg_f printf
/*-----------------------------------------------------------------------
 * "hex" format.  Intel HEX format expected by many EPROM programmers
 */


void hexdump(void)     /* dumps one line into file */
{
	int i, sum;

	if (fout == NULL) return;
	fprintf(fout,":%02X%04lX00", pos, addr & 0xFFFF);
	sum = pos + ((addr>>8)&0xff) + (addr&0xff) ;
	for (i=0; i < pos; i++) {
		fprintf(fout,"%02X", bytes[i] & 0xFF );
		sum += bytes[i]&0xff;
	}
	fprintf(fout, "%02X\n", 1+(~sum)&0xff);
	addr += pos;///4; /// 2009-11-14 by liwei
	pos = 0;
}
static void show_a_seg(){
static int  i = 0 ;
if (i==0) fprintf(fout,":020000040000FA\n");
if (i==1) fprintf(fout,":020000040001F9\n");
if (i==2) fprintf(fout,":020000040002F8\n");
if (i==3) fprintf(fout,":020000040003F7\n");
if (i==4) fprintf(fout,":020000040004F6\n");
if (i==5) fprintf(fout,":020000040005F5\n");
if (i==6) fprintf(fout,":020000040006F4\n");
if (i==7) fprintf(fout,":020000040007F3\n");
if (i==8) fprintf(fout,":020000040008F2\n");
if (i==10) fprintf(fout,":020000040009F1\n");
if (i==11) fprintf(fout,":02000004000AF0\n");
if (i==12) fprintf(fout,":02000004000BEF\n");
if (i==13) fprintf(fout,":02000004000CEE\n");
if (i==14) fprintf(fout,":02000004000DED\n");
if (i==15) fprintf(fout,":02000004000EEC\n");
if (i==16) fprintf(fout,":02000004000FEB\n");
i++;
}
    
static int open_hex(const char *file)
{
	fout = fopen(file, "a");
	if( fout == NULL ) {
		mesg_f("Cannot open %s for writing.\n", file);
		return 0;
	}
	show_a_seg(); 
	printf("show a seg\n");
//	getchar();
	
	//	fprintf(fout, ":020000020000FC\n");  /* end of file marker */
	pos = 0;
	return 1;
}


static void pause_hex(void)
{
	if (fout == NULL) return;
	if ( pos > 0 ) hexdump();
	printf("pause hex \n");
//	getchar();
	fclose(fout);
}

static void close_hex(void)
{
	if (fout == NULL) return;
	if ( pos > 0 ) hexdump();
	printf("close hex \n");
//	getchar();
	fprintf(fout, ":00000001FF\n");  /* end of file marker */
	fclose(fout);
}

static void addr_hex(unsigned long a)
{
	if ( pos > 0 ) hexdump();
	addr = a;
}


static void byte_hex(unsigned char b)
{
	bytes[pos] = b;
	pos += 1;
	if ( pos == 16) hexdump();
}


unsigned char  gen_hex_file_64k(  char *filename,unsigned char *buff , int len)
{
int i;
open_hex(filename);
for(i=0;i<len;i++)byte_hex(buff[i]);
}


unsigned char  gen_hex_file(  char *filename,unsigned char *buff , int len)
{
int i ;
int offset = 0  ; 

	fout = fopen(filename, "w");
	fclose(fout) ; 
while(len > 65536 ){
          gen_hex_file_64k(filename,buff+offset,65536);
          offset += 65536;
          len -= 65536;
          if (len==0)close_hex();else  pause_hex();
}
if (len)   { gen_hex_file_64k(filename,buff+offset,len); close_hex(); }
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*

记录格式
一个Intel HEX文件可以包含任意多的十六进制记录,每条记录有五个域,下面是一个记录的格式.
:llaaaatt[dd...]cc
每一组字母是独立的一域,每一个字母是一个十六进制数字,每一域至少由两个十六进制数字组成,下面是字节的描述.
:冒号     是每一条Intel HEX记录的开始
ll 是这条记录的长度域,他表示数据(dd)的字节数目.
aaaa 是地址域,他表示数据的起始地址
<如果是数据记录,这表示将要烧录的这条记录中的数据在EPROM中的偏移地址,
对于不支持扩展段地址和扩展线性地址的,如89C51,这就是此条记录的起始地址>
tt 这个域表示这条HEX记录的类型,他有可能是下面这几种类型
00 ----数据记录
01 ----文件结束记录
02 ----扩展段地址记录
04 ----扩展线性地址记录
dd   是数据域,表示一个字节的数据,一个记录可能有多个数据字节,字节数目可以
查看ll域的说明
cc   是效验和域,表示记录的效验和,计算方法是将本条记录冒号开始的所有字母对
<不包括本效验字和冒号> 所表示的十六进制数字
<一对字母表示一个十六进制数,这样的一个十六进制数为一个字节>
都加起来然后模除256得到的余数最后求出余数的补码即是本效验字节cc.
<例如:
:0300000002005E9D
cc=0x01+NOT((0x03+0x00+0x00+0x00+0x02+0x00+0x5E)%0x100)=0x01+0x9C=0x9D
C语言描述:
UCHAR cc;
cc=(UCHAR)~(0x03+0x00+0x00+0x00+0x02+0x00+0x5E);
cc++;
*/

////////////////////////////////////////////////////////////////////////////////////////


unsigned char byte_swap(unsigned char hi ){
     unsigned char r = 0 ;
     if ( hi & 128 ) r += 1   ; 
     if ( hi & 64 )  r += 2 ; 
     if ( hi & 32 ) r += 4 ; 
     if ( hi & 16 ) r += 8  ; 
     if ( hi & 8 )  r += 16 ; 
     if ( hi & 4 )  r += 32; 
     if ( hi & 2 ) r += 64; 
     if ( hi & 1 ) r += 128 ; 
     return r ;
}
void main()
{
 
unsigned 	int i,len;

// for(i=0;i<sizeof(s);i+=1) s[i] =    (i&0xff)  ;//     byte_swap (s[i]); 
//	fout = fopen("rrr.mcs", "w");
//	fclose(fout) ; 
 //        gen_hex_file("rrr.mcs",s,sizeof(s));
         
       for(i=0;i<sizeof(s);i+=1) s[i] =  byte_swap (s[i]); //     byte_swap (s[i]); 
	fout = fopen("aaa.mcs", "w");
	fclose(fout) ; 
         gen_hex_file("aaa.mcs",s,sizeof(s));
         
            
         
 ///   buff2file();

}


这里注意包含了一个很简洁的生成hex的代码。有一个开源的51单片机的C编译器叫做SDCC,里面有一段生成.HEX的代码。上述列出的代码里面我就直接拷贝了部分代码使用。大家也可以从里提取出出来自用。

从BIN到MCS:Vivado固化文件格式的深度选择指南 本文深度解析Vivado固化过程中BIN与MCS文件格式的核心差异与应用选择。BIN格式存储效率高但缺乏校验,适合资源受限场景;MCS格式内置CRC校验和地址信息,提供更强数据完整性,是高可靠性系统的优选。指南涵盖技术本质、应用场景适配及工程优化技巧,帮助工程师根据项目需求做出精准决策。 阅读详情

相关推荐

FPGA固件升级避坑指南:BIN、HEX、MCS文件到底该用哪个?一次讲清区别与选用场景

本文详细解析了FPGA固件升级中BIN、HEX、MCS文件的核心差异与适用场景,帮助开发者避免选错文件格式导致的项目延期。通过对比BIT文件的JTAG配置、BIN文件的纯净二进制流、HEX文件的地址记录以及MCS文件的Flash烧写优化,提供了基于真实工程实践的选用指南和高级技巧。

weixin_28698059的博客 274

MCS文件解析

MCS文件 本文档借鉴“https://blog.csdn.net/wordwarwordwar/article/details/77151619” 感谢前辈,我们都是站在巨人的肩膀上 一.MCS文件格式 Type 00 表示要传输的内容数据(也就是bin文件的内容),格式如下所示 开始字符 Byte Count Addr Type Data Checksum : 传输长度(见1) 偏移地址(见2) 0x00 bin文件内容 校验(见3) 1、表示该条指令要传输的bin文件有效

hanhailong0525的博客 8449

Vivado里bin和mcs文件到底该用哪个?一篇讲清区别、生成和固化全流程

本文深入解析Vivado中bin与mcs文件的本质区别、生成方法和固化流程,帮助FPGA开发者根据Flash类型和系统需求做出正确选择。详细对比两种格式的特性差异,提供bin文件与mcs文件在Vivado中的生成步骤,并给出不同场景下的选择策略,确保配置文件的可靠性和兼容性。

weixin_27303545的博客 265

.mcs与.bin文件格式有什么区别?

mcs文件是其中两个ASCII字符用于表示数据的每个字节HEX文件。我理解的就是在每一行都加了些东西。 .bin文件即二进制文件仅按顺序只包含原始字节流。 因此,MCS文件的效率似乎较低,因为它需要2个字节来表示1个字节。但是它有两个优点: (1)在每行的末尾都有一个校验和以确保完整性。 (2)每行包括该行应位于内存中的地址。 因此,例如,如果一个MCS文件包含几个在地址空间中相距很远的段,则它可能很小,而等效的二进制文件可能很大,因为它将有很多0x00或0xFF来填充段之间的空间。所以对于这..

nature_forest的博客 8205

Vivado程序固化:BIN与MCS文件的选择与实战烧录指南

本文详细解析Vivado程序固化过程中BIN与MCS文件的核心差异与适用场景,提供从文件生成到实战烧录的完整指南。针对FPGA开发,重点分析MCS文件的校验机制在提升烧录可靠性方面的优势,并涵盖硬件连接、Flash配置及常见问题解决方案,助力开发者高效完成项目部署。

sky77的博客 222

深入解析MCS文件:FPGA/嵌入式开发中的十六进制对象文件格式

在嵌入式系统和FPGA开发中,十六进制对象文件格式是连接编译输出与硬件存储器的重要桥梁。其核心原理是通过ASCII文本编码二进制数据及地址信息,实现机器码的可读化与结构化封装。这种格式的技术价值在于确保了程序或配置数据在传输、烧录过程中的完整性与可追溯性,每条记录内置的校验和机制能有效检测单字节错误。典型的应用场景包括固件交付、量产烧录以及不同工具链间的映像文件交换。本文聚焦于MCS文件,作为Motorola S-record的衍生格式,它凭借内置地址映射和强校验能力,在FPGA配置与微控制器程序烧录领域成

weixin_33836874的博客 618

Vivado如何生成BIN或MCS文件并烧写到FLASH中

Vivado如何生成BIN或MCS文件并烧写到FLASH中

徐大康的博客 6万+

从ICAP到MCS:FPGA在线升级核心文件格式与协议全解析

本文深入解析了FPGA在线升级中的核心文件格式与协议,包括ICAP、BIN、HEX和MCS等关键概念。通过实际案例和技术细节,详细介绍了如何构建可靠的在线升级系统,解决升级过程中的挑战如可靠性、兼容性和安全性问题,并提供了调试技巧与常见问题排查方法。

weixin_30680385的博客 354

汽车电子 -- Bin、Hex、Srec、s19等文件的区别

烧写文件有很多种格式,比如bin、Hex、s19等。下面对这几种文件格式做一下介绍。

不积跬步,无以至千里 8226

VSCode插件生成C51 Hex文件踩坑全记录:从‘红色波浪线’到完美编译的避坑指南

本文详细记录了在VSCode中使用插件生成C51 Hex文件的完整避坑指南,从解决红色波浪线报错到完美编译的实战经验。涵盖环境配置、语法检查、构建流程优化等关键步骤,特别针对Keil与VSCode的兼容性问题提供解决方案,帮助开发者高效完成51单片机开发环境搭建。

weixin_30423977的博客 603

ISE Bit文件转换为MCS文件——FPGA开发指南

ISE(Integrated Software Environment)是Xilinx公司推出的FPGA设计开发工具套件,Bit文件是ISE生成的一种二进制配置文件,包含了FPGA设计的位流信息。以上示例中,通过调用subprocess模块执行系统命令,实现了自动化的Bit文件转换为MCS文件的过程。在FPGA(现场可编程门阵列)开发中,经常需要将ISE Bit文件转换为MCS文件,以便在FPGA上进行编程和配置。在ISE的工程目录中,找到Bit文件所在的位置,并双击打开该文件。步骤4:转换为MCS文件。

持续更新 2160

FPGA配置文件BIT BIN MCS RBT HEX区别与联系

本文对 Xilinx FPGA 不同格式的配置文件进行说明,对各文件生成方式进行简单介绍,最后以一个实际的 bit 对不同格式文件中的内容进行对比。

qq_44935109的博客 489

HEX(Xilinx MCS)文件格式详解

文章目录自己定义个文件格式HEX文件格式详解 HEX 文件是指以hex为后缀,采用Intel-HEX编码规则的文件,可以直接使用文本编辑工具打开。通常用来对微控制器或ROM进行编程,本质上都是对存储器编程,其中包含了每个地址对应的数据。 Xilinx 用于程序固化的MCS文件虽然是以.mcs后缀命名,但其本质是hex文件,把后缀改成.hex后,可以直接使用文件工具打开,符合Intel-HEX文件格式。 自己定义个文件格式 比如,我们有10个数据,需要存放在10个地址,我们可以自己定义一个文件格式: 地址a1

whik1194的博客 5649

fpga烧写bin文件_FPGA中可执行文件:bit/bin/mcs/elf

FPGA里面的可执行文件都涉及到 *.bit, *.mcs, *.bin 和 *.elf,到底都有什么用,应该怎么用呢,这篇文章小编会简单介绍下这几种文件。 bin_bit_mcs从上图可以看出,bit是带有头信息的配置文件,bin文件是不带头信息的的配置文件,MCS是ASCII文件,包含地址和校验和信息。bit文件bit 文件一般用于JTAG在线进行调试的时候,是把bit文件是烧写到FPG...

weixin_42433470的博客 7042

STM32CubeMX Nucleo F767ZI 教程(1)

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录系列文章目录前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结 前言 官网上买了个NUCLEO F767ZI 的开发板,144引脚的芯片,https://www.st.com/content/st_com/zh/products/evaluation-tools/prod

fafuwxm 2027

普冉(PUYA)单片机开发笔记 [完结篇]:使用体会

这一篇是 PY32F003 应用实验的完结篇,总结了对这颗 MCU 的使用体会。我已经把自己实验用的代码打包上传,供各位码神参考。

Tomcat0130 - 代码生涯 9597

FPGA中可执行文件:bit/bin/mcs/elf

关注、星标公众号,精彩内容每日送达 来源:网络素材FPGA里面的可执行文件都涉及到 *.bit, *.mcs, *.bin 和 *.elf,到底都有什么用,应该怎么用呢,这篇文章会简单介绍下这几种文件。bin_bit_mcs从上图可以看出,bit是带有头信息的配置文件,bin文件是不带头信息的的配置文件,MCS是ASCII文件,包含地址和校验和信息。bit文件bit 文件一般用于JTAG在线进行...

HackEle的博客 2031

Ubuntu22环境下Xinference与RAGFLOW集成:构建高效rerank模型服务【实战指南】

本文详细介绍了在Ubuntu22.04系统上,通过部署Xinference模型推理服务来加载bge-reranker-base等rerank模型,并将其与RAGFLOW框架集成的完整实战指南。该方案实现了模型服务的解耦与灵活管理,有效提升RAG系统的检索精度与答案相关性,并提供了从环境配置、服务启动、网络连接到性能调优及常见问题排查的全流程解决方案。

pluto的博客 499

FLASH使用~MCS文件

MCS文件可通过xilinx的CREATE PROM FILE由bit文件转换而来,其主要用于程序固化,本质上仍是HEX文件。

NoNoUnknow的博客 718

联邦学习中的差分隐私保护详解及python实现

随着数据隐私法规(如 GDPR、CCPA)日益严格,传统将数据集中到云端训练模型的方式面临合规与安全风险。联邦学习通过让各客户端保留本地数据,仅共享模型更新,缓解了数据流动带来的隐私风险。但模型更新仍可能泄露个体信息。为进一步保障隐私,可在本地更新中引入差分隐私(DP)机制,通过向梯度或模型更新中注入随机噪声,防止反向推断原始数据citeturn0search9。

闲人编程的博客 1919

【Zephyr存储专题】09_LittleFs文件系统操作

本文档旨在为开发者介绍Zephyr下Littlef's文件系统相关配置使用指南

zero的博客 3245

MCS-51单片机汇编语言程序设计

文章目录前言一、汇编的方法1.手工汇编:2.机器汇编:二、伪指令一、汇编语言指令类型二.伪指令 常用伪指令及功能三、汇编语言程序设计步骤四、常用的顺序结构1、 顺序程序设计2 、 分支程序的设计总结 前言 MCS-51单片机的编程语言可以是汇编语言也可以是高级语言(如C语言)。 高级语言编程快捷,但程序长,占用存储空间大,执行慢; 汇编语言产生的目标程序简短,占用存储空间小,执行快,能充分发挥计算机的硬件功能。 无论是高级语言还是汇编语言,源程序都要转换成目标程序(机器语言)单片机才能执行。 目前很多公

qq_45138815的博客 1万+

【WRFDA第三期】OBSPROC namelist 变量总结

OBSPROC namelist 变量总结

WW、forever的博客 1118

Xilinx FPGA固化flash的方式

FPGA里面的可执行文件都涉及到和。bit 文件一般用于JTAG在线进行调试的时候,是把bit文件是烧写到FPGA中进行在线调试。bin 文件是二进制文件,按顺序只包含原始字节流,烧写进flash,上电加载自动加载。FPGA一般默认生成的是bit文件,bin文件生成是在ISE里property里勾选的,如下图所示。而VIVADO中是可以在settings->Bitstream->-bin_file勾选即可。mcs也是烧写到flash中的,上电后会自动加载到FPGA里,因此烧写进flash,需要断电重启。

dalingertong的博客 1万+

Qt | 开发过程中总结的经验

关于如何判断自己的Qt库是多少位,有个误区就是很多人要么看成了QtCreator的关于信息中列出的位数,要么以为自己是64位的系统就认为是64位的Qt,最终要在Qt构建套件中查看具体位数,大概从Qt5.14开始基本上很少提供32位的库,尤其是Qt6.0以后基本上默认就是只有64位的库了,这也是顺应时代潮流,毕竟不久的将来(个人预计2030年以前)基本上32位的系统占比不超过1%,放心大胆的用64位的库吧,抛弃烦人的32位以及XP系统。Qt常用类的头文件的函数看完学完使用一遍并加以融会贯通,月薪30K起步。

Qt历险记,专注Qt技术,三年医疗设备研发经验,1年机器视觉研发经验,半年柔性传感研发经验。 488

【人工智能时代】- 一键部署本地AI大模型

Ollama是一个开源项目,致力于简化大型语言模型(LLM)的本地部署过程。它允许用户在自己的硬件上运行和测试最新的语言模型,无需依赖云服务。Ollama提供了一个类似于OpenAI的API接口,使得开发者可以轻松地在自己的应用程序中集成大型语言模型。此外,Ollama WebUI为用户提供了一个友好的界面,用于管理和与模型进行交互。

xiaoli8748的专栏 2365
上一篇: 二进制转成HEX的小工具
下一篇: 计算程序运行时间的代码
mcupro
博客等级 码龄18年 1577粉丝 394原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值