enlazador del cargador de arranque:
/* Entry Point */
ENTRY(Boot_Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20017FFF; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;; /* required amount of heap */
_Min_Stack_Size = 0x400;; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 48K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
}
Enlace de aplicación:
/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20017FFF; /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;; /* required amount of heap */
_Min_Stack_Size = 0x400;; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
FLASH (rx) : ORIGIN = 0x0800C000, LENGTH = 976K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K
}
Bootloader main.c:
#include "stm32l4xx_hal.h"
#define APPLICATION_ADDRESS 0x0800C000
typedef void (*pFunction)(void);
uint32_t checkFirmwareUpdate();
uint32_t performFirmwareUpdate();
void System_Clock_Init(void);
void GPIO_Init(void);
void GPIO_DeInit(void);
int boot_main(void)
{
// initialize hardware
HAL_Init();
System_Clock_Init();
GPIO_Init();
/* Check if a firmware update is required */
if (checkFirmwareUpdate()) {
/* Perform the update */
performFirmwareUpdate();
}
// de-init gpio
GPIO_DeInit();
pFunction appEntry;
uint32_t appStack;
/* Get the application stack pointer (First entry in the application vector table) */
appStack = (uint32_t) *((__IO uint32_t*)APPLICATION_ADDRESS);
/* Get the application entry point (Second entry in the application vector table) */
appEntry = (pFunction) *(__IO uint32_t*) (APPLICATION_ADDRESS + 4);
/* Reconfigure vector table offset register to watch the application bootloader */
SCB->VTOR = APPLICATION_ADDRESS;
/* Set the application stack pointer */
__set_MSP(appStack);
appEntry();
/* Infinite loop */
while (1);
}
uint32_t checkFirmwareUpdate(){
// hold down middle joystick button
//return (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0));
if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0)){ return 1; }
else { return 0; }
}
uint32_t performFirmwareUpdate(){
// turn on green LED
//HAL_GPIO_WritePin(GPIOE, GPIO_PIN_8, GPIO_PIN_SET);
GPIOE->ODR |= (1 << 8);
HAL_Delay(500);
return 0;
}
main.c de aplicación:
#include "stm32l4xx.h"
#include "core_cm4.h"
#define LED_PIN 2
#define LED_TOGGLE() GPIOB->ODR ^= (1 << 2)
#define LED_ON() GPIOB->ODR |= (1 << 2);
#define LED_OFF() GPIOB->ODR &= ~(1 << 2);
volatile int32_t TimeDelay;
void SysTick_Handler (void);
void Delay (uint32_t nTime);
int main() {
// Enable the clock to GPIO Port B
RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;
// MODE: 00: Input mode, 01: General purpose output mode
// 10: Alternate function mode, 11: Analog mode (reset state)
GPIOB->MODER &= ~(0x03<<(2*2)) ; // Clear bit 13 and bit 12
GPIOB->MODER |= (1<<4);
// select push-pull output
GPIOB->OTYPER &= ~(1<<2);
/* Turn on the LED */
SysTick_Config(10000); //10 ms reload period
// toggle LED
while(1) {
LED_TOGGLE();
Delay(100); // wait 1000 ms
};
}
void SysTick_Handler (void) {
if (TimeDelay > 0)
TimeDelay--;
}
void Delay (uint32_t nTime) {
TimeDelay = nTime; // nTime specifies the delay time length
while(TimeDelay != 0); // busy wait
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{
/* infinite loop */
/* use gdb to find out why we're here */
while (1);
}
#endif
Interesantemente, cuando ejecuto una combinación regular srec_cat ( srec_cat boot.hex -Intel app.hex -Intel -O merge.hex -Intel
) recibo algunas advertencias de "valor 0x08000000 redundante (0xFF)", con advertencias adicionales en las direcciones 0x08000001-0x08000003. Luego, la combinación falla cuando obtengo un "valor 0x08000004 contradictorio (anterior = 0x39, este = 0x7D)".
Para superar esto, agrego un desplazamiento al hex de aplicación de 0x0000C000 ( srec_cat boot.hex -Intel app.hex -Intel -offset 0x0000C00 -Output_Block_Size=16 -O merge.hex -Intel
)
Al final del día, el código de mi cargador de arranque funciona cuando ingresa performFirmwareUpdate()
cuando sostengo el botón pulsador en el arranque, pero nunca ingresa a la aplicación ya que no hay LED parpadeando. La aplicación funciona sin el gestor de arranque, por lo que he verificado que el código funciona.
Si puedo aclarar cualquier cosa o incluir cualquier otra cosa, hágamelo saber.