STM32L4 bootloader no puede ingresar a la aplicación

0

He estado siguiendo la guía del gestor de arranque y tratando de escribir un cargador de arranque que simplemente enciende un LED cuando ingresa a performFirmwareUpdate () inducido por un botón. Estoy usando la herramienta ARM GNU en Ubuntu para compilar el código, usando srec_cat para combinar los archivos .hex de mi cargador de arranque y la aplicación, y los coloco en la pizarra usando stlink y el brazo gdb. Cuando actualizo el archivo hexadecimal, creo que van a los lugares correctos en la memoria debido a la salida que obtuve de gdb, mostrando las 2 secciones que se cargan en las ubicaciones de memoria especificadas en sus archivos de vinculador. Desafortunadamente, nunca se accede a la aplicación principal, incluso cuando no se presiona el pulsador. Adjuntaré las partes relevantes de los archivos del enlazador y el código principal aquí.

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.

    
pregunta akivjh

0 respuestas

Lea otras preguntas en las etiquetas