查看: 3354|回复: 7

[其他] 飞思卡尔官方bootloader程序中的flash分频算法

[复制链接]

该用户从未签到

6

主题

24

帖子

0

注册会员

Rank: 2

积分
84
最后登录
2016-8-23
发表于 2016-7-22 14:18:14 | 显示全部楼层 |阅读模式
看飞思卡尔官方给出的bootloader中的flash的分频程序,感到很不解
1、为什么file:/// li16ClockFreq大于12000时,要并上一个0x40
2、if (FSTAT&0x30)         //Check to see if FACCERR or PVIOL are set
       {
          FSTAT |= 0x30;  //write a 1 to FACCERR and PVIOL to clear
       }
      这段代码为什么还要来一个if判断,直接写FSTAT |= 0x30;不就行了吗?

图片中的代码和文字贴出来的代码都一样,其中中文注释是我自己加上去的


  1. uint8 near vfnFlashInit(uint16 li16ClockFreq)
  2. {   
  3.   uint8 lbFlashMask = 0;
  4.   FCNFG = 0x00;           //FLASH配置寄存器,不进行任何操作或请求
  5.   if (li16ClockFreq > 1000)   /*The oscillator must be greater than 1MHz to use the Flash Routines*/
  6.   {
  7.     if (!(FCLKDIV&(0x80)))  //检查FCLKDIV是否已经被写入数据,若没有,则执行if中的语句
  8.     {
  9.       /*
  10.        * The DataSheet specifies that the value of the FCLKDIV must set the Flash Clock in a value
  11.        * between 150KHz and 200KHz. The FDIV8 Bit should be set if the value of the XTAL is greater
  12.        * than 12.8MHz; Instead of using 12.8MHz as a maximum, we are using the value of 12MHz, this
  13.        * makes the code smaller
  14.        */
  15.       if (li16ClockFreq > 12000) /*If the oscillator value is greater than 12000KHz (12.0MHz) set the PRDIV8*/
  16.       {
  17.         li16ClockFreq >>= 3;   /*Divide the frequency by 8*/
  18.         lbFlashMask = 0x40;
  19.       }
  20.       /*Calculate the value to adjust the Flash clock to 200KHz*/
  21.       FCLKDIV = (((uint8)(li16ClockFreq /200)) - 1) | lbFlashMask;
  22.     }

  23.     if (FSTAT&0x30)         //Check to see if FACCERR or PVIOL are set
  24.     {
  25.         FSTAT |= 0x30;  //write a 1 to FACCERR and PVIOL to clear
  26.     }
  27.     return(OK);
  28.   }
  29.   return(ERROR);
  30. }
复制代码


flash分频函数.png

flash分频函数.png




我知道答案 目前已有7人回答
回复

使用道具 举报

  • TA的每日心情

    2016-10-20 09:45
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    80

    主题

    1038

    帖子

    5

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    2223
    最后登录
    2023-11-20
    发表于 2016-7-22 15:45:24 | 显示全部楼层
    截图00.png
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    6

    主题

    24

    帖子

    0

    注册会员

    Rank: 2

    积分
    84
    最后登录
    2016-8-23
     楼主| 发表于 2016-7-22 16:06:30 | 显示全部楼层

    你的意思是不是  红框中的流程图说明要先检查ACCERR和FPVIOL是否置位,如果是   否   的话执行什么什么语句,如果是  是   的话,就执行先将其清零在执行相应的语句,那为什么我贴出的程序中,是FSTAT |= 0x30,用“|”怎么可能是清零呢?只能是置位呀,好疑惑
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2016-10-20 09:45
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    80

    主题

    1038

    帖子

    5

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    2223
    最后登录
    2023-11-20
    发表于 2016-7-22 17:17:04 | 显示全部楼层
    lizaozhang 发表于 2016-7-22 16:06
    你的意思是不是  红框中的流程图说明要先检查ACCERR和FPVIOL是否置位,如果是   否   的话执行什么什么语 ...

    写1是清零!
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    6

    主题

    24

    帖子

    0

    注册会员

    Rank: 2

    积分
    84
    最后登录
    2016-8-23
     楼主| 发表于 2016-7-22 17:22:59 | 显示全部楼层

    我马上要给我自己跪下啦,为什么写1是清零???!!!

    写1不是置位嘛?而且数据手册里也表明,ccif位为1时表明命令运行完成,

    那为什么不直接清零呢?为什么不直接清零呢?用if去判断一下不是显得很多余的吗?
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    郁闷
    2016-10-20 09:42
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    3

    主题

    243

    帖子

    0

    中级会员

    Rank: 3Rank: 3

    积分
    218
    最后登录
    2019-3-14
    发表于 2016-9-20 11:12:20 | 显示全部楼层
    lizaozhang 发表于 2016-7-22 17:22
    我马上要给我自己跪下啦,为什么写1是清零???!!!

    写1不是置位嘛?而且数据手册里也表明,ccif位为 ...

    置位清零~~
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    0

    主题

    6

    帖子

    0

    新手上路

    Rank: 1

    积分
    16
    最后登录
    2016-10-10
    发表于 2016-9-21 15:37:59 | 显示全部楼层
    lizaozhang 发表于 2016-7-22 17:22
    我马上要给我自己跪下啦,为什么写1是清零???!!!

    写1不是置位嘛?而且数据手册里也表明,ccif位为 ...

    在MCU的各种IP中,对flag位进行“写1清0”是最常用和普遍的做法,也有些IP是使用“写0清0”和“写ACK位清0”,对应的寄存器都有详细说明。

    写1清0的优势在于:
    1、有一定提醒作用,通常0表示假,1表示真,写1才表示有意义。
    2、防止误操作,如果这个寄存器是控制位+flag位并存,为了防止配置控制位的时候清掉了flag位,对flag位进行写1清0有一定的必要性。

    另外,使用 |= 的操作来清除flag有一定的风险,比如一个寄存器有2个flag位,现在两个flag为都位1。这时候用"|="的操作来清除其中一位,另外一位也会被误清掉。
    REG_TEST |= 0x01;
    等同于
    temp = REG_TEST;
    REG_TEST = temp|0x01;

    回复 支持 反对

    使用道具 举报

    该用户从未签到

    0

    主题

    6

    帖子

    0

    新手上路

    Rank: 1

    积分
    16
    最后登录
    2016-10-10
    发表于 2016-9-21 16:14:03 | 显示全部楼层
    本帖最后由 xuewen_he_nxp 于 2016-9-21 16:16 编辑

    if (FSTAT&0x30)         //Check to see if FACCERR or PVIOL are set
            {
               FSTAT |= 0x30;  //write a 1 to FACCERR and PVIOL to clear
            }

    这个写法是必须有if判断的,如果FSTAT在没有error flag的情况下给 FSTAT|=0x30;会触发launch command。因为|=操作会造成CCIF清除。
    只有在error flag存在的情况下,CCIF才不会被清除,这是在芯片里做的一个防护,有error的情况下,command不能被launch.

    个人认为,不用 |= 才是更安全的一种做法。
    if (FSTAT&0x30)         //Check to see if FACCERR or PVIOL are set
            {
               FSTAT = 0x30;  //write a 1 to FACCERR and PVIOL to clear
            }
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2025-9-10 23:55 , Processed in 0.110665 second(s), 29 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表