3

I'm contributing to a project that was developed in Coocox CoIDE 2.0.6 for STM32F103RB (128Kb flash). I have to write a custom boot loader using CoIDE that can upgrade the application to the flash via serial. I started writing the boot loader in .c, at the moment it creates some console messages then tries to jump to the application immediately. I'm using this example: https://embetronicx.com/tutorials/microcontrollers/stm32/stm32f1-bootloader/stm32f1-firmware-update-using-custom-bootloader/ As you might found out already, I'm having trouble jumping to the "main" application - it just hangs. I 'm obviously not an expert on the matter.

I created a custom .ld file to the main app:

{ 
  FLASH (rx) : ORIGIN = 0x08004400, LENGTH = 111K
  RAM (rwx) : ORIGIN = 0x200000EC, LENGTH = 20K - 0xEC
}

Also I added this to the main app code:

#define VECT_TAB_OFFSET 0x00004400U

I uploaded the bootloader to 0x08000000 and the main app to 0x08004400 via STLink.

If I look to the .bin file, I see at BASEADDRESS + 4U an address that seems correct: 0x08004ab5. If I'm right, the boot loader should read this entry point address from 0x08004404 and then jump to it. However, I can see in the console "Go to app^@^@" then nothing happens. I also have little clue how to effectively debug an STM32, I've been working with Arduinos before. Could you please guide me by reviewing the code? Thank you much!

main.c

#include "main.h"
#include <stdbool.h>
#include <stdio.h>

#define ETX_APP_START_ADDRESS   0x08004400
UART_HandleTypeDef huart2;

void SystemClock_Config(void);
static void MX_USART2_UART_Init(void);
static void goto_application( void );

int main(void){

  HAL_Init();
  SystemClock_Config();

  MX_USART2_UART_Init();

  printf("Flasher\r\n");
  printf("Go to app\r\n");
  goto_application();

  while (1){

  }
}

void SystemClock_Config(void){

  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

static void MX_USART2_UART_Init(void){
  // USART2 init
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 9600;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart2) != HAL_OK){
    Error_Handler();
  }

}



int fputc(int ch, FILE *f){
    HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
    return ch;
}


static void goto_application( void ){

    typedef void (*jump_app)(void) __attribute__((noreturn));

    uint32_t *_vectable = (__IO uint32_t*)ETX_APP_START_ADDRESS;  // point _vectable to the start of the application at 0x08004400
    HAL_DeInit();

    jump_app app_jump = (jump_app) *(_vectable + 1);   // get the address of the application's reset handler (4th byte in the table)
    SCB->VTOR = _vectable;
    __set_MSP(*_vectable);
    app_jump();

}

void Error_Handler(void){
  __disable_irq();
  while (1)
  {
  }
}

main.h

#ifndef __MAIN_H
#define __MAIN_H

#ifdef __cplusplus
extern "C" {
#endif

#include "stm32f1xx_hal.h"

void Error_Handler(void);

#ifdef __cplusplus
}
#endif

#endif /* __MAIN_H */

FYI I don't own the main app, I'm using a simple Blink example for that.

brhans
  • 14,373
  • 3
  • 34
  • 49
Otto
  • 31
  • 2
  • So, what did debugging the software tell you? – Justme Jun 21 '23 at 20:59
  • Do you have 'real' debugging tools which allow you to step through the code line-by-line, or are you still stuck in the 'just download it and let it run and see what happens' paradigm? – brhans Jun 22 '23 at 04:06
  • This is the biggest pain. It's a custom hardware (not a Bluepill development board) and I only have UART2 for debugging. I also have a header with SW_CLK, SW_IO, 3.3V and GND for upload. Is there any way to do debug using these pins? Sorry for my ignorance but I only started with this platform and there are quite a few restrictions. :( – Otto Jun 22 '23 at 15:23
  • 2
    `Is there any way to do debug using these pins?` Yes, that's a [SWD debug interface](https://wiki.segger.com/SWD) and it is supported by the ST-LINK probe (among many others). – nanash1 Jun 22 '23 at 15:46
  • Maybe we're getting somewhere. I've installed STM32CubeIDE instead of Coocox (despite I've been told not to do). Now the debug is not broken anymore. Just before app_jump() _vectable points to 0x8004400 (OK), its in 0x20005000 (I guess it's the stack so also OK) and app_jump points to 0x8004ab5 (also seems OK). When I click 'continue' nothing seems to happen, the debug runs but I can see nothing. I guess I should see some assembly output? – Otto Jun 22 '23 at 18:30

1 Answers1

0

I removed the fputc() function, the printf() calls and also the include to stdio.h. I also removed HAL_DeInit() and now the code works. I can still write to console using HAL_UART_Transmit() directly so that's not a problem. I can't explain why these changes made it work.

toolic
  • 5,637
  • 5
  • 20
  • 33
Otto
  • 31
  • 2