on 2025-12-16 7:01 AM
In the STM32H7 dual core series (STM32H745/755 and STM32H747/757), some resources are shared and must be initialized only once. This is notably the case for the clock tree. For this purpose, one core waits while the other performs the necessary common initialization.
By default, in the startup sequence generated by STM32CubeMX, the Cortex®-M4 waits in Stop mode while the Cortex®-M7 performs the common initialization.
However, this startup sequence can be adapted. For example, applications that never use low-power modes could avoid this Stop mode sequence.
This article first describes the default Stop mode sequence and then explains how to start with a busy-waiting core. The two cases are considered: either the Cortex®-M4 or the Cortex®-M7 is waiting.
Finally, particular attention is given to some common initializations executed during the system initialization in the system_init() function before the call to the main functions.
In the default startup sequence, the Cortex®-M4 waits in Stop mode. A hardware semaphore HSEM is used to generate the event that wakes up the CPU.
The code is as follows:
/* USER CODE BEGIN Boot_Mode_Sequence_1 */
/*HW semaphore Clock enable*/
__HAL_RCC_HSEM_CLK_ENABLE();
/* Activate HSEM notification for Cortex-M4*/
HAL_HSEM_ActivateNotification(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0));
/*
Domain D2 goes to STOP mode (Cortex-M4 in deep-sleep) waiting for Cortex-M7 to
perform system initialization (system clock config, external memory configuration.. )
*/
HAL_PWREx_ClearPendingEvent();
HAL_PWREx_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFE, PWR_D2_DOMAIN);
/* Clear HSEM flag */
__HAL_HSEM_CLEAR_FLAG(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0));
/* USER CODE END Boot_Mode_Sequence_1 */
The Cortex®-M4 enables the HSEM clock and activates the notifications. After this, the Domain 2 is put in Stop mode. The aim is clearly to stop the Domain 2 clock before initializing it to the values chosen for the application. At the same time, some other shared resources may also be initialized.
When the semaphore notification occurs, the Domain 2 clock is started again, and the Cortex®-M4 wakes up, clears the HSEM flag, and continue the execution of the code.
In parallel, the Cortex®-M7 executes the following code:
/* USER CODE BEGIN Boot_Mode_Sequence_1 */
/* Wait until CPU2 boots and enters in stop mode or timeout*/
timeout = 0xFFFF;
while((__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) != RESET) && (timeout-- > 0));
if ( timeout < 0 )
{
Error_Handler();
}
/* USER CODE END Boot_Mode_Sequence_1 */
/* 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 Boot_Mode_Sequence_2 */
/* When system initialization is finished, Cortex-M7 will release Cortex-M4 by means of
HSEM notification */
/*HW semaphore Clock enable*/
__HAL_RCC_HSEM_CLK_ENABLE();
/*Take HSEM */
HAL_HSEM_FastTake(HSEM_ID_0);
/*Release HSEM in order to notify the CPU2(CM4)*/
HAL_HSEM_Release(HSEM_ID_0,0);
/* wait until CPU2 wakes up from stop mode */
timeout = 0xFFFF;
while((__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) == RESET) && (timeout-- > 0));
if ( timeout < 0 )
{
Error_Handler();
}
/* USER CODE END Boot_Mode_Sequence_2 */
With some small modifications to the startup sequence code, the Cortex®-M4 stays in Run mode, waiting for the completion of the common initialization.
Since the startup sequence is included in a USER CODE BEGIN/USER CODE END section, STM32CubeMX does not regenerate this code if modifications to the configuration are made. Therefore, the changes are preserved.
The code is as follows:
/* USER CODE BEGIN Boot_Mode_Sequence_1 */
/*HW semaphore Clock enable*/
__HAL_RCC_HSEM_CLK_ENABLE();
/*
Wait that Cortex-M4 performs system initialization (system clock config, external memory configuration.. )
*/
while (!__HAL_HSEM_GET_FLAG(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0)));
/* Clear HSEM flag */
__HAL_HSEM_CLEAR_FLAG(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0));
/* USER CODE END Boot_Mode_Sequence_1 */
The Cortex®-M4 is in Run mode and is waiting for the HSEM to be released.
In this configuration, if the Cortex®-M7 has already started, the Cortex®-M4 does not loop but continues with the next instructions and runs its application.
In parallel, the Cortex®-M7 executes the following code:
/* USER CODE BEGIN Boot_Mode_Sequence_1 */
/* USER CODE END Boot_Mode_Sequence_1 */
/* 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 Boot_Mode_Sequence_2 */
/* When system initialization is finished, Cortex-M7 will release Cortex-M4 by means of
HSEM notification */
/*HW semaphore Clock enable*/
__HAL_RCC_HSEM_CLK_ENABLE();
/*Take HSEM */
HAL_HSEM_FastTake(HSEM_ID_0);
/*Release HSEM in order to notify the CPU2(CM4)*/
HAL_HSEM_Release(HSEM_ID_0,0);
/* USER CODE END Boot_Mode_Sequence_2 */
Here, there is no need to monitor the Domain 2 status, making the code simpler. The Cortex®-M7 directly initializes the clock tree and performs any other common configurations that might be added.
Afterwards, it takes and releases the semaphore. As a result, the Cortex®-M4 exits the while loop.
For some reason, you might want to do it the other way around and have the Cortex®-M7 wait in Run mode while the Cortex®-M4 performs the common initialization.
This means the Cortex®-M4 must at least initialize the clocks.
However, STM32CubeMX cannot generate this code for us. It is only aware of the default startup code described at the beginning of this article. As a result, it does not allow selecting which CPU is responsible for the clock tree initialization.
Nevertheless, a workaround can be applied, involving a mix of code generation and manual copy/paste operations.
In STM32CubeMX, the modification is shown in the picture below:
In "Project Manager" → "Advanced Settings", the SystemClock_Config function is always listed under the Cortex®-M7 section. The checkbox on the left indicates that the function code is generated in the Cortex®-M7 main.c file. No alternative is provided here.
However, it is possible to check the box on the right to prevent the function from being called.
At this point, no further action can be taken on the Cortex®-M4 side.
After code generation, the SystemClock_Config function is not called in the Cortex®-M7 main.c file, but still appears in the function prototypes:
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MPU_Config(void);
static void MX_GPIO_Init(void);
And the code is implemented:
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Supply configuration update enable
*/
HAL_PWREx_ConfigSupply(PWR_DIRECT_SMPS_SUPPLY);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI;
RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 4;
RCC_OscInitStruct.PLL.PLLN = 37;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = 2;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLFRACN = 4096;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
|RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
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;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
Here, the Cortex®-M7 waits for the completion of the common initialization. The code in the Sequence_1 section is exactly the same as it was previously for the Cortex®-M4.
/* USER CODE BEGIN Boot_Mode_Sequence_1 */
/*HW semaphore Clock enable*/
__HAL_RCC_HSEM_CLK_ENABLE();
/*
Wait that Cortex-M4 performs system initialization (system clock config, external memory configuration.. )
*/
while (!__HAL_HSEM_GET_FLAG(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0)));
/* Clear HSEM flag */
__HAL_HSEM_CLEAR_FLAG(__HAL_HSEM_SEMID_TO_MASK(HSEM_ID_0));
/* USER CODE END Boot_Mode_Sequence_1 */
As was previously the case for the Cortex®-M7, the Cortex®-M4 must now initialize the clock tree and perform other common configurations. Finally, it notifies the Cortex®-M7 through the semaphore.
The complete Cortex®-M4 startup sequence is now as shown below:
/* USER CODE BEGIN Boot_Mode_Sequence_1 */
/*HW semaphore Clock enable*/
__HAL_RCC_HSEM_CLK_ENABLE();
/* USER CODE END Boot_Mode_Sequence_1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* Configure the system clock */
SystemClock_Config();
/* When system initialization is finished, Cortex-M4 will release Cortex-M7 by means of
HSEM notification */
/*HW semaphore Clock enable*/
__HAL_RCC_HSEM_CLK_ENABLE();
/*Take HSEM */
HAL_HSEM_FastTake(HSEM_ID_0);
/*Release HSEM in order to notify the CPU2(CM4)*/
HAL_HSEM_Release(HSEM_ID_0,0);
/* USER CODE END Init */
The SystemClock_Config function has been manually added to the MCU configuration, at the beginning of the 'USER CODE BEGIN Init' section.
At this point, the prototype and the implementation of the SystemClock_Config function are missing and must be copied from the Cortex®-M7 main.c file.
The prototype is pasted in the 'Private function prototypes' section, between the comments 'USER CODE BEGIN PFP ' and 'USER CODE END PFP '.
/* Private function prototypes -----------------------------------------------*/
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */
void SystemClock_Config(void);
/* USER CODE END PFP */
The complete function implementation is pasted between comments 'USER CODE BEGIN ' and 'USER CODE END '. Section 4 is a suitable location for this.
/* USER CODE BEGIN 4 */
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Supply configuration update enable
*/
HAL_PWREx_ConfigSupply(PWR_DIRECT_SMPS_SUPPLY);
...
...
...
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE END 4 */
The startup sequence is now ready for both cores.
However, some common initializations are executed before this startup sequence during the system initialization. The next section describes the content of the SystemInit() function and how it is adapted to the startup behavior swap between the two MCU cores.
The SystemInit() function is implemented in Common\Src\system_stm32h7xx_dualcore_boot_cm4_cm7.c. It defines some default values common to both cores. Some parts of the function are executed by each CPU, while other parts are conditionally executed by either the Cortex®-M7 or the Cortex®-M4 only.
The default implementation shown below is suitable for the first two startup sequences described in section 1 and section 2 of this article. For the third sequence, where the Cortex®-M7 is busy-waiting (section 3), it is slightly modified.
void SystemInit (void)
{
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << (10*2))|(3UL << (11*2))); /* set CP10 and CP11 Full Access */
#endif
/*SEVONPEND enabled so that an interrupt coming from the CPU(n) interrupt signal is
detectable by the CPU after a WFI/WFE instruction.*/
SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
#if defined(CORE_CM7)
/* Reset the RCC clock configuration to the default reset state ------------*/
/* Increasing the CPU frequency */
if(FLASH_LATENCY_DEFAULT > (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
{
/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
}
/* Set HSION bit */
RCC->CR |= RCC_CR_HSION;
/* Reset CFGR register */
RCC->CFGR = 0x00000000;
/* Reset HSEON, HSECSSON, CSION, HSI48ON, CSIKERON, PLL1ON, PLL2ON and PLL3ON bits */
RCC->CR &= 0xEAF6ED7FU;
/* Decreasing the number of wait states because of lower CPU frequency */
if(FLASH_LATENCY_DEFAULT < (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
{
/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
}
/* Reset D1CFGR register */
RCC->D1CFGR = 0x00000000;
/* Reset D2CFGR register */
RCC->D2CFGR = 0x00000000;
/* Reset D3CFGR register */
RCC->D3CFGR = 0x00000000;
/* Reset PLLCKSELR register */
RCC->PLLCKSELR = 0x02020200;
/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x01FF0000;
/* Reset PLL1DIVR register */
RCC->PLL1DIVR = 0x01010280;
/* Reset PLL1FRACR register */
RCC->PLL1FRACR = 0x00000000;
/* Reset PLL2DIVR register */
RCC->PLL2DIVR = 0x01010280;
/* Reset PLL2FRACR register */
RCC->PLL2FRACR = 0x00000000;
/* Reset PLL3DIVR register */
RCC->PLL3DIVR = 0x01010280;
/* Reset PLL3FRACR register */
RCC->PLL3FRACR = 0x00000000;
/* Reset HSEBYP bit */
RCC->CR &= 0xFFFBFFFFU;
/* Disable all interrupts */
RCC->CIER = 0x00000000;
/* Enable CortexM7 HSEM EXTI line (line 78)*/
EXTI_D2->EMR3 |= 0x4000UL;
if((DBGMCU->IDCODE & 0xFFFF0000U) < 0x20000000U)
{
/* if stm32h7 revY*/
/* Change the switch matrix read issuing capability to 1 for the AXI SRAM target (Target 7) */
*((__IO uint32_t*)0x51008108) = 0x000000001U;
}
#endif /* CORE_CM7*/
#if defined(CORE_CM4)
/* Configure the Vector Table location add offset address for cortex-M4 ------------------*/
#if defined(USER_VECT_TAB_ADDRESS)
SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D2 AXI-RAM or in Internal FLASH */
#endif /* USER_VECT_TAB_ADDRESS */
#elif defined(CORE_CM7)
/*
* Disable the FMC bank1 (enabled after reset).
* This, prevents CPU speculation access on this bank which blocks the use of FMC during
* 24us. During this time the others FMC master (such as LTDC) cannot use it!
*/
FMC_Bank1_R->BTCR[0] = 0x000030D2;
/* Configure the Vector Table location -------------------------------------*/
#if defined(USER_VECT_TAB_ADDRESS)
SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D1 AXI-RAM or in Internal FLASH */
#endif /* USER_VECT_TAB_ADDRESS */
#else
#error Please #define CORE_CM4 or CORE_CM7
#endif /* CORE_CM4 */
}
Particular attention is given to some parts that depend on the startup sequence.
Two lines concern the waking up of the Cortex®-M4 during the default startup sequence described in section 1 of this article. They illustrate the two ways in which the wakeup event can be generated, as described in the Exiting from low-power modes section of the Reference Manual.
1. By setting the SEVONPEND bit in the system control register of the Cortex®-M CPU. Enabled events and all interrupts, including disabled interrupts, can wakeup the CPU, either Cortex®-M4 or Cortex®-M7 since this line is executed by both cores.
/*SEVONPEND enabled so that an interrupt coming from the CPU(n) interrupt signal is
detectable by the CPU after a WFI/WFE instruction.*/
SCB->SCR |= SCB_SCR_SEVONPEND_Msk;
A detailed description is given in the programming manuals PM0253 and PM0214.
2. By configuring an external or internal EXTI line in event mode, which involves unmasking the event input by setting the corresponding bit in the EXTI_CnEMR event mask register.
/* Enable CortexM7 HSEM EXTI line (line 78)*/
EXTI_D2->EMR3 |= 0x4000UL;
In the current case, the event is triggered by the hardware semaphore HSEM to the Cortex®-M4 (CPU2). The corresponding EXTI line number is 78 as shown in the Reference Manual.
The EXTI line 78 event is unmasked in the EXTI_C2EMR3, which is event mask register 3 of CPU2.
These two lines are only used in the default case where the Cortex®-M4 waits in Stop mode (section 1), and only one of these instructions should be necessary.
The biggest part of the SystemInit() function is dedicated to resetting the clock tree configuration to its default state. The execution is conditionally performed by the Cortex®-M7.
#if defined(CORE_CM7)
/* Reset the RCC clock configuration to the default reset state ------------*/
In the case where the Cortex®-M7 is busy-waiting (section 3 of this article), the Cortex®-M4 takes charge of resetting the clock tree. The condition is changed to:
#if defined(CORE_CM4)
/* Reset the RCC clock configuration to the default reset state ------------*/
Moreover, no wakeup event is necessary.
In the end, for the case where the Cortex®-M7 is busy-waiting, the complete SystemInit() function is shown below:
void SystemInit (void)
{
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << (10*2))|(3UL << (11*2))); /* set CP10 and CP11 Full Access */
#endif
#if defined(CORE_CM4)
/* Reset the RCC clock configuration to the default reset state ------------*/
/* Increasing the CPU frequency */
if(FLASH_LATENCY_DEFAULT > (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
{
/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
}
/* Set HSION bit */
RCC->CR |= RCC_CR_HSION;
/* Reset CFGR register */
RCC->CFGR = 0x00000000;
/* Reset HSEON, HSECSSON, CSION, HSI48ON, CSIKERON, PLL1ON, PLL2ON and PLL3ON bits */
RCC->CR &= 0xEAF6ED7FU;
/* Decreasing the number of wait states because of lower CPU frequency */
if(FLASH_LATENCY_DEFAULT < (READ_BIT((FLASH->ACR), FLASH_ACR_LATENCY)))
{
/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
MODIFY_REG(FLASH->ACR, FLASH_ACR_LATENCY, (uint32_t)(FLASH_LATENCY_DEFAULT));
}
/* Reset D1CFGR register */
RCC->D1CFGR = 0x00000000;
/* Reset D2CFGR register */
RCC->D2CFGR = 0x00000000;
/* Reset D3CFGR register */
RCC->D3CFGR = 0x00000000;
/* Reset PLLCKSELR register */
RCC->PLLCKSELR = 0x02020200;
/* Reset PLLCFGR register */
RCC->PLLCFGR = 0x01FF0000;
/* Reset PLL1DIVR register */
RCC->PLL1DIVR = 0x01010280;
/* Reset PLL1FRACR register */
RCC->PLL1FRACR = 0x00000000;
/* Reset PLL2DIVR register */
RCC->PLL2DIVR = 0x01010280;
/* Reset PLL2FRACR register */
RCC->PLL2FRACR = 0x00000000;
/* Reset PLL3DIVR register */
RCC->PLL3DIVR = 0x01010280;
/* Reset PLL3FRACR register */
RCC->PLL3FRACR = 0x00000000;
/* Reset HSEBYP bit */
RCC->CR &= 0xFFFBFFFFU;
/* Disable all interrupts */
RCC->CIER = 0x00000000;
#endif /* CORE_CM4*/
#if defined(CORE_CM4)
/* Configure the Vector Table location add offset address for cortex-M4 ------------------*/
#if defined(USER_VECT_TAB_ADDRESS)
SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D2 AXI-RAM or in Internal FLASH */
#endif /* USER_VECT_TAB_ADDRESS */
#elif defined(CORE_CM7)
if((DBGMCU->IDCODE & 0xFFFF0000U) < 0x20000000U)
{
/* if stm32h7 revY*/
/* Change the switch matrix read issuing capability to 1 for the AXI SRAM target (Target 7) */
*((__IO uint32_t*)0x51008108) = 0x000000001U;
}
/*
* Disable the FMC bank1 (enabled after reset).
* This, prevents CPU speculation access on this bank which blocks the use of FMC during
* 24us. During this time the others FMC master (such as LTDC) cannot use it!
*/
FMC_Bank1_R->BTCR[0] = 0x000030D2;
/* Configure the Vector Table location -------------------------------------*/
#if defined(USER_VECT_TAB_ADDRESS)
SCB->VTOR = VECT_TAB_BASE_ADDRESS | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal D1 AXI-RAM or in Internal FLASH */
#endif /* USER_VECT_TAB_ADDRESS */
#else
#error Please #define CORE_CM4 or CORE_CM7
#endif /* CORE_CM4 */
}
An application that never uses low-power modes could avoid the default Stop mode sequence. It could start with a busy-waiting core, which can be either the Cortex®-M4 or the Cortex®-M7.
Both the startup sequence and the SystemInit() function should be adapted accordingly.
Other templates are provided in the STM32H7 software package under STM32Cube\Repository\STM32Cube_FW_H7_Vx.y.z\Projects\[Board Name]\Templates. The board name is either NUCLEO-H745ZI-Q, STM32H745I-DISCO, STM32H747I-DISCO or STM32H747I-EVAL.