finally working double-tap trigger code
This commit is contained in:
+3
-3
@@ -1,8 +1,5 @@
|
||||
ENTRY( _start )
|
||||
|
||||
__stack_size = 512;
|
||||
PROVIDE( _stack_size = __stack_size );
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/* Try to squeeze down to this target size */
|
||||
@@ -17,6 +14,9 @@ MEMORY
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
PROVIDE(_bootloader_limit = ORIGIN(FLASH) + LENGTH(FLASH));
|
||||
PROVIDE(_bootloader_stack = ORIGIN(USBRAM) + LENGTH(USBRAM));
|
||||
|
||||
.vector :
|
||||
{
|
||||
*(.vector);
|
||||
|
||||
@@ -1,13 +1,98 @@
|
||||
#define R16_BKP_DATAR10 0x40006C28
|
||||
#define BOOT_MAGIC_APP_IMMEDIATELY 0x4170
|
||||
#define BOOT_MAGIC_BOOTLOADER 0x624c
|
||||
|
||||
#define R32_PWR_CTLR 0x40007000
|
||||
|
||||
#define RCC_BASE 0x40021000
|
||||
#define R32_RCC_APB1PCENR 0x4002101C
|
||||
#define R32_RCC_RSTSCKR 0x40021024
|
||||
|
||||
#define SYSTICK_BASE 0xE000F000
|
||||
#define STK_CTLR 0xE000F000
|
||||
#define STK_SR 0xE000F004
|
||||
#define STK_CMPLR 0xE000F010
|
||||
#define WAIT_TIME (500 /* ms */ * 1000 /* assume 8 MHz system clock, div8 */)
|
||||
|
||||
.section .vector,"ax",@progbits
|
||||
.align 1
|
||||
|
||||
.global _start
|
||||
_start:
|
||||
// Use Adafruit(?)-inspired boot entry, namely "double-reset in short succession to enter bootloader"
|
||||
// 1. If the reset wasn't triggered by the nRST pin, go to application
|
||||
// 2. On nRST, if not first reset, go to bootloader
|
||||
// 3. On nRST, if *is* first reset, set magic and wait
|
||||
// 4a. If wait times out, go to application
|
||||
// 4b. If wait doesn't time out but a reset happens again, detect "not first" reset and go to bootloader
|
||||
la a0, RCC_BASE
|
||||
lw a1, (R32_RCC_RSTSCKR-RCC_BASE)(a0)
|
||||
slli a1, a1, (31 - 26)
|
||||
bgez a1, _enter_application_code // if PINRSTF == 0
|
||||
|
||||
// Enable BKP and PWR clock
|
||||
lw a1, (R32_RCC_APB1PCENR-RCC_BASE)(a0)
|
||||
la a2, (1 << 27) | (1 << 28)
|
||||
or a1, a1, a2
|
||||
sw a1, (R32_RCC_APB1PCENR-RCC_BASE)(a0)
|
||||
// Enable BKP write
|
||||
la a0, R32_PWR_CTLR
|
||||
lw a1, (a0)
|
||||
ori a1, a1, (1 << 8)
|
||||
sw a1, (a0)
|
||||
|
||||
// Check for magic values
|
||||
la a3, R16_BKP_DATAR10
|
||||
lhu a1, (a3)
|
||||
la a2, BOOT_MAGIC_APP_IMMEDIATELY
|
||||
beq a1, a2, _enter_application_code
|
||||
la a2, BOOT_MAGIC_BOOTLOADER
|
||||
beq a1, a2, _enter_bootloader
|
||||
|
||||
// Here we're on the first reset
|
||||
sh a2, (a3)
|
||||
la a0, SYSTICK_BASE
|
||||
la a1, WAIT_TIME
|
||||
sw a1, (STK_CMPLR-SYSTICK_BASE)(a0)
|
||||
la a1, 0b111000
|
||||
sw a1, (STK_CTLR-SYSTICK_BASE)(a0)
|
||||
// Seems to spuriously fire immediately if start bit is set concurrently
|
||||
la a1, 0b111001
|
||||
sw a1, (STK_CTLR-SYSTICK_BASE)(a0)
|
||||
1:
|
||||
lw a1, (STK_SR-SYSTICK_BASE)(a0)
|
||||
slli a1, a1, (31 - 0)
|
||||
bgez a1, 1b
|
||||
// Delay done, clear systick and magic
|
||||
sw zero, (STK_CTLR-SYSTICK_BASE)(a0)
|
||||
sw zero, (STK_SR-SYSTICK_BASE)(a0)
|
||||
sh zero, (a3)
|
||||
// If the delay expires, boot the application after all
|
||||
|
||||
_enter_application_code:
|
||||
// Clear all of these enables that we had set
|
||||
la a0, R32_PWR_CTLR
|
||||
lw a1, (a0)
|
||||
xori a1, a1, (1 << 8)
|
||||
sw a1, (a0)
|
||||
la a0, R32_RCC_APB1PCENR
|
||||
lw a1, (a0)
|
||||
la a2, (1 << 27) | (1 << 28)
|
||||
xor a1, a1, a2
|
||||
sw a1, (a0)
|
||||
|
||||
_wipwipwip:
|
||||
j _wipwipwip
|
||||
|
||||
j _bootloader_limit
|
||||
|
||||
_enter_bootloader:
|
||||
// Set up global pointer
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
la sp, _bootloader_stack
|
||||
|
||||
// Load data section from flash to RAM
|
||||
la a0, _data_lma
|
||||
|
||||
Reference in New Issue
Block a user