574997859 发表于 2019-10-16 11:18:46

OPTION BYTE 全部锁死的问题

我在程序里边加入了修改选项字节的功能,以达到程序自动启用芯片读出保护以及扇区写保护,防止扇区数据被误写。但是设备在使用的过程中,经常出现死机的情况,具体情况为,芯片锁死,不再启动,所有的扇区写保护均已开启。具体的,我猜测是读写保护的那一个寄存器为0,看门狗配置选项的寄存器也为0了,大家可以看图片。


拿到设备,读取选项字节的参数,就如上图所示。芯片不能启动,不会工作,断电再上电也一样。
--------------------------------------------------------------------

在我调试的过程中,我发现,程序在读写flash的时候,可能由于读取的字节没有对齐,从而导致了,Flash报错的情况下,类似于WRPERR,OPERR之类的错误出现的时候,继续进行选项字节的操作,就会导致这类的问题发生,于是,我就在操作选项字节的时候,先查询错误状态寄存器,将其清空后,再写入。但一样还是出现了死机的情况。
-------------------------------------------------------------------
该问题曾请教ST专业技术人员未果,所以来论坛找高手来了。
我下面将部分代码贴出来。

【清除错误标志】
/////////////////////////////////////////////////////////////////////////////////
void ClearErrorFlag()
{
      FLASH_Status Sta = FLASH_GetStatus();
      
      while( FLASH_COMPLETE != Sta )
      {
                if( Sta == FLASH_ERROR_WRP )
                {
                        FLASH_ClearFlag(FLASH_FLAG_WRPERR);
                }
                if( Sta == FLASH_ERROR_RD )
                {
                        FLASH_ClearFlag(FLASH_FLAG_RDERR);
                }
                if( Sta == FLASH_ERROR_OPERATION )
                {
                        FLASH_ClearFlag(FLASH_FLAG_OPERR);
                }
                if( Sta == FLASH_ERROR_PROGRAM )
                {
                        FLASH_ClearFlag(FLASH_FLAG_PGSERR);
                        FLASH_ClearFlag(FLASH_FLAG_PGPERR);
                        FLASH_ClearFlag(FLASH_FLAG_PGAERR);
                }
                if( Sta == FLASH_ERROR_PGS )
                {
                        FLASH_ClearFlag(FLASH_FLAG_PGSERR);
                }
                if( Sta == FLASH_ERROR_PGP )
                {
                        FLASH_ClearFlag(FLASH_FLAG_PGPERR);
                }
                if( Sta == FLASH_ERROR_PGA )
                {
                        FLASH_ClearFlag(FLASH_FLAG_PGAERR);
                }
               
                Sta = FLASH_GetStatus();
      }
      
}



【设置选项字节】
/////////////////////////////////////////////////////////////////////////////////


void SetOptionByteWRP(const uint32_t Address, FunctionalState NewState)
{
      uint32_t GetValue;//*(__IO uint16_t*)OPTCR_BYTE2_ADDRESS
      uint32_t OB_WRP;
      MarkType WRP_AddrMark;
      
      ClearErrorFlag();
      
      //传入地址错误判断,直接返回,不操作
      WRP_AddrMark = GetWRP_Sector(Address, &OB_WRP);
      
      if( MarkNull == WRP_AddrMark )
      {
                return;
      }
      
      //验证保护扇区标志
      if( !IS_OB_WRP(OB_WRP) )
      {
                return;
      }
      
      //读取当前要设置的片区写保护状态寄存器
      if( Mark1 == WRP_AddrMark )
      {
                GetValue = *(__IO uint16_t*)OPTCR_BYTE2_ADDRESS;
      }
      else if( Mark2 == WRP_AddrMark )
      {
                GetValue = *(__IO uint16_t*)OPTCR1_BYTE2_ADDRESS;
      }
      
      //读取要设定的扇区标志                0:Active      1:Inactive
      GetValue = (GetValue & OB_WRP)?DISABLE:ENABLE;
      if( GetValue != NewState )
      {
                FLASH_WaitForLastOperation();
                FLASH_OB_Unlock();
                if( Mark1 == WRP_AddrMark )
                {
                        FLASH_OB_WRPConfig(OB_WRP, NewState);
                }
                else if( Mark2 == WRP_AddrMark )
                {
                        FLASH_OB_WRP1Config(OB_WRP, NewState);
                }
                while( FLASH_COMPLETE != FLASH_OB_Launch() );
                FLASH_OB_Lock();
                FLASH_WaitForLastOperation();
      }
      
}


【设置硬狗等选项字节】
/////////////////////////////////////////////////////////////////////////////////



void OptionByte_Other_Program(void)
{
      uint8_t               UsrCfgVal = FLASH_OB_GetUser();
      FlagStatus               RDP_StaVal = FLASH_OB_GetRDP();

      if( UsrCfgVal & 0x01 ||RDP_StaVal == RESET )
      {
                FLASH_OB_Unlock();
                if( UsrCfgVal & 0x01 )
                {
                        FLASH_WaitForLastOperation();
                        FLASH_OB_UserConfig(OB_IWDG_HW, OB_STOP_RST, OB_STDBY_NoRST);
                        FLASH_WaitForLastOperation();
                }
                if( RDP_StaVal == RESET )
                {
                        FLASH_WaitForLastOperation();
                        FLASH_OB_RDPConfig(OB_RDP_Level_1);
                        FLASH_WaitForLastOperation();
                }
                while( FLASH_COMPLETE != FLASH_OB_Launch() );
                FLASH_OB_Lock();
      }
               
}


574997859 发表于 2019-10-18 14:42:02

没人了吗?

butterflyspring 发表于 2019-10-31 12:19:51

改一个这个试试看 if( (UsrCfgVal & 0x01 ||RDP_StaVal) == RESET ) 。

574997859 发表于 2019-12-2 09:34:42

butterflyspring 发表于 2019-10-31 12:19
改一个这个试试看 if( (UsrCfgVal & 0x01 ||RDP_StaVal) == RESET ) 。

现场反馈会锁死,但是测试中不会。我们是工控产品。

butterflyspring 发表于 2019-12-4 11:02:49

那就要看看现场是否有什么不一样的情况了,通常工业现场环境复杂,但对于解决问题来说最直接发现,当然很辛苦:)
页: [1]
查看完整版本: OPTION BYTE 全部锁死的问题