at32_dfu.c (2384B)
1 // Copyright 2021-2023 QMK 2 // Copyright 2023-2024 HorrorTroll <https://github.com/HorrorTroll> 3 // Copyright 2023-2024 Zhaqian <https://github.com/zhaqian12> 4 // SPDX-License-Identifier: GPL-2.0-or-later 5 6 #include "bootloader.h" 7 #include "util.h" 8 9 #include <ch.h> 10 #include <hal.h> 11 #include "wait.h" 12 13 #ifndef AT32_BOOTLOADER_RAM_SYMBOL 14 # define AT32_BOOTLOADER_RAM_SYMBOL __ram0_end__ 15 #endif 16 17 extern uint32_t AT32_BOOTLOADER_RAM_SYMBOL; 18 19 /* This code should be checked whether it runs correctly on platforms */ 20 #define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0)) 21 #define BOOTLOADER_MAGIC 0xDEADBEEF 22 #define MAGIC_ADDR (unsigned long *)(SYMVAL(AT32_BOOTLOADER_RAM_SYMBOL) - 4) 23 24 __attribute__((weak)) void bootloader_marker_enable(void) { 25 uint32_t *marker = (uint32_t *)MAGIC_ADDR; 26 *marker = BOOTLOADER_MAGIC; // set magic flag => reset handler will jump into boot loader 27 } 28 29 __attribute__((weak)) bool bootloader_marker_active(void) { 30 const uint32_t *marker = (const uint32_t *)MAGIC_ADDR; 31 return (*marker == BOOTLOADER_MAGIC) ? true : false; 32 } 33 34 __attribute__((weak)) void bootloader_marker_disable(void) { 35 uint32_t *marker = (uint32_t *)MAGIC_ADDR; 36 *marker = 0; 37 } 38 39 __attribute__((weak)) void bootloader_jump(void) { 40 bootloader_marker_enable(); 41 NVIC_SystemReset(); 42 } 43 44 __attribute__((weak)) void mcu_reset(void) { 45 NVIC_SystemReset(); 46 } 47 48 void enter_bootloader_mode_if_requested(void) { 49 if (bootloader_marker_active()) { 50 bootloader_marker_disable(); 51 52 struct system_memory_vector_t { 53 uint32_t stack_top; 54 void (*entrypoint)(void); 55 }; 56 const struct system_memory_vector_t *bootloader = (const struct system_memory_vector_t *)(AT32_BOOTLOADER_ADDRESS); 57 58 __disable_irq(); 59 60 #if defined(__MPU_PRESENT) && (__MPU_PRESENT == 1U) 61 ARM_MPU_Disable(); 62 #endif 63 64 SysTick->CTRL = 0; 65 SysTick->VAL = 0; 66 SysTick->LOAD = 0; 67 68 // Clear interrupt enable and interrupt pending registers 69 for (int i = 0; i < ARRAY_SIZE(NVIC->ICER); i++) { 70 NVIC->ICER[i] = 0xFFFFFFFF; 71 NVIC->ICPR[i] = 0xFFFFFFFF; 72 } 73 74 __set_CONTROL(0); 75 __set_MSP(bootloader->stack_top); 76 __enable_irq(); 77 78 // Jump to bootloader 79 bootloader->entrypoint(); 80 while (true) { 81 } 82 } 83 }