NC_Zyang 发表于 2014-8-19 20:16:36

飞思卡尔MC9S12XS128的DFLASH问题求助?(已解决)

本帖最后由 NC_Zyang 于 2014-8-20 15:02 编辑

这个是在网上找的例程,有些不懂的地方望大侠们帮帮忙:
#define READword(address)   ((unsigned int)(*(volatile unsigned int *__near)(address)))

#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页面窗口的起始地址
#define LEDCPU PORTK_PK4
#define LEDCPU_dir DDRK_DDRK4

unsigned int    Buffer[]={0x1111,0x2222,0x3333,0x4444};//数据缓存区,只能一次写入四个数据
unsigned int    data_Address=0x0000;
unsigned int    date_read;

void DFlash_Init(void)
{
   while(FSTAT_CCIF==0);            //等待正在处理的FLASH操作完成
   FCLKDIV=0x0F;                  //外部晶振为16M.FLASH时钟不超过1M,具体参照手册
   FCNFG=0x00;                      //禁止中断
   while(FCLKDIV_FDIVLD==0);      //等待时钟设置成功
}
void DFlash_Write(word ADDR16)
{
    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;
    FCCOBIX_CCOBIX=0x04;//写入第三个数据
    FCCOB=Buffer;
    FCCOBIX_CCOBIX=0x05;//写入第四个数据
    FCCOB=Buffer;
      
    FSTAT_CCIF=1;         //写入执行命令
    while(FSTAT_CCIF==0); //等待执行完毕
}

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);
}

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);   //等待执行完成
}
void main(void)
{
    DisableInterrupts;
    LEDCPU_dir=1;
    LEDCPU=1;
    EnableInterrupts;
   
    DFlash_Init();                  //初始化Flash
    DFlash_Erase(data_Address);   //确保先擦除后写入
    DFlash_Write(data_Address);
    date_read=DFlash_Read(data_Address);
    date_read=DFlash_Read(data_Address+2);
    date_read=DFlash_Read(data_Address+4);
    date_read=DFlash_Read(data_Address+6);

    if(date_read==0x1111&&date_read==0x2222&&date_read==0x3333&&date_read==0x4444)//判断数据是否正确
      LEDCPU=0;         //点亮指示灯
for(;;)
{
}
}

这个DFlash_Write是写DFLASH的函数,从datasheet的599页知道这个全局地址是0x100000+ADDR16,这里的ADDR16写的是0x0000;那么这个起始写的地址就是0X100000吧,datasheet已经截图了。
从主函数可以知道第一个数据0x1111在地址0x100000里,0x2222在地址0x100002里,0x3333在地址0x100004里,0x4444在地址0x100006里,通过仿真也验证了全局地址里面存的数据就是对应的数据;
但是在 DFlash_Read读DLFASH函数中,(destination & (DFLASH_PAGE_SIZE - 1)) + DFLASH_PAGE_WINDOW_START这个却是0x8000,起始读地址就是从0x108000开始的?
#define READword(address)   ((unsigned int)(*(volatile unsigned int *__near)(address)))这个用near指针,说明是在64k内,那么它所取地址范围就是0~0XFFFF内咯?怎么会知道0x100000里呢?
此外,在datasheet第137页里面可知道1KB的FLASH地址是从0x100800~0x100BFF的,但是上面的起始地址却是0x100000开始的?
上面的代码都是仿真过了的,而且正确。
请了解这个的帮我解答解答上面的疑问,谢谢。

FSL_TICS_ZJJ 发表于 2014-8-20 11:27:52

楼主你确定你的0x1111,0x2222,0x3333,0x4444都写进了DFLASH的0x100000这个地址开始?
你有没有仿真看看这个数据在Flash的地址情况。
还有你读取的时候,你也可以仿真看看,你的操作的地址是多少。

NC_Zyang 发表于 2014-8-20 13:45:47

FSL_TICS_ZJJ 发表于 2014-8-20 11:27
楼主你确定你的0x1111,0x2222,0x3333,0x4444都写进了DFLASH的0x100000这个地址开始?
你有没有仿真看看这个 ...

全部都是通过仿真器看了地址里的数据的,都是对的。

NC_Zyang 发表于 2014-8-20 13:55:25

终于解决了,不好好理解第一幅图的话还真不知道其原理,在第一幅图中,DFLASH在Global Memory Map的地址是0x100000~0x13FFFF,对应到Local Memory Map是0x0800~0x0c00,DFLASH一共256KB,在Local Memory Map却只有1KB,所以就会有EPAGE来配置,EPAGE来配置页地址,每页为1KB,这样就可以寻址到Global Memory Map的256KB了。
操作DFLASH写的是写Global Memory Address,所以是从0x100000开始的,读DFLASH是从Local Memory Address读的,所以开始地址是0x0800,如果起始写地址是0X100400,读数据的地址也是0x0800,只不过EPAGE变成1了,而前一个EPAGE为0.

FSL_TICS_ZJJ 发表于 2014-8-20 13:59:40

NC_Zyang 发表于 2014-8-20 13:45
全部都是通过仿真器看了地址里的数据的,都是对的。

那你现在的问题就是起始地址从0x100000开始,而实际操作却是从0x000000开始对吧。
这样吧,我不是16位的工程师,所以不是太熟悉这款芯片。
你到我们官网提交一个技术服务请求,会有相关的16位工程师帮你解答。
建立服务请求的链接:http://www.amobbs.com/thread-5570020-1-1.html
点击提交服务请求(service request)按钮,然后按照流程走。

NC_Zyang 发表于 2014-8-20 14:04:19

FSL_TICS_ZJJ 发表于 2014-8-20 13:59
那你现在的问题就是起始地址从0x100000开始,而实际操作却是从0x000000开始对吧。
这样吧,我不是16位的 ...

谢谢哈,现在已经解决了,主要的问题是DFLASH写操作的时候地址是GLOCAL ADDRESS开始,DFLASH读操作是LOCAL ADDRESS开始的,以前一位读写地址都是从GLOCAL开始的,主要是英文水平不过关,看英文资料没有理解清楚。

FSL_TICS_ZJJ 发表于 2014-8-20 14:30:14

NC_Zyang 发表于 2014-8-20 14:04
谢谢哈,现在已经解决了,主要的问题是DFLASH写操作的时候地址是GLOCAL ADDRESS开始,DFLASH读操作是LOCA ...

解决了就好啊。
一般应用RM中都讲的很清楚。
16位flash的操作和KINETIS还是有些区别的,之前看到你前面的local,就在想,是不是操作的前面的,呵呵。
如果你问题解决了,还请帮我及时结贴啊。
在你标题的结尾加上(已解决)。

NC_Zyang 发表于 2014-8-20 15:00:30

FSL_TICS_ZJJ 发表于 2014-8-20 14:30
解决了就好啊。
一般应用RM中都讲的很清楚。
16位flash的操作和KINETIS还是有些区别的,之前看到你前面的 ...

这个怎么加(已解决)呢?没有弄过呢。

FSL_TICS_ZJJ 发表于 2014-8-20 15:04:30

NC_Zyang 发表于 2014-8-20 15:00
这个怎么加(已解决)呢?没有弄过呢。

你已经加好了,就是编辑一楼,然后在标题后面加(已解决)。

jiang887786 发表于 2014-9-2 14:42:02

哎,我一直对这个EPAGE地址映射什么的一头雾水,现在是也没完全理解。哪位大师帮我指点一下多好!楼主能说说吗?

NC_Zyang 发表于 2014-9-6 14:05:14

jiang887786 发表于 2014-9-2 14:42
哎,我一直对这个EPAGE地址映射什么的一头雾水,现在是也没完全理解。哪位大师帮我指点一下多好!楼主能说 ...

你可以看到EPAGE的介绍,看的到全局地址的格式,然后你看低10位是CPU的Local Address,EPAGE就是设置它的页地址,因为我们DFLASH有256KB,在操作中给他分为了256个页,每页为1K,这么就有256KB的存储空间,在这里,256页就是用EPAGE来操作的,然后低10位就是CPU Local Address,就举个例子吧,我全局地址设置为0b00100 00000001
0100000000,16进制为0x100500,但是你访问肯定是访问CPU的当地地址,当地地址是0x100,这个时候如果是设置EPAGE为0,那么读取的地址就是0x100100,如果你设置EPAGE为1,那么读取的地址就是0x100500了。可能描述不是很清楚吧。大体意思是这样的。

jiang887786 发表于 2014-9-6 15:05:07

不好意思,我英文不行。谢谢楼主指教,看了10分钟我基本上理解了。那么这就是我们所说的地址映射吗?比如我们要访问16进制为0x100500地址的数据时,是cpu自己自动填写EPAGE为0x01的是吧?
题外话:2的10次方为1024,也就是1kb(暂且这样说)。然后呢EPAGE刚好处在bit10-bit17的位置上面,0-255,刚好是256,那么256*1024byte刚好是256kb。楼主你说我说的对不对呢?飞思卡尔这样设计也蛮有意思的吧!谢谢楼主指教,有问题再来回帖。感谢!

NC_Zyang 发表于 2014-9-6 17:05:12

jiang887786 发表于 2014-9-6 15:05
不好意思,我英文不行。谢谢楼主指教,看了10分钟我基本上理解了。那么这就是我们所说的地址映射吗?比如我 ...

这个主要飞思卡尔是这么设计的,如果要看其他MCU是否这么设计,需要看先关datasheet。然后就是哪个EPAGE不是CPU去控制,是我们程序去设置,就像你要读0x100500的话,那么你应该先把EPAGE设置成0x01,然后再去读地址0x100.
页: [1]
查看完整版本: 飞思卡尔MC9S12XS128的DFLASH问题求助?(已解决)