历史上的今天
今天是:2025年07月14日(星期一)
2021年07月14日 | MC9S12XE bootloader开发
2021-07-14 来源:eefocus
1、几条重要语句
1、RELOCATE_TO
该语句在prm文件中使用,如果一个代码段在运行时被移动到另一个不同的地方,则使用该语句定义。由于MC9S12XE系列单片机的FLASH模块在运行时不同同时进行读写,所以需要将对FLASH进行操作的代码移动到RAM内运行,而且如果在进行FLASH操作时,若有中断发生,那么也需要将中断程序移动到RAM中。所以对于存放FLASH操作和中断代码的内存需要利用RELOCATE_TO重定位到RAM中,示例如下:RAM_CODE = READ_ONLY 0xF000 TO 0xFEFF RELOCATE_TO 0x3800;
2、#pragma
#pragma是比较复杂的预处理指令,本文只讲涉及到的#pragma CODE_SEG xxx,预处理指令#pragma CODE_SEG xxx指示链接器将该句以下的代码放入xxx,直到遇到#pragma CODE_SEG DEFAULT.
3、#pragma与RELOCATE_TO的关系
在我们开发bootloader时,需要对FLASH进行操作,将存放APP代码的FLASH区域擦除并写入新的APP代码。由于bootloader代码也在FLASH内,故需要将bootloader中对FLASH操作的代码移动到RAM内执行。在程序中我们需要把移动到RAM内的代码整合到一起,放到一个代码段,利用#pragma CODE_SEG可以完成这个任务,比如本文中采用#pragma CODE_SEG CODE_RAM来定义一个代码段CODE_RAM,表示运行时要移动到RAM中的代码,然后我们定义一个存放CODE_RAM的内存区RAM_CODE,由于代码下载时下载到FLASH内,所以我们需要重定位,利用RELOCATE_TO完成,RAM_CODE = READ_ONLY 0xF000 TO 0xFEFF RELOCATE_TO 0x3800;,表示代码存储地址为0xF000-0xFEFF,而实际运行时需要移动到0x3800也就是RAM中运行。最后我们在PLACEMENT中将CODE_RAM放入RAM_CODE,也就是CODE_RAM INTO RAM_CODE;。
4、#define __SEG_START_REF(a)…
RELOCATE_TO虽然定义了CODE_RAM的存放区域和要移动的RAM的起始地址,但是单片机并不会自动将FLASH中的代码移动到RAM内,需要程序自己移动,故我们需要CODE_RAM代码的具体起始地址和大小,可利用以下代码完成.
#define __SEG_START_REF(a) __SEG_START_ ## a
#define __SEG_END_REF(a) __SEG_END_ ## a
#define __SEG_SIZE_REF(a) __SEG_SIZE_ ## a
#define __SEG_START_DEF(a) extern byte __SEG_START_REF (a) []
#define __SEG_END_DEF(a) extern byte __SEG_END_REF (a) []
#define __SEG_SIZE_DEF(a) extern byte __SEG_SIZE_REF (a) []
__SEG_START_DEF (CODE_RAM);
__SEG_END_DEF (CODE_RAM);
__SEG_SIZE_DEF (CODE_RAM);
上述代码定义了代码段的起始地址、大小和结束地址,在移动代码到RAM时需要用到。
2、bootloader开发流程
1、将运行时需要移动RAM内的代码用"#prama CODE_SEG xxx"单独分类,包括FLASH的擦除、写入、中断向量表和中断代码,之所以要将中断向量表和中断代码移入RAM,是为了防止FLASH擦写时对FLASH读取造成错误;
示例代码如下(.c部分,但是.h中的函数声明也需放在#pragma CODE_SEG CODE_RAM内):
1)Flash擦除与烧写部分
#pragma CODE_SEG CODE_RAM
byte FLASH_EraseSector(dword g_addr)
{
if((g_addr>=0x780000)&&(g_addr<=0x7FFFFF)&&((g_addr&0x00000007)==0))//判断全局地址的正确性,XEQ512 P_FLASH全局地址范围为0x78_0000-0x7F_FFFF
{ //P_FLASH Sector地址要求为对齐地址,低3位需为0
while(!FSTAT_CCIF); //等之前的FLASH指令完成
if(FSTAT_ACCERR|FSTAT_FPVIOL)
{
FSTAT = 0x30; //清ACCERR/FPVIOL
}
FCCOBIX = 0x00;
FCCOBHI = FLASH_CMD_ERASE_SECTOR; //写入擦除P_FLASH SECTOR指令
FCCOBLO = (byte)(g_addr>>16); //写入全局地址的高7位
FCCOBIX = 0x01;
FCCOB = (word)(g_addr & 0x0000FFFF); //写入全局地址的低16位
FSTAT = 0x80; //清零FLASH_CCIF,启动FLASH 指令
while(!FSTAT_CCIF); //等待指令完成
if(FSTAT_ACCERR | FSTAT_FPVIOL) //判断指令执行结果
return 0;
else
return 1;
}
else
{
return 0;
}
}
byte FLASH_EraseBlock(dword g_addr)
{
if((g_addr>=0x780000)&&(g_addr<=0x7FFFFF)) //判断全局地址的正确性,XEQ512 P_FLASH全局地址范围为0x78_0000-0x7F_FFFF
{
while(!FSTAT_CCIF); //等之前的FLASH指令完成
if(FSTAT_ACCERR|FSTAT_FPVIOL)
{
FSTAT = 0x30; //清ACCERR/FPVIOL
}
FCCOBIX = 0x00;
FCCOBHI = FLASH_CMD_ERASE_BLOCK; //写入擦除P_FLASH Block指令
FCCOBLO = (byte)(g_addr>>16); //写入全局地址的高7位
FCCOBIX = 0x01;
FCCOB = (word)(g_addr & 0x0000FFFF); //写入全局地址的低16位
FSTAT = 0x80; //清零FLASH_CCIF,启动FLASH 指令
while(!FSTAT_CCIF); //等待指令完成
if(FSTAT_ACCERR | FSTAT_FPVIOL) //判断指令执行结果
return 0;
else
return 1;
}
else
{
return 0;
}
}
byte FLASH_ProgramRecordPhrase(dword g_addr, byte *phrase)
{
if((g_addr>=0x780000)&&(g_addr<=0x7FFFFF)) //判断全局地址的正确性,XEQ512 P_FLASH全局地址范围为0x78_0000-0x7F_FFFF
{
byte i;
while(!FSTAT_CCIF); //等之前的FLASH指令完成
if(FSTAT_ACCERR|FSTAT_FPVIOL)
{
FSTAT = 0x30; //清零 ACCERR/FPVIOL
}
FCCOBIX = 0x00;
FCCOBHI = FLASH_CMD_PROGRAM_RECORD; //写入烧录P_FLASH Record的指令
FCCOBLO = (byte)(g_addr>>16); //写入全局地址的高7位
FCCOBIX = 0x01;
FCCOB = (word)(g_addr & 0x0000ffff); //写入全局地址的低16位
for(i=2;i<6;i++) //写8个字节数据到FCCOB寄存器
{
FCCOBIX = i;
FCCOBHI = *phrase;
FCCOBLO = *(phrase+1);
phrase = phrase+2;
}
FSTAT = 0x80; //清零FLASH_CCIF,启动FLASH 指令
while(!FSTAT_CCIF); //等待指令完成
if(FSTAT_ACCERR | FSTAT_FPVIOL) //判断指令执行结果
return 0;
else
return 1;
}
else
{
return 0;
}
}
#pragma CODE_SEG DEFAULT
2)中断函数部分
#pragma CODE_SEG CODE_RAM
interrupt void PIT0_Isr(void){
g_Pit0_Cnt++;
if(g_Pit0_Cnt>=3600000)
{
g_Pit0_Cnt=0;
}
PITTF_PTF0=1; //清零超时标志位
}
dword CAN2MCU(dword id)
{
dword result=0;
dword temp_id1=0;
dword temp_id2=0;
temp_id1=(id>>1)&0x3FFFF;
temp_id2=(id>>3)&0x1FFC0000;
result=temp_id1|temp_id2;
return result;
}
interrupt void CAN0_Rx_Isr(void)
{
g_Rx_Can_Msg.id.id_byte[0] = CAN0RXIDR0;
g_Rx_Can_Msg.id.id_byte[1] = CAN0RXIDR1;
g_Rx_Can_Msg.id.id_byte[2] = CAN0RXIDR2;
g_Rx_Can_Msg.id.id_byte[3] = CAN0RXIDR3;
g_Rx_Can_Msg.id.id_dword=CAN2MCU(g_Rx_Can_Msg.id.id_dword);
g_Rx_Can_Msg.data[0] = CAN0RXDSR0;
g_Rx_Can_Msg.data[1] = CAN0RXDSR1;
g_Rx_Can_Msg.data[2] = CAN0RXDSR2;
g_Rx_Can_Msg.data[3] = CAN0RXDSR3;
g_Rx_Can_Msg.data[4] = CAN0RXDSR4;
g_Rx_Can_Msg.data[5] = CAN0RXDSR5;
g_Rx_Can_Msg.data[6] = CAN0RXDSR6;
g_Rx_Can_Msg.data[7] = CAN0RXDSR7;
g_Rx_Can_Msg.len=CAN0RXDLR&0x0f;
g_Rx_Can_Msg.rx_flag=1;
Quene_AddMsg(g_Rx_Can_Msg);
CAN0RFLG_RXF=1;
}
#pragma CODE_SEG DEFAULT
2、修改prm文件,根据需移入RAM代码段大小分配FLASH大小和RAM起始地址;
3、将flash内代码移动到对应的RAM地址内;
#define __SEG_START_REF(a) __SEG_START_ ## a
#define __SEG_END_REF(a) __SEG_END_ ## a
#define __SEG_SIZE_REF(a) __SEG_SIZE_ ## a
#define __SEG_START_DEF(a) extern byte __SEG_START_REF (a) []
#define __SEG_END_DEF(a) extern byte __SEG_END_REF (a) []
#define __SEG_SIZE_DEF(a) extern byte __SEG_SIZE_REF (a) []
__SEG_START_DEF (CODE_RAM);
__SEG_END_DEF (CODE_RAM);
__SEG_SIZE_DEF (CODE_RAM);
void CopyCodeToRAM(void)
{
byte *p_src;
byte *p_dst;
word seg_size;
word i=0;
p_src = (byte *)__SEG_START_REF(CODE_RAM);
p_dst = (byte *)0x3800;
seg_size =(word)__SEG_SIZE_REF(CODE_RAM);
for(i=0;i if((word)p_dst > 0x3F00) _asm(nop); *p_dst++ = *p_src++; } } 4、对中断向量表进行修改,主要是将中断向量表定义在RAM区; #define VECTORTABLEBASEADDR 0x3F00 #define PIT0ISRVECTORNUM 0x7A #define CAN0RXISRVECTORNUM 0xB2 void Isr_Init() { IVBR=VECTORTABLEBASEADDR>>8; *(word*)(VECTORTABLEBASEADDR+PIT0ISRVECTORNUM)=(word)PIT0_Isr; *(word*)(VECTORTABLEBASEADDR+CAN0RXISRVECTORNUM)=(word)CAN0_Rx_Isr; } 5、进行所需驱动的设计; 6、擦除存放APP代码的FLASH区域; 7、根据接收的上位机发送的S19文件中的record将代码按地址烧写到Flash内; 8、程序烧写完毕后,跳转到APP的启动地址,开始运行APP。
史海拾趣
|
非易失性铁电存储器(FRAM)和集成半导体产品供应商及开发商Ramtron International宣布,韩国现代Hyundai Autonet公司选用了其生产的FRAM产品用于该公司的汽车智能安全气囊和乘客传感器中。 据介绍,非易失性存储器(FRAM)具有读写寿命长、写入数 ...… 查看全部问答> |
|
随着Windows Embedded CE的发展,对象存储的作用越来越小,而大容量的永久存储设备被越来越多地采用。Windows Embedded CE文件系统是一种灵活的模块化设计,它允许自定义文件系统、筛选器和多种不同的块设备类型。一般来说,Windows Embedded CE基 ...… 查看全部问答> |
|
如题,谁知道做这两件事要哪些专业的工具??谁有介绍下或者发点资料下载下。谢谢,路过的大侠快来帮忙呀 如题,如果要负责公司交换机PC等维护,需要些什么工具了,本人之前没有做过,现在有可能转行了!所以请教各位大侠!!谢谢!! [ 本帖最后 ...… 查看全部问答> |
|
arm板与称重显示控制器通过rs232连接,在arm上打开串口调试程序,波特率什么的设置好,但是一点反应都没有,主要是想要把称重显示控制器上的读数读取过来。请问,是什么原因,还需要在arm的系统wince中安装称重显示控制器的驱动程序才行?大家帮下 ...… 查看全部问答> |
|
config.bib之NK SIZE RAMIMAGE 与 ROMSIZE关系? NK 80100000 01F00000 RAMIMAGE RAM 82000000   ...… 查看全部问答> |
|
菜鸟请教:我在使用Application Verifier for Mobile 5.0时为什么总报shimeng错误 我想用Application Verifier for Mobile 5.0测试我的应用程序,我按照教程将 Transport 和 startup设置为Microsoft ActiveSync,然后进行“Connect...”结果总是提示“Unable to load shimeng(shim.dll)on device” 注:这个时候PPC是打开了的,与 ...… 查看全部问答> |
|
例如PORTA的引脚2和PORTB的引脚2,好像不能同时作为EXTI的外部中断引脚?我从手册上看,第n个EXTI源只能来自指定端 ...… 查看全部问答> |
|
据调查,许多写字楼都不同程度地存在着危害公共健康的污染,空气品质的问题以及湿度的平衡、光照、通风状况和清洁程度都直接关系人们的健康。办公室的环境也会直接影响员工的情绪,某种意义上比大气、水质、噪声等污染更为严重,它会涣散人们工作的 ...… 查看全部问答> |




