XET256芯片PFlash读写功能问题
时间:10-02
整理:3721RD
点击:
最近在做将控制器上的XDP512更换成XET256芯片后的代码调试,关于PFlash的擦除、读写功能均按照官方demo编写,且代码段运行时放在RAM段执行,现在遇到的问题是,使用PE调试全速运行到Pflash函数时,程序就会跳转到不正确地址运行,但如果在进入该函数时单步调试,PFlash写入和读写都正确,在读写前增加延时的方法也试了还是不行,我把测试PFLASH功能的代码贴出来,希望各位大神指点以下,不胜感激~~
#define DFLASH_LOWEST_START_PAGE 0x00 //定义data flash的起始页
#define DFLASH_START 0x00100000 //定义data flash的起始地址
#define DFLASH_PAGE_SIZE 0x0400 //定义data flash的大小为1K.
#define DFLASH_PAGE_WINDOW_START 0x0800 //定义data flash页面窗口的起始地址
unsigned int Buffer1[4]={0x1111,0x2222,0x3333,0x4444};//数据缓存区,只能一次写入四个数据
unsigned int data_Address=0x0000;
unsigned char date_read[8];
#pragma CODE_SEG Flash_Driver_FLASH//在PRM文件中该Flash段关联到RAM区0x2E00开始
void PFlash_Erase(word ADDR16)
{
while(FSTAT_CCIF==0);
if(FSTAT_ACCERR) //判断并清除标志位;
FSTAT_ACCERR=1;
if(FSTAT_FPVIOL) //判断并清除标志位;
FSTAT_FPVIOL=1;
FCCOBIX_CCOBIX=0x00;
FCCOB=0x0A7E; //写入擦除命令和高位地址
FCCOBIX_CCOBIX=0x01;
FCCOB=ADDR16; //写入低16位的地址
FSTAT_CCIF=1; //启动执行命令
while(FSTAT_CCIF==0); //等待执行完成
}
void PFlash_Write(UInt16 ADDR16,UInt16 *Buffer)
{
while(FSTAT_CCIF==0);
if(FSTAT_ACCERR) //判断并清除标志位;
FSTAT_ACCERR=1;
if(FSTAT_FPVIOL) //判断并清除标志位;
FSTAT_FPVIOL=1;
FCCOBIX_CCOBIX=0x00;
FCCOB=0x067E; //写入命令和高位地址
FCCOBIX_CCOBIX=0x01; //地址后16位
FCCOB=ADDR16; //写入低16位地址
FCCOBIX_CCOBIX=0x02; //写入第一个数据
FCCOB=*Buffer;
FCCOBIX_CCOBIX=0x03; //写入第二个数据
FCCOB=*(Buffer+1);
FCCOBIX_CCOBIX=0x04; //写入第三个数据
FCCOB=*(Buffer+2);
FCCOBIX_CCOBIX=0x05; //写入第四个数据
FCCOB=*(Buffer+3);
FSTAT_CCIF=1; //写入执行命令
}
//#pragma CODE_SEG DEFAULT
/*************************************************************/
/* 向DFLASH写入数据 */
/*************************************************************/
void DFlash_Write(UInt16 ADDR16,UInt16 *Buffer)
{
while(FSTAT_CCIF==0);
if(FSTAT_ACCERR) //判断并清除标志位;
FSTAT_ACCERR=1;
if(FSTAT_FPVIOL) //判断并清除标志位;
FSTAT_FPVIOL=1;
FCCOBIX_CCOBIX=0x00;
FCCOB=0x1110; //写入命令和高位地址
FCCOBIX_CCOBIX=0x01; //地址后16位
FCCOB=ADDR16; //写入低16位地址
FCCOBIX_CCOBIX=0x02; //写入第一个数据
FCCOB=*Buffer;
FCCOBIX_CCOBIX=0x03; //写入第二个数据
FCCOB=*(Buffer+1);
FCCOBIX_CCOBIX=0x04; //写入第三个数据
FCCOB=*(Buffer+2);
FCCOBIX_CCOBIX=0x05; //写入第四个数据
FCCOB=*(Buffer+3);
FSTAT_CCIF=1; //写入执行命令
while(FSTAT_CCIF==0); //等待执行完毕
}
/*************************************************************/
/* 擦除DFLASH的一个分区 */
/*************************************************************/
void DFlash_Erase(word ADDR16)
{
while(FSTAT_CCIF==0);
if(FSTAT_ACCERR) //判断并清除标志位;
FSTAT_ACCERR=1;
if(FSTAT_FPVIOL) //判断并清除标志位;
FSTAT_FPVIOL=1;
FCCOBIX_CCOBIX=0x00;
FCCOB=0x1210; //写入擦除命令和高位地址
FCCOBIX_CCOBIX=0x01;
FCCOB=ADDR16; //写入低16位的地址
FSTAT_CCIF=1; //启动执行命令
while(FSTAT_CCIF==0); //等待执行完成
}
/*************************************************************/
/* 由DFLASH读取数据 */
/*************************************************************/
word DFlash_Read (word destination)
{
byte lastepage; //用于存储EPAGE的值
byte epage; //用于计算EPAGE的值
unsigned int data; //读取出的数据
lastepage = EPAGE; //保存EPAGE的值
epage = (byte)((DFLASH_LOWEST_START_PAGE)+(destination >>10)); //计算EPAGE
EPAGE=epage; //给EPAGE赋值
data = READword((destination & (DFLASH_PAGE_SIZE - 1)) + DFLASH_PAGE_WINDOW_START); //读取页面窗口中的数据
EPAGE= lastepage; //恢复EPAGE的值
return(data);
}
#pragma CODE_SEG HCS12_Main_FLASH
//#pragma CODE_SEG PwrOff_RAM
void main(void)
{ UInt8 i;
unsigned char *far Addr ;
Addr = (unsigned char *far)0x7e0000;
DisableInterrupts ;//关闭中断
ECT_TSCR2_TOI = 0 ;
MainInit() ;//初始化函数,包括硬件初始化及变量初始化 / /放入Main_Init_FLASH
FlashDriver2RAM() ;//FLash的CCP相关驱动映射到RAM区
PowerOn_ValueInit() ;//控制板上电初始化 标定量及掉电保护区变量赋值
EnableInterrupts ;//开启中断
OSEK_Startcall() ;
DFlash_Erase(data_Address);
DFlash_Write(data_Address,Buffer1);
PFlash_Erase(data_Address); //确保先擦除后写入
PFlash_Write(data_Address,Buffer1);
date_read[0]=*(Addr);
date_read[1]=*(Addr+1);
date_read[2]=*(Addr+2);
date_read[3]=*(Addr+3);
date_read[4]=*(Addr+4);
date_read[5]=*(Addr+5);
date_read[6]=*(Addr+6);
date_read[7]=*(Addr+7);
MSCAN4Trans(ID_TCUandVCU,date_read) ;//
for(;;)
{
// _FEED_COP(); /* feeds the dog */
if(CCP_ProgramingFlg==0)
{
// MainProgram() ;//循环调用主控制策略
}
} /* loop forever */
/* please make sure that you never leave main */
}
#pragma CODE_SEG DEFAULT
#define DFLASH_LOWEST_START_PAGE 0x00 //定义data flash的起始页
#define DFLASH_START 0x00100000 //定义data flash的起始地址
#define DFLASH_PAGE_SIZE 0x0400 //定义data flash的大小为1K.
#define DFLASH_PAGE_WINDOW_START 0x0800 //定义data flash页面窗口的起始地址
unsigned int Buffer1[4]={0x1111,0x2222,0x3333,0x4444};//数据缓存区,只能一次写入四个数据
unsigned int data_Address=0x0000;
unsigned char date_read[8];
#pragma CODE_SEG Flash_Driver_FLASH//在PRM文件中该Flash段关联到RAM区0x2E00开始
void PFlash_Erase(word ADDR16)
{
while(FSTAT_CCIF==0);
if(FSTAT_ACCERR) //判断并清除标志位;
FSTAT_ACCERR=1;
if(FSTAT_FPVIOL) //判断并清除标志位;
FSTAT_FPVIOL=1;
FCCOBIX_CCOBIX=0x00;
FCCOB=0x0A7E; //写入擦除命令和高位地址
FCCOBIX_CCOBIX=0x01;
FCCOB=ADDR16; //写入低16位的地址
FSTAT_CCIF=1; //启动执行命令
while(FSTAT_CCIF==0); //等待执行完成
}
void PFlash_Write(UInt16 ADDR16,UInt16 *Buffer)
{
while(FSTAT_CCIF==0);
if(FSTAT_ACCERR) //判断并清除标志位;
FSTAT_ACCERR=1;
if(FSTAT_FPVIOL) //判断并清除标志位;
FSTAT_FPVIOL=1;
FCCOBIX_CCOBIX=0x00;
FCCOB=0x067E; //写入命令和高位地址
FCCOBIX_CCOBIX=0x01; //地址后16位
FCCOB=ADDR16; //写入低16位地址
FCCOBIX_CCOBIX=0x02; //写入第一个数据
FCCOB=*Buffer;
FCCOBIX_CCOBIX=0x03; //写入第二个数据
FCCOB=*(Buffer+1);
FCCOBIX_CCOBIX=0x04; //写入第三个数据
FCCOB=*(Buffer+2);
FCCOBIX_CCOBIX=0x05; //写入第四个数据
FCCOB=*(Buffer+3);
FSTAT_CCIF=1; //写入执行命令
}
//#pragma CODE_SEG DEFAULT
/*************************************************************/
/* 向DFLASH写入数据 */
/*************************************************************/
void DFlash_Write(UInt16 ADDR16,UInt16 *Buffer)
{
while(FSTAT_CCIF==0);
if(FSTAT_ACCERR) //判断并清除标志位;
FSTAT_ACCERR=1;
if(FSTAT_FPVIOL) //判断并清除标志位;
FSTAT_FPVIOL=1;
FCCOBIX_CCOBIX=0x00;
FCCOB=0x1110; //写入命令和高位地址
FCCOBIX_CCOBIX=0x01; //地址后16位
FCCOB=ADDR16; //写入低16位地址
FCCOBIX_CCOBIX=0x02; //写入第一个数据
FCCOB=*Buffer;
FCCOBIX_CCOBIX=0x03; //写入第二个数据
FCCOB=*(Buffer+1);
FCCOBIX_CCOBIX=0x04; //写入第三个数据
FCCOB=*(Buffer+2);
FCCOBIX_CCOBIX=0x05; //写入第四个数据
FCCOB=*(Buffer+3);
FSTAT_CCIF=1; //写入执行命令
while(FSTAT_CCIF==0); //等待执行完毕
}
/*************************************************************/
/* 擦除DFLASH的一个分区 */
/*************************************************************/
void DFlash_Erase(word ADDR16)
{
while(FSTAT_CCIF==0);
if(FSTAT_ACCERR) //判断并清除标志位;
FSTAT_ACCERR=1;
if(FSTAT_FPVIOL) //判断并清除标志位;
FSTAT_FPVIOL=1;
FCCOBIX_CCOBIX=0x00;
FCCOB=0x1210; //写入擦除命令和高位地址
FCCOBIX_CCOBIX=0x01;
FCCOB=ADDR16; //写入低16位的地址
FSTAT_CCIF=1; //启动执行命令
while(FSTAT_CCIF==0); //等待执行完成
}
/*************************************************************/
/* 由DFLASH读取数据 */
/*************************************************************/
word DFlash_Read (word destination)
{
byte lastepage; //用于存储EPAGE的值
byte epage; //用于计算EPAGE的值
unsigned int data; //读取出的数据
lastepage = EPAGE; //保存EPAGE的值
epage = (byte)((DFLASH_LOWEST_START_PAGE)+(destination >>10)); //计算EPAGE
EPAGE=epage; //给EPAGE赋值
data = READword((destination & (DFLASH_PAGE_SIZE - 1)) + DFLASH_PAGE_WINDOW_START); //读取页面窗口中的数据
EPAGE= lastepage; //恢复EPAGE的值
return(data);
}
#pragma CODE_SEG HCS12_Main_FLASH
//#pragma CODE_SEG PwrOff_RAM
void main(void)
{ UInt8 i;
unsigned char *far Addr ;
Addr = (unsigned char *far)0x7e0000;
DisableInterrupts ;//关闭中断
ECT_TSCR2_TOI = 0 ;
MainInit() ;//初始化函数,包括硬件初始化及变量初始化 / /放入Main_Init_FLASH
FlashDriver2RAM() ;//FLash的CCP相关驱动映射到RAM区
PowerOn_ValueInit() ;//控制板上电初始化 标定量及掉电保护区变量赋值
EnableInterrupts ;//开启中断
OSEK_Startcall() ;
DFlash_Erase(data_Address);
DFlash_Write(data_Address,Buffer1);
PFlash_Erase(data_Address); //确保先擦除后写入
PFlash_Write(data_Address,Buffer1);
date_read[0]=*(Addr);
date_read[1]=*(Addr+1);
date_read[2]=*(Addr+2);
date_read[3]=*(Addr+3);
date_read[4]=*(Addr+4);
date_read[5]=*(Addr+5);
date_read[6]=*(Addr+6);
date_read[7]=*(Addr+7);
MSCAN4Trans(ID_TCUandVCU,date_read) ;//
for(;;)
{
// _FEED_COP(); /* feeds the dog */
if(CCP_ProgramingFlg==0)
{
// MainProgram() ;//循环调用主控制策略
}
} /* loop forever */
/* please make sure that you never leave main */
}
#pragma CODE_SEG DEFAULT
已经解决,在进行PFlash操作时将所有中断关闭,就可以正常读写了
大家好!我司专注飞思卡尔,ADI单片机,主要分销国内外现货库存,可以提供免费样品/规格书,专业工程帮忙代烧录程序,有售烧录器。希望能帮到大家! 联系方式:QQ:799929715
你好,你这个对pflash操作的时候,必须关闭中断的原因,你找到了吗?我现在也遇到这种问题,但是我想知道具体原因是什么,我查了我现在的S12 芯片的手册,但是里面没有说明。
肯定是开了中断后,没有给出中断向量,程序因为进入中断,但是没有中断向量引入,导致程序跑飞了。你可以加入中断后,给出中断向量,让中断可以运行起来,这样就可以正常使用了。
我看到你的初始化中有一个CCP的初始化,你也在做和英卡的通信么?
算是吧,是基于标准CCP协议的,但是没有英卡,是自己开发的基于周立功的刷程序工具
中断向量引入 怎么做? 不是很明白,能详细讲解一下吗
不清楚你用的什么中断,但是,开启了中断,得给出一下指向向量,我一般是放在.prm文件中,不过不是很好。对了,最近我也在做bootloader的固件更新,表示一脸懵逼,还想请教一下,具体怎么操作?