
我在程序里边加入了修改选项字节的功能,以达到程序自动启用芯片读出保护以及扇区写保护,防止扇区数据被误写。但是设备在使用的过程中,经常出现死机的情况,具体情况为,芯片锁死,不再启动,所有的扇区写保护均已开启。具体的,我猜测是读写保护的那一个寄存器为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(); } } |
现场反馈会锁死,但是测试中不会。我们是工控产品。