Hi all,
I'm working on an STM32G491 processor, and one of our requirements is to have a UART bootloader. No biggie, the controller has a UART (and several other) bootloaders in the system memory. In the past I've used it with USB and DFU and it works alright.
The development environment is the usual STM32CubeIDE with initialising over CubeMX. I'm using FreeRTOS as well, but I was able to jump into bootloader mode by using this code (reference only):
#include "bootload.h"
const uint8_t bootload_cmd[5] = BOOTLOAD_COMMAND;
void (*JumpToApplication)(void);
void bootload_enable(void)
{
/* Disable LPUART1 */
HAL_UART_DeInit(&hlpuart1);
HAL_UART_DeInit(&huart1);
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_2|GPIO_PIN_3);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_3;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* Send system to sleep */
vTaskSuspendAll();
vPortRaiseBASEPRI();
/* Disable all interrupts */
__disable_irq();
/* Disable Systick timer */
SysTick->CTRL = 0;
/* Clear Interrupt Enable Register & Interrupt Pending Register */
for (uint32_t i = 0; i < 8; i++)
{
NVIC->ICER[i]=0xFFFFFFFF;
NVIC->ICPR[i]=0xFFFFFFFF;
}
/* Re-enable all interrupts */
__enable_irq();
/* Set the main stack pointer to the boot loader stack */
__set_MSP(*(uint32_t *)BOOTLOADER_ADDRESS);
/* Jump to system memory bootloader */
JumpToApplication = (void (*)(void)) (*((uint32_t *) ((BOOTLOADER_ADDRESS + 4))));
JumpToApplication();
while(1);
}
Anyway, the code works.
A few days later I decided I want to switch to VSCode for coding, compiling and flashing. I followed a few instructions online and it's not as hard as it seems. CubeMX generates a Makefile of the project, what could possibly go wrong?
Well, I had to adapt most of the flags between what the IDE was doing and what the makefile was telling the compiler. I "think" I managed most of it, but to be fair I might have missed the odd flag here or there. So or so, after a few trial and error I was able to run my application OK. Everything worked as expected, and compilation, flashing, etc worked well.
At some point I tested again the "enter bootloader" mode, but that failed miserably. After a lot of testing and some debugging later I found out that the micro went into HardFault mode, and it happened just by trying to enter the "JumpToApplication()" address. The complaint was a BusFault error (I think, I don't have the code open anymore).
I went back to compile with the IDE, and lo and behold, it all works fine again. So for the time being I'm coding in VS code and using a 1.7GB IDE to click the compile and flash buttons
I'm guessing that I'm missing some flag, option or something that tells the micro to allow jumping to that address, but from what I've looked (not extensively) I cannot find the difference between the Makefile flags and the IDE flags. At some point I even copied them verbatim. I might have missed the assembler flags. As additional information, I'm using the arm-none-eabi-gcc binaries that are part of the IDE (plugin.blablabla.stmarm....) and I am flashing using the ST-Link V2. For flashing with the makefile I used:
flash:
STM32_Programmer_CLI -c port=SWD freq=4000 -w $(BUILD_DIR)\$(TARGET).elf
Have you guys had issues with that before? Any information where I should be looking at is appreciated. It's not a dealbreaker fortunately, more like an annoyance...
Cheers,
Alberto