feat: verify assembly bootloader factory recovery
This commit is contained in:
@@ -50,11 +50,18 @@ int _Asm_TIM4Vector
|
||||
; 因此从0x8501开始读取三字节入口地址,避免写死主程序启动地址。
|
||||
_Asm_Reset:
|
||||
sim
|
||||
; STM8复位后的默认HSI时钟为16MHz/8,约2MHz。
|
||||
; Bootloader和应用程序均使用16MHz系统时钟。
|
||||
ldw x, #0x03FF
|
||||
ldw sp, x
|
||||
mov 0x50C6, #0x00
|
||||
call _Asm_SPI_Init
|
||||
call _Asm_SPI_CheckJedec
|
||||
; 外部Flash故障时不阻止已有主程序运行。
|
||||
tnz a
|
||||
jrne _Asm_JumpApplication
|
||||
jreq _Asm_SpiOK
|
||||
jpf _Asm_JumpApplication
|
||||
_Asm_SpiOK:
|
||||
; PA3配置为带上拉输入,按键按下时读取为低电平。
|
||||
mov 0x5002, #0x00
|
||||
mov 0x5003, #0x08
|
||||
@@ -84,7 +91,9 @@ _Asm_WaitOneMs:
|
||||
jrne _Asm_KeyWaitLoop
|
||||
; 长按已超过5秒,优先执行出厂固件恢复。
|
||||
call _Asm_CheckFactoryMetadata
|
||||
jrne _Asm_NormalBoot
|
||||
jreq _Asm_FactoryKeyMetaOK
|
||||
jpf _Asm_NormalBoot
|
||||
_Asm_FactoryKeyMetaOK:
|
||||
jpf _Asm_FactoryRecovery
|
||||
|
||||
_Asm_NormalBoot:
|
||||
@@ -223,21 +232,21 @@ _Asm_CheckFactoryMetadata:
|
||||
; 读取4字节固件长度,只接受不超过应用区的长度。
|
||||
ldw x, #0x2004
|
||||
call _Asm_SPI_ReadByteX
|
||||
; 长度为高字节在前:前两个字节必须为0。
|
||||
tnz a
|
||||
jrne _Asm_FactoryMetadataInvalid
|
||||
incw x
|
||||
call _Asm_SPI_ReadByteX
|
||||
tnz a
|
||||
jrne _Asm_FactoryMetadataInvalid
|
||||
incw x
|
||||
call _Asm_SPI_ReadByteX
|
||||
ld 0x0000, a
|
||||
ld 0x000E, a
|
||||
incw x
|
||||
call _Asm_SPI_ReadByteX
|
||||
ld 0x0001, a
|
||||
ld 0x000F, a
|
||||
incw x
|
||||
call _Asm_SPI_ReadByteX
|
||||
; 当前应用区小于64KB,高16位必须为0。
|
||||
tnz a
|
||||
jrne _Asm_FactoryMetadataInvalid
|
||||
incw x
|
||||
call _Asm_SPI_ReadByteX
|
||||
tnz a
|
||||
jrne _Asm_FactoryMetadataInvalid
|
||||
; 长度不能为0,也不能超过0x1800字节的应用空间。
|
||||
ld a, 0x0000
|
||||
or a, 0x0001
|
||||
@@ -287,20 +296,21 @@ _Asm_CheckOtaMetadata:
|
||||
jrne _Asm_OtaMetadataInvalid
|
||||
ldw x, #0x5004
|
||||
call _Asm_SPI_ReadByteX
|
||||
; OTA长度同样为4字节高字节在前,前两个字节必须为0。
|
||||
tnz a
|
||||
jrne _Asm_OtaMetadataInvalid
|
||||
incw x
|
||||
call _Asm_SPI_ReadByteX
|
||||
tnz a
|
||||
jrne _Asm_OtaMetadataInvalid
|
||||
incw x
|
||||
call _Asm_SPI_ReadByteX
|
||||
ld 0x0000, a
|
||||
ld 0x000E, a
|
||||
incw x
|
||||
call _Asm_SPI_ReadByteX
|
||||
ld 0x0001, a
|
||||
ld 0x000F, a
|
||||
incw x
|
||||
call _Asm_SPI_ReadByteX
|
||||
tnz a
|
||||
jrne _Asm_OtaMetadataInvalid
|
||||
incw x
|
||||
call _Asm_SPI_ReadByteX
|
||||
tnz a
|
||||
jrne _Asm_OtaMetadataInvalid
|
||||
ld a, 0x0000
|
||||
or a, 0x0001
|
||||
jreq _Asm_OtaMetadataInvalid
|
||||
@@ -460,7 +470,9 @@ _Asm_CrcBitLoop:
|
||||
srl 0x000B
|
||||
rrc 0x000A
|
||||
ld a, 0x000A
|
||||
xor a, #0xA1
|
||||
; CRC-16/MODBUS反射算法多项式为0xA001,拆成寄存器操作时:
|
||||
; 高字节异或0xA0,低字节异或0x01。
|
||||
xor a, #0x01
|
||||
ld 0x000A, a
|
||||
ld a, 0x000B
|
||||
xor a, #0xA0
|
||||
@@ -493,7 +505,8 @@ _Asm_ValidateFactoryImage:
|
||||
ld a, #0xFF
|
||||
ld 0x000A, a
|
||||
ld 0x000B, a
|
||||
ldw x, 0x0004
|
||||
; 出厂固件镜像从外部Flash 0x000000开始,不能跳过前4字节向量表。
|
||||
ldw x, #0x0000
|
||||
ldw y, 0x0000
|
||||
_Asm_ValidateLoop:
|
||||
ld a, 0x0000
|
||||
@@ -518,26 +531,32 @@ _Asm_ValidateFail:
|
||||
ret
|
||||
|
||||
;-------------------------------------------------------------------------------
|
||||
; 擦除内部应用区0x8500~0x9FFF,每次擦除一个64字节块。
|
||||
; 擦除内部应用区0x8500~0x9FFF。
|
||||
; 这里采用STM8官方支持的字节擦除方式:逐地址写入0x00并等待EOP。
|
||||
; 不使用块擦除模式,避免块擦除关键步骤必须从RAM执行的问题。
|
||||
;-------------------------------------------------------------------------------
|
||||
_Asm_EraseApplication:
|
||||
ld a, #0x56
|
||||
ld 0x5062, a
|
||||
ld a, #0xAE
|
||||
ld 0x5062, a
|
||||
ldw x, #0x8500
|
||||
_Asm_EraseBlock:
|
||||
ld a, #0x20
|
||||
; 退出块擦除/块编程模式,恢复普通字节擦除/编程方式。
|
||||
ld a, #0x00
|
||||
ld 0x505B, a
|
||||
ld a, #0xDF
|
||||
ld a, #0xFF
|
||||
ld 0x505C, a
|
||||
ldw x, #0x8500
|
||||
_Asm_EraseByte:
|
||||
; 字节擦除由向目标地址写入0x00触发;写指令后CPU会等待本次操作完成。
|
||||
ld a, #0x00
|
||||
ld (x), a
|
||||
_Asm_EraseWait:
|
||||
; 本项目STM8S003寄存器定义中,FLASH_IAPSR.EOP为bit2(掩码0x04)。
|
||||
; 置1表示当前擦除操作已完成。
|
||||
btjf 0x505F, #2, _Asm_EraseWait
|
||||
addw x, #64
|
||||
incw x
|
||||
cpw x, #0xA000
|
||||
jrne _Asm_EraseBlock
|
||||
jrne _Asm_EraseByte
|
||||
ld a, #0x00
|
||||
ret
|
||||
|
||||
@@ -549,7 +568,15 @@ _Asm_CopyFactoryImage:
|
||||
ld 0x0000, a
|
||||
ld a, 0x000F
|
||||
ld 0x0001, a
|
||||
ldw x, 0x0004
|
||||
; 搬运阶段采用STM8的单字节编程方式:
|
||||
; 只向目标地址执行一次写操作,不设置块编程CR2/NCR2模式。
|
||||
; 这样每个字节写入后都可以单独等待EOP完成。
|
||||
ld a, #0x00
|
||||
ld 0x505B, a
|
||||
ld a, #0xFF
|
||||
ld 0x505C, a
|
||||
; 搬运必须从出厂镜像第0字节开始,保持应用向量表与0x8500对齐。
|
||||
ldw x, #0x0000
|
||||
ldw y, #0x8500
|
||||
_Asm_CopyLoop:
|
||||
ld a, 0x0000
|
||||
@@ -557,13 +584,11 @@ _Asm_CopyLoop:
|
||||
jreq _Asm_CopyOK
|
||||
call _Asm_SPI_ReadByteX
|
||||
ld 0x000C, a
|
||||
ld a, #0x01
|
||||
ld 0x505B, a
|
||||
ld a, #0xFE
|
||||
ld 0x505C, a
|
||||
ld a, 0x000C
|
||||
ld (y), a
|
||||
_Asm_CopyWait:
|
||||
; 本项目STM8S003寄存器定义中,FLASH_IAPSR.EOP为bit2(掩码0x04)。
|
||||
; 置1表示当前字节编程已完成。
|
||||
btjf 0x505F, #2, _Asm_CopyWait
|
||||
incw x
|
||||
incw y
|
||||
@@ -582,7 +607,8 @@ _Asm_VerifyApplication:
|
||||
ld 0x0000, a
|
||||
ld a, 0x000F
|
||||
ld 0x0001, a
|
||||
ldw x, 0x0004
|
||||
; 回读校验与写入过程使用同一个外部Flash起始地址0x000000。
|
||||
ldw x, #0x0000
|
||||
ldw y, #0x8500
|
||||
_Asm_VerifyLoop:
|
||||
ld a, 0x0000
|
||||
|
||||
Reference in New Issue
Block a user