This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
我执行 hex2000 -map *.map -a *.out后生成了两个hex文件,一个叫*.a00一个叫*.a01我到底该用哪一个呢。
你给我的工具生成的hex文件咋没指出这段程序是下载到哪个地址的。
终于看明白a00和a01原来一个是16位的高字节一个是16位的低字节,要把两个拼接起来才是一个完整的程序。
那通过CCS的post build step就可以产生ASCII的hex文件。
CCS3.3生成HEX
1.找到CCS3.3的安装目录。在C2000目录找到一个叫hex2000.exe的可执行文件。我是在下面这个目录下找到的,供您参考。C:\CCStudio_v3.3PLA\C2000\cgtools\bin 2.把要转的xxx.out文件拷到这个目录下。 3.在电脑上进入 start->run->cmd进入命令行窗口。用DOS命令进入hex2000.exe的安装目录。 hex2000 -romwidth 16 -memwidth 16 -i -o xxx.hex xxx.out就会在当前目录下生成一个叫xxx.hex的文件。
CCSv5生成HEX
1.在IDE中选择 菜单 project->propertise打开下面界面。 2.在左侧选中CCS Build 在右侧的选项卡中点击Steps 3.在最下方Apply Predefined Step选中 Create flash image: Intel-HEX 4.在编译的时候会自动生成一个xxx.hex文件。
如果要改成ASCII的hex文件,只要修改上面的命令行-i 改成-a
Eric
您好,请教您一个问题。我也想把.out转换成.hex文件,用做串口在线升级用。
您说的:“hex2000 -romwidth 16 -memwidth 16 -i -o xxx.hex xxx.out”,里面好像没有输入与.out文件对应的.map文件?
而且是不是还得通过 -e 输入指引导完成后,程序开始执行的入口地址?
还想请教一下就是关于hex文件的格式问题,比如ASCII格式,S-motorola格式等,这些不同的格式对在线升级有程序有什么影响?
xiansheng,
在命令行上增加一句 -map epwm_adc_soc.map
程序开始执行的入口地址?我认为不用。
你所需要的就是将.out文件转换成hex文件,hex文件即使对应flash地址要烧写的内容,只要把这些内容烧写进去就可以了。
至于ASCII格式或是Intel格式,这些里面都还有包含一些地址信息,或是其他符号,你需要通过上位机解析出来,哪个地址烧写什么数据,然后通过串口和芯片上的升级程序通信,将这些信息传送给芯片上的升级代码,升级代码调用flash API,烧写对应的地址。
所以上位机以及芯片上的升级代码配合起来就是CCS的烧写功能。
Eric
举个例,比如有两个数为0x1122、0x3344那么a00文件中存的是22 44,a01文件中存的是 11 33。你把这些字符转化为数字,a01的左移8位和a00的相与就可以了。
/* 十六进制字符串转换为整数 */
static unsigned long htoi(char *str, unsigned *end)
{
int i, n = 0;
unsigned long tmp = 0;
for (i = 0; i < 8; i ++)
{
if ((str[i] >= 'A') && (str[i] <= 'F'))
{
n = str[i] - 'A' + 10;
}
else if ((str[i] >= 'a') && (str[i] <= 'f'))
{
n = str[i] - 'a' + 10;
}
else if ((str[i] >= '0') && (str[i] <= '9'))
{
n = str[i] - '0';
}
else
{
break;
}
tmp = tmp * 16 + n;
}
if (end != NULL)
*end = i + 1;
return tmp;
}
这是转换程序,end会指出在遇到第几个字符转化结束。比如 char *str = "A2 3D 4C"那么转换结果为162,遇到A2后面的空格结束*end = 3。
公司的产品在几年前就设计好了,那个时候没考虑升级的问题硬件上就没留串口。但是产品中使用了双口ram和上位机ARM平台通信而且有界面。
所以在不改动硬件的情况下只有自己写bootloader。我的思路也很简单,就是先规定出升级中用到的命令和数据格式,比如擦出扇区、编程、进入升级模式等。
在应用程序中收到进入升级模式的命令后在内存中设置一个标志就打开看门狗复位系统。复位后首先进入bootloader然后检查那个内存标志从而选择进入应用程序还是bootloader。如果进入bootloader则会接收数据、解析命令、校验数据的合法性然后再调用TI官方的API。
/* 命令头文件 */
#ifndef __COMMAND_H__
#define __COMMAND_H__
#ifndef WORD
typedef unsigned short WORD;
#endif
#define PT_CMD (('M' << 8) | 'C') /* command packet type */
#define PT_DATA (('A' << 8) | 'D') /* data packet type */
#define PT_ACK (('C' << 8) | 'A') /* acknowledge packet type */
#define ACK_EOK 0 /* 成功 */
#define ACK_ECHK 1 /* 数据校验出错 */
#define ACK_EUNKNOWN 2 /* 无法识别的命令 */
#define ACK_ESIZE 3 /* 包大小错误 */
#define ACK_EBUSY 4 /* 需要等待 */
#define FLAG_DFORWORD 0xA000 /* 数据转发 */
/* 所有包的包头 */
struct pkt_hdr
{
WORD usrdata;
WORD type;
WORD tsize;
WORD chksum;
};
/* 命令包包头 */
struct cmd_hdr
{
WORD usrdata;/* 用户自定义用途 */
WORD type; /* 固定值为'C''M'(command) */
WORD tsize; /* 命令包总大小(total size)以8位字节为单位 */
WORD chksum; /* 对整个包的校验和(包括参数) */
WORD id; /* 命令的ID号(发送方自定) */
WORD retry; /* 标示此命令是否是重试上一次的操作 */
WORD cmd; /* 命令码 */
};
typedef struct cmd_hdr cmd_hdr_t;
/* 数据包包头 */
struct data_hdr
{
WORD usrdata;/* 用户自定义用途 */
WORD type; /* 固定值为'D''A'(data) */
WORD tsize; /* 整个包大小(8位字节单位) */
WORD chksum; /* 对整个包的校验和(包括数据) */
WORD addrL; /* 数据地址低16位(以8位字节为单位) */
WORD addrH; /* 数据地址高16位(以8位字节为单位) */
};
/* 确认包包头 */
struct ack_hdr
{
WORD usrdata;/* 用户自定义用途 */
WORD type; /* 固定值为'A''C'(acknowledge) */
WORD tsize; /* 整个包大小(8位字节单位) */
WORD chksum; /* 对整个包的校验和(包括数据,如果有) */
WORD id; /* 需要与命令包中的id相同 */
WORD status; /* 命令执行状态0为成功1为校验错误,其它值参见各命令 */
};
typedef enum
{
CMD_ALIVE = 0, /* 测试下位机是否处于激活状态 */
CMD_UPDATE = 1, /* 要求下位机进入升级模式 */
CMD_DOUT = 2, /* 将会有数据输出到下位机 */
CMD_DIN = 3, /* 从下位机获取数据 */
CMD_ERASE = 4, /* 擦除扇区 */
CMD_PROGRAM= 5, /* 扇区编程 */
CMD_VERIFY = 6, /* 数据确认 */
CMD_SEC_RSV= 7, /* 查询下位机的保留扇区 */
CMD_ENTRY = 8, /* 编程入口点的指令(0x3F7FF6处) */
}cmd_t;
#define ALIVE_REP_APP 0 /* 是应用程序在应答alive命令 */
#define ALIVE_REP_BTL 1 /* 是bootloader在应答alive命令 */
struct alive_reply
{
struct ack_hdr head;
WORD replier;
};
struct sec_rsv_reply
{
struct ack_hdr head;
WORD sectors;
};
/* 擦除扇区命令请求包 */
struct erase_request
{
struct cmd_hdr head;
WORD sectors;
};
/* 编程命令请求包 */
struct program_request
{
struct cmd_hdr head;
WORD p_addrL; /* 被编程地址的低16位 */
WORD p_addrH; /* 被编程地址的高16位 */
WORD immediately; /* 收到命令后立即用携带的数据编程 */
WORD s_addrL; /* 存储程序数据地址的低16位 */
WORD s_addrH; /* 存储程序数据地址的高16位 */
WORD size; /* 编程的数据大小 */
};
/* 设置应用程序入口地址命令请求包 */
struct entry_request
{
struct cmd_hdr head;
WORD run; /* 设置入口地址后是否跳转到这个地址 */
WORD entry[2]; /* 入口点 */
};
#endif
您的思路是先通过通信,在ram中设置标志,之后通过看门狗复位。
装置再次启动,在您写的bootloader中程序中读到之前写的标志,之后进行通信接收数据,经校验无误后,调用Flash API进行擦,写,校验。
那么您的启动方式还应该是flash启动,而且你做的bootloader中应该有对串口程序的初始化,以及接收、发送函数吧? 而且烧写到单独一片flash中?
我现在也在做在线升级,不过我不打算在bootloader中做通信和擦、写、校验,我打算在复位看门狗之前做这些事情。
xiansheng 您好!
我要做的基于CAN通信的,我想应该把它放到单独的一片flash中;我想问下您所说的不打算在bootloader中做通信和擦、写、校验,是什么意思啊?
您好! 我打算在通信程序里完成在线升级功能,之后再通过看门狗复位。在接收到上位机发来的升级指令后,调用把数据写入一个空白的flash C区里,经校验无误后再通过flash API函数把数据接入flash A B D中。 擦,写,校验都是flash API的函数。
咱俩思路不一样,你是通过can boot方式来做的,也就是需要跳线的那种方式。我还是用flash启动的方式做。
所以你不需要用到flash api的东西,只要把hex文件正确生成,再下发就可以了。
呵呵,您误会了,我也是需要用到flash api将下载的数据流写到flash区的;但我现在遇到一个问题就是,如果应用程序收到升级指令,并且符合升级条件,那如何跳转到自定义的bootloader程序啊?您知道吗?
你好,我是想通过can在线升级程序,现在也是遇到了如何将ccs3.3编译之后的.out文件,生产最终的bin文件,按照你所说的生成hex文件操作一遍之后,是不是每次ccs3.3编译完之后就自动生产了hex文件了啊?另外,如何确定程序烧写起始地址和结束地址啊?
我是用can在线烧写,根据您的提示我就.OUt文件转为Hex后又转为bin,调用flash API将bin文件烧录到dsp中,问题是在调用调用flash API时需要指出烧写起始地址,这个起始地址是怎么找的,或定义的呢?难道用out.文件转为Hex后又转为bin后就默认了起始地址了?
搜索者
你好,为什么需要转换成bin文件呢?
在我的理解,如果在线烧写,应该有上位机软件根据协议发送烧写数据,然后C2000在通过CAN接收数据,调用FLASH烧写。
那么这里所要的起始地址,数据,等,就都是要靠上位机来解析的。地址和数据都在hex文件中有。
Eric
我是用can自己写的引导烧写程序,我了解到的是can通讯是需要发送bin文件的,所以想将hex文件转为bin文件,我在想能不能有种简便的方式将,out转hex文件,在转为bin文件,能否将这些功能嵌套在编译CCS3.3编译器中,编译一次ccs3.3时,out、hex和bin文件都一起能出来。我是个菜鸟,能够将详细说明下如何通过hex文件看起始地址吗?谢谢!
你好,我现在用的通过ccs3.3编译完整个工程后,生产的.out文件,用你推荐的out转.hex文件方式后,通过查看hex文件数据,由out转hex文件也对,现在遇到一个问题是再有hex转bin文件,发现转为的bin只有开头和结尾正确,中间的数值都不对,这是为什么呢,能够给我推荐咱ti常用的hex转bin的工具吗,我用得51Hex_Bin。另外用的Hex2Bin工具也不行,转为的bin全部为0,不知道为何,再次期待你的解答,谢谢
生成ASICII格式的hex文件后,你用记事本打开会发现里面是'0'至'F'的一些字符。比如"A1 D4 55 DD"之类,那么'A''1'就表示一个8位数0xA1(161)。你用我在这个帖子前面的回复中给出的字符转十进制数的函数就可以得到hex文件中所有十进制数。
我现在用的是ccs3.3,dsp芯片是tms320f2808,现在是想通过can通讯来实现程序的在线升级,我之前没有做过这方面呢,你有经验一般用,你觉得hex通常需要什么格式的啊。intel格式,摩托罗拉格式还是ASCII格式?
我现在用的是ccs3.3,dsp芯片是tms320f2808,现在是想通过can通讯来实现程序的在线升级,我之前没有做过这方面呢,你有经验,你觉得hex通常需要什么格式的啊。intel格式,摩托罗拉格式还是ASCII格式?我这块确实遇到麻烦了,没有做过,所以在此就多麻烦各位大侠了!
intel 的hex文件, 或是ASCII 的hex文件也好,都是类似的,包含地址,数据。文档SPRU513F有对这两种格式的说明。
上位机解析成一个个数据包,跟芯片上自己编写的升级程序制定好一个协议,接收数据并烧写。
Eric
上位机解析成一个个数据包,我发现intel 的hex文件, 或是ASCII 的hex文件,地址并不是连续的,我每次解析时需要对每一段不连续的地址进行分析?分别烧进对应的地址空间去。我在想有没有能够生产地址连续的hex的文件?,这样地址连续了,就只考虑起始地址和结束地址地址就行了,不用考虑每一段不连续的地址了,这样通讯起来也简单。谢谢您每次的耐心的解答。
你好,我生产的hex文件某一段如下:我用的hex命令是hex2000 -romwidth 16 -memwidth 16 -i -o xxx.hex H100.out
:06 E050 00 9A 00 FE 86 00 06 A6
:20 E054 00 81AD 0000 81B5 0000 81B7 0000 81B9 0000 81D1 0000 81D3 0000 81E9 0000 81EB 0000 5A,这样就会发现E053的数据是没有的,我通过ccs在线调试发现E053的数据是FFFF,所以在这就没有数据,我的疑问是从E050到E054这块中有个断层即E053造成地址没有连续,那我每次进行烧写时需要先判断地址,在判断数据长度,就是您所说的一块一块的烧写对吗?我这样的理解对吗,有没有更好的方式呢,期待帮助中,谢谢!
能不能有种可以使生产hex文件地址联系的方式将E053的数据也加上,这样我解析时就只考虑起始地址就行了,然后烧写完全按顺序向下烧写直至结束就行了,不必每次都判断地址在判断地址的长度。
我对这块了解甚少,希望大侠们给我提供更好的思路。
我之前工程中只要一个main函数时,我定义如下的三个变量,运行时这个三个变量值都是正常为1,但是当我在mian函数之
前增加了一个bootmain在线烧写主函数后,在如此定义的话,以下三个变量都是0而不是1,这是为什么,是因为cmd配置有
错造成的吗,我仔细核对了下cmd配置没有重叠的部分,应该是没有问题。您遇见过这样现象吗,有何解决办法吗?大体的意思是程序先进入bootmain判断是否在线烧写更新程序,否则的话进入主函数main。谢谢
UINT16 Com_off=1;
UINT16 Com_on=1;
UINT16 Com_off_fault=1;
void Warn(void)
{
.......
}