說明:
很多IC廠家僅釋出了內部Flash演算法檔案,並沒有提供讀防寫演算法檔案,也就是選項位元組演算法檔案,需要我們製作。
實際上當前已經發布的TOOL版本,已經自制很多了。但是依然有些廠家還沒自制,所以陸續開始為這些廠家提供讀防寫支援。
實現效果:
本次新增國民技術的N32G003,從2.26版本開始將正式帶此支援,支援解除和使能。
實現程式碼和原理
透過H7-TOOL的LUA小程式就可以方便的實現保護解除和使能,不需要自制演算法檔案。
對應的程式碼如下,這個不需要使用者去管,已經封裝到TOOL裡面了,這裡給大家分享是方便大家瞭解:
--暫存器 local FLASH_FLASHKEY = 0x40022004 local FLASH_OPTKEY = 0x40022008 local FLASH_CTRL = 0x40022010 local FLASH_FLASH_STS = 0x4002200C local FLASH_OB_Address = 0x1FFFF600 --暫存器bit local CTRL_Set_OPTER = 0x00000020 local CTRL_Set_START = 0x00000040 local CTRL_Reset_OPTER = 0x0000FFDF local CTRL_Set_OPTPG = 0x00000010 local FLASH_FLAG_PGERR = 0x00000004 -- /*!< FLASH Program error flag */ local FLASH_FLAG_WRPERR = 0x00000010 -- /*!< FLASH Write protected error flag */ local FLASH_FLAG_EOP = 0x00000020 -- /*!< FLASH End of Operation flag */ local FLASH_STS_CLRFLAG = 0x34 -- (FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR | FLASH_FLAG_EOP) local FLASH_RDP_RDP1 = 0x000000FF -- /*!< Read protection option byte */ local FLASH_USER_USER = 0x00FF0000 -- /*!< User option byte */ local FLASH_FLAG_BUSY = 0x00000001 -- /*!< FLASH Busy flag */ local OBR_USER_MSK = 0x000000FC local L1_RDP_Key = 0xFFFF00A5 --常量值 local UNLOCK_KEY1 = 0x45670123 local UNLOCK_KEY2 = 0xCDEF89AB local OB_UNLOCK_KEY1 = 0x45670123 local OB_UNLOCK_KEY2 = 0xCDEF89AB --判斷data陣列標誌,全部為0則退出 function CheckFlagQuit0(data, mask) local i local ret if (MULTI_MODE > 0) then ret = 0 for i = 1, MULTI_MODE, 1 do ret = ret | (data[i] & mask) end else ret = data[1] & mask end return ret end --等待超時,(解除讀保護時會執行全面擦除) function FLASH_WaitForLastOpt(void) local i local reg = {} for i = 1, 5000, 1 do reg = {pg_read32(FLASH_FLASH_STS)} if (CheckFlagQuit0(reg, FLASH_FLAG_BUSY) == 0) then break end delayms(1) end end --晶片專有的解除保護函式 function MCU_RemoveProtect(void) MCU_ProgOptionBytes(OB_SECURE_OFF) end --沒有FLM的MCU,用指令碼實現程式設計OB。 返回 "OK" or "error" function MCU_ProgOptionBytes(ob) local err = "OK" local ob_8 local ob1 --local usertmp print("MCU_ProgOptionBytes()") pg_write32(FLASH_FLASHKEY, UNLOCK_KEY1) pg_write32(FLASH_FLASHKEY, UNLOCK_KEY2) pg_write32(FLASH_OPTKEY, OB_UNLOCK_KEY1) pg_write32(FLASH_OPTKEY, OB_UNLOCK_KEY2) --FLASH->CTRL |= CTRL_Set_OPTER; --value,re = pg_read32(0x40022010) --value = (value | CTRL_Set_OPTER) --print(string.format("(0x40022010) = 0x%x",value)) pg_write32(FLASH_CTRL, 0x220) --FLASH->CTRL |= CTRL_Set_START; --value,re = pg_read32(0x40022010) --value = (value | CTRL_Set_START) --print(string.format("(0x40022010) = 0x%x",value)) pg_write32(FLASH_CTRL, 0x260) -- 等的操作完成 FLASH_WaitForLastOpt() -- FLASH.FLASH_STS = 0x34 -- FLASH_ClearFlag(FLASH_STS_CLRFLAG) pg_write32(FLASH_FLASH_STS, FLASH_STS_CLRFLAG) -- if the erase operation is completed, disable the OPTER Bit -- FLASH->CTRL &= CTRL_Reset_OPTER; -- value,re = pg_read32(0x40022010) -- value = (value & CTRL_Reset_OPTER) -- print(string.format("(0x40022010) = 0x%x",value)) pg_write32(FLASH_CTRL, 0x200) -- Enable the Option Bytes Programming operation -- FLASH->CTRL |= CTRL_Set_OPTPG; -- value,re = pg_read32(0x40022010) -- print(string.format("(0x40022010) = 0x%x",value)) -- value = (value | CTRL_Set_OPTPG) pg_write32(FLASH_CTRL, 0x210) -- FLASH.FLASH_OB 解除保護 -- value,re = pg_read32(0x4002201C) -- usertmp = ((value & OBR_USER_MSK) << 0x0E) -- usertmp = ((L1_RDP_Key & FLASH_RDP_RDP1) | usertmp) -- print(string.format("(0x4002201C) = 0x%x",value)) ob_8 = hex_to_bin(ob) --hex字串轉為二進位制陣列 ob1 = string.byte(ob_8, 1) + (((string.byte(ob_8, 2)) << 16) & 0xFF0000) pg_write32(FLASH_OB_Address, ob1) -- 等的操作完成 FLASH_WaitForLastOpt() delayms(500) return err end
透過TOOL的暫存器檢測功能可以瞭解各種暫存器地址和狀態資訊,大大方便演算法檔案自制: