cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H750IBT6 Bootloader Problem

MKoca.1
Senior

Hello everyone. I am trying to write a bootloader with STM32H750IBT6 and mt25ql512. I am trying to adapt the ExtMem_Boot example of STM32H750-DK to STM32H750IBT6 by modifying it, but I can't succeed. It doesn't make sense why STM32H750IBT6 does not work. In the software;

JumpToApplication = (pFunction) (*(__IO uint32_t*) (APPLICATION_ADDRESS + 4));
__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
JumpToApplication();


but JumpToApplication(); enters HardFault and I get SCB->CFSR = 1025. Whatever I did, I was not successful. Attached I share the bootloader and application projects.

MKoca1_0-1729669938505.png

 

typedef void (*pFunction)(void);

pFunction JumpToApplication;

int main(void)

{



/* USER CODE BEGIN 1 */

CPU_CACHE_Enable();

/* USER CODE END 1 */



/* MPU Configuration--------------------------------------------------------*/

MPU_Config();



/* MCU Configuration--------------------------------------------------------*/



/* Reset of all peripherals, Initializes the Flash interface and the Systick. */

HAL_Init();



/* USER CODE BEGIN Init */



/* USER CODE END Init */



/* Configure the system clock */

SystemClock_Config();



/* USER CODE BEGIN SysInit */



/* USER CODE END SysInit */



/* Initialize all configured peripherals */

MX_GPIO_Init();

/* USER CODE BEGIN 2 */

if(Memory_Startup() != MEMORY_OK)

{

Error_Handler();

}



CPU_CACHE_Disable();

/* Disable Systick interrupt */

SysTick->CTRL = 0;



JumpToApplication = (pFunction) (*(__IO uint32_t*) (APPLICATION_ADDRESS + 4));

__set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);

JumpToApplication();

/* USER CODE END 2 */



/* Infinite loop */

/* USER CODE BEGIN WHILE */

while (1)

{

/* USER CODE END WHILE */



/* USER CODE BEGIN 3 */

}

/* USER CODE END 3 */

}
8 REPLIES 8
Imen.D
ST Employee

Hello @MKoca.1 ,

Did you try to follow the steps and tips in this article How to jump to system bootloader from application ... - STMicroelectronics Community ?

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen

Personally I'd skip the setting of MSP, do a "LDR SP" over in the app code's Reset_Handler

Check the values in the Initial SP, PC vectors, say that (PC & 0xF0000001) == 0x90000001

Print out the values for diagnostic/telemetry purposes.

Set the SCB->VTOR in SystemInit(), ideally based off a symbol for the Vector Table the linker provides AS-BUILT

Would recommend getting UART output via STDIO (printf, puts, etc) and a viable HardFault_Handler() to report situation quickly/effectively.

https://github.com/cturvey/RandomNinjaChef/blob/main/KeilHardFault.c

 

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
cleonb322
Associate III

Before jumping to the main application, make sure you DeInit all the clocks, peripherals, and interrupts you used in the bootloader. 

 

in my case: 

HAL_SD_MspDeInit(&hsd1);

__HAL_RCC_TIM1_CLK_DISABLE();

 

HAL_RCC_DeInit();

HAL_DeInit();

Yeah, you might want to tread carefully there with external memory and clocks.

The trick really is not to have to revisit the clock and external memory and pins a second time.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
MKoca.1
Senior

@Imen.D @cleonb322 @Tesla DeLorean  

Thank you very much for your valuable comments. I have tried every method for 1 week. The processor is acting like an ***, no matter what you try, there is no change. In the STM32H750B-DK kit, in the ExtMem-Boot example, it can jump to the 0x90000000 address of the MT25QL512 flash without changing anything. But I can't jump to the 0x90000000 address with the STM32H750IBT6 and MT25QL512 flash, I'm really going crazy. Please help me with this, I really lost a lot of time.

 

MKoca1_0-1729749486254.pngMKoca1_1-1729749542631.png

 

cleonb322
Associate III

if your binary is small enough, try jumping to an internal address for testing. maybe your MT25QL512  isn't configured correctly and don't forget to setup the MPU region for the external Flash.

Perhaps it's NOT a software issue?

If it works well on the reference platform, you need to look at the design and the placed components more critically.

Clocking is likely different. For reliable MCU function the power supply and VCAP/LDO performance is important. Are thing more stable when you leave it run from the 64 MHz HSI clock? Does it fail in the same way, and every time you power up?

Validate the content of the External Flash, use say CRC or SHA256/MD5 and validate the content is reliably readable

Initial board bring-up can be a quite daunting and difficult task.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
MKoca.1
Senior

Hello everyone. Thank you very much for your answers, dear authorities.
If I make the bootloader system clock 64 MHz HSI or 400MHz HSE with QSPIHandle.Init.ClockPrescaler = 10, the QSPI configuration is completed without errors. I made some changes in my main, and this time I get stuck at 0xa759000 and the system shuts down. Also, in bootloader debug state, I can read address 0x90000000, but I can't read external memory (0x900000000) in CubeProgrammer. I use "CLIVEONE-MT25QL512A_STM32H7XX-PB2-PB10-PF8-PF9-PE2-PD13.stldr" as external loader. I shared the code and images related to the events below.

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "memory.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
typedef  void (*pFunction)(void);
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

QSPI_HandleTypeDef hqspi;

/* USER CODE BEGIN PV */
pFunction JumpToApplication;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MPU_Config(void);
static void MX_GPIO_Init(void);
static void MX_QUADSPI_Init(void);
/* USER CODE BEGIN PFP */
static void CPU_CACHE_Enable(void);
static void CPU_CACHE_Disable(void);
static void MPU_Config (void);
static uint32_t Memory_Startup(void);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */
	  CPU_CACHE_Enable();
  /* USER CODE END 1 */

  /* MPU Configuration--------------------------------------------------------*/
  MPU_Config();

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */
  if(Memory_Startup() != MEMORY_OK)
  {
    Error_Handler();
  }

  CPU_CACHE_Disable();

  HAL_RCC_DeInit();

  for(int i = 0; i < 8; i++){
	  NVIC->ICER[i] = 0xFFFFFFFF;
	  __DSB();
	  __ISB();
  }

  SysTick->CTRL = 0;



  JumpToApplication = (pFunction) (*(__IO uint32_t*) (APPLICATION_ADDRESS + 4));
  __set_MSP(*(__IO uint32_t*) APPLICATION_ADDRESS);
  SCB->VTOR = APPLICATION_ADDRESS;
  JumpToApplication();
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
//  MX_GPIO_Init();
//  MX_QUADSPI_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
	  RCC_ClkInitTypeDef RCC_ClkInitStruct;
	  RCC_OscInitTypeDef RCC_OscInitStruct;
	  HAL_StatusTypeDef ret = HAL_OK;

	  /*!< Supply configuration update enable */
	   HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY); /* PWR set to LDO for the STM32H750B-DISCO board */

	  /* The voltage scaling allows optimizing the power consumption when the device is
	     clocked below the maximum system frequency, to update the voltage scaling value
	     regarding system frequency refer to product datasheet.  */
	  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

	  while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

	  /* Enable HSE Oscillator and activate PLL with HSE as source */
	  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
	  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
	  RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
	  RCC_OscInitStruct.CSIState = RCC_CSI_OFF;
	  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
	  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

	  RCC_OscInitStruct.PLL.PLLM = 5;
	  RCC_OscInitStruct.PLL.PLLN = 160;
	  RCC_OscInitStruct.PLL.PLLFRACN = 0;
	  RCC_OscInitStruct.PLL.PLLP = 2;
	  RCC_OscInitStruct.PLL.PLLR = 2;
	  RCC_OscInitStruct.PLL.PLLQ = 4;

	  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
	  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_2;
	  ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
	  if(ret != HAL_OK)
	  {
	    Error_Handler();
	  }

	  /* Select PLL as system clock source and configure  bus clocks dividers */
	  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_D1PCLK1 | RCC_CLOCKTYPE_PCLK1 | \
	                                 RCC_CLOCKTYPE_PCLK2  | RCC_CLOCKTYPE_D3PCLK1);

	  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
	  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
	  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
	  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
	  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
	  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
	  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
	  ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4);
	  if(ret != HAL_OK)
	  {
	    Error_Handler();
	  }
}

/**
  * @brief QUADSPI Initialization Function
  * @PAram None
  * @retval None
  */
static void MX_QUADSPI_Init(void)
{

  /* USER CODE BEGIN QUADSPI_Init 0 */

  /* USER CODE END QUADSPI_Init 0 */

  /* USER CODE BEGIN QUADSPI_Init 1 */

  /* USER CODE END QUADSPI_Init 1 */
  /* QUADSPI parameter configuration*/
  hqspi.Instance = QUADSPI;
  hqspi.Init.ClockPrescaler = 255;
  hqspi.Init.FifoThreshold = 1;
  hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
  hqspi.Init.FlashSize = 1;
  hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE;
  hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
  hqspi.Init.FlashID = QSPI_FLASH_ID_1;
  hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
  if (HAL_QSPI_Init(&hqspi) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN QUADSPI_Init 2 */

  /* USER CODE END QUADSPI_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @PAram None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOE_CLK_ENABLE();
  __HAL_RCC_GPIOF_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */
uint32_t Memory_Startup(void)
{
  uint32_t status = HAL_OK;

  /* Volatile Memory Configuration */
#if (DATA_AREA == USE_EXTERNAL_SDRAM) || (CODE_AREA == USE_EXTERNAL_SDRAM)
  status |= SDRAM_Startup();
#endif

  /* Non-Volatile Memory Configuration */
#if (CODE_AREA == USE_QSPI) || (BINARY_AREA == USE_SPI_NOR)
  status |= QSPI_Startup(QSPI_MODE);
#endif

  #if (BINARY_AREA == USE_MMC)
  status |= MMC_Startup();
#endif

  return status;
}

static void CPU_CACHE_Enable(void)
{
  /* Enable I-Cache */
  SCB_EnableICache();

  /* Enable D-Cache */
  SCB_EnableDCache();
}

/**
  * @brief  CPU L1-Cache disable.
  * @PAram  None
  * @retval None
  */
static void CPU_CACHE_Disable(void)
{
  /* Disable I-Cache */
  SCB_DisableICache();

  /* Disable D-Cache */
  SCB_DisableDCache();
}
/* USER CODE END 4 */

 /* MPU Configuration */

void MPU_Config(void)
{
  MPU_Region_InitTypeDef MPU_InitStruct = {0};

  /* Disables the MPU */
  HAL_MPU_Disable();

  /** Initializes and configures the Region and the memory to be protected
  */
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  MPU_InitStruct.Number = MPU_REGION_NUMBER0;
  MPU_InitStruct.BaseAddress = 0x0;
  MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
  MPU_InitStruct.SubRegionDisable = 0x87;
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
  MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
  MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

  HAL_MPU_ConfigRegion(&MPU_InitStruct);

  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  MPU_InitStruct.BaseAddress = 0x90000000;
  MPU_InitStruct.Size = MPU_REGION_SIZE_64MB;
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
  MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
  MPU_InitStruct.Number = MPU_REGION_NUMBER2;
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
  MPU_InitStruct.SubRegionDisable = 0x0;
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

  HAL_MPU_ConfigRegion(&MPU_InitStruct);
  /* Enables the MPU */
  HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

}

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @PAram  file: pointer to the source file name
  * @PAram  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 

MKoca1_0-1729808313804.png

MKoca1_1-1729808372050.png

MKoca1_2-1729808553252.png

MKoca1_3-1729808628294.png