[feat] add fw_header

This commit is contained in:
zhji 2025-06-02 12:57:09 +08:00
parent 6afed2f349
commit 38dec013f8
9 changed files with 227 additions and 27 deletions

View File

@ -3,7 +3,11 @@
#include "reg.h" #include "reg.h"
#define FW_ADDRESS (64 * 1024)
#define MAGIC_HEAD (0x64616568) /* ASCII of "head" */
struct fw_header_s { struct fw_header_s {
uint32_t magic;
uint32_t size; uint32_t size;
uint32_t jump_address; uint32_t jump_address;
/* syspll config */ /* syspll config */
@ -18,10 +22,10 @@ struct fw_header_s {
uint8_t usbpll_postdiv2; /* must be in 1~7 */ uint8_t usbpll_postdiv2; /* must be in 1~7 */
/* system clock div */ /* system clock div */
uint32_t sysclk_div; /* 1~2^24-1 is available */ uint32_t sysclk_div; /* 1~2^24-1 is available */
uint8_t regulator_voltage; /* 5~15 is available, Voltage = 0.05 * regulator_voltage + 0.55V */
uint8_t resv;
/* flash config */ /* flash config */
uint16_t flash_div; /* 0 is for disable, 2~65534 is available, must be even value */ uint16_t flash_div; /* 0 is for disable, 2~65534 is available, must be even value */
uint16_t flash_resv;
uint32_t resv;
/* checksum */ /* checksum */
uint32_t checksum; uint32_t checksum;
}; };

View File

@ -1 +1,25 @@
#include "common.h" #include "common.h"
__attribute__((section(".fw_header"))) struct fw_header_s fw_header = {
.magic = MAGIC_HEAD,
.size = sizeof(struct fw_header_s),
.jump_address = 0x10010000 + sizeof(struct fw_header_s),
/* syspll config */
.syspll_refdiv = 1, /* must be in 1~63, fref/refdiv must >= 5MHz */
.syspll_feedback = 125, /* must be in 16~320, fvco must be in 750MHz~1600MHz */
.syspll_postdiv1 = 6, /* must be in 1~7 */
.syspll_postdiv2 = 1, /* must be in 1~7 */
/* usbpll config */
.usbpll_refdiv = 1, /* must be in 1~63, fref/refdiv must >= 5MHz */
.usbpll_feedback = 96, /* must be in 16~320, fvco must be in 750MHz~1600MHz */
.usbpll_postdiv1 = 4, /* must be in 1~7 */
.usbpll_postdiv2 = 2, /* must be in 1~7 */
/* system clock div */
.sysclk_div = 1, /* 1~2^24-1 is available */
.regulator_voltage = 15, /* 5~15 is available, Voltage = 0.05 * regulator_voltage + 0.55V */
.resv = 0,
/* flash config */
.flash_div = 4, /* 0 is for disable, 2~65534 is available, must be even value */
/* checksum */
.checksum = 0,
};

View File

@ -52,19 +52,20 @@ void __attribute__((section(".text.boot2_pre"))) boot2_copy_self(void)
ioqspi_hw->io[1].ctrl = GPIO_OVER_OUT_HIGH; ioqspi_hw->io[1].ctrl = GPIO_OVER_OUT_HIGH;
} }
#include "common.h"
#include "resets.h" #include "resets.h"
#include "clock.h" #include "clock.h"
#include "uart.h" #include "uart.h"
#include "flash.h" #include "flash.h"
#include "watchdog.h" #include "watchdog.h"
#include "timer.h" #include "timer.h"
#include "stdio.h" #include "jump.h"
uint8_t uart_tx_buffer[512]; uint8_t tx_buffer[512] __attribute__((aligned(4)));
uint8_t uart_rx_buffer[512]; uint8_t rx_buffer[512] __attribute__((aligned(4)));
struct uart_cfg_s uart_cfg = { struct uart_cfg_s uart_cfg = {
.baudrate = 2 * 1000 * 1000, .baudrate = 750 * 1000,
.mode = UART_MODE_TX_RX, .mode = UART_MODE_TX_RX,
.data_bits = UART_DATABITS_8, .data_bits = UART_DATABITS_8,
.parity = UART_PARITY_NONE, .parity = UART_PARITY_NONE,
@ -141,7 +142,7 @@ void uart_process(uint16_t code, uint16_t length)
uint16_t i; uint16_t i;
uint32_t v1, v2; uint32_t v1, v2;
p = uart_rx_buffer + 8; p = rx_buffer + 8;
if ((length > 0) && (length <= 4)) { if ((length > 0) && (length <= 4)) {
return; return;
} }
@ -168,7 +169,7 @@ void uart_process(uint16_t code, uint16_t length)
process_return_ok(); process_return_ok();
} else if (code == 0x0003) { } else if (code == 0x0003) {
process_return_ok(); process_return_ok();
process_flash_read(v1, uart_tx_buffer, v2); process_flash_read(v1, tx_buffer, v2);
} }
} }
@ -187,10 +188,10 @@ void uart_state_machine(uint8_t id)
uart_rx_length = 0; uart_rx_length = 0;
return; return;
} }
code = ((uint16_t)uart_rx_buffer[0] << 8) | (uint16_t)uart_rx_buffer[1]; code = ((uint16_t)rx_buffer[0] << 8) | (uint16_t)rx_buffer[1];
code_inv = ((uint16_t)uart_rx_buffer[2] << 8) | (uint16_t)uart_rx_buffer[3]; code_inv = ((uint16_t)rx_buffer[2] << 8) | (uint16_t)rx_buffer[3];
length = ((uint16_t)uart_rx_buffer[4] << 8) | (uint16_t)uart_rx_buffer[5]; length = ((uint16_t)rx_buffer[4] << 8) | (uint16_t)rx_buffer[5];
length_inv = ((uint16_t)uart_rx_buffer[6] << 8) | (uint16_t)uart_rx_buffer[7]; length_inv = ((uint16_t)rx_buffer[6] << 8) | (uint16_t)rx_buffer[7];
if ((code != (uint16_t)~code_inv) || (length != (uint16_t)~length_inv)) { if ((code != (uint16_t)~code_inv) || (length != (uint16_t)~length_inv)) {
uart_rx_length = 0; uart_rx_length = 0;
return; return;
@ -198,28 +199,23 @@ void uart_state_machine(uint8_t id)
uart_process(code, length); uart_process(code, length);
uart_rx_length = 0; uart_rx_length = 0;
} else { } else {
uart_rx_buffer[uart_rx_length++] = uart0_hw->dr & 0xFF; rx_buffer[uart_rx_length++] = uart0_hw->dr & 0xFF;
time_fifo_empty = timer_count_read(); time_fifo_empty = timer_count_read();
if (uart_rx_length >= sizeof(uart_rx_buffer)) { if (uart_rx_length >= sizeof(rx_buffer)) {
uart_rx_length = 0; uart_rx_length = 0;
return; return;
} }
} }
} }
__attribute__((naked)) void jump_to_address(uint32_t address) {
__asm volatile (
"bx %0\n"
:
: "r" (address)
);
}
int main(void) int main(void)
{ {
uint32_t boot_pin_low, boot_pin_high; uint32_t boot_pin_low, boot_pin_high;
struct fw_header_s *header;
system_clock_config(SYSTEM_CLOCK_FREQ_120MHZ); clock_ref_set(CLOCK_REF_SRC_XOSC_GLITCHLESS, 1);
clock_sys_set(CLOCK_SYS_SRC_REF_GLITCHLESS, 1);
clock_peri_set(ENABLE, CLOCK_PERI_SRC_XOSC);
reset_unreset_blocks_wait(RESETS_BLOCK_IO_BANK0 | RESETS_BLOCK_PADS_BANK0 | RESETS_BLOCK_UART0 | RESETS_BLOCK_TIMER); reset_unreset_blocks_wait(RESETS_BLOCK_IO_BANK0 | RESETS_BLOCK_PADS_BANK0 | RESETS_BLOCK_UART0 | RESETS_BLOCK_TIMER);
gpio_init(0, GPIO_FUNC_UART | GPIO_PULL_UP | GPIO_DRIVE_4MA); /* UART_TX pin */ gpio_init(0, GPIO_FUNC_UART | GPIO_PULL_UP | GPIO_DRIVE_4MA); /* UART_TX pin */
@ -239,12 +235,23 @@ int main(void)
} }
} }
if (boot_pin_high > boot_pin_low) { if (boot_pin_high > boot_pin_low) {
for (uint32_t i = 0; i < 4; i++) {
tx_buffer[i] = 0x55;
}
uart_write_block(UART_ID_0, tx_buffer, 4);
while (1) { while (1) {
uart_state_machine(UART_ID_0); uart_state_machine(UART_ID_0);
} }
} else { } else {
flash_enter_quad_xip(6); flash_read(FW_ADDRESS, rx_buffer, FLASH_READ_SIZE);
jump_to_address(0x10010000 | 1); header = (struct fw_header_s *)rx_buffer;
if (jump_check_is_failed(header)) {
flash_enter_quad_xip(6);
jump_to_address((uint32_t)(uintptr_t *)(FW_ADDRESS | XIP_BASE | 1));
} else {
jump_pre_config(header);
jump_to_address(((struct fw_header_s *)header)->jump_address | 1);
}
} }
return 0; return 0;

View File

@ -1,5 +1,6 @@
file(GLOB FILELIST file(GLOB FILELIST
flash.c flash.c
jump.c
) )
set(TARGET src) set(TARGET src)

56
example/boot2/src/jump.c Normal file
View File

@ -0,0 +1,56 @@
#include "jump.h"
#include "common.h"
#include "system.h"
#include "clock.h"
#include "flash.h"
int jump_check_is_failed(void *addr)
{
uint32_t size, sum;
uint32_t *p;
struct fw_header_s *header;
header = (struct fw_header_s *)addr;
if (header->magic != MAGIC_HEAD) {
return -1;
}
if (header->size != sizeof(struct fw_header_s)) {
return -2;
}
sum = 0;
size = header->size;
p = (uint32_t *)header;
for (uint32_t i = 0; i < size / 4; i++) {
sum += p[i];
}
if (sum != 0xFFFFFFFF) {
return -3;
}
return 0;
}
void jump_pre_config(void *addr)
{
struct fw_header_s *header;
header = (struct fw_header_s *)addr;
clock_ref_set(CLOCK_REF_SRC_XOSC_GLITCHLESS, 1);
clock_sys_set(CLOCK_SYS_SRC_REF_GLITCHLESS, 1);
system_regulator_set(header->regulator_voltage);
clock_syspll_init(header->syspll_refdiv, \
header->syspll_feedback, \
header->syspll_postdiv1, \
header->syspll_postdiv2);
clock_usbpll_init(header->usbpll_refdiv, \
header->usbpll_feedback, \
header->usbpll_postdiv1, \
header->usbpll_postdiv2);
clock_sys_set(CLOCK_SYS_SRC_SYSPLL, header->sysclk_div);
clock_peri_set(ENABLE, CLOCK_PERI_SRC_SYSPLL);
flash_enter_quad_xip(header->flash_div);
}
void jump_to_address(uint32_t addr)
{
((void (*)(void))(addr | 1))();
}

18
example/boot2/src/jump.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef __JUMP_H__
#define __JUMP_H__
#include "stdint.h"
#ifdef __cplusplus
extern "C" {
#endif
int jump_check_is_failed(void *addr);
void jump_pre_config(void *addr);
void jump_to_address(uint32_t addr);
#ifdef __cplusplus
}
#endif
#endif /* __JUMP_H__ */

View File

@ -11,7 +11,8 @@ _stack_top_core1 = 0x20041000 + 4 * 1024;
PHDRS PHDRS
{ {
fw_header PT_LOAD FLAGS(5); /* R + X */ fw_header PT_LOAD FLAGS(6); /* R + X */
isr_reset PT_LOAD FLAGS(6); /* R + X */
text PT_LOAD FLAGS(5); /* R + X */ text PT_LOAD FLAGS(5); /* R + X */
rodata PT_LOAD FLAGS(6); /* R + W */ rodata PT_LOAD FLAGS(6); /* R + W */
data PT_LOAD FLAGS(6); /* R + W */ data PT_LOAD FLAGS(6); /* R + W */
@ -24,10 +25,16 @@ SECTIONS
{ {
. = ALIGN(4); . = ALIGN(4);
KEEP(*(.fw_header)) KEEP(*(.fw_header))
KEEP(*(.text.isr_reset))
. = ALIGN(4); . = ALIGN(4);
} >FLASH :fw_header } >FLASH :fw_header
.isr_reset :
{
. = ALIGN(4);
KEEP(*(.text.isr_reset))
. = ALIGN(4);
} >FLASH :isr_reset
.text : .text :
{ {
. = ALIGN(4); . = ALIGN(4);

View File

@ -23,6 +23,9 @@ LDFLAGS += -Wl,--gc-sections
LDFLAGS += -nostartfiles LDFLAGS += -nostartfiles
LDFLAGS += -Wl,-Map=$(EXAMPLE_NAME).map LDFLAGS += -Wl,-Map=$(EXAMPLE_NAME).map
LDFLAGS += -Wl,--print-memory-usage LDFLAGS += -Wl,--print-memory-usage
ifndef BOOT2_PRE_CRC
LDFLAGS += -ufw_header
endif
CMAKE := cmake CMAKE := cmake
ELF2UF2 := $(SDK_BASE_DIR)/tools/elf2uf2 ELF2UF2 := $(SDK_BASE_DIR)/tools/elf2uf2
@ -54,12 +57,19 @@ cmake_definition+= -DEXAMPLE_BASE_DIR=$(EXAMPLE_BASE_DIR)
FINAL_NAME_PRE := $(EXAMPLE_BASE_DIR)/build/$(EXAMPLE_NAME) FINAL_NAME_PRE := $(EXAMPLE_BASE_DIR)/build/$(EXAMPLE_NAME)
FW_HEADER_CHECKSUM ?= fw_header_checksum.bin
post:build post:build
ifdef BOOT2_PRE_CRC ifdef BOOT2_PRE_CRC
@$(CROSS_COMPILE)objcopy -O binary --only-section=.boot2_pre $(FINAL_NAME_PRE).elf $(BOOT2_PRE_CRC) @$(CROSS_COMPILE)objcopy -O binary --only-section=.boot2_pre $(FINAL_NAME_PRE).elf $(BOOT2_PRE_CRC)
@python3 $(SDK_BASE_DIR)/tools/boot2_pre_crc.py $(BOOT2_PRE_CRC) @python3 $(SDK_BASE_DIR)/tools/boot2_pre_crc.py $(BOOT2_PRE_CRC)
@$(CROSS_COMPILE)objcopy --update-section .boot2_pre=$(BOOT2_PRE_CRC) $(FINAL_NAME_PRE).elf @$(CROSS_COMPILE)objcopy --update-section .boot2_pre=$(BOOT2_PRE_CRC) $(FINAL_NAME_PRE).elf
@rm $(BOOT2_PRE_CRC) @rm $(BOOT2_PRE_CRC)
else
@$(CROSS_COMPILE)objcopy -O binary --only-section=.fw_header $(FINAL_NAME_PRE).elf $(FW_HEADER_CHECKSUM)
@python3 $(SDK_BASE_DIR)/tools/checksum.py $(FW_HEADER_CHECKSUM)
@$(CROSS_COMPILE)objcopy --update-section .fw_header=$(FW_HEADER_CHECKSUM) $(FINAL_NAME_PRE).elf
@rm $(FW_HEADER_CHECKSUM)
endif endif
@$(CROSS_COMPILE)objcopy -O binary $(FINAL_NAME_PRE).elf $(FINAL_NAME_PRE).bin @$(CROSS_COMPILE)objcopy -O binary $(FINAL_NAME_PRE).elf $(FINAL_NAME_PRE).bin
@$(CROSS_COMPILE)objdump -d -S $(FINAL_NAME_PRE).elf > $(FINAL_NAME_PRE).asm @$(CROSS_COMPILE)objdump -d -S $(FINAL_NAME_PRE).elf > $(FINAL_NAME_PRE).asm

73
tools/checksum.py Normal file
View File

@ -0,0 +1,73 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
import sys
import struct
def calculate_checksum(data):
"""计算小端序校验和每4字节相加后取反32位无符号"""
if len(data) % 4 != 0:
raise ValueError("Data length must be multiple of 4")
sum_val = 0
# 遍历所有4字节块最后4字节除外
for i in range(0, len(data)-4, 4):
chunk = data[i:i+4]
value = struct.unpack('<I', chunk)[0] # 小端序解析
sum_val = (sum_val + value) & 0xFFFFFFFF # 32位溢出保护
return (~sum_val) & 0xFFFFFFFF # 取反并保持32位
def process_file(filename):
"""处理文件的主函数"""
try:
# 读取文件内容(二进制模式)
with open(filename, 'rb+') as f:
original_data = f.read()
data_len = len(original_data)
# ========== 验证阶段 ==========
# 1. 检查文件长度是否为4的倍数
if data_len % 4 != 0:
raise ValueError(f"文件长度 {data_len} 不是4的倍数")
# 2. 检查第二个4字节是否等于文件长度
if data_len >= 8:
declared_length = struct.unpack('<I', original_data[4:8])[0]
if declared_length != data_len:
raise ValueError(
f"长度声明不匹配:文件头声明={declared_length},实际={data_len}"
)
# ========== 计算校验和 ==========
checksum = calculate_checksum(original_data)
# ========== 写入校验和 ==========
# 定位到文件最后4字节
f.seek(-4, os.SEEK_END)
f.write(struct.pack('<I', checksum)) # 小端序写入
print(f"[成功] 文件 {filename} 已更新校验码0x{checksum:08X}")
return True
except Exception as e:
print(f"[错误] 处理文件 {filename} 失败:{str(e)}")
return False
if __name__ == "__main__":
# 参数检查
if len(sys.argv) != 2:
print("用法: python checksum.py <文件名>")
sys.exit(1)
input_file = sys.argv[1]
# 文件存在性检查
if not os.path.isfile(input_file):
print(f"[错误] 文件不存在: {input_file}")
sys.exit(1)
# 执行处理
if not process_file(input_file):
sys.exit(1)