H7-TOOL自制Flash讀防寫演算法系列,為國民技術N32G003製作讀寫使能和解除演算法,支援線上燒錄和離線燒錄使用(2024-07-31)

硬汉嵌入式發表於2024-07-31

說明

很多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的暫存器檢測功能可以瞭解各種暫存器地址和狀態資訊,大大方便演算法檔案自制:

相關文章