[Lua] 纯文本查看 复制代码
-------------------------------------------------------
-- 文件名 : PY32F0_Lib.lua
-- 版 本 : V1.0 2022-04-15
-- 说 明 :
-------------------------------------------------------
--复位期间执行的函数. 目的:debug期间冻结看门狗时钟,低功耗模式启动HCLK和FCLK
function InitUnderReset(void)
local str = "error"
print("InitUnderReset()")
--Write32(0xE000EDF0, 0xA05F0001); // Enable Core Debug via DHCSR
--Write32(0x4002103C, Read32(0x4002103C) | 0x08000000); // Set RCC_APBENR1.DBGEN
-- if (pg_write32(0xE000EDF0, 0xA05F0001) == 0) then
-- goto quit_err
-- end
-- if (pg_write32(0x4002103C, pg_write32(0x4002103C) | 0x08000000) == 0) then
-- goto quit_err
-- end
-- --Write32(0x40015804, DbgMCU_CR); // DBGMCU_CR: Configure MCU Debug
-- -- Write32(0x40015808, DbgMCU_APB_Fz1); // DBGMCU_APB_FZ1: Configure APB Peripheral Freeze1 Behavior
-- -- Write32(0x4001580C, DbgMCU_APB_Fz2); // DBGMCU_APB_FZ2: Configure APB Peripheral Freeze2 Behavior
-- if (pg_write32(0x40015804, 2) == 0) then
-- goto quit_err
-- end
-- if (pg_write32(0x40015808, 0) == 0) then
-- goto quit_err
-- end
-- if (pg_write32(0x4001580C, 0) == 0) then
-- goto quit_err
-- end
-- if (ReadDeviceID() ~= 0) then
-- goto quit_err
-- end
::quit_ok::
str = "OK"
::quit_err::
print(str)
return str
end
--读芯片ID
function ReadDeviceID(void)
local str
local err = 0
local j
local ch_num
if (MULTI_MODE == 0) then
ch_num = 1
else
ch_num = MULTI_MODE
end
g_DevID = {pg_read32(0x40015800)} --全局变量g_DevID[]
str = "..DeviceID = "
for j = 1, ch_num, 1 do
str = str..string.format("%08X ", g_DevID[j])
if (g_DevID[j] == 0) then
if (ABORT_ON_ERROR == 1) then
err = 1
end
end
end
print(str)
return err
end
--[[
PY32F031 Flash 操作 — Lua 版 (合并版)
包含: 整片擦除 (MCU_EraseMass) + 选项字节编程 (MCU_ProgOptionBytes)
不配置时钟,不配置看门狗,由调用方确保芯片在正确时钟下运行。
寄存器地址速查 (FLASH base = 0x40022000):
KEYR 0x40022008 Flash 解锁 (KEY1=0x45670123, KEY2=0xCDEF89AB)
OPTKEYR 0x4002200C OB 解锁 (OPTKEY1=0x08192A3B, OPTKEY2=0x4C5D6E7F)
SR 0x40022010 状态 (EOP bit0 / WRPERR bit4 / OPTVERR bit15 / BSY bit16)
CR 0x40022014 控制 (MER bit2 / OPTSTRT bit17 / EOPIE bit24 / OPTLOCK bit30 / LOCK bit31)
OPTR 0x40022020 选项寄存器 (20位)
SDKR 0x40022024 SDK 寄存器
WRPR 0x4002202C 写保护寄存器
Flash 基地址: 0x08000000
OB 基地址: 0x1FFF0E80
]]
-- ========================================================================
-- 寄存器常量
-- ========================================================================
local FLASH_KEYR = 0x40022008
local FLASH_OPTKEYR = 0x4002200C
local FLASH_SR = 0x40022010
local FLASH_CR = 0x40022014
local FLASH_OPTR = 0x40022020
local FLASH_SDKR = 0x40022024
local FLASH_WRPR = 0x4002202C
local FLASH_OB_ADDR = 0x1FFF0E80
local FLASH_BASE_ADDR = 0x08000000
-- Flash Control Register bits
local FLASH_CR_PG = 0x00000001 -- bit 0: 页编程
local FLASH_CR_PER = 0x00000002 -- bit 1: 页擦除
local FLASH_CR_MER = 0x00000004 -- bit 2: 整片擦除
local FLASH_CR_OPTSTRT = 0x00020000 -- bit 17: 启动 OB 编程
local FLASH_CR_EOPIE = 0x01000000 -- bit 24: EOP 中断使能
local FLASH_CR_OPTLOCK = 0x40000000 -- bit 30: OB 锁定
local FLASH_CR_LOCK = 0x80000000 -- bit 31: Flash 锁定
-- Flash Status Register bits
local FLASH_SR_EOP = 0x00000001 -- bit 0: 操作完成
local FLASH_SR_WRPERR = 0x00000010 -- bit 4: 写保护错误
local FLASH_SR_OPTVERR = 0x00008000 -- bit 15: OB 有效性错误
local FLASH_SR_BSY = 0x00010000 -- bit 16: 忙标志
-- 错误标志掩码
local FLASH_OB_ERR = FLASH_SR_WRPERR | FLASH_SR_OPTVERR
-- 解锁常量
local UNLOCK_KEY1 = 0x45670123
local UNLOCK_KEY2 = 0xCDEF89AB
local OB_UNLOCK_KEY1 = 0x08192A3B
local OB_UNLOCK_KEY2 = 0x4C5D6E7F
-- ========================================================================
-- 辅助函数
-- ========================================================================
--[[
判断data数组标志,成功返回mask,失败返回0
(用于检查是否所有核心的标志位都等于 mask)
]]
function SWD_CheckFlagQuit0(data, mask)
local i
local ret
if (MULTI_MODE > 0) then
for i = 1, MULTI_MODE, 1 do
ret = (data[i] & mask)
if (ret ~= mask) then
ret = 0
break
end
end
else
ret = (data[1] & mask)
if (ret ~= mask) then
ret = 0
end
end
return ret
end
--[[
判断data数组标志,全部为0则退出
(用于检查所有核心与 mask 的 AND 结果是否为 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
-- 读32位寄存器 (兼容MULTI_MODE,取第一个核心)
local function rd32(addr)
return ({pg_read32(addr)})[1]
end
-- 修改寄存器指定位 (等价 C 的 MODIFY_REG)
local function rmw32(addr, clearmask, setmask)
local val = rd32(addr)
pg_write32(addr, (val & ~clearmask) | setmask)
end
-- 等待 BSY 清零,返回1=成功,0=超时
local function WaitBSY(timeout)
local reg = {}
local j = 0
for i = 1, timeout, 1 do
j = j + 1
reg = {pg_read32(FLASH_SR)}
if (CheckFlagQuit0(reg, FLASH_SR_BSY) == 0) then
break
end
delayms(10)
end
print(string.format("WaitBSY() 等待时间: %dms", j * 10))
return (CheckFlagQuit0(reg, FLASH_SR_BSY) == 0) and 1 or 0
end
-- ========================================================================
-- 整片擦除
-- ========================================================================
--[[
芯片专有的整片擦除
流程: 解锁Flash → 清标志/等BSY → 使能MER → 触发擦除 → 等BSY → 检查EOP → 清理 → 锁定Flash
返回: "OK" or "FAIL"
]]
function MCU_EraseMass(void)
local reg = {}
local val
local i
-- 1. 解锁 Flash
pg_write32(0x40022008, 0x45670123) -- FLASH->KEYR = KEY1
pg_write32(0x40022008, 0xCDEF89AB) -- FLASH->KEYR = KEY2
-- 2. 清除 EOP 标志 (写1清零), 等待 BSY 清零
pg_write32(0x40022010, 0x00000001) -- SR |= EOP (w1c)
for i = 1, 1000, 1 do
reg = {pg_read32(0x40022010)}
if (SWD_CheckFlagQuit0(reg, 0x00010000) == 0) then
break
end
delayms(1)
end
-- 3. 使能整片擦除: MER(bit2) + EOPIE(bit24)
val = rd32(0x40022014)
pg_write32(0x40022014, val | 0x01000004)
-- 4. 触发擦除 (向 Flash 基地址写 0xFF)
pg_write32(0x08000000, 0x000000FF)
delayms(1)
-- 5. 等待擦除完成 (BSY 清零)
for i = 1, 10000, 1 do
reg = {pg_read32(0x40022010)}
if (SWD_CheckFlagQuit0(reg, 0x00010000) == 0) then
break
end
delayms(1)
end
-- 6. 检查 EOP 标志
reg = {pg_read32(0x40022010)}
if (SWD_CheckFlagQuit0(reg, 0x00000001) == 0) then
print("PY32F031 EraseMass: EOP not set, FAILED")
val = rd32(0x40022014)
pg_write32(0x40022014, val & ~0x01000004) -- 清 MER+EOPIE
pg_write32(0x40022014, 0x80000000) -- 锁定 Flash
return "FAIL"
end
-- 7. 清除 MER 和 EOPIE
val = rd32(0x40022014)
pg_write32(0x40022014, val & ~0x01000004)
-- 8. 复位 EOP 标志
pg_write32(0x40022010, 0x00000001)
-- 9. 锁定 Flash
--val = rd32(0x40022014)
--pg_write32(0x40022014, val | 0x80000000) -- CR |= LOCK
print("PY32F031 EraseMass OK")
return "OK"
end
-- ========================================================================
-- 选项字节编程
-- ========================================================================
-- OB 配置值 (8字节: OPTR + BOR + SDKR + WRPR, 各2字节小端)
--OB_SECURE_OFF = "AA B8 00 00 1F 00 FF FF" -- SECURE_ENABLE = 0, 编程完毕后写入
--OB_SECURE_ON = "00 B8 00 00 1F 00 FF FF" -- SECURE_ENABLE = 1, 编程完毕后写入
--[[
解析8字节OB数据
格式: OPTR(2) + BOR(2) + SDKR(2) + WRPR(2), 各小端
返回: optr_final(20位), sdkr(16位), wrpr(16位)
对应 C 代码:
optr = *((u32*)(buf+0x00)) & 0xFFFF;
bor = *((u32*)(buf+0x04)) & 0xF;
optr = optr | (bor << 16);
sdkr = *((u32*)(buf+0x08)) & 0xFFFF;
wrpr = *((u32*)(buf+0x0C)) & 0xFFFF;
]]
local function ParseOB(ob)
local ob_bin = hex_to_bin(ob)
local optr = string.byte(ob_bin, 1) | (string.byte(ob_bin, 2) << 8)
local bor = string.byte(ob_bin, 3) | (string.byte(ob_bin, 4) << 8)
local sdkr = string.byte(ob_bin, 5) | (string.byte(ob_bin, 6) << 8)
local wrpr = string.byte(ob_bin, 7) | (string.byte(ob_bin, 8) << 8)
-- BOR[3:0] 合并到 OPTR[19:16]
local optr_final = (optr & 0xFFFF) | ((bor & 0xF) << 16)
return optr_final & 0xFFFFF, sdkr & 0xFFFF, wrpr & 0xFFFF
end
--[[
编程选项字节
参数: ob — 8字节hex字符串, 如 "AA B8 00 00 1F 00 FF FF"
返回: "OK" or "error"
对应 C 代码 FLASH_OB ProgramPage():
1. 写 OPTR / SDKR / WRPR 寄存器
2. CR |= OPTSTRT + EOPIE
3. M32(0x1FFF0E80) = 0xFF (触发)
4. 等 BSY 清零
5. 检查 EOP
6. 清 OPTSTRT + EOPIE
7. 锁定 OB + Flash
]]
function MCU_ProgOptionBytes(ob)
local err = "OK"
local reg = {}
print("MCU_ProgOptionBytes()")
-- 1. 解锁 Flash
pg_write32(FLASH_KEYR, UNLOCK_KEY1)
pg_write32(FLASH_KEYR, UNLOCK_KEY2)
-- 2. 解锁 Option Bytes
pg_write32(FLASH_OPTKEYR, OB_UNLOCK_KEY1)
pg_write32(FLASH_OPTKEYR, OB_UNLOCK_KEY2)
-- 3. 清除错误标志 (写1清零)
pg_write32(FLASH_SR, FLASH_OB_ERR)
-- 4. 解析 OB 数据
local optr_val, sdkr_val, wrpr_val = ParseOB(ob)
print(string.format("OPTR=0x%05X SDKR=0x%04X WRPR=0x%04X",
optr_val, sdkr_val, wrpr_val))
-- 5. 清除 EOP 标志,等待 BSY 清零
pg_write32(FLASH_SR, FLASH_SR_EOP)
WaitBSY(500)
-- 6. 写入 OPTR / SDKR / WRPR 寄存器
pg_write32(FLASH_OPTR, optr_val)
pg_write32(FLASH_SDKR, sdkr_val)
pg_write32(FLASH_WRPR, wrpr_val)
-- 7. 启动 OB 编程: CR |= OPTSTRT + EOPIE
rmw32(FLASH_CR, 0, FLASH_CR_OPTSTRT | FLASH_CR_EOPIE)
-- 8. 触发写入 (向 OB 基地址写 0xFF, 等价 C 的 M32(0x1FFF0E80)=0xFF + DSB)
pg_write32(FLASH_OB_ADDR, 0x000000FF)
-- 9. 等待编程完成
print("等待OB编程完成......")
WaitBSY(500)
delayms(10)
-- 10. 检查 EOP 标志 (成功标志)
reg = {pg_read32(FLASH_SR)}
if (CheckFlagQuit0(reg, FLASH_SR_EOP) == 0) then
print("PY32F031 ProgOB: EOP not set, FAILED")
err = "error"
end
-- 11. 检查错误标志
reg = {pg_read32(FLASH_SR)}
if (CheckFlagQuit0(reg, FLASH_OB_ERR) ~= 0) then
print("PY32F031 ProgOB: error flags set, FAILED")
err = "error"
end
-- 12. 清除 OPTSTRT + EOPIE
rmw32(FLASH_CR, FLASH_CR_OPTSTRT | FLASH_CR_EOPIE, 0)
-- 13. 锁定 Option Bytes 和 Flash
rmw32(FLASH_CR, 0, FLASH_CR_OPTLOCK)
rmw32(FLASH_CR, 0, FLASH_CR_LOCK)
if (err == "OK") then
print("PY32F031 ProgOB OK")
end
return err
end
--[[
芯片专有的解除保护函数
返回: "OK" or "error"
]]
function MCU_RemoveProtect(void)
return MCU_ProgOptionBytes(OB_SECURE_OFF)
end