Initial bootloader commit
This commit is contained in:
223
btl_main.c
Normal file
223
btl_main.c
Normal file
@@ -0,0 +1,223 @@
|
||||
/*********************************************************************
|
||||
* SEGGER Microcontroller GmbH *
|
||||
* The Embedded Experts *
|
||||
**********************************************************************
|
||||
|
||||
-------------------------- END-OF-HEADER -----------------------------
|
||||
|
||||
File : main.c
|
||||
Purpose : Generic application start
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "em_device.h"
|
||||
|
||||
/// Bare boot table. Can be mapped on top of vector table to access contents.
|
||||
typedef struct {
|
||||
/// Pointer to top of stack
|
||||
uint32_t *stackTop;
|
||||
/// Pointer to reset vector
|
||||
void (*resetVector)(void);
|
||||
/// Reserved pointers to fault handlers
|
||||
uint32_t reserved0[5];
|
||||
/// Reserved pointers to RESERVED fields
|
||||
uint32_t reserved1[3];
|
||||
/// Pointer to bootloader table
|
||||
void *table;
|
||||
/// Reserved pointers to SVC and DebugMon interrupts
|
||||
uint32_t reserved2[2];
|
||||
/// Pointer to application signature
|
||||
void *signature;
|
||||
} BareBootTable_t;
|
||||
|
||||
#define BTL_FIRST_STAGE_BASE FLASH_BASE
|
||||
#define BTL_APPLICATION_BASE (FLASH_BASE + 0x00006000UL)
|
||||
|
||||
|
||||
|
||||
|
||||
__attribute__ ((noreturn)) static void jumpToApplicationRoutine(uint32_t startOfAppSpace);
|
||||
//static void bootToApp(uint32_t startOfAppSpace);
|
||||
/*********************************************************************
|
||||
*
|
||||
* main()
|
||||
*
|
||||
* Function description
|
||||
* Application entry point.
|
||||
*/
|
||||
int btl_main(void) {
|
||||
|
||||
int i;
|
||||
|
||||
printf("Running the bootloader!\n");
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
printf("Hello World %d!\n", i);
|
||||
}
|
||||
|
||||
//TODO trigger reset
|
||||
|
||||
|
||||
do {
|
||||
i++;
|
||||
} while (1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Jump to app
|
||||
*/
|
||||
/*
|
||||
__attribute__ ((noreturn, naked)) static void bootToApp(uint32_t startOfAppSpace)
|
||||
{
|
||||
jumpToApplicationRoutine(startOfAppSpace);
|
||||
while (1) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
*/
|
||||
__attribute__ ((noreturn)) static inline void jumpToApplicationRoutine(uint32_t startOfAppSpace)
|
||||
{
|
||||
#if defined(BOOTLOADER_SECURE)
|
||||
|
||||
// Erase rw section
|
||||
__ASM volatile(
|
||||
"ldr r3,=0 \n"
|
||||
"mov r1, %[rwStart] \n" // Load start address
|
||||
"mov r2, %[rwEnd] \n" // Load end address
|
||||
#if defined(__GNUC__)
|
||||
"mov r4, %[bssStart] \n" // Load bss section start address
|
||||
"mov r5, %[bssEnd] \n" // Load bss section end address
|
||||
#endif
|
||||
"data_clean_up_loop: \n"
|
||||
"cmp r1, r2 \n" // Check if we have reached the end address
|
||||
"beq data_clean_up_finished \n"
|
||||
"str r3, [r1] \n" // Clear the RAM content pointed by R1
|
||||
"add r1, r1, #4 \n" // Increment by 4 to get to the next word address
|
||||
"b data_clean_up_loop \n"
|
||||
"data_clean_up_finished: \n"
|
||||
#if defined(__GNUC__)
|
||||
"bss_clean_up_loop: \n"
|
||||
"cmp r4, r5 \n" // Check if we have reached the end address
|
||||
"beq bss_clean_up_finished \n"
|
||||
"str r3, [r4] \n" // Clear the RAM content pointed by R4
|
||||
"add r4, r4, #4 \n" // Increment by 4 to get to the next word address
|
||||
"b bss_clean_up_loop \n"
|
||||
"bss_clean_up_finished: \n"
|
||||
#endif
|
||||
: //No outputs
|
||||
#if defined(__GNUC__)
|
||||
:[rwStart] "r" (&__data_start__), [rwEnd] "r" (&__data_end__), [bssStart] "r" (&__bss_start__), [bssEnd] "r" (&__bss_end__) //Inputs
|
||||
: "r1", "r2", "r3", "r4", "r5" //Clobbered registers
|
||||
);
|
||||
#else
|
||||
:[rwStart] "r" (&STACKSEAL$$Limit), [rwEnd] "r" (&HEAP$$Base) //Inputs
|
||||
: "r1", "r2", "r3" //Clobbered registers
|
||||
);
|
||||
#endif
|
||||
|
||||
#if defined(TEST_BOOTLOADER_RAM_CLEAN_UP)
|
||||
__ASM volatile(
|
||||
"mov r5, %[dataSection] \n" // Address of the last word in the rw section
|
||||
"mov r6, %[stackSection] \n" // Address of the last word in the stack section
|
||||
"mov r7, #0xFEEB \n" // Magic word stored at the end of data and stack sections
|
||||
"sub r5, r5, #4 \n"
|
||||
"sub r6, r6, #4 \n"
|
||||
"str r7, [r5] \n" // Store magic word at the end of data section
|
||||
"str r7, [r6] \n" // Store magic word at the end of stack section
|
||||
: //No outputs
|
||||
#if defined(__GNUC__)
|
||||
:[dataSection] "r" (&__bss_end__), [stackSection] "r" (&__StackTop) //Inputs
|
||||
: "r5", "r6", "r7", "r3" //Clobbered registers
|
||||
);
|
||||
#else
|
||||
:[dataSection] "r" (&HEAP$$Base), [stackSection] "r" (&CSTACK$$Limit) //Inputs
|
||||
: "r5", "r6", "r7", "r3" //Clobbered registers
|
||||
);
|
||||
#endif
|
||||
#endif // end of TEST_BOOTLOADER_RAM_CLEAN_UP
|
||||
|
||||
#endif // end of BOOTLOADER_SECURE
|
||||
|
||||
#if defined(BOOTLOADER_SECURE)
|
||||
// We should not leave any traces of the secure bootloader before jumping into the application
|
||||
// clean up entire RAM content except for the reset reason word
|
||||
__ASM volatile(
|
||||
"ldr r4,=0 \n"
|
||||
"mov r2, %[stackBase] \n" // Load start address
|
||||
"mov r3, %[stackTop] \n" // Load end address
|
||||
#if defined(TEST_BOOTLOADER_RAM_CLEAN_UP)
|
||||
"sub r3, r3, #4 \n" // Account for magic word at the top of stack section
|
||||
#endif
|
||||
"mov r1, %[ramBase] \n"
|
||||
"cmp r2, r1 \n" // Check if stack base is equal to SRAM_BASE
|
||||
"bne ram_clean_up_loop \n"
|
||||
"add r2, r2, #4 \n" // Increment by 4 to omit reset reason word in SRAM
|
||||
"ram_clean_up_loop: \n"
|
||||
"cmp r2, r3 \n" // Check if we have reached the end address
|
||||
"beq ram_clean_up_finished \n"
|
||||
"str r4, [r2] \n" // Clear the RAM content pointed by R2
|
||||
"add r2, r2, #4 \n" // Increment by 4 to get to the next word address
|
||||
"b ram_clean_up_loop \n"
|
||||
"ram_clean_up_finished: \n"
|
||||
#else
|
||||
// Load SP and PC of application
|
||||
__ASM volatile(
|
||||
#endif // BOOTLOADER_SECURE
|
||||
"mov r0, %[startOfAppSpace] \n" // Load address of SP into R0
|
||||
"ldr r1, [r0] \n" // Load SP into R1
|
||||
"msr msp, r1 \n" // Set MSP
|
||||
"msr psp, r1 \n" // Set PSP
|
||||
"ldr r0, [r0, #4] \n" // Load PC into R0
|
||||
"mov pc, r0 \n" // Set PC
|
||||
: // No outputs
|
||||
#if defined(BOOTLOADER_SECURE)
|
||||
#if defined(__GNUC__)
|
||||
:[startOfAppSpace] "r" (startOfAppSpace), [stackBase] "r" (&__StackLimit), [stackTop] "r" (&__StackTop), [ramBase] "r" (SRAM_BASE) // Inputs
|
||||
: "r0", "r1", "r2", "r3", "r4" // Clobbered registers
|
||||
);
|
||||
#else
|
||||
:[startOfAppSpace] "r" (startOfAppSpace), [stackBase] "r" (&CSTACK$$Base), [stackTop] "r" (&CSTACK$$Limit), [ramBase] "r" (SRAM_BASE)
|
||||
: "r0", "r1", "r2", "r3", "r4" // Clobbered registers
|
||||
);
|
||||
#endif // __GNUC__
|
||||
#else
|
||||
:[startOfAppSpace] "r" (startOfAppSpace) // Inputs
|
||||
: "r0", "r1" // Clobbered registers
|
||||
);
|
||||
#endif // BOOTLOADER_SECURE
|
||||
while (1) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************//**
|
||||
* @brief
|
||||
* Initialize the system.
|
||||
*
|
||||
* @details
|
||||
* Do required generic HW system init.
|
||||
*
|
||||
* @note
|
||||
* This function is invoked during system init, before the main() routine
|
||||
* and any data has been initialized. For this reason, it cannot do any
|
||||
* initialization of variables etc.
|
||||
*****************************************************************************/
|
||||
void btl_init(void)
|
||||
{
|
||||
BareBootTable_t* startOfAppSpace = (BareBootTable_t *)BTL_APPLICATION_BASE;
|
||||
|
||||
// does application exist
|
||||
uint32_t pc = *(uint32_t *)(startOfAppSpace + 4);
|
||||
if (pc == 0xFFFFFFFF) {
|
||||
printf("no data in application image!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
SCB->VTOR = (uint32_t)startOfAppSpace;
|
||||
|
||||
jumpToApplicationRoutine((uint32_t)startOfAppSpace);
|
||||
|
||||
}
|
||||
/*************************** End of file ****************************/
|
||||
Reference in New Issue
Block a user