diff --git a/driver/inc/common.h b/driver/inc/common.h index acdc096..3dcbf37 100644 --- a/driver/inc/common.h +++ b/driver/inc/common.h @@ -3,7 +3,11 @@ #include "reg.h" +#define FW_ADDRESS (64 * 1024) +#define MAGIC_HEAD (0x64616568) /* ASCII of "head" */ + struct fw_header_s { + uint32_t magic; uint32_t size; uint32_t jump_address; /* syspll config */ @@ -18,10 +22,10 @@ struct fw_header_s { uint8_t usbpll_postdiv2; /* must be in 1~7 */ /* system clock div */ 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 */ uint16_t flash_div; /* 0 is for disable, 2~65534 is available, must be even value */ - uint16_t flash_resv; - uint32_t resv; /* checksum */ uint32_t checksum; }; diff --git a/driver/src/common.c b/driver/src/common.c index 67c02a2..f2ace47 100644 --- a/driver/src/common.c +++ b/driver/src/common.c @@ -1 +1,25 @@ #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, +}; diff --git a/example/boot2/main.c b/example/boot2/main.c index 343bdf5..8e3b553 100644 --- a/example/boot2/main.c +++ b/example/boot2/main.c @@ -52,19 +52,20 @@ void __attribute__((section(".text.boot2_pre"))) boot2_copy_self(void) ioqspi_hw->io[1].ctrl = GPIO_OVER_OUT_HIGH; } +#include "common.h" #include "resets.h" #include "clock.h" #include "uart.h" #include "flash.h" #include "watchdog.h" #include "timer.h" -#include "stdio.h" +#include "jump.h" -uint8_t uart_tx_buffer[512]; -uint8_t uart_rx_buffer[512]; +uint8_t tx_buffer[512] __attribute__((aligned(4))); +uint8_t rx_buffer[512] __attribute__((aligned(4))); struct uart_cfg_s uart_cfg = { - .baudrate = 2 * 1000 * 1000, + .baudrate = 750 * 1000, .mode = UART_MODE_TX_RX, .data_bits = UART_DATABITS_8, .parity = UART_PARITY_NONE, @@ -141,7 +142,7 @@ void uart_process(uint16_t code, uint16_t length) uint16_t i; uint32_t v1, v2; - p = uart_rx_buffer + 8; + p = rx_buffer + 8; if ((length > 0) && (length <= 4)) { return; } @@ -168,7 +169,7 @@ void uart_process(uint16_t code, uint16_t length) process_return_ok(); } else if (code == 0x0003) { 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; return; } - code = ((uint16_t)uart_rx_buffer[0] << 8) | (uint16_t)uart_rx_buffer[1]; - code_inv = ((uint16_t)uart_rx_buffer[2] << 8) | (uint16_t)uart_rx_buffer[3]; - length = ((uint16_t)uart_rx_buffer[4] << 8) | (uint16_t)uart_rx_buffer[5]; - length_inv = ((uint16_t)uart_rx_buffer[6] << 8) | (uint16_t)uart_rx_buffer[7]; + code = ((uint16_t)rx_buffer[0] << 8) | (uint16_t)rx_buffer[1]; + code_inv = ((uint16_t)rx_buffer[2] << 8) | (uint16_t)rx_buffer[3]; + length = ((uint16_t)rx_buffer[4] << 8) | (uint16_t)rx_buffer[5]; + length_inv = ((uint16_t)rx_buffer[6] << 8) | (uint16_t)rx_buffer[7]; if ((code != (uint16_t)~code_inv) || (length != (uint16_t)~length_inv)) { uart_rx_length = 0; return; @@ -198,28 +199,23 @@ void uart_state_machine(uint8_t id) uart_process(code, length); uart_rx_length = 0; } 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(); - if (uart_rx_length >= sizeof(uart_rx_buffer)) { + if (uart_rx_length >= sizeof(rx_buffer)) { uart_rx_length = 0; return; } } } -__attribute__((naked)) void jump_to_address(uint32_t address) { - __asm volatile ( - "bx %0\n" - : - : "r" (address) - ); -} - int main(void) { 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); 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) { + for (uint32_t i = 0; i < 4; i++) { + tx_buffer[i] = 0x55; + } + uart_write_block(UART_ID_0, tx_buffer, 4); while (1) { uart_state_machine(UART_ID_0); } } else { - flash_enter_quad_xip(6); - jump_to_address(0x10010000 | 1); + flash_read(FW_ADDRESS, rx_buffer, FLASH_READ_SIZE); + 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; diff --git a/example/boot2/src/CMakeLists.txt b/example/boot2/src/CMakeLists.txt index 5c87fca..1dad8ed 100644 --- a/example/boot2/src/CMakeLists.txt +++ b/example/boot2/src/CMakeLists.txt @@ -1,5 +1,6 @@ file(GLOB FILELIST flash.c +jump.c ) set(TARGET src) diff --git a/example/boot2/src/jump.c b/example/boot2/src/jump.c new file mode 100644 index 0000000..0db9a1b --- /dev/null +++ b/example/boot2/src/jump.c @@ -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))(); +} diff --git a/example/boot2/src/jump.h b/example/boot2/src/jump.h new file mode 100644 index 0000000..0b2bc8c --- /dev/null +++ b/example/boot2/src/jump.h @@ -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__ */ \ No newline at end of file diff --git a/flash.ld b/flash.ld index a78a52d..2abe0ba 100644 --- a/flash.ld +++ b/flash.ld @@ -11,7 +11,8 @@ _stack_top_core1 = 0x20041000 + 4 * 1024; 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 */ rodata PT_LOAD FLAGS(6); /* R + W */ data PT_LOAD FLAGS(6); /* R + W */ @@ -24,10 +25,16 @@ SECTIONS { . = ALIGN(4); KEEP(*(.fw_header)) - KEEP(*(.text.isr_reset)) . = ALIGN(4); } >FLASH :fw_header + .isr_reset : + { + . = ALIGN(4); + KEEP(*(.text.isr_reset)) + . = ALIGN(4); + } >FLASH :isr_reset + .text : { . = ALIGN(4); diff --git a/project.build b/project.build index 4122bc5..2a34923 100644 --- a/project.build +++ b/project.build @@ -23,6 +23,9 @@ LDFLAGS += -Wl,--gc-sections LDFLAGS += -nostartfiles LDFLAGS += -Wl,-Map=$(EXAMPLE_NAME).map LDFLAGS += -Wl,--print-memory-usage +ifndef BOOT2_PRE_CRC +LDFLAGS += -ufw_header +endif CMAKE := cmake 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) +FW_HEADER_CHECKSUM ?= fw_header_checksum.bin + post:build ifdef 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) @$(CROSS_COMPILE)objcopy --update-section .boot2_pre=$(BOOT2_PRE_CRC) $(FINAL_NAME_PRE).elf @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 @$(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 diff --git a/tools/checksum.py b/tools/checksum.py new file mode 100644 index 0000000..a2647f9 --- /dev/null +++ b/tools/checksum.py @@ -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('= 8: + declared_length = struct.unpack('") + 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)