From 2b2c3b03ce14bbd3b40c4d2d8242a56dbac6f10b Mon Sep 17 00:00:00 2001 From: H Yi Date: Fri, 21 Jul 2023 14:00:01 -0500 Subject: [PATCH 01/11] add BOOT_LOAD_PIN support. add jeff probe board. And support for flash bootloader from SRAM which does not touch application code --- Makefile | 24 ++++- boards/jeff_probe/board.mk | 4 + boards/jeff_probe/board_config.h | 20 ++++ inc/uf2.h | 6 ++ scripts/samd21j17a_self_sram_bl.ld | 159 +++++++++++++++++++++++++++ scripts/samd21j17a_sram_bl.ld | 165 +++++++++++++++++++++++++++++ src/fat.c | 27 ++++- src/main.c | 47 ++++++++ src/selfmain.c | 6 ++ src/utils.c | 5 + 10 files changed, 458 insertions(+), 5 deletions(-) create mode 100644 boards/jeff_probe/board.mk create mode 100644 boards/jeff_probe/board_config.h create mode 100644 scripts/samd21j17a_self_sram_bl.ld create mode 100644 scripts/samd21j17a_sram_bl.ld diff --git a/Makefile b/Makefile index 435a75c6..0b24d431 100755 --- a/Makefile +++ b/Makefile @@ -29,9 +29,25 @@ $(WFLAGS) UF2_VERSION_BASE = $(shell git describe --dirty --always --tags) ifeq ($(CHIP_FAMILY), samd21) -LINKER_SCRIPT=scripts/samd21j18a.ld -BOOTLOADER_SIZE=8192 -SELF_LINKER_SCRIPT=scripts/samd21j18a_self.ld + BOOTLOADER_SIZE = 8192 + SRAM_BASE_ADDR = 0x20000000 + ifeq ($(USE_SRAM_BL_FLASH),1) + CFLAGS += -DSRAM_BASE_ADDR=$(SRAM_BASE_ADDR) -DSRAM_BL_SIZE=0x2800 + ifdef CONV_SRAM_BL + CFLAGS += -DUSE_STD_FLASH_BL + UPDATE_BL_OFST = $(BOOTLOADER_SIZE) + SELF_LINKER_SCRIPT = scripts/samd21j18a_self.ld + else + UPDATE_BL_OFST = $(SRAM_BASE_ADDR) + SELF_LINKER_SCRIPT = scripts/samd21j17a_self_sram_bl.ld + endif + LINKER_SCRIPT = scripts/samd21j17a_sram_bl.ld + else + + UPDATE_BL_OFST = $(BOOTLOADER_SIZE) + LINKER_SCRIPT = scripts/samd21j18a.ld + SELF_LINKER_SCRIPT = scripts/samd21j18a_self.ld + endif endif ifeq ($(CHIP_FAMILY), samd51) @@ -174,7 +190,7 @@ $(SELF_EXECUTABLE): $(SELF_OBJECTS) -T$(SELF_LINKER_SCRIPT) \ -Wl,-Map,$(BUILD_PATH)/update-$(NAME).map -o $(BUILD_PATH)/update-$(NAME).elf $(SELF_OBJECTS) arm-none-eabi-objcopy -O binary $(BUILD_PATH)/update-$(NAME).elf $(BUILD_PATH)/update-$(NAME).bin - python3 lib/uf2/utils/uf2conv.py -b $(BOOTLOADER_SIZE) -c -o $@ $(BUILD_PATH)/update-$(NAME).bin + python3 lib/uf2/utils/uf2conv.py -b $(UPDATE_BL_OFST) -c -o $@ $(BUILD_PATH)/update-$(NAME).bin $(BUILD_PATH)/%.o: src/%.c $(wildcard inc/*.h boards/*/*.h) $(BUILD_PATH)/uf2_version.h echo "$<" diff --git a/boards/jeff_probe/board.mk b/boards/jeff_probe/board.mk new file mode 100644 index 00000000..26380e49 --- /dev/null +++ b/boards/jeff_probe/board.mk @@ -0,0 +1,4 @@ +CHIP_FAMILY = samd21 +CHIP_VARIANT = SAMD21E17A + +USE_SRAM_BL_FLASH = 1 diff --git a/boards/jeff_probe/board_config.h b/boards/jeff_probe/board_config.h new file mode 100644 index 00000000..91e401a9 --- /dev/null +++ b/boards/jeff_probe/board_config.h @@ -0,0 +1,20 @@ +#ifndef BOARD_CONFIG_H +#define BOARD_CONFIG_H + +#define VENDOR_NAME "Flirc" +#define PRODUCT_NAME "Jeff Probe" +#define VOLUME_LABEL "JEFF_BOOT" +#define INDEX_URL "https://flirc.tv/products/flirc-jeffprobe" +#define BOARD_ID "SAMD21E17A-Jeff_Probe" + +#define USB_VID 0x1d50 +#define USB_PID 0x6017 + +#define LED_PIN PIN_PA10 + +#define BOOT_LOAD_PIN PIN_PA27 + +// This is needed because SAMD21E17A only has 128kB of flash +#define FLASH_NUM_ROWS 512 + +#endif diff --git a/inc/uf2.h b/inc/uf2.h index 6d13c786..7ee46055 100644 --- a/inc/uf2.h +++ b/inc/uf2.h @@ -248,6 +248,7 @@ void padded_memcpy(char *dst, const char *src, int len); #endif #define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set #define DBL_TAP_MAGIC_QUICK_BOOT 0xf02669ef +#define DBL_TAP_MAGIC_SRAM_BL 0xf03669ef #if USE_SINGLE_RESET #ifdef SAMD21 @@ -321,6 +322,11 @@ void RGBLED_set_color(uint32_t color); #define LED_RX_TGL() #endif +// For BOOT_LOAD_PIN +#if defined(BOOT_LOAD_PIN) +#define BOOT_PIN_MASK (1U << (BOOT_LOAD_PIN & 0x1f)) +#endif + extern uint32_t timerHigh, resetHorizon; void timerTick(void); void delay(uint32_t ms); diff --git a/scripts/samd21j17a_self_sram_bl.ld b/scripts/samd21j17a_self_sram_bl.ld new file mode 100644 index 00000000..05ffcd27 --- /dev/null +++ b/scripts/samd21j17a_self_sram_bl.ld @@ -0,0 +1,159 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21J18A + * + * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00004000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0x1000; + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + /* + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + */ + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > ram + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > ram + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/scripts/samd21j17a_sram_bl.ld b/scripts/samd21j17a_sram_bl.ld new file mode 100644 index 00000000..a9007326 --- /dev/null +++ b/scripts/samd21j17a_sram_bl.ld @@ -0,0 +1,165 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21J18A + * + * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00002000 + ram (rwx) : ORIGIN = 0x20002800, LENGTH = 0x00001800 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0x0800; + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + /* + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + */ + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; + + _binfo_start = 0x00002000 - 4 * 4; + .binfo _binfo_start : { + KEEP(*(.binfo)) ; + } > rom +} diff --git a/src/fat.c b/src/fat.c index 70da28fb..11100715 100644 --- a/src/fat.c +++ b/src/fat.c @@ -219,8 +219,18 @@ void write_block(uint32_t block_no, uint8_t *data, bool quiet, WriteState *state return; } +#ifdef SRAM_BL_SIZE + bool use_flash = bl->targetAddr >= APP_START_ADDRESS && bl->targetAddr < FLASH_SIZE; + bool use_sram = bl->targetAddr >= SRAM_BASE_ADDR && bl->targetAddr < (SRAM_BASE_ADDR + SRAM_BL_SIZE); +#endif + if ((bl->flags & UF2_FLAG_NOFLASH) || bl->payloadSize != 256 || (bl->targetAddr & 0xff) || - bl->targetAddr < APP_START_ADDRESS || bl->targetAddr >= FLASH_SIZE) { +#ifdef SRAM_BL_SIZE + !(use_flash||use_sram) +#else + bl->targetAddr < APP_START_ADDRESS || bl->targetAddr >= FLASH_SIZE +#endif + ){ #if USE_DBG_MSC if (!quiet) logval("invalid target addr", bl->targetAddr); @@ -229,7 +239,22 @@ void write_block(uint32_t block_no, uint8_t *data, bool quiet, WriteState *state // copied from a device; we still want to count these blocks to reset properly } else { // logval("write block at", bl->targetAddr); +#ifdef SRAM_BL_SIZE + if ( use_flash) { + flash_write_row((void *)bl->targetAddr, (void *)bl->data); + *DBL_TAP_PTR = 0; + }else{ + memcpy((void*)bl->targetAddr, (void*)bl->data, FLASH_ROW_SIZE); + if ( bl->targetAddr == SRAM_BASE_ADDR ){ + uint32_t bootAddr = bl->data[4] | (bl->data[5]<<8) | (bl->data[6]<<16) | (bl->data[7]<<24); + if( bootAddr > SRAM_BASE_ADDR && bootAddr < (SRAM_BASE_ADDR + SRAM_BL_SIZE) ){ + *DBL_TAP_PTR = DBL_TAP_MAGIC_SRAM_BL; + } + } + } +#else flash_write_row((void *)bl->targetAddr, (void *)bl->data); +#endif } if (state && bl->numBlocks) { diff --git a/src/main.c b/src/main.c index 095fa0a0..5b9d5135 100644 --- a/src/main.c +++ b/src/main.c @@ -96,6 +96,20 @@ extern int8_t led_tick_step; * */ static void check_start_application(void) { +#ifdef SRAM_BL_SIZE + register uint32_t app_start_address asm("r6") ; + + bool boot_sram = *DBL_TAP_PTR == DBL_TAP_MAGIC_SRAM_BL; + uint32_t base_addr = boot_sram ? SRAM_BASE_ADDR : APP_START_ADDRESS; + uint32_t addr_limit = boot_sram ? SRAM_BASE_ADDR+SRAM_BL_SIZE : FLASH_SIZE; + + app_start_address = *(uint32_t *)( base_addr + 4 ); + if ( app_start_address < base_addr || app_start_address > addr_limit ){ + /* Stay in bootloader */ + return; + } + +#else uint32_t app_start_address; /* Load the Reset Handler address of the application */ @@ -109,6 +123,25 @@ static void check_start_application(void) { /* Stay in bootloader */ return; } +#endif + +#if defined(BOOT_LOAD_PIN) + volatile PortGroup *boot_port = (volatile PortGroup *)(&(PORT->Group[BOOT_LOAD_PIN / 32])); + volatile bool boot_en; + + /* Enable the input mode in Boot GPIO Pin */ + boot_port->DIRCLR.reg = BOOT_PIN_MASK; + boot_port->PINCFG[BOOT_LOAD_PIN & 0x1F].reg = PORT_PINCFG_INEN | PORT_PINCFG_PULLEN; + boot_port->OUTSET.reg = BOOT_PIN_MASK; + /* Read the BOOT_LOAD_PIN status */ + boot_en = (boot_port->IN.reg) & BOOT_PIN_MASK; + + /* Check the bootloader enable condition */ + if (!boot_en) { + /* Stay in bootloader */ + return; + } +#endif #if USE_SINGLE_RESET if (SINGLE_RESET()) { @@ -126,6 +159,10 @@ static void check_start_application(void) { if (RESET_CONTROLLER->RCAUSE.bit.POR) { *DBL_TAP_PTR = 0; } +#ifdef SRAM_BL_SIZE + else if ( *DBL_TAP_PTR == DBL_TAP_MAGIC_SRAM_BL ) { + } +#endif else if (*DBL_TAP_PTR == DBL_TAP_MAGIC) { *DBL_TAP_PTR = 0; return; // stay in bootloader @@ -145,11 +182,21 @@ static void check_start_application(void) { RGBLED_set_color(COLOR_LEAVE); #endif +#ifdef SRAM_BL_SIZE + /* Rebase the vector table base address */ + SCB->VTOR = (uint32_t) base_addr ; +// jump_to_app (app_start_address, *(uint32_t *)base_addr); +// register uint32_t tmp_start asm("r6") = app_start_address; + /* Rebase the Stack Pointer */ + __set_MSP(*(uint32_t *)base_addr); + +#else /* Rebase the Stack Pointer */ __set_MSP(*(uint32_t *)APP_START_ADDRESS); /* Rebase the vector table base address */ SCB->VTOR = ((uint32_t)APP_START_ADDRESS & SCB_VTOR_TBLOFF_Msk); +#endif /* Jump to application Reset Handler in the application */ asm("bx %0" ::"r"(app_start_address)); diff --git a/src/selfmain.c b/src/selfmain.c index 91496d96..d1c065f2 100644 --- a/src/selfmain.c +++ b/src/selfmain.c @@ -183,6 +183,10 @@ int main(void) { logmsg("Update successful!"); +#ifdef SRAM_BL_SIZE + *DBL_TAP_PTR = 0; +#endif + // re-base int vector back to bootloader, so that the flash erase // below doesn't write over the vectors. SCB->VTOR = 0; @@ -191,8 +195,10 @@ int main(void) { // bootloader doesn't run us a second time. We don't need to erase to write // zeros. The remainder of the write unit will be set to 1s which should // preserve the existing values but its not critical. +#if ( (! defined(SRAM_BL_SIZE)) || defined(USE_STD_FLASH_BL) ) uint32_t zeros[2] = {0, 0}; flash_write_words((void *)(BOOTLOADER_K * 1024), zeros, 2); +#endif #ifdef SAMD21 // Re-enable BOOTPROT diff --git a/src/utils.c b/src/utils.c index f1f3224a..7a506efa 100644 --- a/src/utils.c +++ b/src/utils.c @@ -79,7 +79,12 @@ int writeNum(char *buf, uint32_t n, bool full) { void resetIntoApp() { // reset without waiting for double tap (only works for one reset) RGBLED_set_color(COLOR_LEAVE); +#ifdef SRAM_BL_SIZE + if ( *DBL_TAP_PTR != DBL_TAP_MAGIC_SRAM_BL) + *DBL_TAP_PTR = DBL_TAP_MAGIC_QUICK_BOOT; +#else *DBL_TAP_PTR = DBL_TAP_MAGIC_QUICK_BOOT; +#endif NVIC_SystemReset(); } From fe875c4a485fe15d747d1eff1668afd68f3b9074 Mon Sep 17 00:00:00 2001 From: Richard Campbell Date: Mon, 2 Oct 2023 07:33:48 -0700 Subject: [PATCH 02/11] do not leave dotstar on after exiting bootloader --- inc/uf2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/uf2.h b/inc/uf2.h index 6d13c786..d11fa3c5 100644 --- a/inc/uf2.h +++ b/inc/uf2.h @@ -153,7 +153,7 @@ #define COLOR_START 0x000040 #define COLOR_USB 0x004000 #define COLOR_UART 0x404000 -#define COLOR_LEAVE 0x400040 +#define COLOR_LEAVE 0x000000 #endif /* From abf9802d045b68f169806bff467f22426dc1bbda Mon Sep 17 00:00:00 2001 From: H Yi Date: Fri, 21 Jul 2023 14:00:01 -0500 Subject: [PATCH 03/11] add BOOT_LOAD_PIN support. add jeff probe board. And support for flash bootloader from SRAM which does not touch application code --- Makefile | 24 ++++- boards/jeff_probe/board.mk | 4 + boards/jeff_probe/board_config.h | 20 ++++ inc/uf2.h | 6 ++ scripts/samd21j17a_self_sram_bl.ld | 159 +++++++++++++++++++++++++++ scripts/samd21j17a_sram_bl.ld | 165 +++++++++++++++++++++++++++++ src/fat.c | 27 ++++- src/main.c | 47 ++++++++ src/selfmain.c | 6 ++ src/utils.c | 5 + 10 files changed, 458 insertions(+), 5 deletions(-) create mode 100644 boards/jeff_probe/board.mk create mode 100644 boards/jeff_probe/board_config.h create mode 100644 scripts/samd21j17a_self_sram_bl.ld create mode 100644 scripts/samd21j17a_sram_bl.ld diff --git a/Makefile b/Makefile index 435a75c6..0b24d431 100755 --- a/Makefile +++ b/Makefile @@ -29,9 +29,25 @@ $(WFLAGS) UF2_VERSION_BASE = $(shell git describe --dirty --always --tags) ifeq ($(CHIP_FAMILY), samd21) -LINKER_SCRIPT=scripts/samd21j18a.ld -BOOTLOADER_SIZE=8192 -SELF_LINKER_SCRIPT=scripts/samd21j18a_self.ld + BOOTLOADER_SIZE = 8192 + SRAM_BASE_ADDR = 0x20000000 + ifeq ($(USE_SRAM_BL_FLASH),1) + CFLAGS += -DSRAM_BASE_ADDR=$(SRAM_BASE_ADDR) -DSRAM_BL_SIZE=0x2800 + ifdef CONV_SRAM_BL + CFLAGS += -DUSE_STD_FLASH_BL + UPDATE_BL_OFST = $(BOOTLOADER_SIZE) + SELF_LINKER_SCRIPT = scripts/samd21j18a_self.ld + else + UPDATE_BL_OFST = $(SRAM_BASE_ADDR) + SELF_LINKER_SCRIPT = scripts/samd21j17a_self_sram_bl.ld + endif + LINKER_SCRIPT = scripts/samd21j17a_sram_bl.ld + else + + UPDATE_BL_OFST = $(BOOTLOADER_SIZE) + LINKER_SCRIPT = scripts/samd21j18a.ld + SELF_LINKER_SCRIPT = scripts/samd21j18a_self.ld + endif endif ifeq ($(CHIP_FAMILY), samd51) @@ -174,7 +190,7 @@ $(SELF_EXECUTABLE): $(SELF_OBJECTS) -T$(SELF_LINKER_SCRIPT) \ -Wl,-Map,$(BUILD_PATH)/update-$(NAME).map -o $(BUILD_PATH)/update-$(NAME).elf $(SELF_OBJECTS) arm-none-eabi-objcopy -O binary $(BUILD_PATH)/update-$(NAME).elf $(BUILD_PATH)/update-$(NAME).bin - python3 lib/uf2/utils/uf2conv.py -b $(BOOTLOADER_SIZE) -c -o $@ $(BUILD_PATH)/update-$(NAME).bin + python3 lib/uf2/utils/uf2conv.py -b $(UPDATE_BL_OFST) -c -o $@ $(BUILD_PATH)/update-$(NAME).bin $(BUILD_PATH)/%.o: src/%.c $(wildcard inc/*.h boards/*/*.h) $(BUILD_PATH)/uf2_version.h echo "$<" diff --git a/boards/jeff_probe/board.mk b/boards/jeff_probe/board.mk new file mode 100644 index 00000000..26380e49 --- /dev/null +++ b/boards/jeff_probe/board.mk @@ -0,0 +1,4 @@ +CHIP_FAMILY = samd21 +CHIP_VARIANT = SAMD21E17A + +USE_SRAM_BL_FLASH = 1 diff --git a/boards/jeff_probe/board_config.h b/boards/jeff_probe/board_config.h new file mode 100644 index 00000000..91e401a9 --- /dev/null +++ b/boards/jeff_probe/board_config.h @@ -0,0 +1,20 @@ +#ifndef BOARD_CONFIG_H +#define BOARD_CONFIG_H + +#define VENDOR_NAME "Flirc" +#define PRODUCT_NAME "Jeff Probe" +#define VOLUME_LABEL "JEFF_BOOT" +#define INDEX_URL "https://flirc.tv/products/flirc-jeffprobe" +#define BOARD_ID "SAMD21E17A-Jeff_Probe" + +#define USB_VID 0x1d50 +#define USB_PID 0x6017 + +#define LED_PIN PIN_PA10 + +#define BOOT_LOAD_PIN PIN_PA27 + +// This is needed because SAMD21E17A only has 128kB of flash +#define FLASH_NUM_ROWS 512 + +#endif diff --git a/inc/uf2.h b/inc/uf2.h index d11fa3c5..756e753f 100644 --- a/inc/uf2.h +++ b/inc/uf2.h @@ -248,6 +248,7 @@ void padded_memcpy(char *dst, const char *src, int len); #endif #define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set #define DBL_TAP_MAGIC_QUICK_BOOT 0xf02669ef +#define DBL_TAP_MAGIC_SRAM_BL 0xf03669ef #if USE_SINGLE_RESET #ifdef SAMD21 @@ -321,6 +322,11 @@ void RGBLED_set_color(uint32_t color); #define LED_RX_TGL() #endif +// For BOOT_LOAD_PIN +#if defined(BOOT_LOAD_PIN) +#define BOOT_PIN_MASK (1U << (BOOT_LOAD_PIN & 0x1f)) +#endif + extern uint32_t timerHigh, resetHorizon; void timerTick(void); void delay(uint32_t ms); diff --git a/scripts/samd21j17a_self_sram_bl.ld b/scripts/samd21j17a_self_sram_bl.ld new file mode 100644 index 00000000..05ffcd27 --- /dev/null +++ b/scripts/samd21j17a_self_sram_bl.ld @@ -0,0 +1,159 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21J18A + * + * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00004000 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0x1000; + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + /* + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + */ + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > ram + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > ram + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/scripts/samd21j17a_sram_bl.ld b/scripts/samd21j17a_sram_bl.ld new file mode 100644 index 00000000..a9007326 --- /dev/null +++ b/scripts/samd21j17a_sram_bl.ld @@ -0,0 +1,165 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21J18A + * + * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00002000 + ram (rwx) : ORIGIN = 0x20002800, LENGTH = 0x00001800 +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0x0800; + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + /* + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + */ + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; + + _binfo_start = 0x00002000 - 4 * 4; + .binfo _binfo_start : { + KEEP(*(.binfo)) ; + } > rom +} diff --git a/src/fat.c b/src/fat.c index 70da28fb..11100715 100644 --- a/src/fat.c +++ b/src/fat.c @@ -219,8 +219,18 @@ void write_block(uint32_t block_no, uint8_t *data, bool quiet, WriteState *state return; } +#ifdef SRAM_BL_SIZE + bool use_flash = bl->targetAddr >= APP_START_ADDRESS && bl->targetAddr < FLASH_SIZE; + bool use_sram = bl->targetAddr >= SRAM_BASE_ADDR && bl->targetAddr < (SRAM_BASE_ADDR + SRAM_BL_SIZE); +#endif + if ((bl->flags & UF2_FLAG_NOFLASH) || bl->payloadSize != 256 || (bl->targetAddr & 0xff) || - bl->targetAddr < APP_START_ADDRESS || bl->targetAddr >= FLASH_SIZE) { +#ifdef SRAM_BL_SIZE + !(use_flash||use_sram) +#else + bl->targetAddr < APP_START_ADDRESS || bl->targetAddr >= FLASH_SIZE +#endif + ){ #if USE_DBG_MSC if (!quiet) logval("invalid target addr", bl->targetAddr); @@ -229,7 +239,22 @@ void write_block(uint32_t block_no, uint8_t *data, bool quiet, WriteState *state // copied from a device; we still want to count these blocks to reset properly } else { // logval("write block at", bl->targetAddr); +#ifdef SRAM_BL_SIZE + if ( use_flash) { + flash_write_row((void *)bl->targetAddr, (void *)bl->data); + *DBL_TAP_PTR = 0; + }else{ + memcpy((void*)bl->targetAddr, (void*)bl->data, FLASH_ROW_SIZE); + if ( bl->targetAddr == SRAM_BASE_ADDR ){ + uint32_t bootAddr = bl->data[4] | (bl->data[5]<<8) | (bl->data[6]<<16) | (bl->data[7]<<24); + if( bootAddr > SRAM_BASE_ADDR && bootAddr < (SRAM_BASE_ADDR + SRAM_BL_SIZE) ){ + *DBL_TAP_PTR = DBL_TAP_MAGIC_SRAM_BL; + } + } + } +#else flash_write_row((void *)bl->targetAddr, (void *)bl->data); +#endif } if (state && bl->numBlocks) { diff --git a/src/main.c b/src/main.c index 095fa0a0..5b9d5135 100644 --- a/src/main.c +++ b/src/main.c @@ -96,6 +96,20 @@ extern int8_t led_tick_step; * */ static void check_start_application(void) { +#ifdef SRAM_BL_SIZE + register uint32_t app_start_address asm("r6") ; + + bool boot_sram = *DBL_TAP_PTR == DBL_TAP_MAGIC_SRAM_BL; + uint32_t base_addr = boot_sram ? SRAM_BASE_ADDR : APP_START_ADDRESS; + uint32_t addr_limit = boot_sram ? SRAM_BASE_ADDR+SRAM_BL_SIZE : FLASH_SIZE; + + app_start_address = *(uint32_t *)( base_addr + 4 ); + if ( app_start_address < base_addr || app_start_address > addr_limit ){ + /* Stay in bootloader */ + return; + } + +#else uint32_t app_start_address; /* Load the Reset Handler address of the application */ @@ -109,6 +123,25 @@ static void check_start_application(void) { /* Stay in bootloader */ return; } +#endif + +#if defined(BOOT_LOAD_PIN) + volatile PortGroup *boot_port = (volatile PortGroup *)(&(PORT->Group[BOOT_LOAD_PIN / 32])); + volatile bool boot_en; + + /* Enable the input mode in Boot GPIO Pin */ + boot_port->DIRCLR.reg = BOOT_PIN_MASK; + boot_port->PINCFG[BOOT_LOAD_PIN & 0x1F].reg = PORT_PINCFG_INEN | PORT_PINCFG_PULLEN; + boot_port->OUTSET.reg = BOOT_PIN_MASK; + /* Read the BOOT_LOAD_PIN status */ + boot_en = (boot_port->IN.reg) & BOOT_PIN_MASK; + + /* Check the bootloader enable condition */ + if (!boot_en) { + /* Stay in bootloader */ + return; + } +#endif #if USE_SINGLE_RESET if (SINGLE_RESET()) { @@ -126,6 +159,10 @@ static void check_start_application(void) { if (RESET_CONTROLLER->RCAUSE.bit.POR) { *DBL_TAP_PTR = 0; } +#ifdef SRAM_BL_SIZE + else if ( *DBL_TAP_PTR == DBL_TAP_MAGIC_SRAM_BL ) { + } +#endif else if (*DBL_TAP_PTR == DBL_TAP_MAGIC) { *DBL_TAP_PTR = 0; return; // stay in bootloader @@ -145,11 +182,21 @@ static void check_start_application(void) { RGBLED_set_color(COLOR_LEAVE); #endif +#ifdef SRAM_BL_SIZE + /* Rebase the vector table base address */ + SCB->VTOR = (uint32_t) base_addr ; +// jump_to_app (app_start_address, *(uint32_t *)base_addr); +// register uint32_t tmp_start asm("r6") = app_start_address; + /* Rebase the Stack Pointer */ + __set_MSP(*(uint32_t *)base_addr); + +#else /* Rebase the Stack Pointer */ __set_MSP(*(uint32_t *)APP_START_ADDRESS); /* Rebase the vector table base address */ SCB->VTOR = ((uint32_t)APP_START_ADDRESS & SCB_VTOR_TBLOFF_Msk); +#endif /* Jump to application Reset Handler in the application */ asm("bx %0" ::"r"(app_start_address)); diff --git a/src/selfmain.c b/src/selfmain.c index 91496d96..d1c065f2 100644 --- a/src/selfmain.c +++ b/src/selfmain.c @@ -183,6 +183,10 @@ int main(void) { logmsg("Update successful!"); +#ifdef SRAM_BL_SIZE + *DBL_TAP_PTR = 0; +#endif + // re-base int vector back to bootloader, so that the flash erase // below doesn't write over the vectors. SCB->VTOR = 0; @@ -191,8 +195,10 @@ int main(void) { // bootloader doesn't run us a second time. We don't need to erase to write // zeros. The remainder of the write unit will be set to 1s which should // preserve the existing values but its not critical. +#if ( (! defined(SRAM_BL_SIZE)) || defined(USE_STD_FLASH_BL) ) uint32_t zeros[2] = {0, 0}; flash_write_words((void *)(BOOTLOADER_K * 1024), zeros, 2); +#endif #ifdef SAMD21 // Re-enable BOOTPROT diff --git a/src/utils.c b/src/utils.c index f1f3224a..7a506efa 100644 --- a/src/utils.c +++ b/src/utils.c @@ -79,7 +79,12 @@ int writeNum(char *buf, uint32_t n, bool full) { void resetIntoApp() { // reset without waiting for double tap (only works for one reset) RGBLED_set_color(COLOR_LEAVE); +#ifdef SRAM_BL_SIZE + if ( *DBL_TAP_PTR != DBL_TAP_MAGIC_SRAM_BL) + *DBL_TAP_PTR = DBL_TAP_MAGIC_QUICK_BOOT; +#else *DBL_TAP_PTR = DBL_TAP_MAGIC_QUICK_BOOT; +#endif NVIC_SystemReset(); } From dc692af76899ca55cb1eb2bc08b1aa962b5ce17c Mon Sep 17 00:00:00 2001 From: H Yi Date: Sun, 21 Jan 2024 13:20:20 -0600 Subject: [PATCH 04/11] fixed compilation error; rebase to master branch --- Makefile | 4 +- scripts/samd21j17a_self_conv_bl.ld | 160 +++++++++++++++++++++++++++++ src/cdc_enumerate.c | 2 +- 3 files changed, 163 insertions(+), 3 deletions(-) create mode 100644 scripts/samd21j17a_self_conv_bl.ld diff --git a/Makefile b/Makefile index 0b24d431..80c583ae 100755 --- a/Makefile +++ b/Makefile @@ -32,11 +32,11 @@ ifeq ($(CHIP_FAMILY), samd21) BOOTLOADER_SIZE = 8192 SRAM_BASE_ADDR = 0x20000000 ifeq ($(USE_SRAM_BL_FLASH),1) - CFLAGS += -DSRAM_BASE_ADDR=$(SRAM_BASE_ADDR) -DSRAM_BL_SIZE=0x2800 + CFLAGS += -DSRAM_BASE_ADDR=$(SRAM_BASE_ADDR) -DSRAM_BL_SIZE=0x2800 -DLED_BUILTIN=10 ifdef CONV_SRAM_BL CFLAGS += -DUSE_STD_FLASH_BL UPDATE_BL_OFST = $(BOOTLOADER_SIZE) - SELF_LINKER_SCRIPT = scripts/samd21j18a_self.ld + SELF_LINKER_SCRIPT = scripts/samd21j17a_self_conv_bl.ld else UPDATE_BL_OFST = $(SRAM_BASE_ADDR) SELF_LINKER_SCRIPT = scripts/samd21j17a_self_sram_bl.ld diff --git a/scripts/samd21j17a_self_conv_bl.ld b/scripts/samd21j17a_self_conv_bl.ld new file mode 100644 index 00000000..12a8f968 --- /dev/null +++ b/scripts/samd21j17a_self_conv_bl.ld @@ -0,0 +1,160 @@ +/** + * \file + * + * \brief Linker script for running in internal FLASH on the SAMD21J18A + * + * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved. + * + * \asf_license_start + * + * \page License + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of Atmel may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 4. This software may only be redistributed and used in connection with an + * Atmel microcontroller product. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE + * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * \asf_license_stop + * + */ + + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +SEARCH_DIR(.) + +/* Memory Spaces Definitions */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00002000, LENGTH = 128k -8k + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16k +} + +/* The stack size used by the application. NOTE: you need to adjust according to your application. */ +STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0x1000; + +/* Section Definitions */ +SECTIONS +{ + .text : + { + . = ALIGN(4); + _sfixed = .; + KEEP(*(.vectors .vectors.*)) + *(.text .text.* .gnu.linkonce.t.*) + *(.glue_7t) *(.glue_7) + *(.rodata .rodata* .gnu.linkonce.r.*) + *(.ARM.extab* .gnu.linkonce.armextab.*) + + /* Support C constructors, and C destructors in both user code + and the C library. This also provides support for C++ code. */ + . = ALIGN(4); + KEEP(*(.init)) + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + + . = ALIGN(4); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*crtend.o(.ctors)) + + /* + + . = ALIGN(4); + KEEP(*(.fini)) + + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*crtend.o(.dtors)) + */ + + . = ALIGN(4); + _efixed = .; /* End of text section */ + } > rom + + /* .ARM.exidx is sorted, so has to go in its own output section. */ + PROVIDE_HIDDEN (__exidx_start = .); + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > rom + PROVIDE_HIDDEN (__exidx_end = .); + + . = ALIGN(4); + _etext = .; + + .relocate : AT (_etext) + { + . = ALIGN(4); + _srelocate = .; + *(.ramfunc .ramfunc.*); + *(.data .data.*); + . = ALIGN(4); + _erelocate = .; + } > ram + + /* .bss section which is used for uninitialized data */ + .bss (NOLOAD) : + { + . = ALIGN(4); + _sbss = . ; + _szero = .; + *(.bss .bss.*) + *(COMMON) + . = ALIGN(4); + _ebss = . ; + _ezero = .; + } > ram + + /* stack section */ + .stack (NOLOAD): + { + . = ALIGN(8); + _sstack = .; + . = . + STACK_SIZE; + . = ALIGN(8); + _estack = .; + } > ram + + . = ALIGN(4); + _end = . ; +} diff --git a/src/cdc_enumerate.c b/src/cdc_enumerate.c index 2626c89f..7cf5dec6 100644 --- a/src/cdc_enumerate.c +++ b/src/cdc_enumerate.c @@ -721,7 +721,7 @@ uint32_t USB_WriteCore(const void *pData, uint32_t length, uint8_t ep_num, bool //* \brief Send zero length packet through the control endpoint //*---------------------------------------------------------------------------- void AT91F_USB_SendZlp(void) { - uint8_t c; + uint8_t c=0; USB_Write(&c, 0, 0); } From 81b5a11ec94d3182894a771bce40f91574fda6c2 Mon Sep 17 00:00:00 2001 From: H Yi Date: Sun, 21 Jan 2024 13:57:00 -0600 Subject: [PATCH 05/11] fixed self update and makefile --- Makefile | 3 +-- src/selfmain.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 80c583ae..1e944de8 100755 --- a/Makefile +++ b/Makefile @@ -32,12 +32,11 @@ ifeq ($(CHIP_FAMILY), samd21) BOOTLOADER_SIZE = 8192 SRAM_BASE_ADDR = 0x20000000 ifeq ($(USE_SRAM_BL_FLASH),1) - CFLAGS += -DSRAM_BASE_ADDR=$(SRAM_BASE_ADDR) -DSRAM_BL_SIZE=0x2800 -DLED_BUILTIN=10 ifdef CONV_SRAM_BL - CFLAGS += -DUSE_STD_FLASH_BL UPDATE_BL_OFST = $(BOOTLOADER_SIZE) SELF_LINKER_SCRIPT = scripts/samd21j17a_self_conv_bl.ld else + CFLAGS += -DSRAM_BASE_ADDR=$(SRAM_BASE_ADDR) -DSRAM_BL_SIZE=0x2800 -DLED_BUILTIN=10 UPDATE_BL_OFST = $(SRAM_BASE_ADDR) SELF_LINKER_SCRIPT = scripts/samd21j17a_self_sram_bl.ld endif diff --git a/src/selfmain.c b/src/selfmain.c index d1c065f2..2b674478 100644 --- a/src/selfmain.c +++ b/src/selfmain.c @@ -195,7 +195,7 @@ int main(void) { // bootloader doesn't run us a second time. We don't need to erase to write // zeros. The remainder of the write unit will be set to 1s which should // preserve the existing values but its not critical. -#if ( (! defined(SRAM_BL_SIZE)) || defined(USE_STD_FLASH_BL) ) +#if (! defined(SRAM_BL_SIZE) ) uint32_t zeros[2] = {0, 0}; flash_write_words((void *)(BOOTLOADER_K * 1024), zeros, 2); #endif From 8efb6d57c193d91321557f56ee5000abd2a3bb6f Mon Sep 17 00:00:00 2001 From: H Yi Date: Sun, 21 Jan 2024 14:01:47 -0600 Subject: [PATCH 06/11] update board.mk for jeff probe --- boards/jeff_probe/board.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/boards/jeff_probe/board.mk b/boards/jeff_probe/board.mk index 26380e49..8a5f3b11 100644 --- a/boards/jeff_probe/board.mk +++ b/boards/jeff_probe/board.mk @@ -2,3 +2,4 @@ CHIP_FAMILY = samd21 CHIP_VARIANT = SAMD21E17A USE_SRAM_BL_FLASH = 1 +# CONV_SRAM_BL = 1 From f6f6ca6f1ce2d7b55d448b6a5cd4ce5cec563f09 Mon Sep 17 00:00:00 2001 From: H Yi Date: Sun, 21 Jan 2024 14:43:26 -0600 Subject: [PATCH 07/11] revert back makefile --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 1e944de8..43f8fc96 100755 --- a/Makefile +++ b/Makefile @@ -32,11 +32,12 @@ ifeq ($(CHIP_FAMILY), samd21) BOOTLOADER_SIZE = 8192 SRAM_BASE_ADDR = 0x20000000 ifeq ($(USE_SRAM_BL_FLASH),1) + CFLAGS += -DSRAM_BASE_ADDR=$(SRAM_BASE_ADDR) -DSRAM_BL_SIZE=0x2800 ifdef CONV_SRAM_BL + CFLAGS += -DUSE_STD_FLASH_BL UPDATE_BL_OFST = $(BOOTLOADER_SIZE) SELF_LINKER_SCRIPT = scripts/samd21j17a_self_conv_bl.ld else - CFLAGS += -DSRAM_BASE_ADDR=$(SRAM_BASE_ADDR) -DSRAM_BL_SIZE=0x2800 -DLED_BUILTIN=10 UPDATE_BL_OFST = $(SRAM_BASE_ADDR) SELF_LINKER_SCRIPT = scripts/samd21j17a_self_sram_bl.ld endif From 73f02c2b60faa017271583c94ccafef903a0a882 Mon Sep 17 00:00:00 2001 From: H Yi Date: Sun, 21 Jan 2024 15:58:02 -0600 Subject: [PATCH 08/11] allow board.mk passing CFLAGS to Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 43f8fc96..ad087203 100755 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ WFLAGS = \ -Wno-deprecated-declarations -Wpacked -Wredundant-decls -Wnested-externs \ -Wlong-long -Wunreachable-code -Wcast-align \ -Wno-missing-braces -Wno-overflow -Wno-shadow -Wno-attributes -Wno-packed -Wno-pointer-sign -CFLAGS = $(COMMON_FLAGS) \ +CFLAGS += $(COMMON_FLAGS) \ -x c -c -pipe -nostdlib \ --param max-inline-insns-single=500 \ -fno-strict-aliasing -fdata-sections -ffunction-sections \ From 169bbc818c13e7092a8ab200263b08a8c85c75c0 Mon Sep 17 00:00:00 2001 From: H Yi Date: Sun, 21 Jan 2024 15:58:55 -0600 Subject: [PATCH 09/11] add CRYSTALLESS to jeff probe build --- boards/jeff_probe/board.mk | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/boards/jeff_probe/board.mk b/boards/jeff_probe/board.mk index 8a5f3b11..b54a176c 100644 --- a/boards/jeff_probe/board.mk +++ b/boards/jeff_probe/board.mk @@ -1,5 +1,6 @@ -CHIP_FAMILY = samd21 -CHIP_VARIANT = SAMD21E17A +CHIP_FAMILY = samd21 +CHIP_VARIANT = SAMD21E17A -USE_SRAM_BL_FLASH = 1 -# CONV_SRAM_BL = 1 +USE_SRAM_BL_FLASH = 1 +CONV_SRAM_BL = 1 +CFLAGS += -DCRYSTALLESS From fb184ce775c99b40ffcfbef158a38097d74a1d54 Mon Sep 17 00:00:00 2001 From: H Yi Date: Sun, 21 Jan 2024 15:59:16 -0600 Subject: [PATCH 10/11] working on selfmain --- src/selfmain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/selfmain.c b/src/selfmain.c index 2b674478..82291385 100644 --- a/src/selfmain.c +++ b/src/selfmain.c @@ -183,7 +183,7 @@ int main(void) { logmsg("Update successful!"); -#ifdef SRAM_BL_SIZE +#if ( defined(SRAM_BL_SIZE) && (!defined(USE_STD_FLASH_BL) ) ) *DBL_TAP_PTR = 0; #endif @@ -195,7 +195,7 @@ int main(void) { // bootloader doesn't run us a second time. We don't need to erase to write // zeros. The remainder of the write unit will be set to 1s which should // preserve the existing values but its not critical. -#if (! defined(SRAM_BL_SIZE) ) +#if ( (! defined(SRAM_BL_SIZE)) || defined(USE_STD_FLASH_BL) ) uint32_t zeros[2] = {0, 0}; flash_write_words((void *)(BOOTLOADER_K * 1024), zeros, 2); #endif From d0289bf79b72978d98980c024e77b0460a4b1e43 Mon Sep 17 00:00:00 2001 From: H Yi Date: Sun, 21 Jan 2024 16:35:55 -0600 Subject: [PATCH 11/11] update board makefile --- boards/jeff_probe/board.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boards/jeff_probe/board.mk b/boards/jeff_probe/board.mk index b54a176c..79c2b815 100644 --- a/boards/jeff_probe/board.mk +++ b/boards/jeff_probe/board.mk @@ -2,5 +2,5 @@ CHIP_FAMILY = samd21 CHIP_VARIANT = SAMD21E17A USE_SRAM_BL_FLASH = 1 -CONV_SRAM_BL = 1 +#CONV_SRAM_BL = 1 CFLAGS += -DCRYSTALLESS