Move vector table to beginning of flash image (#10)
* Move vector table to beginning of flash image. Modify a boot2 to use the table. * Move binary info header up between ELF entry and reset handler * Extract common routines from boot2_w25q080 into helper files * Non-default boot2s: use common routines, make callable as void(*)(void) * BSD3 headers on boot2 files (people might want to use them elsewhere) * Promote binary info header to its own section, + comment/readability changes * Fix scope of asminclude path (fixes user custom boot2 definitions) * Rename symbol, clarify comment
This commit is contained in:
@ -144,40 +144,61 @@ __unhandled_user_irq:
|
||||
unhandled_user_irq_num_in_r0:
|
||||
bkpt #0
|
||||
|
||||
.section .reset, "ax"
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// This is the beginning of the image, which is entered from stage2 or bootrom USB MSD watchdog reboot
|
||||
.section .binary_info_header, "a"
|
||||
|
||||
// note if we are NO_FLASH then start: below is currently identical anyway, so save 4 bytes
|
||||
#if !PICO_NO_FLASH
|
||||
// We simply install our own vector table and redirect through it
|
||||
ldr r0, =__vectors
|
||||
b __vector_entry
|
||||
// Header must be in first 256 bytes of main image (i.e. excluding flash boot2).
|
||||
// For flash builds we put it immediately after vector table; for NO_FLASH the
|
||||
// vectors are at a +0x100 offset because the bootrom enters RAM images directly
|
||||
// at their lowest address, so we put the header in the VTOR alignment hole.
|
||||
|
||||
#if !PICO_NO_BINARY_INFO
|
||||
binary_info_header:
|
||||
.word BINARY_INFO_MARKER_START
|
||||
.word __binary_info_start
|
||||
.word __binary_info_end
|
||||
.word data_cpy_table // we may need to decode pointers that are in RAM at runtime.
|
||||
.word BINARY_INFO_MARKER_END
|
||||
#endif
|
||||
|
||||
// ELF entry point generally called when we load an ELF via debugger
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
.section .reset, "ax"
|
||||
|
||||
// On flash builds, the vector table comes first in the image (conventional).
|
||||
// On NO_FLASH builds, the reset handler section comes first, as the entry
|
||||
// point is at offset 0 (fixed due to bootrom), and VTOR is highly-aligned.
|
||||
// Image is entered in various ways:
|
||||
//
|
||||
// - NO_FLASH builds are entered from beginning by UF2 bootloader
|
||||
//
|
||||
// - Flash builds vector through the table into _reset_handler from boot2
|
||||
//
|
||||
// - Either type can be entered via _entry_point by the debugger, and flash builds
|
||||
// must then be sent back round the boot sequence to properly initialise flash
|
||||
|
||||
// ELF entry point:
|
||||
.type _entry_point,%function
|
||||
.thumb_func
|
||||
.global _entry_point
|
||||
_entry_point:
|
||||
|
||||
#if PICO_NO_FLASH
|
||||
// non flash
|
||||
// Vector through our own table (SP, VTOR will not have been set up at
|
||||
// this point). Same path for debugger entry and bootloader entry.
|
||||
ldr r0, =__vectors
|
||||
#else
|
||||
// todo clear watchdog?
|
||||
// When using flash, we install and use the ROM vector table to go thru regular bootrom/stage2 flash sequence
|
||||
// Debugger tried to run code after loading, so SSI is in 03h-only mode.
|
||||
// Go back through bootrom + boot2 to properly initialise flash.
|
||||
movs r0, #0
|
||||
#endif
|
||||
|
||||
__vector_entry:
|
||||
ldr r1, =(PPB_BASE + M0PLUS_CPUID_OFFSET)
|
||||
str r0, [r1, #8]
|
||||
ldr r1, =(PPB_BASE + M0PLUS_VTOR_OFFSET)
|
||||
str r0, [r1]
|
||||
ldmia r0!, {r1, r2}
|
||||
msr msp, r1
|
||||
bx r2
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Reset handler:
|
||||
// - initialises .data
|
||||
// - clears .bss
|
||||
@ -188,11 +209,12 @@ __vector_entry:
|
||||
.type _reset_handler,%function
|
||||
.thumb_func
|
||||
_reset_handler:
|
||||
// Hang all cores except core 0
|
||||
// Only core 0 should run the C runtime startup code; core 1 is normally
|
||||
// sleeping in the bootrom at this point but check to be sure
|
||||
ldr r0, =(SIO_BASE + SIO_CPUID_OFFSET)
|
||||
ldr r0, [r0]
|
||||
cmp r0, #0
|
||||
bne wait_for_vector
|
||||
bne hold_non_core0_in_bootrom
|
||||
|
||||
adr r4, data_cpy_table
|
||||
|
||||
@ -243,15 +265,6 @@ data_cpy:
|
||||
blo data_cpy_loop
|
||||
bx lr
|
||||
|
||||
#if !PICO_NO_BINARY_INFO
|
||||
binary_info_header:
|
||||
.word BINARY_INFO_MARKER_START
|
||||
.word __binary_info_start
|
||||
.word __binary_info_end
|
||||
.word data_cpy_table // we may need to decode pointers that are in RAM at runtime.
|
||||
.word BINARY_INFO_MARKER_END
|
||||
#endif
|
||||
|
||||
.align 2
|
||||
data_cpy_table:
|
||||
#if PICO_COPY_TO_RAM
|
||||
@ -284,11 +297,12 @@ runtime_init:
|
||||
bx lr
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// In case core 1's VTOR has already been moved into flash, we need to handle
|
||||
// core 1 reset. However, we do so by just jumping back into bootrom version of
|
||||
// wait_for_vector
|
||||
// If core 1 somehow gets into crt0 due to a spectacular VTOR mishap, we need to
|
||||
// catch it and send back to the sleep-and-launch code in the bootrom. Shouldn't
|
||||
// happen (it should sleep in the ROM until given an entry point via the
|
||||
// cross-core FIFOs) but it's good to be defensive.
|
||||
|
||||
wait_for_vector:
|
||||
hold_non_core0_in_bootrom:
|
||||
ldr r0, = 'W' | ('V' << 8)
|
||||
bl rom_func_lookup
|
||||
bx r0
|
||||
@ -312,4 +326,4 @@ __get_current_exception:
|
||||
.section .heap
|
||||
.align 2
|
||||
.equ HeapSize, PICO_HEAP_SIZE
|
||||
.space HeapSize
|
||||
.space HeapSize
|
||||
|
@ -59,12 +59,11 @@ SECTIONS
|
||||
*/
|
||||
|
||||
.text : {
|
||||
__reset_start = .;
|
||||
KEEP (*(.reset))
|
||||
. = ALIGN(256);
|
||||
__reset_end = .;
|
||||
ASSERT(__reset_end - __reset_start == 256, "ERROR: reset section should only be 256 bytes");
|
||||
__logical_binary_start = .;
|
||||
KEEP (*(.vectors))
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.reset))
|
||||
/* TODO revisit this now memset/memcpy/float in ROM */
|
||||
/* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
|
||||
* FLASH ... we will include any thing excluded here in .data below by default */
|
||||
@ -246,6 +245,8 @@ SECTIONS
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
|
||||
ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
||||
|
@ -59,12 +59,11 @@ SECTIONS
|
||||
*/
|
||||
|
||||
.flashtext : {
|
||||
__reset_start = .;
|
||||
KEEP (*(.reset))
|
||||
. = ALIGN(256);
|
||||
__reset_end = .;
|
||||
ASSERT(__reset_end - __reset_start == 256, "ERROR: reset section should only be 256 bytes");
|
||||
__logical_binary_start = .;
|
||||
KEEP (*(.vectors))
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.reset))
|
||||
}
|
||||
|
||||
.rodata : {
|
||||
@ -247,6 +246,8 @@ SECTIONS
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
|
||||
ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
||||
|
@ -59,12 +59,11 @@ SECTIONS
|
||||
*/
|
||||
|
||||
.text : {
|
||||
__reset_start = .;
|
||||
KEEP (*(.reset))
|
||||
. = ALIGN(256);
|
||||
__reset_end = .;
|
||||
ASSERT(__reset_end - __reset_start == 256, "ERROR: reset section should only be 256 bytes");
|
||||
__logical_binary_start = .;
|
||||
KEEP (*(.vectors))
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
KEEP (*(.reset))
|
||||
/* TODO revisit this now memset/memcpy/float in ROM */
|
||||
/* bit of a hack right now to exclude all floating point and time critical (e.g. memset, memcpy) code from
|
||||
* FLASH ... we will include any thing excluded here in .data below by default */
|
||||
@ -246,6 +245,8 @@ SECTIONS
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
|
||||
ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
||||
|
@ -32,19 +32,21 @@ ENTRY(_entry_point)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* Watchdog reboot into RAM (via USB MSD will enter) image at the start of .text
|
||||
The debugger will use the ELF entry point, which is the _entry_point
|
||||
symbol if present, otherwise defaults to start of .text.
|
||||
/* Note in NO_FLASH builds the entry point for both the bootrom, and debugger
|
||||
entry (ELF entry point), are *first* in the image, and the vector table
|
||||
follows immediately afterward. This is because the bootrom enters RAM
|
||||
binaries directly at their lowest address (preferring main RAM over XIP
|
||||
cache-as-SRAM if both are used).
|
||||
*/
|
||||
|
||||
.text : {
|
||||
__reset_start = .;
|
||||
__logical_binary_start = .;
|
||||
__reset_start = .;
|
||||
KEEP (*(.reset))
|
||||
/* reset should come first */
|
||||
KEEP (*(.reset))
|
||||
. = ALIGN(256);
|
||||
__reset_end = .;
|
||||
ASSERT(__reset_end - __reset_start == 256, "ERROR: reset section should only be 256 bytes");
|
||||
KEEP (*(.binary_info_header))
|
||||
__binary_info_header_end = .;
|
||||
. = ALIGN(256);
|
||||
KEEP (*(.vectors))
|
||||
*(.time_critical*)
|
||||
*(.text*)
|
||||
@ -208,6 +210,8 @@ SECTIONS
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed")
|
||||
|
||||
ASSERT( __binary_info_header_end - __logical_binary_start <= 256, "Binary info must be in first 256 bytes of the binary")
|
||||
/* todo assert on extra code */
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user