gpt4 book ai didi

c - STM32F405 的引导加载程序未跳转至应用程序

转载 作者:行者123 更新时间:2023-11-30 16:44:55 25 4
gpt4 key购买 nike

我有一个非常小的引导加载程序,位于主固件前面,该固件运行在基于 STM32F405VGT 芯片的定制设计板上。它对两个应用程序的startup.s 和链接器文件进行了相当少的修改。主应用程序在加载到闪 stub 目录时运行良好,但无法从引导加载程序启动。

单步执行代码时,一旦尝试启动应用程序,程序就会进入 WWDG_IRQHandler,它是 Default_Handler 的别名,并且只是在无限循环中旋转(对于引导加载程序禁用了 WWDG) .

引导加载程序代码:

    uint32_t addr = 0x08010000;

/* Get the application stack pointer (First entry in the application vector table) */
uint32_t appStack = (uint32_t) *((__IO uint32_t*) addr);

/* Get the application entry point (Second entry in the application vector table) */
ApplicationEntryPoint entryPoint = (ApplicationEntryPoint)*((__IO uint32_t*)(addr + sizeof(uint32_t)));

/* would expect the value of entryPoint to be 0x802bc9c based on the values in the .map file as well as the actual values downloaded from the image using openocd. Instead, it comes back as 0x802bc9d, not sure if this is related to THUMB code */

/* Reconfigure vector table offset register to match the application location */
SCB->VTOR = addr;

/* Set the application stack pointer */
__set_MSP(appStack);

/* Start the application */
entryPoint();

这是应用程序的 .ld 文件:

/* Include memory map */
/* Uncomment this section to use the real memory map */
MEMORY
{
BOOTLOADER (rx) : ORIGIN = 0x08000000, LENGTH = 32K
USER_PROPS (rw) : ORIGIN = 0x08008000, LENGTH = 16K
SYS_PROPS (r) : ORIGIN = 0x0800C000, LENGTH = 16K
APP_CODE (rx) : ORIGIN = 0x08010000, LENGTH = 448K
SWAP (rx) : ORIGIN = 0x08070000, LENGTH = 384K

RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
BOOT_RAM (xrw) : ORIGIN = 0x2001E000, LENGTH = 8K
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
}

/* Uncomment this section to load directly into root memory */
/*
MEMORY
{
APP_CODE (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
}
*/

/* Highest address of the user mode stack */
_estack = 0x20020000; /* end of 128K RAM */

/* Entry Point */
ENTRY(Reset_Handler)



/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x000; /* required amount of heap (none) */
_Min_Stack_Size = 0x400; /* required amount of stack */

SECTIONS
{


/* The startup code goes first into EEPROM */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >APP_CODE


/* The program code and other data goes into EEPROM */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame)

KEEP (*(.init))
KEEP (*(.fini))

. = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} >APP_CODE

/* Constant data goes into EEPROM */
.rodata :
{
. = ALIGN(4);
*(.rodata) /* .rodata sections (constants, strings, etc.) */
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
. = ALIGN(4);
} >APP_CODE

.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >APP_CODE
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >APP_CODE
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >APP_CODE


/* used by the startup to initialize data */
_sidata = LOADADDR(.data);

/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */

. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM AT> APP_CODE

/* Uninitialized data section */
. = ALIGN(4);
.bss :
{
/* This is used by the startup in order to initialize the .bss secion */
_sbss = .; /* define a global symbol at bss start */
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)

. = ALIGN(4);
_ebss = .; /* define a global symbol at bss end */
__bss_end__ = _ebss;
} >RAM

/* User_heap_stack section, used to check that there is enough RAM left */
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( end = . );
PROVIDE ( _end = . );
. = . + _Min_Heap_Size;
. = . + _Min_Stack_Size;
. = ALIGN(8);
} >RAM

/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}

.ARM.attributes 0 : { *(.ARM.attributes) }
}

引导加载程序 .ld 是相同的,只是所有对 APP_CODE 的引用都被替换为 BOOTLOADER

这是引导加载程序的startup.s 文件。应用程序的startup.s文件是相同的,除了Boot_Reset_Handler被称为Reset_Handler:

.syntax unified
.cpu cortex-m4
.fpu softvfp
.thumb

.global g_pfnVectors
.global Default_Handler

/* start address for the initialization values of the .data section.
defined in linker script */
.word _sidata
/* start address for the .data section. defined in linker script */
.word _sdata
/* end address for the .data section. defined in linker script */
.word _edata
/* start address for the .bss section. defined in linker script */
.word _sbss
/* end address for the .bss section. defined in linker script */
.word _ebss
/* stack used for SystemInit_ExtMemCtl; always internal RAM used */

/**
* @brief This is the code that gets called when the processor first
* starts execution following a reset event. Only the absolutely
* necessary set is performed, after which the application
* supplied main() routine is called.
* @param None
* @retval : None
*/

.section .text.Boot_Reset_Handler
.weak Boot_Reset_Handler
.type Boot_Reset_Handler, %function
Boot_Reset_Handler:
ldr sp, =_estack /* set stack pointer */

/* Copy the data segment initializers from flash to SRAM */
movs r1, #0
b LoopCopyDataInit

CopyDataInit:
ldr r3, =_sidata
ldr r3, [r3, r1]
str r3, [r0, r1]
adds r1, r1, #4

LoopCopyDataInit:
ldr r0, =_sdata
ldr r3, =_edata
adds r2, r0, r1
cmp r2, r3
bcc CopyDataInit
ldr r2, =_sbss
b LoopFillZerobss
/* Zero fill the bss segment. */
FillZerobss:
movs r3, #0
str r3, [r2], #4

LoopFillZerobss:
ldr r3, = _ebss
cmp r2, r3
bcc FillZerobss

/* Call the clock system intitialization function.*/
bl SystemInit
/* Call static constructors */
bl __libc_init_array
/* Call the application's entry point.*/
bl main
bx lr
.size Boot_Reset_Handler, .-Boot_Reset_Handler

/**
* @brief This is the code that gets called when the processor receives an
* unexpected interrupt. This simply enters an infinite loop, preserving
* the system state for examination by a debugger.
* @param None
* @retval None
*/
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop
.size Default_Handler, .-Default_Handler

.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors



g_pfnVectors:
.word _estack
.word Boot_Reset_Handler

.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word DebugMon_Handler
.word 0
.word PendSV_Handler
.word SysTick_Handler
...

我想指出,这不是 Bootloader for Cortex M4 - Jump to loaded Application 的重复,尽管问题看起来很相似,但该帖子的作者没有充分解释问题是如何解决的。

一切都是使用用于嵌入式开发的标准 gcc 工具构建的。

最佳答案

我在各种 STM32 Cortex-M3 和 M4 部件上使用了以下方法:

给定以下内联汇编函数:

__asm void boot_jump( uint32_t address )
{
LDR SP, [R0] ;Load new stack pointer address
LDR PC, [R0, #4] ;Load new program counter address
}

引导加载程序切换到应用程序镜像:

// Switch off core clock before switching vector table
SysTick->CTRL = 0 ;

// Switch off any other enabled interrupts too
...

// Switch vector table
SCB->VTOR = APPLICATION_START_ADDR ;

//Jump to start address
boot_jump( APPLICATION_START_ADDR ) ;

其中 APPLICATION_START_ADDR 是应用程序区域的基地址(示例中的 addr);该地址是应用程序 vector 表的开始,它以初始堆栈指针和复位 vector 开始,boot_jump()函数将它们加载到 SP 和 PC 寄存器中以启动应用程序,就像它已经启动一样已在重置时启动。应用程序的复位 vector 包含应用程序的执行起始地址。

此解决方案与您的解决方案之间的明显区别是在切换 vector 表之前禁用任何中断生成器。当然,您可能不会在引导加载程序中使用任何中断。

关于c - STM32F405 的引导加载程序未跳转至应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44315852/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com