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.

【求教】FLASH写操作时的分频系数设置

Other Parts Discussed in Thread: MSP430G2553

以前写FLASH时一直没怎么注意分频系数FN的选择,都简单一句FCTL2=FWKEY + FSSEL0 +FN0;

后来做了一批产品后发现保存在FLASH信息段的数据偶尔会出错,一直没找到原因。

今天仔细检查的时候突然发觉,FCTL2寄存器有分频的设置,会不会是分频系数设置的问题?

我仔细查了下MSP430G2553的数据手册,发现FLASH有个闪存时序生成器频率fFTG为257-476kHz的说明。

对这个不怎么理解,是不是说,要写FLASH时,要配置FCTL2的分频系数到fFTG范围?

例如:

MCLK=1M时,分频系数要设置为FCTL2=FWKEY+FSSEL0+FN0+FN1;即3分频,得到的闪存频率就是300多k,符合fFTG范围。

MCLK=8M时,分频系数要设置为FCTL2=FWKEY+FSSEL0+FN3+FN4;即24分频,得到的闪存频率就是接近350k,符合fFTG范围。

上面的两个理解是不是正确?是不是配置正确的分频后,写FLASH数值就不会出错?

另外我以前MCLK一直设置为8M,分频配置为FCTL2=FWKEY + FSSEL0 +FN0;这样是不是就是导致偶尔FLASH数据错误的原因?做测试板的时候没发现这个问题,做出批量后才发现的。

  • ddd ddd,

    关于你的理解,有以下几点建议:

    1. 你的配置中,FSSEL0应该对应FLASH的source clock应该为ACLK, 而非MCLK, 故计算时,不可用MCLK. 如果计算的fFTG在datasheet中所指的范围之外的话,写和擦写的结果是不可预料的。

    2. 即使你设置fFTG在datasheet中所指定的范围之内了,也有可能会出现FLASH数据偶尔出错的,因为FLASH操作有很多注意事项:

    A: 进行FLASH写或擦除时,供电电压必须大于等于2.2V;

    B: 若是在FLASH写或擦除过程中,由于电源不稳或干扰太大等导致clock failure, 也有可能会导致数据出错,可以通过查询对应FAIL flag是否被置来确定。

    希望对你有帮助!O(∩_∩)O~

  • 谢谢解答,亦既是说即便fFTG设置对了,也可能会有读写出的数据不正确的现象吗?

    那我将FLASH读写都加上验证,写数据的时候,写入数据,然后将写入的数据读出来,再将读出的数据和原写入的数据对照,相同则通过,不同则重新写,这样做应该就可以了吧。

    //下面是写数据的代码

    char *p;//flash指针
    p=(char *)0x1000; // 指定指针位置
    p++;
    _DINT();//关中断
    FCTL2=FWKEY + FSSEL_1 + FN0+FN1;//选择MCLK,3分频
    FCTL1=FWKEY + ERASE;//允许擦除
    FCTL3=FWKEY; //解锁

    *p=0; //任意写一数据,该段会全部擦除
    while(FCTL3&BUSY);
    FCTL1=FWKEY+WRT; //允许写入
    while(FCTL3&BUSY);
    do
    {
      *(p+0)=ID[0];
      *(p+1)=ID[1];
      *(p+2)=ID[2];
      *(p+3)=ID[3];
    while(FCTL3&BUSY);
    }
    while((*(p+0)!=ID[0])||(*(p+1)!=ID[1])||(*(p+2)!=ID[2])||(*(p+3)!=ID[3]));//检验读出的数据和写入的数据是否一致
    FCTL1=FWKEY;
    FCTL3=FWKEY+LOCK;//锁定
    _EINT();//开中断

    //下面是读数据的代码

    char *p;//flash指针
    p=(char *)0x1000; // 指定指针位置
    p++;
    do
    {
    ID[0]=*(p+0);
    ID[1]=*(p+1);
    ID[2]=*(p+2);
    ID[3]=*(p+3);
    }
    while((ID[0]!=*(p+0))||(ID[1]!=*(p+1))||(ID[2]!=*(p+2))||(ID[3]!=*(p+3)));

    这样处理应该没问题吧?

  • ddd ddd,

    是的,即便fFTG设置对了,也可能会有读写出的数据不正确的现象。你的方法可以增加正确的概率,但是会导致效率的下降。更建议你整体检查一下系统设计和布板,增加系统的抗干扰性能。