From 3eefbaa2b550745dc8fef2f7e9a54d6eb7402ad1 Mon Sep 17 00:00:00 2001 From: Dien-Nhung Nguyen-Phu Date: Tue, 15 Apr 2025 12:43:05 +0700 Subject: [PATCH 1/2] WIP: port MCUboot --- .github/workflows/build.yaml | 8 + .gitmodules | 7 + Makefile | 114 ++++++++-- app.ld | 174 ++++++++++++++++ bootloader.ld | 183 ++++++++++++++++ external/mcuboot | 1 + external/tinycrypt | 1 + inc/common/debug.h | 15 ++ inc/flash_map_backend/flash_map_backend.h | 71 +++++++ inc/mcuboot_config/mcuboot_config.h | 175 ++++++++++++++++ inc/mcuboot_config/mcuboot_logging.h | 16 ++ inc/os/os_malloc.h | 6 + inc/sysflash/sysflash.h | 24 +++ src/boot-entry.c | 75 +++++++ src/debug.h | 12 +- src/main.c | 2 + src/mcuboot.c | 243 ++++++++++++++++++++++ 17 files changed, 1102 insertions(+), 25 deletions(-) create mode 100644 .gitmodules create mode 100644 app.ld create mode 100644 bootloader.ld create mode 160000 external/mcuboot create mode 160000 external/tinycrypt create mode 100644 inc/common/debug.h create mode 100644 inc/flash_map_backend/flash_map_backend.h create mode 100644 inc/mcuboot_config/mcuboot_config.h create mode 100644 inc/mcuboot_config/mcuboot_logging.h create mode 100644 inc/os/os_malloc.h create mode 100644 inc/sysflash/sysflash.h create mode 100644 src/boot-entry.c create mode 100644 src/mcuboot.c diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index c457943..544ccbc 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -17,6 +17,7 @@ jobs: steps: - uses: actions/checkout@v4 with: + submodules: 'true' fetch-depth: 0 # fetch tags for versioning - name: Cache toolchain @@ -32,6 +33,13 @@ jobs: wget http://file-oss.mounriver.com/tools/${{ env.MRS_TOOLCHAIN }}.tar.xz tar -xvf ${{ env.MRS_TOOLCHAIN }}.tar.xz + - name: Install dependencies for MCUboot imgtool + run: | + pip3 install -e external/mcuboot/scripts/ + + - name: Install srec_cat + run: sudo apt-get update && sudo apt-get install -y srecord + - name: Build firmware run: | export PREFIX=${{ env.MRS_TOOLCHAIN }}/RISC-V_Embedded_GCC/bin/riscv-none-embed- diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..9c6cca8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,7 @@ +[submodule "external/mcuboot"] + path = external/mcuboot + url = https://github.com/mcu-tools/mcuboot.git + branch = v2.1.0 +[submodule "external/tinycrypt"] + path = external/tinycrypt + url = https://github.com/intel/tinycrypt.git diff --git a/Makefile b/Makefile index a4e6916..1c24589 100644 --- a/Makefile +++ b/Makefile @@ -8,12 +8,14 @@ TARGET = badgemagic-ch582 # building variables ###################################### # Uncomment below line to enable debugging -# DEBUG = 1 +DEBUG = 1 # Uncomment below to build for USB-C version -# USBC_VERSION = 1 +USBC_VERSION = 1 # optimization for size OPT = -Os +OPENOCD ?= ../MRS_Toolchain_Linux_x64_V1.91/OpenOCD/bin/openocd + ####################################### # Get current version @@ -55,7 +57,6 @@ CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_uart1.c \ CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_usb2dev.c \ CH5xx_ble_firmware_library/StdPeriphDriver/CH58x_spi1.c \ CH5xx_ble_firmware_library/RVMSIS/core_riscv.c \ -src/main.c \ src/debug.c \ src/leddrv.c \ src/button.c \ @@ -83,7 +84,54 @@ src/resource.c \ src/animation.c \ src/font.c \ src/power.c \ - +src/mcuboot.c \ + +MCUBOOT_DIR := external/mcuboot +IMGTOOL_PY := $(MCUBOOT_DIR)/scripts/imgtool.py +MCUBOOT_SRC_DIR := $(MCUBOOT_DIR)/boot/bootutil/src +MCUBOOT_INC_DIR := $(MCUBOOT_DIR)/boot/bootutil/include + +MCUBOOT_SRC_FILES += \ +$(MCUBOOT_SRC_DIR)/boot_record.c \ +$(MCUBOOT_SRC_DIR)/bootutil_misc.c \ +$(MCUBOOT_SRC_DIR)/bootutil_public.c \ +$(MCUBOOT_SRC_DIR)/caps.c \ +$(MCUBOOT_SRC_DIR)/encrypted.c \ +$(MCUBOOT_SRC_DIR)/fault_injection_hardening.c \ +$(MCUBOOT_SRC_DIR)/fault_injection_hardening_delay_rng_mbedtls.c \ +$(MCUBOOT_SRC_DIR)/image_ecdsa.c \ +$(MCUBOOT_SRC_DIR)/image_ed25519.c \ +$(MCUBOOT_SRC_DIR)/image_rsa.c \ +$(MCUBOOT_SRC_DIR)/image_validate.c \ +$(MCUBOOT_SRC_DIR)/loader.c \ +$(MCUBOOT_SRC_DIR)/swap_misc.c \ +$(MCUBOOT_SRC_DIR)/swap_move.c \ +$(MCUBOOT_SRC_DIR)/swap_scratch.c \ +$(MCUBOOT_SRC_DIR)/tlv.c + +TINYCRYPT_DIR := external/tinycrypt/lib +TINYCRYPT_SRC_DIR := $(TINYCRYPT_DIR)/source +TINYCRYPT_INC_DIR := $(TINYCRYPT_DIR)/include + +TINYCRYPT_SRC_FILES += \ +$(TINYCRYPT_SRC_DIR)/aes_decrypt.c \ +$(TINYCRYPT_SRC_DIR)/aes_encrypt.c \ +$(TINYCRYPT_SRC_DIR)/cbc_mode.c \ +$(TINYCRYPT_SRC_DIR)/ccm_mode.c \ +$(TINYCRYPT_SRC_DIR)/cmac_mode.c \ +$(TINYCRYPT_SRC_DIR)/ctr_mode.c \ +$(TINYCRYPT_SRC_DIR)/ctr_prng.c \ +$(TINYCRYPT_SRC_DIR)/hmac.c \ +$(TINYCRYPT_SRC_DIR)/hmac_prng.c \ +$(TINYCRYPT_SRC_DIR)/sha256.c \ +$(TINYCRYPT_SRC_DIR)/utils.c +# ecc.c +# ecc_dh.c +# ecc_dsa.c +# ecc_platform_specific.c + +C_SOURCES += $(TINYCRYPT_SRC_FILES) +C_SOURCES += $(MCUBOOT_SRC_FILES) # ASM sources ASM_SOURCES = \ @@ -121,11 +169,14 @@ MCU = $(CPU) $(FPU) $(FLOAT-ABI) AS_INCLUDES = # C includes -C_INCLUDES = \ +C_INCLUDES += \ -ICH5xx_ble_firmware_library/StdPeriphDriver/inc \ -ICH5xx_ble_firmware_library/RVMSIS \ -ICH5xx_ble_firmware_library/Core \ -ICH5xx_ble_firmware_library/BLE \ +-Iinc \ +-Iexternal/tinycrypt/lib/include \ +-I$(MCUBOOT_INC_DIR) # compile gcc flags ASFLAGS = $(MCU) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections @@ -151,7 +202,7 @@ CFLAGS += -MMD -MP # LDFLAGS ####################################### # link script -LDSCRIPT = CH5xx_ble_firmware_library/Ld/Link.ld +# LDSCRIPT = CH5xx_ble_firmware_library/Ld/Link.ld # libraries LIBS = -lc -lm -lnosys \ @@ -159,11 +210,18 @@ LIBS = -lc -lm -lnosys \ ./CH5xx_ble_firmware_library/BLE/LIBCH58xBLE.a \ LIBDIR = -LDFLAGS = $(MCU) -mno-save-restore -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -Wunused -Wuninitialized -T $(LDSCRIPT) -nostartfiles -Xlinker --gc-sections -Wl,-Map=$(BUILD_DIR)/$(TARGET).map --specs=nano.specs $(LIBS) +LDFLAGS = $(MCU) -mno-save-restore -fmessage-length=0 -fsigned-char \ + -ffunction-sections -fdata-sections -Wunused -Wuninitialized -nostartfiles \ + -Xlinker --gc-sections -Wl,-Map=$(BUILD_DIR)/$(TARGET).map \ + --specs=nano.specs $(LIBS) \ # default action: build all -all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin - +all: $(BUILD_DIR)/$(TARGET).elf \ +$(BUILD_DIR)/$(TARGET).hex \ +$(BUILD_DIR)/$(TARGET).bin \ +$(BUILD_DIR)/$(TARGET).signed.bin \ +$(BUILD_DIR)/mcuboot.bin \ +$(BUILD_DIR)/combined.bin \ ####################################### # build the application @@ -182,9 +240,14 @@ $(BUILD_DIR)/%.o: %.S Makefile @mkdir -pv $(dir $@) $(AS) -c $(CFLAGS) $< -o $@ -$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile +$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) $(BUILD_DIR)/src/main.o Makefile app.ld + @mkdir -pv $(dir $@) + $(CC) $(OBJECTS) $(BUILD_DIR)/src/main.o -T app.ld $(LDFLAGS) -o $@ + $(SZ) $@ + +$(BUILD_DIR)/mcuboot.elf: $(OBJECTS) $(BUILD_DIR)/src/boot-entry.o Makefile bootloader.ld @mkdir -pv $(dir $@) - $(CC) $(OBJECTS) $(LDFLAGS) -o $@ + $(CC) $(OBJECTS) $(BUILD_DIR)/src/boot-entry.o $(LDFLAGS) -T bootloader.ld -o $@ $(SZ) $@ $(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf @@ -193,16 +256,37 @@ $(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf $(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf @mkdir -pv $(dir $@) - $(BIN) $< $@ + $(BIN) $< $@ + +$(BUILD_DIR)/combined.bin: $(BUILD_DIR)/mcuboot.bin $(BUILD_DIR)/$(TARGET).signed.bin + srec_cat $(BUILD_DIR)/mcuboot.bin -Binary -offset 0 \ + -fill 0xff 0 0x0010000 \ + $(BUILD_DIR)/$(TARGET).signed.bin -Binary -offset 0x00010000 \ + -o $@ -Binary \ ####################################### # Program ####################################### program: $(BUILD_DIR)/$(TARGET).elf - sudo wch-openocd -f /usr/share/wch-openocd/openocd/scripts/interface/wch-riscv.cfg -c 'init; halt; program $(BUILD_DIR)/$(TARGET).elf; reset; wlink_reset_resume; exit;' + $(OPENOCD) -f interface/wch-riscv.cfg -c 'init; halt; program $(BUILD_DIR)/combined.bin ; reset; wlink_reset_resume; exit;' + +debug: + $(OPENOCD) -f debug.cfg + +$(BUILD_DIR)/$(TARGET).signed.bin: $(BUILD_DIR)/$(TARGET).bin + python $(IMGTOOL_PY) sign \ + --header-size 0x200 \ + --align 4 \ + -S 204800 \ + -v 1.0.0 \ + --pad-header \ + $< $@ + +isp: $(BUILD_DIR)/$(TARGET).elf + wchisp flash $(BUILD_DIR)/$(TARGET).elf -isp: $(BUILD_DIR)/$(TARGET).bin - wchisp flash $(BUILD_DIR)/$(TARGET).bin +isp-bootld: $(BUILD_DIR)/mcuboot.elf + wchisp flash $(BUILD_DIR)/mcuboot.elf -E ####################################### # clean up diff --git a/app.ld b/app.ld new file mode 100644 index 0000000..5126ab6 --- /dev/null +++ b/app.ld @@ -0,0 +1,174 @@ +ENTRY( _start ) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00010000, LENGTH = 384k + RAM (xrw) : ORIGIN = 0x20003800, LENGTH = 32K +} + +SECTIONS +{ + .init : + { + _sinit = .; + . = ALIGN(4); + KEEP(*(SORT_NONE(.init))) + . = ALIGN(4); + _einit = .; + } >FLASH AT>FLASH + +/* .vector : + { + *(.vector); + } >FLASH AT>FLASH */ + + .highcodelalign : + { + . = ALIGN(4); + PROVIDE(_highcode_lma = .); + } >FLASH AT>FLASH + + .highcode : + { + . = ALIGN(4); + PROVIDE(_highcode_vma_start = .); + *(.vector); + KEEP(*(SORT_NONE(.vector_handler))) + *(.highcode); + *(.highcode.*); + . = ALIGN(4); + PROVIDE(_highcode_vma_end = .); + } >RAM AT>FLASH + + .text : + { + . = ALIGN(4); + KEEP(*(SORT_NONE(.handle_reset))) + *(.text) + *(.text.*) + *(.rodata) + *(.rodata*) + *(.sdata2.*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t.*) + . = ALIGN(4); + } >FLASH AT>FLASH + + .fini : + { + KEEP(*(SORT_NONE(.fini))) + . = ALIGN(4); + } >FLASH AT>FLASH + + PROVIDE( _etext = . ); + PROVIDE( _eitcm = . ); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH AT>FLASH + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH AT>FLASH + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH AT>FLASH + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >FLASH AT>FLASH + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >FLASH AT>FLASH + + .dalign : + { + . = ORIGIN(RAM) + MAX(0x800 , SIZEOF(.highcode)); + } >RAM AT>FLASH + + .dlalign : + { + . = ALIGN(4); + PROVIDE(_data_lma = .); + } >FLASH AT>FLASH + + .data : + { + . = ALIGN(4); + PROVIDE(_data_vma = .); + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + . = ALIGN(4); + PROVIDE( _edata = .); + } >RAM AT>FLASH + + .bss : + { + . = ALIGN(4); + PROVIDE( _sbss = .); + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss*) + *(.gnu.linkonce.b.*) + *(COMMON*) + . = ALIGN(4); + PROVIDE( _ebss = .); + } >RAM AT>FLASH + PROVIDE( _end = _ebss); + PROVIDE( end = . ); + + .stack ORIGIN(RAM)+LENGTH(RAM) : + { + . = ALIGN(4); + PROVIDE(_eusrstack = . ); + } >RAM +} \ No newline at end of file diff --git a/bootloader.ld b/bootloader.ld new file mode 100644 index 0000000..ef6c1e9 --- /dev/null +++ b/bootloader.ld @@ -0,0 +1,183 @@ +ENTRY( _start ) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K + /* APP (rx) : ORIGIN = 0x00010000, LENGTH = 200K */ + RAM (xrw) : ORIGIN = 0x20003800, LENGTH = 32K +} + +SECTIONS +{ + .init : + { + _sinit = .; + . = ALIGN(4); + KEEP(*(SORT_NONE(.init))) + . = ALIGN(4); + _einit = .; + } >FLASH AT>FLASH + +/* .vector : + { + *(.vector); + } >FLASH AT>FLASH */ + + .highcodelalign : + { + . = ALIGN(4); + PROVIDE(_highcode_lma = .); + } >FLASH AT>FLASH + + .highcode : + { + . = ALIGN(4); + PROVIDE(_highcode_vma_start = .); + *(.vector); + KEEP(*(SORT_NONE(.vector_handler))) + *(.highcode); + *(.highcode.*); + . = ALIGN(4); + PROVIDE(_highcode_vma_end = .); + } >RAM AT>FLASH + + .text : + { + . = ALIGN(4); + KEEP(*(SORT_NONE(.handle_reset))) + *(.text) + *(.text.*) + *(.rodata) + *(.rodata*) + *(.sdata2.*) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t.*) + . = ALIGN(4); + } >FLASH AT>FLASH + + .fini : + { + KEEP(*(SORT_NONE(.fini))) + . = ALIGN(4); + } >FLASH AT>FLASH + + PROVIDE( _etext = . ); + PROVIDE( _eitcm = . ); + + .preinit_array : + { + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + } >FLASH AT>FLASH + + .init_array : + { + PROVIDE_HIDDEN (__init_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*))) + KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors)) + PROVIDE_HIDDEN (__init_array_end = .); + } >FLASH AT>FLASH + + .fini_array : + { + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*))) + KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors)) + PROVIDE_HIDDEN (__fini_array_end = .); + } >FLASH AT>FLASH + + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin.o(.ctors)) + KEEP (*crtbegin?.o(.ctors)) + + /* We don't want to include the .ctor section from + the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } >FLASH AT>FLASH + + .dtors : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*crtbegin?.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } >FLASH AT>FLASH + + .dalign : + { + . = ORIGIN(RAM) + MAX(0x800 , SIZEOF(.highcode)); + } >RAM AT>FLASH + + .dlalign : + { + . = ALIGN(4); + PROVIDE(_data_lma = .); + } >FLASH AT>FLASH + + .data : + { + . = ALIGN(4); + PROVIDE(_data_vma = .); + *(.gnu.linkonce.r.*) + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(8); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(8); + *(.srodata.cst16) + *(.srodata.cst8) + *(.srodata.cst4) + *(.srodata.cst2) + *(.srodata .srodata.*) + . = ALIGN(4); + PROVIDE( _edata = .); + } >RAM AT>FLASH + + .bss : + { + . = ALIGN(4); + PROVIDE( _sbss = .); + *(.sbss*) + *(.gnu.linkonce.sb.*) + *(.bss*) + *(.gnu.linkonce.b.*) + *(COMMON*) + . = ALIGN(4); + PROVIDE( _ebss = .); + } >RAM AT>FLASH + + /* . = ORIGIN(APP); + .app : + { + *(.app) + } >APP AT>APP */ + + PROVIDE( _end = _ebss); + PROVIDE( end = . ); + + + .stack ORIGIN(RAM)+LENGTH(RAM) : + { + . = ALIGN(4); + PROVIDE(_eusrstack = . ); + } >RAM +} \ No newline at end of file diff --git a/external/mcuboot b/external/mcuboot new file mode 160000 index 0000000..9c99326 --- /dev/null +++ b/external/mcuboot @@ -0,0 +1 @@ +Subproject commit 9c99326b9756dbcc35b524636d99ed5f3e6cb29b diff --git a/external/tinycrypt b/external/tinycrypt new file mode 160000 index 0000000..cf24c90 --- /dev/null +++ b/external/tinycrypt @@ -0,0 +1 @@ +Subproject commit cf24c907a61c01bc2c4e1ee0ae24457c27a840a2 diff --git a/inc/common/debug.h b/inc/common/debug.h new file mode 100644 index 0000000..9ee5413 --- /dev/null +++ b/inc/common/debug.h @@ -0,0 +1,15 @@ +#ifndef __COMMON_DEBUG_H__ +#define __COMMON_DEBUG_H__ + +#include + +#ifdef DEBUG +#define PRINT(X...) printf(X) +#else +#define PRINT(X...) +#endif + +#define _TRACE() PRINT("> "); PRINT(__FILE__); PRINT(": "); PRINT(__func__); \ + PRINT("()\n") + +#endif /* __COMMON_DEBUG_H__ */ diff --git a/inc/flash_map_backend/flash_map_backend.h b/inc/flash_map_backend/flash_map_backend.h new file mode 100644 index 0000000..1e61c44 --- /dev/null +++ b/inc/flash_map_backend/flash_map_backend.h @@ -0,0 +1,71 @@ +#ifndef __FLASH_MAP_BACKEND_H__ +#define __FLASH_MAP_BACKEND_H__ + +#include +#include + +struct flash_area { + uint8_t fa_id; /** The slot/scratch identification */ + uint8_t fa_device_id; /** The device id (usually there's only one) */ + uint16_t pad16; + uint32_t fa_off; /** The flash offset from the beginning */ + uint32_t fa_size; /** The size of this sector */ +}; + +typedef struct flash_area fa_t; + +//! Structure describing a sector within a flash area. +struct flash_sector { + //! Offset of this sector, from the start of its flash area (not device). + uint32_t fs_off; + + //! Size of this sector, in bytes. + uint32_t fs_size; +}; + +/*< Obtains ID of the flash area characterized by `fa` */ +int flash_area_get_id(const fa_t *fa); + +/*< Obtains ID of a device the flash area `fa` described region resides on */ +int flash_area_get_device_id(const fa_t *fa); + +/*< Obtains offset, from the beginning of a device, the flash area described + * region starts at */ + uint32_t flash_area_get_off(const fa_t *fa); + +/*< Obtains size, from the offset, of the flash area `fa` characterized region */ +uint32_t flash_area_get_size(const fa_t *fa); + +//! Opens the area for use. id is one of the `fa_id`s */ +int flash_area_open(uint8_t id, const fa_t **area_outp); +void flash_area_close(const fa_t *fa); + +//! Reads `len` bytes of flash memory at `off` to the buffer at `dst` +int flash_area_read(const fa_t *fa, uint32_t off, void *dst, + uint32_t len); +//! Writes `len` bytes of flash memory at `off` from the buffer at `src` +int flash_area_write(const fa_t *fa, uint32_t off, const void *src, + uint32_t len); +//! Erases `len` bytes of flash memory at `off` +int flash_area_erase(const fa_t *fa, uint32_t off, uint32_t len); + +//! Returns this `flash_area`s alignment +size_t flash_area_align(const fa_t *area); +//! Returns the value read from an erased flash area byte +uint8_t flash_area_erased_val(const fa_t *area); + +//! Given flash area ID, return info about sectors within the area +int flash_area_get_sectors(int fa_id, uint32_t *count, + struct flash_sector *sectors); + +__attribute__((deprecated)) +int flash_area_to_sectors(int idx, int *cnt, fa_t *ret); + +//! Returns the `fa_id` for slot, where slot is 0 (primary) or 1 (secondary). +//! +//! `image_index` (0 or 1) is the index of the image. Image index is +//! relevant only when multi-image support support is enabled +int flash_area_id_from_multi_image_slot(int image_index, int slot); +int flash_area_id_from_image_slot(int slot); + +#endif /* __FLASH_MAP_BACKEND_H__ */ diff --git a/inc/mcuboot_config/mcuboot_config.h b/inc/mcuboot_config/mcuboot_config.h new file mode 100644 index 0000000..dbea8c2 --- /dev/null +++ b/inc/mcuboot_config/mcuboot_config.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2018 Open Source Foundries Limited + * Copyright (c) 2019-2024 Arm Limited + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __MCUBOOT_CONFIG_H__ +#define __MCUBOOT_CONFIG_H__ + +/* + * Template configuration file for MCUboot. + * + * When porting MCUboot to a new target, copy it somewhere that your + * include path can find it as mcuboot_config/mcuboot_config.h, and + * make adjustments to suit your platform. + * + * For examples, see: + * + * boot/zephyr/include/mcuboot_config/mcuboot_config.h + * boot/mynewt/mcuboot_config/include/mcuboot_config/mcuboot_config.h + */ + +/* + * Signature types + * + * You must choose exactly one signature type. + */ + +/* Uncomment for RSA signature support */ +/* #define MCUBOOT_SIGN_RSA */ + +/* Uncomment for ECDSA signatures using curve P-256. */ +/* #define MCUBOOT_SIGN_EC256 */ + +/* + * Public key handling + * + * Choose one or none from the different public key handling options. + */ + +/* Uncomment to use key hash(es) instead of incorporating + * the public key into the code. */ +/* #define MCUBOOT_HW_KEY */ +/* Uncomment to use builtin key(s) instead of incorporating + * the public key into the code. */ +/* #define MCUBOOT_BUILTIN_KEY */ + +/* + * Upgrade mode + * + * The default is to support A/B image swapping with rollback. Other modes + * with simpler code path, which only supports overwriting the existing image + * with the update image or running the newest image directly from its flash + * partition, are also available. + * + * You can enable only one mode at a time from the list below to override + * the default upgrade mode. + */ + +/* Uncomment to enable the overwrite-only code path. */ +/* #define MCUBOOT_OVERWRITE_ONLY */ + +#ifdef MCUBOOT_OVERWRITE_ONLY +/* Uncomment to only erase and overwrite those primary slot sectors needed + * to install the new image, rather than the entire image slot. */ +/* #define MCUBOOT_OVERWRITE_ONLY_FAST */ +#endif + +/* Uncomment to enable the direct-xip code path. */ +/* #define MCUBOOT_DIRECT_XIP */ +/* Uncomment to enable the revert mechanism in direct-xip mode. */ +/* #define MCUBOOT_DIRECT_XIP_REVERT */ + +/* Uncomment to enable the ram-load code path. */ +/* #define MCUBOOT_RAM_LOAD */ + +/* + * Cryptographic settings + * + * You must choose between mbedTLS and Tinycrypt as source of + * cryptographic primitives. Other cryptographic settings are also + * available. + */ + +/* Uncomment to use ARM's mbedTLS cryptographic primitives */ +/* #define MCUBOOT_USE_MBED_TLS */ +/* Uncomment to use Tinycrypt's. */ +#define MCUBOOT_USE_TINYCRYPT + +/* + * Always check the signature of the image in the primary slot before booting, + * even if no upgrade was performed. This is recommended if the boot + * time penalty is acceptable. + */ +#define MCUBOOT_VALIDATE_PRIMARY_SLOT + +/* + * Flash abstraction + */ + +/* Uncomment if your flash map API supports flash_area_get_sectors(). + * See the flash APIs for more details. */ +// #define MCUBOOT_USE_FLASH_AREA_GET_SECTORS + +/* Default maximum number of flash sectors per image slot; change + * as desirable. */ +#define MCUBOOT_MAX_IMG_SECTORS 128 + +/* Default number of separately updateable images; change in case of + * multiple images. */ +#define MCUBOOT_IMAGE_NUMBER 1 + +/* + * Logging + */ + +/* + * If logging is enabled the following functions must be defined by the + * platform: + * + * MCUBOOT_LOG_MODULE_REGISTER(domain) + * Register a new log module and add the current C file to it. + * + * MCUBOOT_LOG_MODULE_DECLARE(domain) + * Add the current C file to an existing log module. + * + * MCUBOOT_LOG_ERR(...) + * MCUBOOT_LOG_WRN(...) + * MCUBOOT_LOG_INF(...) + * MCUBOOT_LOG_DBG(...) + * + * The function priority is: + * + * MCUBOOT_LOG_ERR > MCUBOOT_LOG_WRN > MCUBOOT_LOG_INF > MCUBOOT_LOG_DBG + */ +#define MCUBOOT_HAVE_LOGGING 1 + +/* + * Assertions + */ + +/* Uncomment if your platform has its own mcuboot_config/mcuboot_assert.h. + * If so, it must provide an ASSERT macro for use by bootutil. Otherwise, + * "assert" is used. */ +/* #define MCUBOOT_HAVE_ASSERT_H */ + +/* + * Watchdog feeding + */ + +/* This macro might be implemented if the OS / HW watchdog is enabled while + * doing a swap upgrade and the time it takes for a swapping is long enough + * to cause an unwanted reset. If implementing this, the OS main.c must also + * enable the watchdog (if required)! + * + * #define MCUBOOT_WATCHDOG_FEED() + * do { do watchdog feeding here! } while (0) + */ +#define MCUBOOT_WATCHDOG_FEED() \ + do { \ + /* TODO: to be implemented */ \ + } while (0) + +/* If a OS ports support single thread mode or is bare-metal then: + * This macro implements call that switches CPU to an idle state, from which + * the CPU may be woken up by, for example, UART transmission event. + * + * Otherwise this macro should be no-op. + */ +#define MCUBOOT_CPU_IDLE() \ + do { \ + } while (0) + +#endif /* __MCUBOOT_CONFIG_H__ */ diff --git a/inc/mcuboot_config/mcuboot_logging.h b/inc/mcuboot_config/mcuboot_logging.h new file mode 100644 index 0000000..94ee9ed --- /dev/null +++ b/inc/mcuboot_config/mcuboot_logging.h @@ -0,0 +1,16 @@ +#ifndef __MCUBOOT_LOGGING_H__ +#define __MCUBOOT_LOGGING_H__ + +#include "common/debug.h" +#include "mcuboot_config.h" + +#define MCUBOOT_LOG_ERR(_fmt, ...) PRINT(" [ERR] " _fmt "\n", ##__VA_ARGS__) +#define MCUBOOT_LOG_WRN(_fmt, ...) PRINT(" [WRN] " _fmt "\n", ##__VA_ARGS__) +#define MCUBOOT_LOG_INF(_fmt, ...) PRINT(" [INF] " _fmt "\n", ##__VA_ARGS__) +#define MCUBOOT_LOG_DBG(_fmt, ...) PRINT(" [DBG] " _fmt "\n", ##__VA_ARGS__) + +#define MCUBOOT_LOG_MODULE_DECLARE(...) +#define MCUBOOT_LOG_MODULE_REGISTER(...) + + +#endif /* __MCUBOOT_LOGGING_H__ */ diff --git a/inc/os/os_malloc.h b/inc/os/os_malloc.h new file mode 100644 index 0000000..aa7bea1 --- /dev/null +++ b/inc/os/os_malloc.h @@ -0,0 +1,6 @@ +#ifndef __MCUBOOT_OS_MALLOC_H__ +#define __MCUBOOT_OS_MALLOC_H__ + +#include + +#endif /* __MCUBOOT_OS_MALLOC_H__ */ diff --git a/inc/sysflash/sysflash.h b/inc/sysflash/sysflash.h new file mode 100644 index 0000000..7c8ece4 --- /dev/null +++ b/inc/sysflash/sysflash.h @@ -0,0 +1,24 @@ +#ifndef __SYSFLASH_H__ +#define __SYSFLASH_H__ + +//! A user-defined identifier for different storage mediums +//! (i.e internal flash, external NOR flash, eMMC, etc) +#define FLASH_DEVICE_INTERNAL_FLASH 0 + +//! An arbitrarily high slot ID we will use to indicate that +//! there is not slot +#define FLASH_SLOT_DOES_NOT_EXIST 255 + +//! NB: MCUboot expects this define to exist but it's only used +//! if MCUBOOT_SWAP_USING_SCRATCH=1 is set +#define FLASH_AREA_IMAGE_SCRATCH FLASH_SLOT_DOES_NOT_EXIST + +//! The slot we will use to track the bootloader allocation +#define FLASH_AREA_BOOTLOADER 0 + +//! A mapping to primary and secondary/upgrade slot +//! given an image_index. We'll plan to use +#define FLASH_AREA_IMAGE_PRIMARY(i) ((i == 0) ? 1 : 255) +#define FLASH_AREA_IMAGE_SECONDARY(i) ((i == 0) ? 2 : 255) + +#endif /* __SYSFLASH_H__ */ diff --git a/src/boot-entry.c b/src/boot-entry.c new file mode 100644 index 0000000..11d4f3b --- /dev/null +++ b/src/boot-entry.c @@ -0,0 +1,75 @@ +#include "CH58x_common.h" +#include +#include + +// /* Import a binary file */ +// #define IMPORT_BIN(sect, file, sym) asm (\ +// ".section "#sect "\n" \ +// ".balign 4\n" /* Word alignment */\ +// ".global " #sym "\n" /* Export the object address */\ +// #sym ":\n" /* Define the object label */\ +// ".incbin \"" file "\"\n" /* Import the file */\ +// ".global _sizeof_" #sym "\n" /* Export the object size */\ +// ".set _sizeof_" #sym ", . - " #sym "\n" /* Define the object size */\ +// ".balign 4\n" /* Word alignment */\ +// ) +// // __attribute__((section(".highcode"))) +// IMPORT_BIN(.app, "build/badgemagic-ch582.signed.bin", main_bin); +// /* Declaration of symbols (any type can be used) */ +// extern const unsigned char main_bin[], _sizeof_main_bin[]; + +static void debug_init() +{ + GPIOA_SetBits(GPIO_Pin_9); + GPIOA_ModeCfg(GPIO_Pin_8, GPIO_ModeIN_PU); + GPIOA_ModeCfg(GPIO_Pin_9, GPIO_ModeOut_PP_5mA); + UART1_DefInit(); + UART1_BaudRateCfg(921600); +} + +void start_app(uint32_t pc, uint32_t sp) { + // __asm volatile ("la sp, %0" : : "r" (sp) : ); + + PRINT("Attempting jump pc=%x, sp=%x\n", pc, sp); + void (*application_reset_handler)(void) = (void *)pc; + (( void (*) ( void )) ((int*)pc))(); +} + +void do_boot(struct boot_rsp *rsp) { + PRINT("Starting Main Application"); + PRINT(" Image Start Offset: 0x%x", (int)rsp->br_image_off); + + // We run from internal flash. Base address of this medium is 0x0 + uint32_t vector_table = 0x0 + rsp->br_image_off + rsp->br_hdr->ih_hdr_size; + + uint32_t *app_code = (uint32_t *)vector_table; + uint32_t app_sp = app_code[0]; + uint32_t app_start = app_code[1]; + + PRINT(" Vector Table Start Address: 0x%x. PC=0x%x, SP=0x%x", + (int)vector_table, app_start, app_sp); + + // // We need to move the vector table to reflect the location of the main application + // volatile uint32_t *vtor = (uint32_t *)0xE000ED08; + // *vtor = (vector_table & 0xFFFFFFF8); + + start_app(vector_table, app_sp); +} + +int main() { + SetSysClock(CLK_SOURCE_PLL_60MHz); + + debug_init(); + PRINT("\nDebug console is on UART%d\n", DEBUG); + + struct boot_rsp rsp; + int rv = boot_go(&rsp); + + if (rv == 0) { + // 'rsp' contains the start address of the image + do_boot(&rsp); + } + PRINT("\rv failed\n"); + + while(1); +} \ No newline at end of file diff --git a/src/debug.h b/src/debug.h index 6378f4b..6f3f702 100644 --- a/src/debug.h +++ b/src/debug.h @@ -1,15 +1,7 @@ #ifndef __DEBUG_H__ #define __DEBUG_H__ -#include - -#ifdef DEBUG -#define PRINT(X...) printf(X) -#else -#define PRINT(X...) -#endif - -#define _TRACE() PRINT("> "); PRINT(__FILE__); PRINT(": "); PRINT(__func__); \ - PRINT("()\n") +// TODO: move delete this file and replace the references to this below file: +#include "common/debug.h" #endif /* __DEBUG_H__ */ diff --git a/src/main.c b/src/main.c index 33a1a34..61985a2 100644 --- a/src/main.c +++ b/src/main.c @@ -20,6 +20,8 @@ #include "usb/usb.h" #include "legacyctrl.h" +#include + #define NEXT_STATE(v, min, max) \ (v)++; \ if ((v) >= (max)) \ diff --git a/src/mcuboot.c b/src/mcuboot.c new file mode 100644 index 0000000..6cb8655 --- /dev/null +++ b/src/mcuboot.c @@ -0,0 +1,243 @@ +#include +#include + +#include +#include +#include + +#include +#include +#include + +#define BOOTLD_OFFS (0x0) +#define BOOTLD_SIZE (64 * 1024) + +#define APP_PRIMARY_OFFS (BOOTLD_OFFS + BOOTLD_SIZE) +#define APP_SIZE (200 * 1024) +#define APP_SECONDARY_OFFS (APP_PRIMARY_OFFS + APP_SIZE) + +static const fa_t bootloader = { + .fa_id = FLASH_AREA_BOOTLOADER, + .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH, + .fa_off = BOOTLD_OFFS, + .fa_size = BOOTLD_SIZE, +}; + +static const fa_t primary_img0 = { + .fa_id = FLASH_AREA_IMAGE_PRIMARY(0), + .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH, + .fa_off = APP_PRIMARY_OFFS, + .fa_size = APP_SIZE, +}; + +static const fa_t secondary_img0 = { + .fa_id = FLASH_AREA_IMAGE_SECONDARY(0), + .fa_device_id = FLASH_DEVICE_INTERNAL_FLASH, + .fa_off = APP_SECONDARY_OFFS, + .fa_size = APP_SIZE, +}; + +static const fa_t *s_flash_areas[] = { + &bootloader, + &primary_img0, + &secondary_img0, +}; + +#define ARRAY_SIZE(arr) sizeof(arr)/sizeof(arr[0]) + +static const fa_t *fa_lookup(uint8_t id) +{ + for (int i = 0; i < ARRAY_SIZE(s_flash_areas); i++) { + if(id == s_flash_areas[i]->fa_id) { + return s_flash_areas[i]; + } + } + return NULL; +} + +int flash_area_open(uint8_t id, const fa_t **area_outp) +{ + MCUBOOT_LOG_DBG("%s: ID=%d", __func__, (int)id); + *area_outp = fa_lookup(id); + return area_outp != NULL ? 0 : -1; +} + +void flash_area_close(const fa_t *area) +{ + +} + +int flash_area_read(const fa_t *fa, uint32_t off, void *dst, + uint32_t len) +{ + // MCUBOOT_LOG_DBG("%s", __func__); + if (fa->fa_device_id != FLASH_DEVICE_INTERNAL_FLASH) { + return -1; + } + + const uint32_t end_offset = off + len; + if (end_offset > fa->fa_size) { + MCUBOOT_LOG_ERR("%s: Out of Bounds (0x%x vs 0x%x)", __func__, end_offset, fa->fa_size); + return -1; + } + + // TODO: find some way to access the flash over memory mapped address while + // code flash is protected + uint32_t addr = (fa->fa_off + off); + FLASH_ROM_READ(addr, dst, len); + // memcpy(dst, addr, len); + + return 0; +} + +int flash_area_write(const fa_t *fa, uint32_t off, const void *src, + uint32_t len) +{ + MCUBOOT_LOG_DBG("%s", __func__); + if (fa->fa_device_id != FLASH_DEVICE_INTERNAL_FLASH) { + return -1; + } + + const uint32_t end_offset = off + len; + if (end_offset > fa->fa_size) { + MCUBOOT_LOG_ERR("%s: Out of Bounds (0x%x vs 0x%x)", __func__, end_offset, fa->fa_size); + return -1; + } + + const uint32_t addr = fa->fa_off + off; + MCUBOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)addr, (int)len); + + FLASH_ROM_WRITE(addr, src, len); + + #if VALIDATE_PROGRAM_OP + if (FLASH_ROM_VERIFY(addr, src, len) != 0) { + MCUBOOT_LOG_ERR("%s: Program Failed", __func__); + assert(0); + } + #endif + + return 0; +} + +int flash_area_erase(const fa_t *fa, uint32_t off, uint32_t len) +{ + if (fa->fa_device_id != FLASH_DEVICE_INTERNAL_FLASH) { + return -1; + } + + if ((len % EEPROM_BLOCK_SIZE) != 0 || (off % EEPROM_BLOCK_SIZE) != 0) { + MCUBOOT_LOG_ERR("%s: Not aligned on sector Offset: 0x%x Length: 0x%x", __func__, + (int)off, (int)len); + return -1; + } + + const uint32_t start_addr = fa->fa_off + off; + MCUBOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len); + + FLASH_ROM_ERASE(start_addr, len); + + #if VALIDATE_PROGRAM_OP + for (size_t i = 0; i < len; i++) { + uint8_t *val = (void *)(start_addr + i); + if (*val != 0xff) { + MCUBOOT_LOG_ERR("%s: Erase at 0x%x Failed", __func__, (int)val); + assert(0); + } + } + #endif + + return 0; +} + +size_t flash_area_align(const fa_t *area) +{ + return FLASH_MIN_WR_SIZE; +} + +uint8_t flash_area_erased_val(const fa_t *area) +{ + return 0xff; +} + +int flash_area_get_sectors(int fa_id, uint32_t *count, + struct flash_sector *sectors) +{ + MCUBOOT_LOG_DBG("%s", __func__); + const fa_t *fa = fa_lookup(fa_id); + if (fa->fa_device_id != FLASH_DEVICE_INTERNAL_FLASH) { + return -1; + } + + const size_t sector_size = EEPROM_BLOCK_SIZE; + uint32_t total_count = 0; + for (size_t off = 0; off < fa->fa_size; off += sector_size) { + // Note: Offset here is relative to flash area, not device + sectors[total_count].fs_off = off; + sectors[total_count].fs_size = sector_size; + total_count++; + } + + *count = total_count; + return 0; +} + +int flash_area_id_from_multi_image_slot(int image_index, int slot) +{ + MCUBOOT_LOG_DBG("%s", __func__); + switch (slot) { + case 0: + return FLASH_AREA_IMAGE_PRIMARY(image_index); + case 1: + return FLASH_AREA_IMAGE_SECONDARY(image_index); + } + + MCUBOOT_LOG_ERR("Unexpected Request: image_index=%d, slot=%d", + image_index, slot); + return -1; +} + +int flash_area_id_from_image_slot(int slot) +{ + return flash_area_id_from_multi_image_slot(0, slot); +} + + +/*< Obtains ID of the flash area characterized by `fa` */ +int flash_area_get_id(const fa_t *fa) +{ + return fa->fa_id; +} + +/*< Obtains ID of a device the flash area `fa` described region resides on */ +int flash_area_get_device_id(const fa_t *fa) +{ + return fa->fa_device_id; +} + +/*< Obtains offset, from the beginning of a device, the flash area described +* region starts at */ +uint32_t flash_area_get_off(const fa_t *fa) +{ + return fa->fa_off; +} + +/*< Obtains size, from the offset, of the flash area `fa` characterized region */ +uint32_t flash_area_get_size(const fa_t *fa) +{ + return fa->fa_size; +} + +int flash_area_to_sectors(int idx, int *cnt, fa_t *ret) +{ + MCUBOOT_LOG_DBG("%s: idx=%d cnt=%d", __func__, idx, *cnt); + + fa_t *fa = fa_lookup(idx); + if (fa->fa_device_id != FLASH_DEVICE_INTERNAL_FLASH) { + return -1; + } + + *cnt = fa->fa_size / EEPROM_BLOCK_SIZE; + memcpy(ret, fa, sizeof(fa_t)); + + return 0; +} \ No newline at end of file From 7ddcca75d75c51b5de1da019ffb76de86233f07f Mon Sep 17 00:00:00 2001 From: Dien-Nhung Nguyen-Phu Date: Mon, 5 May 2025 12:30:52 +0700 Subject: [PATCH 2/2] WIP: can upload over USB CDC ACM but slow tested with AuTerm - slow cannot work with `mcumgr` or `smpmgr` due to small MTU --- .gdbinit | 36 +++ .gitmodules | 4 + Makefile | 54 +++-- app.ld | 51 ++-- app.startup.S | 193 ++++++++++++++++ bootloader.ld | 8 +- .../startup_CH583.S => bootloader.startup.S | 120 +++++----- external/lwrb | 1 + inc/base64/base64.h | 14 ++ inc/common/debug.h | 2 + inc/crc/crc16.h | 12 + src/util/crc.h => inc/crc/crc8.h | 0 inc/hal/hal_system.h | 11 + inc/mcuboot_config/mcuboot_config.h | 6 + inc/os/endian.h | 27 +++ inc/os/os_cputime.h | 11 + openocd.cfg | 5 + src/boot-entry.c | 88 ++++--- src/config.c | 2 +- src/debug.c | 8 + src/leddrv.c | 6 +- src/main.c | 17 ++ src/mcuboot.c | 81 +++++-- src/usb/debug.c | 6 +- src/usb/debug.h | 16 ++ src/usb/setup.c | 2 +- src/util/base64.c | 218 ++++++++++++++++++ src/util/crc.c | 41 +++- 28 files changed, 871 insertions(+), 169 deletions(-) create mode 100644 .gdbinit create mode 100644 app.startup.S rename CH5xx_ble_firmware_library/Startup/startup_CH583.S => bootloader.startup.S (57%) create mode 160000 external/lwrb create mode 100644 inc/base64/base64.h create mode 100644 inc/crc/crc16.h rename src/util/crc.h => inc/crc/crc8.h (100%) create mode 100644 inc/hal/hal_system.h create mode 100644 inc/os/endian.h create mode 100644 inc/os/os_cputime.h create mode 100644 openocd.cfg create mode 100644 src/util/base64.c diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..a08a5f0 --- /dev/null +++ b/.gdbinit @@ -0,0 +1,36 @@ +target ext :3333 +monitor init +monitor reset +monitor halt + +add-symbol-file build/mcuboot.elf +add-symbol-file build/badgemagic-ch582.elf +break src/boot-entry.c:HardFault_Handler +# break src/boot-entry.c:start_app +# break src/boot-entry.c:boot + +break src/mcuboot.c:110 + + +# break *0x10200 + +layout asm +layout split + +# c +# n +# n +# n +# n +# print rv +# set rv=0 +# symbol-file build/badgemagic-ch582.elf +# c +# break app.startup.S:162 +# break app.startup.S:184 +# break src/main.c:main +# break src/main.c:HardFault_Handler + +# c + +# jump src/main.c:main \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 9c6cca8..317c105 100644 --- a/.gitmodules +++ b/.gitmodules @@ -5,3 +5,7 @@ [submodule "external/tinycrypt"] path = external/tinycrypt url = https://github.com/intel/tinycrypt.git +[submodule "external/lwrb"] + path = external/lwrb + url = https://github.com/MaJerle/lwrb.git + branch = v3.2.0 diff --git a/Makefile b/Makefile index 1c24589..e10a37d 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ USBC_VERSION = 1 # optimization for size OPT = -Os -OPENOCD ?= ../MRS_Toolchain_Linux_x64_V1.91/OpenOCD/bin/openocd +OPENOCD ?= ../MRS_Toolchain_Linux_x64_V1.92/OpenOCD/bin/openocd ####################################### @@ -68,6 +68,7 @@ src/ble/profile/ng.c \ src/config.c \ src/legacyctrl.c \ src/util/crc.c \ +src/util/base64.c \ src/ngctrl.c \ src/ble/setup.c \ src/ble/peripheral.c \ @@ -90,6 +91,10 @@ MCUBOOT_DIR := external/mcuboot IMGTOOL_PY := $(MCUBOOT_DIR)/scripts/imgtool.py MCUBOOT_SRC_DIR := $(MCUBOOT_DIR)/boot/bootutil/src MCUBOOT_INC_DIR := $(MCUBOOT_DIR)/boot/bootutil/include +MCUBOOT_SERIAL_SRC_DIR := $(MCUBOOT_DIR)/boot/boot_serial/src +MCUBOOT_SERIAL_INC_DIR := $(MCUBOOT_DIR)/boot/boot_serial/include +MCUBOOT_ZCBOR_SRC_DIR := $(MCUBOOT_DIR)/boot/zcbor/src +MCUBOOT_ZCBOR_INC_DIR := $(MCUBOOT_DIR)/boot/zcbor/include MCUBOOT_SRC_FILES += \ $(MCUBOOT_SRC_DIR)/boot_record.c \ @@ -107,7 +112,13 @@ $(MCUBOOT_SRC_DIR)/loader.c \ $(MCUBOOT_SRC_DIR)/swap_misc.c \ $(MCUBOOT_SRC_DIR)/swap_move.c \ $(MCUBOOT_SRC_DIR)/swap_scratch.c \ -$(MCUBOOT_SRC_DIR)/tlv.c +$(MCUBOOT_SRC_DIR)/tlv.c \ +$(MCUBOOT_SERIAL_SRC_DIR)/boot_serial.c \ +$(MCUBOOT_SERIAL_SRC_DIR)/boot_serial_encryption.c \ +$(MCUBOOT_SERIAL_SRC_DIR)/zcbor_bulk.c \ +$(MCUBOOT_ZCBOR_SRC_DIR)/zcbor_common.c \ +$(MCUBOOT_ZCBOR_SRC_DIR)/zcbor_decode.c \ +$(MCUBOOT_ZCBOR_SRC_DIR)/zcbor_encode.c \ TINYCRYPT_DIR := external/tinycrypt/lib TINYCRYPT_SRC_DIR := $(TINYCRYPT_DIR)/source @@ -125,17 +136,18 @@ $(TINYCRYPT_SRC_DIR)/hmac.c \ $(TINYCRYPT_SRC_DIR)/hmac_prng.c \ $(TINYCRYPT_SRC_DIR)/sha256.c \ $(TINYCRYPT_SRC_DIR)/utils.c -# ecc.c -# ecc_dh.c -# ecc_dsa.c -# ecc_platform_specific.c + +LWRB_DIR := external/lwrb/lwrb +LWRB_SRC_DIR := $(LWRB_DIR)/src +LWRB_INC_DIR := $(LWRB_DIR)/src/include + +LWRB_SRC_FILES += \ +$(LWRB_SRC_DIR)/lwrb/lwrb.c \ +$(LWRB_SRC_DIR)/lwrb/lwrb_ex.c \ C_SOURCES += $(TINYCRYPT_SRC_FILES) C_SOURCES += $(MCUBOOT_SRC_FILES) - -# ASM sources -ASM_SOURCES = \ -CH5xx_ble_firmware_library/Startup/startup_CH583.S +C_SOURCES += $(LWRB_SRC_FILES) ####################################### # binaries @@ -176,7 +188,10 @@ C_INCLUDES += \ -ICH5xx_ble_firmware_library/BLE \ -Iinc \ -Iexternal/tinycrypt/lib/include \ --I$(MCUBOOT_INC_DIR) +-I$(MCUBOOT_INC_DIR) \ +-I$(MCUBOOT_SERIAL_INC_DIR) \ +-I$(MCUBOOT_ZCBOR_INC_DIR) \ +-I$(LWRB_INC_DIR) \ # compile gcc flags ASFLAGS = $(MCU) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections @@ -240,14 +255,14 @@ $(BUILD_DIR)/%.o: %.S Makefile @mkdir -pv $(dir $@) $(AS) -c $(CFLAGS) $< -o $@ -$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) $(BUILD_DIR)/src/main.o Makefile app.ld +$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) $(BUILD_DIR)/src/main.o $(BUILD_DIR)/app.startup.o Makefile app.ld @mkdir -pv $(dir $@) - $(CC) $(OBJECTS) $(BUILD_DIR)/src/main.o -T app.ld $(LDFLAGS) -o $@ + $(CC) $(OBJECTS) $(BUILD_DIR)/src/main.o $(BUILD_DIR)/app.startup.o -T app.ld $(LDFLAGS) -o $@ $(SZ) $@ -$(BUILD_DIR)/mcuboot.elf: $(OBJECTS) $(BUILD_DIR)/src/boot-entry.o Makefile bootloader.ld +$(BUILD_DIR)/mcuboot.elf: $(OBJECTS) $(BUILD_DIR)/src/boot-entry.o $(BUILD_DIR)/bootloader.startup.o Makefile bootloader.ld @mkdir -pv $(dir $@) - $(CC) $(OBJECTS) $(BUILD_DIR)/src/boot-entry.o $(LDFLAGS) -T bootloader.ld -o $@ + $(CC) $(OBJECTS) $(BUILD_DIR)/src/boot-entry.o $(BUILD_DIR)/bootloader.startup.o $(LDFLAGS) -T bootloader.ld -o $@ $(SZ) $@ $(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf @@ -267,11 +282,13 @@ $(BUILD_DIR)/combined.bin: $(BUILD_DIR)/mcuboot.bin $(BUILD_DIR)/$(TARGET).signe ####################################### # Program ####################################### -program: $(BUILD_DIR)/$(TARGET).elf +program: $(BUILD_DIR)/combined.bin $(OPENOCD) -f interface/wch-riscv.cfg -c 'init; halt; program $(BUILD_DIR)/combined.bin ; reset; wlink_reset_resume; exit;' debug: - $(OPENOCD) -f debug.cfg + wlink reset + wlink halt + $(OPENOCD) -f openocd.cfg $(BUILD_DIR)/$(TARGET).signed.bin: $(BUILD_DIR)/$(TARGET).bin python $(IMGTOOL_PY) sign \ @@ -282,6 +299,9 @@ $(BUILD_DIR)/$(TARGET).signed.bin: $(BUILD_DIR)/$(TARGET).bin --pad-header \ $< $@ +wlink-combine: + wlink flash build/combined.bin + isp: $(BUILD_DIR)/$(TARGET).elf wchisp flash $(BUILD_DIR)/$(TARGET).elf diff --git a/app.ld b/app.ld index 5126ab6..d509b81 100644 --- a/app.ld +++ b/app.ld @@ -2,8 +2,8 @@ ENTRY( _start ) MEMORY { - FLASH (rx) : ORIGIN = 0x00010000, LENGTH = 384k - RAM (xrw) : ORIGIN = 0x20003800, LENGTH = 32K + FLASH (rx) : ORIGIN = 0x00010200, LENGTH = (448K - 0x00010200) + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K } SECTIONS @@ -13,37 +13,14 @@ SECTIONS _sinit = .; . = ALIGN(4); KEEP(*(SORT_NONE(.init))) + KEEP(*(SORT_NONE(.handle_reset))) . = ALIGN(4); _einit = .; } >FLASH AT>FLASH - -/* .vector : - { - *(.vector); - } >FLASH AT>FLASH */ - - .highcodelalign : - { - . = ALIGN(4); - PROVIDE(_highcode_lma = .); - } >FLASH AT>FLASH - - .highcode : - { - . = ALIGN(4); - PROVIDE(_highcode_vma_start = .); - *(.vector); - KEEP(*(SORT_NONE(.vector_handler))) - *(.highcode); - *(.highcode.*); - . = ALIGN(4); - PROVIDE(_highcode_vma_end = .); - } >RAM AT>FLASH - + .text : { . = ALIGN(4); - KEEP(*(SORT_NONE(.handle_reset))) *(.text) *(.text.*) *(.rodata) @@ -119,10 +96,28 @@ SECTIONS KEEP (*(.dtors)) } >FLASH AT>FLASH + .highcodelalign : + { + . = ALIGN(4); + PROVIDE(_highcode_lma = .); + } >FLASH AT>FLASH + + .highcode : + { + . = ALIGN(4); + PROVIDE(_highcode_vma_start = .); + *(.vector); + KEEP(*(SORT_NONE(.vector_handler))) + *(.highcode); + *(.highcode.*); + . = ALIGN(4); + PROVIDE(_highcode_vma_end = .); + } >RAM AT>FLASH + .dalign : { . = ORIGIN(RAM) + MAX(0x800 , SIZEOF(.highcode)); - } >RAM AT>FLASH + } >RAM AT>FLASH .dlalign : { diff --git a/app.startup.S b/app.startup.S new file mode 100644 index 0000000..df2b62d --- /dev/null +++ b/app.startup.S @@ -0,0 +1,193 @@ + .section .init,"ax",@progbits + .global _start + .align 1 +_start: + j handle_reset + + .section .vector,"ax",@progbits + .align 1 +_vector_base: + .option norvc// + + .word 0 + .word 0 + .word NMI_Handler + .word HardFault_Handler + .word 0xF5F9BDA9 + .word Ecall_M_Mode_Handler + .word 0 + .word 0 + .word Ecall_U_Mode_Handler + .word Break_Point_Handler + .word 0 + .word 0 + .word SysTick_Handler + .word 0 + .word SW_Handler + .word 0 + // External Interrupts + .word TMR0_IRQHandler // 0: TMR0 + .word GPIOA_IRQHandler // GPIOA + .word GPIOB_IRQHandler // GPIOB + .word SPI0_IRQHandler // SPI0 + .word BB_IRQHandler // BLEB + .word LLE_IRQHandler // BLEL + .word USB_IRQHandler // USB + .word USB2_IRQHandler // USB2 + .word TMR1_IRQHandler // TMR1 + .word TMR2_IRQHandler // TMR2 + .word UART0_IRQHandler // UART0 + .word UART1_IRQHandler // UART1 + .word RTC_IRQHandler // RTC + .word ADC_IRQHandler // ADC + .word I2C_IRQHandler // I2C + .word PWMX_IRQHandler // PWMX + .word TMR3_IRQHandler // TMR3 + .word UART2_IRQHandler // UART2 + .word UART3_IRQHandler // UART3 + .word WDOG_BAT_IRQHandler // WDOG_BAT + + .option rvc// + + .section .vector_handler, "ax", @progbits + .weak NMI_Handler + .weak HardFault_Handler + .weak Ecall_M_Mode_Handler + .weak Ecall_U_Mode_Handler + .weak Break_Point_Handler + .weak SysTick_Handler + .weak SW_Handler + .weak TMR0_IRQHandler + .weak GPIOA_IRQHandler + .weak GPIOB_IRQHandler + .weak SPI0_IRQHandler + .weak BB_IRQHandler + .weak LLE_IRQHandler + .weak USB_IRQHandler + .weak USB2_IRQHandler + .weak TMR1_IRQHandler + .weak TMR2_IRQHandler + .weak UART0_IRQHandler + .weak UART1_IRQHandler + .weak RTC_IRQHandler + .weak ADC_IRQHandler + .weak I2C_IRQHandler + .weak PWMX_IRQHandler + .weak TMR3_IRQHandler + .weak UART2_IRQHandler + .weak UART3_IRQHandler + .weak WDOG_BAT_IRQHandler + +NMI_Handler: 1: j 1b +HardFault_Handler: 1: j 1b +Ecall_M_Mode_Handler: 1: j 1b +Ecall_U_Mode_Handler: 1: j 1b +Break_Point_Handler: 1: j 1b +SysTick_Handler: 1: j 1b +SW_Handler: 1: j 1b +TMR0_IRQHandler: 1: j 1b +GPIOA_IRQHandler: 1: j 1b +GPIOB_IRQHandler: 1: j 1b +SPI0_IRQHandler: 1: j 1b +BB_IRQHandler: 1: j 1b +LLE_IRQHandler: 1: j 1b +USB_IRQHandler: 1: j 1b +USB2_IRQHandler: 1: j 1b +TMR1_IRQHandler: 1: j 1b +TMR2_IRQHandler: 1: j 1b +UART0_IRQHandler: 1: j 1b +UART1_IRQHandler: 1: j 1b +RTC_IRQHandler: 1: j 1b +ADC_IRQHandler: 1: j 1b +I2C_IRQHandler: 1: j 1b +PWMX_IRQHandler: 1: j 1b +TMR3_IRQHandler: 1: j 1b +UART2_IRQHandler: 1: j 1b +UART3_IRQHandler: 1: j 1b +WDOG_BAT_IRQHandler: 1: j 1b + + .section .handle_reset,"ax",@progbits + .weak handle_reset + .align 1 +handle_reset: +.option push +.option norelax + la gp, __global_pointer$ +.option pop +1: + la sp, _eusrstack + +// Load highcode code section from flash to RAM +2: + la a0, _highcode_lma + la a1, _highcode_vma_start + la a2, _highcode_vma_end + bgeu a1, a2, 2f +1: + lw t0, (a0) + sw t0, (a1) + addi a0, a0, 4 + addi a1, a1, 4 + bltu a1, a2, 1b + + // Load data section from flash to RAM +2: + la a0, _data_lma + la a1, _data_vma + la a2, _edata + bgeu a1, a2, 2f +1: + lw t0, (a0) + sw t0, (a1) + addi a0, a0, 4 + addi a1, a1, 4 + bltu a1, a2, 1b +2: + // clear bss section + la a0, _sbss + la a1, _ebss + bgeu a0, a1, 2f +1: + sw zero, (a0) + addi a0, a0, 4 + bltu a0, a1, 1b +2: + + // Microprocessor Configuration Registers (corecfgr) + // This register is mainly used to configure the microprocessor pipeline, + // instruction prediction and other related features, and generally does not + // need to be operated. The relevant MCU products are configured with default + // values in the startup file + li t0, 0x1f + csrw 0xbc0, t0 + + // Interrupt System Control Register (INTSYSCR) + // INESTEN = 1: Interrupt nesting function enabled + // HWSTKEN = 1: HPE function enabled + li t0, 0x3 + csrw 0x804, t0 + + // Machine Mode Status Register (mstatus) + // MPIE = 1: Interrupt enable state before entering interrupt + // MIE = 1: Machine mode interrupt enable + li t0, 0x1888 + csrs mstatus, t0 + + // Configure The interrupt vector table base address to `_vector_base` + // MODE1 = 1: Identify by absolute address, support full range, but must jump to + // absolute address mode + // MODE0 = 1: Address offset based on interrupt number *4. + la t0, _vector_base + ori t0, t0, 3 + csrw mtvec, t0 + + // Machine Mode Exception Program Pointer Register (mepc) + // When an exception occurs, *mepc* stores the address of PC then the chip + // enters the exception routine and switch to M-mode. Once the routine return + // (mret), the value of *mepc* will write back to PC and switch to U-mode + // Since the chip have been in M-mode on boot, here we are trying to mimic + // an exception routine, in order to SWITCH TO U-MODE + la t0, main + csrw mepc, t0 + mret + // j main diff --git a/bootloader.ld b/bootloader.ld index ef6c1e9..85d1b0f 100644 --- a/bootloader.ld +++ b/bootloader.ld @@ -3,8 +3,7 @@ ENTRY( _start ) MEMORY { FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 64K - /* APP (rx) : ORIGIN = 0x00010000, LENGTH = 200K */ - RAM (xrw) : ORIGIN = 0x20003800, LENGTH = 32K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 32K } SECTIONS @@ -18,11 +17,6 @@ SECTIONS _einit = .; } >FLASH AT>FLASH -/* .vector : - { - *(.vector); - } >FLASH AT>FLASH */ - .highcodelalign : { . = ALIGN(4); diff --git a/CH5xx_ble_firmware_library/Startup/startup_CH583.S b/bootloader.startup.S similarity index 57% rename from CH5xx_ble_firmware_library/Startup/startup_CH583.S rename to bootloader.startup.S index b408515..130c982 100644 --- a/CH5xx_ble_firmware_library/Startup/startup_CH583.S +++ b/bootloader.startup.S @@ -1,15 +1,3 @@ -/********************************** (C) COPYRIGHT ******************************* - * File Name : startup_ch58x.s - * Author : WCH - * Version : V1.0.0 - * Date : 2021/02/25 - * Description : - ********************************************************************************* - * Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. - * Attention: This software (modified or not) and binary are used for - * microcontroller manufactured by Nanjing Qinheng Microelectronics. - *******************************************************************************/ - .section .init,"ax",@progbits .global _start .align 1 @@ -23,20 +11,21 @@ _vector_base: .word 0 .word 0 - .word NMI_Handler /* NMI Handler */ - .word HardFault_Handler /* Hard Fault Handler */ + .word NMI_Handler + .word HardFault_Handler .word 0xF5F9BDA9 - .word Ecall_M_Mode_Handler /* 5 */ + .word Ecall_M_Mode_Handler .word 0 .word 0 - .word Ecall_U_Mode_Handler /* 8 */ - .word Break_Point_Handler /* 9 */ + .word Ecall_U_Mode_Handler + .word Break_Point_Handler .word 0 .word 0 - .word SysTick_Handler /* SysTick Handler */ + .word SysTick_Handler .word 0 - .word SW_Handler /* SW Handler */ + .word SW_Handler .word 0 + /* External Interrupts */ .word TMR0_IRQHandler /* 0: TMR0 */ .word GPIOA_IRQHandler /* GPIOA */ @@ -90,33 +79,33 @@ _vector_base: .weak UART3_IRQHandler .weak WDOG_BAT_IRQHandler -NMI_Handler: 1: j 1b -HardFault_Handler: 1: j 1b -Ecall_M_Mode_Handler: 1: j 1b -Ecall_U_Mode_Handler: 1: j 1b -Break_Point_Handler: 1: j 1b -SysTick_Handler: 1: j 1b -SW_Handler: 1: j 1b -TMR0_IRQHandler: 1: j 1b -GPIOA_IRQHandler: 1: j 1b -GPIOB_IRQHandler: 1: j 1b -SPI0_IRQHandler: 1: j 1b -BB_IRQHandler: 1: j 1b -LLE_IRQHandler: 1: j 1b -USB_IRQHandler: 1: j 1b -USB2_IRQHandler: 1: j 1b -TMR1_IRQHandler: 1: j 1b -TMR2_IRQHandler: 1: j 1b -UART0_IRQHandler: 1: j 1b -UART1_IRQHandler: 1: j 1b -RTC_IRQHandler: 1: j 1b -ADC_IRQHandler: 1: j 1b -I2C_IRQHandler: 1: j 1b -PWMX_IRQHandler: 1: j 1b -TMR3_IRQHandler: 1: j 1b -UART2_IRQHandler: 1: j 1b -UART3_IRQHandler: 1: j 1b -WDOG_BAT_IRQHandler: 1: j 1b +NMI_Handler: 1: j 1b +HardFault_Handler: 1: j 1b +Ecall_M_Mode_Handler: 1: j 1b +Ecall_U_Mode_Handler: 1: j 1b +Break_Point_Handler: 1: j 1b +SysTick_Handler: 1: j 1b +SW_Handler: 1: j 1b +TMR0_IRQHandler: 1: j 1b +GPIOA_IRQHandler: 1: j 1b +GPIOB_IRQHandler: 1: j 1b +SPI0_IRQHandler: 1: j 1b +BB_IRQHandler: 1: j 1b +LLE_IRQHandler: 1: j 1b +USB_IRQHandler: 1: j 1b +USB2_IRQHandler: 1: j 1b +TMR1_IRQHandler: 1: j 1b +TMR2_IRQHandler: 1: j 1b +UART0_IRQHandler: 1: j 1b +UART1_IRQHandler: 1: j 1b +RTC_IRQHandler: 1: j 1b +ADC_IRQHandler: 1: j 1b +I2C_IRQHandler: 1: j 1b +PWMX_IRQHandler: 1: j 1b +TMR3_IRQHandler: 1: j 1b +UART2_IRQHandler: 1: j 1b +UART3_IRQHandler: 1: j 1b +WDOG_BAT_IRQHandler: 1: j 1b .section .handle_reset,"ax",@progbits .weak handle_reset @@ -164,25 +153,36 @@ handle_reset: addi a0, a0, 4 bltu a0, a1, 1b 2: - /* 流水线控制位 & 动态预测控制位 */ + + /* Microprocessor Configuration Registers (corecfgr) */ + /* + This register is mainly used to configure the microprocessor pipeline, + instruction prediction and other related features, and generally does not + need to be operated. The relevant MCU products are configured with default + values in the startup file */ li t0, 0x1f csrw 0xbc0, t0 - /* 打开嵌套中断、硬件压栈功能 */ + + /* Interrupt System Control Register (INTSYSCR) */ + /* INESTEN = 1: Interrupt nesting function enabled */ + /* HWSTKEN = 1: HPE function enabled */ li t0, 0x3 csrw 0x804, t0 - - li t0, 0x88 - csrs mstatus, t0 - la t0, _vector_base - /* 配置向量表模式为绝对地址模式 */ - ori t0, t0, 3 - csrw mtvec, t0 + /* Machine Mode Status Register (mstatus) */ + /* MPIE = 1: Interrupt enable state before entering interrupt */ + /* MIE = 1: Machine mode interrupt enable */ + li t0, 0x88 + csrs mstatus, t0 - la t0, main - csrw mepc, t0 - - - mret + csrs pmpaddr0, x0 + /* Configure The interrupt vector table base address to `_vector_base` */ + /* MODE1 = 1: Identify by absolute address, support full range, but must jump to + absolute address mode */ + /* MODE0 = 1: Address offset based on interrupt number *4. */ + la t0, _vector_base + ori t0, t0, 3 + csrw mtvec, t0 + j boot diff --git a/external/lwrb b/external/lwrb new file mode 160000 index 0000000..77b2bdb --- /dev/null +++ b/external/lwrb @@ -0,0 +1 @@ +Subproject commit 77b2bdbecf60cd80e449f5c61bde72ec195efac4 diff --git a/inc/base64/base64.h b/inc/base64/base64.h new file mode 100644 index 0000000..bf6ebe2 --- /dev/null +++ b/inc/base64/base64.h @@ -0,0 +1,14 @@ +#ifndef __BASE64_H__ +#define __BASE64_H__ + +#include + +size_t base64_decode_len(const char *in); + +int base64_encode(uint8_t *dst, size_t dlen, size_t *olen, const uint8_t *src, + size_t slen); + +int base64_decode(uint8_t *dst, size_t dlen, size_t *olen, const uint8_t *src, + size_t slen); + +#endif /* __BASE64_H__ */ diff --git a/inc/common/debug.h b/inc/common/debug.h index 9ee5413..d5756b6 100644 --- a/inc/common/debug.h +++ b/inc/common/debug.h @@ -12,4 +12,6 @@ #define _TRACE() PRINT("> "); PRINT(__FILE__); PRINT(": "); PRINT(__func__); \ PRINT("()\n") +void dump_mem(void *ptr, int len); + #endif /* __COMMON_DEBUG_H__ */ diff --git a/inc/crc/crc16.h b/inc/crc/crc16.h new file mode 100644 index 0000000..5a7c56b --- /dev/null +++ b/inc/crc/crc16.h @@ -0,0 +1,12 @@ +#ifndef __CRC16_H__ +#define __CRC16_H__ + +uint16_t crc16_ccitt_update (uint16_t crc, uint8_t data); +uint16_t crc16_cal(uint16_t crc, uint8_t *data, int len); + +static inline uint16_t crc16_ccitt(uint16_t crc, uint8_t *data, int len) +{ + return crc16_cal(crc, data, len); +} + +#endif /* __CRC16_H__ */ diff --git a/src/util/crc.h b/inc/crc/crc8.h similarity index 100% rename from src/util/crc.h rename to inc/crc/crc8.h diff --git a/inc/hal/hal_system.h b/inc/hal/hal_system.h new file mode 100644 index 0000000..7f5c5c1 --- /dev/null +++ b/inc/hal/hal_system.h @@ -0,0 +1,11 @@ +#ifndef __HAL_SYSTEM_H__ +#define __HAL_SYSTEM_H__ + +#include + +static inline void hal_system_reset() +{ + SYS_ResetExecute(); +} + +#endif /* __HAL_SYSTEM_H__ */ diff --git a/inc/mcuboot_config/mcuboot_config.h b/inc/mcuboot_config/mcuboot_config.h index dbea8c2..f3772c2 100644 --- a/inc/mcuboot_config/mcuboot_config.h +++ b/inc/mcuboot_config/mcuboot_config.h @@ -172,4 +172,10 @@ do { \ } while (0) +#define MCUBOOT_PERUSER_MGMT_GROUP_ENABLED (0) +#define CRC16_INITIAL_CRC (0) +#define BASE64_ENCODE_SIZE(in_size) ((((((in_size) - 1) / 3) * 4) + 4) + 1) +#define MCUBOOT_BOOT_MGMT_ECHO 1 +// #define MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD 1 + #endif /* __MCUBOOT_CONFIG_H__ */ diff --git a/inc/os/endian.h b/inc/os/endian.h new file mode 100644 index 0000000..13c30c4 --- /dev/null +++ b/inc/os/endian.h @@ -0,0 +1,27 @@ +#ifndef __OS_ENDIAN_H__ +#define __OS_ENDIAN_H__ + +#include + +static inline uint32_t htonl(uint32_t x) +{ + return __htonl(x); +} + +static inline uint16_t htons(uint16_t x) +{ + return __htons(x); +} + +static inline uint32_t ntohl(uint32_t x) +{ + return __ntohl(x); +} + +static inline uint16_t ntohs(uint16_t x) +{ + return __ntohs(x); +} + + +#endif /* __OS_ENDIAN_H__ */ diff --git a/inc/os/os_cputime.h b/inc/os/os_cputime.h new file mode 100644 index 0000000..4bb8971 --- /dev/null +++ b/inc/os/os_cputime.h @@ -0,0 +1,11 @@ +#ifndef __OS_CPUTIME_H__ +#define __OS_CPUTIME_H__ + +#include + +static inline void os_cputime_delay_usecs(int t) +{ + mDelayuS(t); +} + +#endif /* __OS_CPUTIME_H__ */ diff --git a/openocd.cfg b/openocd.cfg new file mode 100644 index 0000000..ddd8b96 --- /dev/null +++ b/openocd.cfg @@ -0,0 +1,5 @@ +source [find interface/wch-riscv.cfg] + +init +halt +reset \ No newline at end of file diff --git a/src/boot-entry.c b/src/boot-entry.c index 11d4f3b..2b4d4d7 100644 --- a/src/boot-entry.c +++ b/src/boot-entry.c @@ -1,22 +1,11 @@ #include "CH58x_common.h" #include #include +#include +#include +#include -// /* Import a binary file */ -// #define IMPORT_BIN(sect, file, sym) asm (\ -// ".section "#sect "\n" \ -// ".balign 4\n" /* Word alignment */\ -// ".global " #sym "\n" /* Export the object address */\ -// #sym ":\n" /* Define the object label */\ -// ".incbin \"" file "\"\n" /* Import the file */\ -// ".global _sizeof_" #sym "\n" /* Export the object size */\ -// ".set _sizeof_" #sym ", . - " #sym "\n" /* Define the object size */\ -// ".balign 4\n" /* Word alignment */\ -// ) -// // __attribute__((section(".highcode"))) -// IMPORT_BIN(.app, "build/badgemagic-ch582.signed.bin", main_bin); -// /* Declaration of symbols (any type can be used) */ -// extern const unsigned char main_bin[], _sizeof_main_bin[]; +#include "usb/usb.h" static void debug_init() { @@ -27,49 +16,72 @@ static void debug_init() UART1_BaudRateCfg(921600); } -void start_app(uint32_t pc, uint32_t sp) { - // __asm volatile ("la sp, %0" : : "r" (sp) : ); - - PRINT("Attempting jump pc=%x, sp=%x\n", pc, sp); - void (*application_reset_handler)(void) = (void *)pc; - (( void (*) ( void )) ((int*)pc))(); +__INTERRUPT +__HIGH_CODE +void HardFault_Handler(void) +{ + PRINT("HardFault happen\n"); + while(1); } void do_boot(struct boot_rsp *rsp) { - PRINT("Starting Main Application"); - PRINT(" Image Start Offset: 0x%x", (int)rsp->br_image_off); + PRINT(" Image Start Offset: 0x%x", (int)rsp->br_image_off); - // We run from internal flash. Base address of this medium is 0x0 - uint32_t vector_table = 0x0 + rsp->br_image_off + rsp->br_hdr->ih_hdr_size; + int fw_address = 0x0 + rsp->br_image_off + rsp->br_hdr->ih_hdr_size; - uint32_t *app_code = (uint32_t *)vector_table; - uint32_t app_sp = app_code[0]; - uint32_t app_start = app_code[1]; + PRINT("Attempting jump pc=%x\n", fw_address); + ((void (*) ( void )) ((int*)fw_address))(); +} - PRINT(" Vector Table Start Address: 0x%x. PC=0x%x, SP=0x%x", - (int)vector_table, app_start, app_sp); +lwrb_t fifo; +uint8_t fifo_buf[1024]; - // // We need to move the vector table to reflect the location of the main application - // volatile uint32_t *vtor = (uint32_t *)0xE000ED08; - // *vtor = (vector_table & 0xFFFFFFF8); +void rx_to_fifo(uint8_t *buf, uint16_t len) +{ + PFIC_DisableAllIRQ(); + lwrb_write(&fifo, buf, len); + PFIC_EnableAllIRQ(); +} - start_app(vector_table, app_sp); +int read(char *str, int cnt, int *newline) +{ + int rb = lwrb_read(&fifo, str, cnt); + if (rb > 0 && str[rb-1] == '\n') { + *newline = 1; + PRINT("> read: %d %s\n", rb, str); + } else { + *newline = 0; + } + return rb; } -int main() { - SetSysClock(CLK_SOURCE_PLL_60MHz); +void write(const char *ptr, int cnt) +{ + PRINT("> write: %s %d\n", ptr, cnt); + cdc_tx_poll(ptr, cnt, 1000); +} + +struct boot_uart_funcs boot_uart = { + read, write, +}; +int boot() { + SetSysClock(CLK_SOURCE_PLL_60MHz); debug_init(); PRINT("\nDebug console is on UART%d\n", DEBUG); + lwrb_init(&fifo, fifo_buf, sizeof(fifo_buf)); + cdc_onWrite(rx_to_fifo); + usb_start(); + boot_serial_start(&boot_uart); + struct boot_rsp rsp; int rv = boot_go(&rsp); if (rv == 0) { - // 'rsp' contains the start address of the image do_boot(&rsp); } PRINT("\rv failed\n"); - while(1); + abort(); } \ No newline at end of file diff --git a/src/config.c b/src/config.c index ac91b85..148e982 100644 --- a/src/config.c +++ b/src/config.c @@ -6,7 +6,7 @@ #include "resource.h" #include "res/foss-asia-2.xbm" #include "debug.h" -#include "util/crc.h" +#include #include "ISP583.h" #include diff --git a/src/debug.c b/src/debug.c index e0137af..6650a4a 100644 --- a/src/debug.c +++ b/src/debug.c @@ -32,4 +32,12 @@ int _write(int fd, char *buf, int size) return size; } +void dump_mem(void *ptr, int len) +{ + for (int i = 0; i < len; i++) { + PRINT(" %02x", ((uint8_t*)ptr)[i]); + } + PRINT("\n"); +} + #endif \ No newline at end of file diff --git a/src/leddrv.c b/src/leddrv.c index 37c3e4b..ba04976 100644 --- a/src/leddrv.c +++ b/src/leddrv.c @@ -101,8 +101,10 @@ static const pindesc_t led_pins[LED_PINCOUNT] = { PINDESC(A, 11), // G PINDESC(B, 9), // H PINDESC(B, 8), // I - PINDESC(B, 15), // J - PINDESC(B, 14), // K + + PINDESC(B, 17), // J + PINDESC(B, 16), // K + PINDESC(B, 13), // L PINDESC(B, 12), // M PINDESC(B, 5), // N diff --git a/src/main.c b/src/main.c index 61985a2..95f0149 100644 --- a/src/main.c +++ b/src/main.c @@ -409,12 +409,29 @@ void handle_after_rx() } } +__INTERRUPT +__HIGH_CODE +void HardFault_Handler(void) +{ + PRINT("HardFault happen\n"); + while(1); +} + +__INTERRUPT +__HIGH_CODE +void Break_Point_Handler(void) +{ + PRINT("Break point handler happen\n"); + // while(1); +} + int main() { SetSysClock(CLK_SOURCE_PLL_60MHz); debug_init(); PRINT("\nDebug console is on UART%d\n", DEBUG); + // abort(); cdc_onWrite(legacy_usb_rx); hiddev_onWrite(legacy_usb_rx); diff --git a/src/mcuboot.c b/src/mcuboot.c index 6cb8655..fa511fc 100644 --- a/src/mcuboot.c +++ b/src/mcuboot.c @@ -59,6 +59,11 @@ int flash_area_open(uint8_t id, const fa_t **area_outp) { MCUBOOT_LOG_DBG("%s: ID=%d", __func__, (int)id); *area_outp = fa_lookup(id); + // sys_safe_access_enable(); + // // enable flash Rom write/erase + // R8_GLOB_ROM_CFG |= RB_ROM_CTRL_EN | RB_ROM_DATA_WE | RB_ROM_CODE_WE; + // sys_safe_access_disable(); + // FLASH_ROM_START_IO(); return area_outp != NULL ? 0 : -1; } @@ -90,6 +95,38 @@ int flash_area_read(const fa_t *fa, uint32_t off, void *dst, return 0; } +static int write_flash_align(uint32_t addr, const void *src, uint32_t len) +{ + int ret, i; + uint32_t split_sz = EEPROM_PAGE_SIZE; + __attribute__ ((aligned (4))) uint8_t src_aligned [split_sz]; + + if ((uint32_t)src % 4 == 0) { // src is aligned to 4 + return - FLASH_ROM_WRITE(addr, src, len); + } + + if (len <= split_sz) { + memcpy(src_aligned, src, len); + return - FLASH_ROM_WRITE(addr, src_aligned, len); + } + + // if len > split_sz + for (i = 0; i < len - split_sz; i += split_sz) { + MCUBOOT_LOG_DBG("addr %08x, src_aligned %08x, len %08x", addr + i, (int)src_aligned, split_sz); + memcpy(src_aligned, src + i, split_sz); + ret = FLASH_ROM_WRITE(addr + i, src_aligned, split_sz); + if (ret) { + return -1; + } + } + split_sz = i - len; // remain size + i = len - split_sz; + MCUBOOT_LOG_DBG("addr %08x, src_aligned %08x, len %08x", addr + i, (int)src_aligned, split_sz); + memcpy(src_aligned, src + i, split_sz); + return - FLASH_ROM_WRITE(addr + i, src_aligned, split_sz); +} + +__HIGH_CODE int flash_area_write(const fa_t *fa, uint32_t off, const void *src, uint32_t len) { @@ -103,11 +140,22 @@ int flash_area_write(const fa_t *fa, uint32_t off, const void *src, MCUBOOT_LOG_ERR("%s: Out of Bounds (0x%x vs 0x%x)", __func__, end_offset, fa->fa_size); return -1; } + + uint32_t addr = fa->fa_off + off; + MCUBOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, addr, len); + if (len == 0) { + MCUBOOT_LOG_WRN("Zero length"); + return 0; + } - const uint32_t addr = fa->fa_off + off; - MCUBOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)addr, (int)len); - - FLASH_ROM_WRITE(addr, src, len); + _TRACE(); + uint32_t pirqv; + MCUBOOT_LOG_DBG("addr %08x, src %08x, len %08x", addr, (int)src, len); + // FLASH_ROM_WRITE(addr, src, len); + int ret = write_flash_align(addr, src, len); + dump_mem(addr, len); + // mDelaymS(1); + _TRACE(); #if VALIDATE_PROGRAM_OP if (FLASH_ROM_VERIFY(addr, src, len) != 0) { @@ -116,7 +164,7 @@ int flash_area_write(const fa_t *fa, uint32_t off, const void *src, } #endif - return 0; + return ret; } int flash_area_erase(const fa_t *fa, uint32_t off, uint32_t len) @@ -134,24 +182,31 @@ int flash_area_erase(const fa_t *fa, uint32_t off, uint32_t len) const uint32_t start_addr = fa->fa_off + off; MCUBOOT_LOG_DBG("%s: Addr: 0x%08x Length: %d", __func__, (int)start_addr, (int)len); - FLASH_ROM_ERASE(start_addr, len); + uint32_t *val = (void *)start_addr; + // dump_mem(val, 100); + if (FLASH_ROM_ERASE(start_addr, len)) { + MCUBOOT_LOG_ERR("Flash erase failed"); + return -1; + } - #if VALIDATE_PROGRAM_OP - for (size_t i = 0; i < len; i++) { - uint8_t *val = (void *)(start_addr + i); - if (*val != 0xff) { + // dump_mem(val, 100); + // #if VALIDATE_PROGRAM_OP + for (size_t i = 0; i < (len / 4) - 1; i++) { + val++; + // dump_mem(val, 4); + if (*val != 0xf3f9bda9) { MCUBOOT_LOG_ERR("%s: Erase at 0x%x Failed", __func__, (int)val); - assert(0); + while(1); } } - #endif + // #endif return 0; } size_t flash_area_align(const fa_t *area) { - return FLASH_MIN_WR_SIZE; + return 4; } uint8_t flash_area_erased_val(const fa_t *area) diff --git a/src/usb/debug.c b/src/usb/debug.c index 95d756e..5ef2ccc 100644 --- a/src/usb/debug.c +++ b/src/usb/debug.c @@ -1,5 +1,7 @@ #include "debug.h" +#ifdef USB_DEBUG_ENABLED + void print_setuppk(USB_SETUP_REQ *request) { PRINT("Setup request:\n"); @@ -79,4 +81,6 @@ void print_intflag_reg() overflow ? "FIFO overflow" : "0", suspend ? "Suspend" : "0", xfer_complete ? "Xfer completed" : "0"); -} \ No newline at end of file +} + +#endif /* USB_DEBUG_ENABLED */ \ No newline at end of file diff --git a/src/usb/debug.h b/src/usb/debug.h index 0aa0ebb..ef835e4 100644 --- a/src/usb/debug.h +++ b/src/usb/debug.h @@ -4,8 +4,24 @@ #include "CH58x_common.h" #include "../debug.h" +#ifdef USB_DEBUG_ENABLED + void print_setuppk(USB_SETUP_REQ *setup_req_pk); void print_status_reg(); void print_intflag_reg(); +#else /* USB_DEBUG_ENABLED */ + +#undef PRINT() +#define PRINT(X...) do {} while(0) +#undef _TRACE() +#define _TRACE() do {} while(0) + +#define print_setuppk(x) do {} while(0) +#define print_status_reg() do {} while(0) +#define print_intflag_reg() do {} while(0) + + +#endif /* USB_DEBUG_ENABLED */ + #endif /* __USB_DEBUG_H__ */ diff --git a/src/usb/setup.c b/src/usb/setup.c index d53c318..7e8270f 100644 --- a/src/usb/setup.c +++ b/src/usb/setup.c @@ -123,7 +123,7 @@ void usb_start() { /* This should be placed first, the python script always looks for the first interface (not the interface number) */ - hiddev_init(); + // hiddev_init(); cdc_acm_init(); diff --git a/src/util/base64.c b/src/util/base64.c new file mode 100644 index 0000000..1c35fed --- /dev/null +++ b/src/util/base64.c @@ -0,0 +1,218 @@ +#include +#include +#include +#include + +#include + +size_t base64_decode_len(const char *in) { + if (in == NULL) { + return 0; + } + + size_t len = strlen(in); + + if (len == 0 || len % 4 != 0) { + return 0; + } + + size_t decoded_len = (len / 4) * 3; + + if (in[len - 1] == '=') { + decoded_len--; + if (len >= 2 && in[len - 2] == '=') { + decoded_len--; + } + } + + return decoded_len; +} + +static const uint8_t base64_enc_map[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', + 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/' +}; + +static const uint8_t base64_dec_map[128] = { + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 62, 127, 127, 127, 63, 52, 53, + 54, 55, 56, 57, 58, 59, 60, 61, 127, 127, + 127, 64, 127, 127, 127, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 127, 127, 127, 127, 127, 127, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, 51, 127, 127, 127, 127, 127 +}; + +#define BASE64_SIZE_T_MAX ((size_t) -1) /* SIZE_T_MAX is not standard */ + +/* + * Encode a buffer into base64 format + */ +int base64_encode(uint8_t *dst, size_t dlen, size_t *olen, const uint8_t *src, + size_t slen) +{ + size_t i, n; + int C1, C2, C3; + uint8_t *p; + + if (slen == 0) { + *olen = 0; + return 0; + } + + n = slen / 3 + (slen % 3 != 0); + + if (n > (BASE64_SIZE_T_MAX - 1) / 4) { + *olen = BASE64_SIZE_T_MAX; + return -ENOMEM; + } + + n *= 4; + + if ((dlen < n + 1) || (!dst)) { + *olen = n + 1; + return -ENOMEM; + } + + n = (slen / 3) * 3; + + for (i = 0, p = dst; i < n; i += 3) { + C1 = *src++; + C2 = *src++; + C3 = *src++; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F]; + *p++ = base64_enc_map[C3 & 0x3F]; + } + + if (i < slen) { + C1 = *src++; + C2 = ((i + 1) < slen) ? *src++ : 0; + + *p++ = base64_enc_map[(C1 >> 2) & 0x3F]; + *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F]; + + if ((i + 1) < slen) { + *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F]; + } else { + *p++ = '='; + } + + *p++ = '='; + } + + *olen = p - dst; + *p = 0U; + + return 0; +} + +/* + * Decode a base64-formatted buffer + */ +int base64_decode(uint8_t *dst, size_t dlen, size_t *olen, const uint8_t *src, + size_t slen) +{ + size_t i, n; + uint32_t j, x; + uint8_t *p; + + /* First pass: check for validity and get output length */ + for (i = n = j = 0U; i < slen; i++) { + /* Skip spaces before checking for EOL */ + x = 0U; + while (i < slen && src[i] == ' ') { + ++i; + ++x; + } + + /* Spaces at end of buffer are OK */ + if (i == slen) { + break; + } + + if ((slen - i) >= 2 && src[i] == '\r' && src[i + 1] == '\n') { + continue; + } + + if (src[i] == '\n') { + continue; + } + + /* Space inside a line is an error */ + if (x != 0U) { + return -EINVAL; + } + + if (src[i] == '=' && ++j > 2) { + return -EINVAL; + } + + if (src[i] > 127 || base64_dec_map[src[i]] == 127U) { + return -EINVAL; + } + + if (base64_dec_map[src[i]] < 64 && j != 0U) { + return -EINVAL; + } + + n++; + } + + if (n == 0) { + *olen = 0; + return 0; + } + + /* The following expression is to calculate the following formula + * without risk of integer overflow in n: + * n = ( ( n * 6 ) + 7 ) >> 3; + */ + n = (6 * (n >> 3)) + ((6 * (n & 0x7) + 7) >> 3); + n -= j; + + if (dst == NULL || dlen < n) { + *olen = n; + return -ENOMEM; + } + + for (j = 3U, n = x = 0U, p = dst; i > 0; i--, src++) { + + if (*src == '\r' || *src == '\n' || *src == ' ') { + continue; + } + + j -= (base64_dec_map[*src] == 64U); + x = (x << 6) | (base64_dec_map[*src] & 0x3F); + + if (++n == 4) { + n = 0; + if (j > 0) { + *p++ = (unsigned char)(x >> 16); + } + if (j > 1) { + *p++ = (unsigned char)(x >> 8); + } + if (j > 2) { + *p++ = (unsigned char)(x); + } + } + } + + *olen = p - dst; + + return 0; +} diff --git a/src/util/crc.c b/src/util/crc.c index 7efce15..54ba937 100644 --- a/src/util/crc.c +++ b/src/util/crc.c @@ -1,4 +1,5 @@ -#include "crc.h" +#include +#include // Polynomial: x^8 + x^2 + x + 1 (0xE0) uint8_t crc8_ccitt_update (uint8_t inCrc, uint8_t inData) @@ -22,4 +23,42 @@ uint8_t crc_cal(uint8_t *a, int len) crc = crc8_ccitt_update(crc, a[i]); } return crc; +} + +#define POLY (0x1021) +#define HI8(a) (((a) >> 8) & 0xFF) +#define LO8(a) ((a) & 0xFF) + +uint16_t crc16_ccitt_update(uint16_t crc, uint8_t data) +{ + data ^= LO8(crc); + data ^= data << 4; + return ((((uint16_t)data << 8) | HI8(crc)) ^ (uint8_t)(data >> 4) + ^ ((uint16_t)data << 3)); +} + +// uint16_t crc16_cal(uint16_t crc, uint8_t *data, int len) +// { +// for (int i=0; i> 8) ^ *data) << 8; + for (i = 0; i < 8; i++) { + if (c & 0x8000) + c = (c << 1) ^ POLY; + else + c = c << 1; + } + crc = c ^ (crc << 8); + } + return crc; } \ No newline at end of file