当我跳转到应用程序时中断不起作用(STM32)
Interrupts Not Working When I Jump to Application (STM32)
更新:也许更好的问题是我应该如何调试这个问题?我正在使用 VS Code 和 OpenOCD 调试器。我总是清理构建。 JumpToApplication() 后我能做的最好的事情就是查看当我 pause/step 进入时调试器停止的地址。
我能够将程序闪存到分区 A (@address 0x8060000) 并使用 CRC 检查对其进行验证。该程序在 while 循环中运行任何东西(LED3 切换,UART);然而,基于定时器中断的 LED2 切换不起作用。当我正常刷新程序时(即不使用我的引导加载程序)它可以 100% 工作,包括 LED2 切换。
以下是我处理过的一些资源 (1, 2, 3, AN2606)。我如何让中断为我的第二个应用程序工作?资源建议我清除挂起的中断,但我不知道解决该问题的最佳方法。在我的引导加载程序应用程序中,我使用了 ETH、UART 和 GPIO 外围设备,因此我将阅读手册并读取寄存器以清除中断标志,但是其他中断(如 NMI、HardFault)呢,我是否必须弄清楚如何清除它们出色地?通过我的 Google 搜索,我没有找到任何方便的函数来清除所有挂起的中断,是否存在?
下面我包含了 0x8000000 处的引导加载程序应用程序的跳转 function/linker 文件和 0x8060000 处的应用程序的 main.c/linker 文件:
引导加载程序中的跳转函数位于 0x8000000
void ApplicationManager::RunActivePartition()
{
JumpToApplication = (void (*)(void)) (*((uint32_t *) (active_partition.address + 4)));
/* Set vector table offset register */
SetVectorTable(MemoryInfo::BTLR_ADDRESS, MemoryInfo::PARTITION_A_OFFSET_FROM_BTLR);
/* STM32 needs the stack pointer to start at the beginning of
** the application in flash. This must happen last */
__set_MSP(*(__IO uint32_t*) active_partition.address);
JumpToApplication();
/*************** Other things I have tried ***************/
/* Reset RCC clock configuration */
// HAL_RCC_DeInit();
/* Disable peripheral clocks */
// __HAL_RCC_GPIOA_CLK_DISABLE();
// __HAL_RCC_GPIOB_CLK_DISABLE();
// __HAL_RCC_GPIOC_CLK_DISABLE();
// __HAL_RCC_GPIOD_CLK_DISABLE();
// __HAL_RCC_GPIOG_CLK_DISABLE();
// __HAL_RCC_GPIOH_CLK_DISABLE();
// __HAL_RCC_PWR_CLK_DISABLE();
/* Disable Peripherals */
// HAL_CRC_MspDeInit(&hcrc);
// HAL_UART_DeInit(&huart3);
/* Disable and reset systick timer */
// SysTick->CTRL= 0;
// SysTick->LOAD = 0;
// SysTick->VAL = 0;
/* Disable all interrupts */
// __disable_irq();
/* Clear pending interrupts */
/* Remap system memory */
// SYSCFG->MEMRMP = SYSCFG_MEMRMP_MEM_MODE_0; //
/*************** What I want to add when more basic implementation works ***************/
// /* Relocate vector interrupt table to RAM */
// CopyVectorInterruptTable();
// /* TODO: Patch VIT with bootloader interrupt handlers (ex: hard fault handler) */
// PatchVectorInterruptTable();
// if (!CopyandPatchOkay())
// {
// LOG_DEBUG("Vector interrupt table not probably copied and/or patched \n");
// }
// else
// {
// LOG_DEBUG("Device ready to jump into application \n");
// }
}
应用程序的链接器文件(引导程序)0x8000000
/* Highest address of the user mode stack */
_estack = 0x20010000; /* 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
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K
}
申请跳转到 0x8060000
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim10)
{
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
SCB->VTOR = 0x8060000; //---- @berendi's suggestion
/* USER CODE END 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 SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART3_UART_Init();
MX_TIM10_Init();
/* USER CODE BEGIN 2 */
uint32_t count = 0;
HAL_TIM_Base_Start_IT(&htim10);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
for (uint32_t i=0; i < 100000; i++);
HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
_printf("Hi %d \n", count);
count++;
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
应用程序的链接器文件(中断闪烁)0x8060000
/* Highest address of the user mode stack */
_estack = 0x20010000; /* 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
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx) : ORIGIN = 0x8060000, LENGTH = 1024K
}
在STM32CubeMX生成的工程中,system_stm32f4xx.c
中的SystemInit()
函数,由main()
之前的启动代码调用,将向量table地址寄存器重置为开始闪存的。
/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
/* -- snip -- */
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
您可以直接编辑此文件(而不是再次在项目上 运行 STM32CubeMX,因为它 appears to overwrite this file),或者只需在 main()
中再次设置正确的值,然后再启用中断。
更新:也许更好的问题是我应该如何调试这个问题?我正在使用 VS Code 和 OpenOCD 调试器。我总是清理构建。 JumpToApplication() 后我能做的最好的事情就是查看当我 pause/step 进入时调试器停止的地址。
我能够将程序闪存到分区 A (@address 0x8060000) 并使用 CRC 检查对其进行验证。该程序在 while 循环中运行任何东西(LED3 切换,UART);然而,基于定时器中断的 LED2 切换不起作用。当我正常刷新程序时(即不使用我的引导加载程序)它可以 100% 工作,包括 LED2 切换。
以下是我处理过的一些资源 (1, 2, 3, AN2606)。我如何让中断为我的第二个应用程序工作?资源建议我清除挂起的中断,但我不知道解决该问题的最佳方法。在我的引导加载程序应用程序中,我使用了 ETH、UART 和 GPIO 外围设备,因此我将阅读手册并读取寄存器以清除中断标志,但是其他中断(如 NMI、HardFault)呢,我是否必须弄清楚如何清除它们出色地?通过我的 Google 搜索,我没有找到任何方便的函数来清除所有挂起的中断,是否存在?
下面我包含了 0x8000000 处的引导加载程序应用程序的跳转 function/linker 文件和 0x8060000 处的应用程序的 main.c/linker 文件:
引导加载程序中的跳转函数位于 0x8000000
void ApplicationManager::RunActivePartition()
{
JumpToApplication = (void (*)(void)) (*((uint32_t *) (active_partition.address + 4)));
/* Set vector table offset register */
SetVectorTable(MemoryInfo::BTLR_ADDRESS, MemoryInfo::PARTITION_A_OFFSET_FROM_BTLR);
/* STM32 needs the stack pointer to start at the beginning of
** the application in flash. This must happen last */
__set_MSP(*(__IO uint32_t*) active_partition.address);
JumpToApplication();
/*************** Other things I have tried ***************/
/* Reset RCC clock configuration */
// HAL_RCC_DeInit();
/* Disable peripheral clocks */
// __HAL_RCC_GPIOA_CLK_DISABLE();
// __HAL_RCC_GPIOB_CLK_DISABLE();
// __HAL_RCC_GPIOC_CLK_DISABLE();
// __HAL_RCC_GPIOD_CLK_DISABLE();
// __HAL_RCC_GPIOG_CLK_DISABLE();
// __HAL_RCC_GPIOH_CLK_DISABLE();
// __HAL_RCC_PWR_CLK_DISABLE();
/* Disable Peripherals */
// HAL_CRC_MspDeInit(&hcrc);
// HAL_UART_DeInit(&huart3);
/* Disable and reset systick timer */
// SysTick->CTRL= 0;
// SysTick->LOAD = 0;
// SysTick->VAL = 0;
/* Disable all interrupts */
// __disable_irq();
/* Clear pending interrupts */
/* Remap system memory */
// SYSCFG->MEMRMP = SYSCFG_MEMRMP_MEM_MODE_0; //
/*************** What I want to add when more basic implementation works ***************/
// /* Relocate vector interrupt table to RAM */
// CopyVectorInterruptTable();
// /* TODO: Patch VIT with bootloader interrupt handlers (ex: hard fault handler) */
// PatchVectorInterruptTable();
// if (!CopyandPatchOkay())
// {
// LOG_DEBUG("Vector interrupt table not probably copied and/or patched \n");
// }
// else
// {
// LOG_DEBUG("Device ready to jump into application \n");
// }
}
应用程序的链接器文件(引导程序)0x8000000
/* Highest address of the user mode stack */
_estack = 0x20010000; /* 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
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 2048K
}
申请跳转到 0x8060000
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim10)
{
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
SCB->VTOR = 0x8060000; //---- @berendi's suggestion
/* USER CODE END 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 SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART3_UART_Init();
MX_TIM10_Init();
/* USER CODE BEGIN 2 */
uint32_t count = 0;
HAL_TIM_Base_Start_IT(&htim10);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
for (uint32_t i=0; i < 100000; i++);
HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
_printf("Hi %d \n", count);
count++;
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
应用程序的链接器文件(中断闪烁)0x8060000
/* Highest address of the user mode stack */
_estack = 0x20010000; /* 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
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192K
CCMRAM (rw) : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx) : ORIGIN = 0x8060000, LENGTH = 1024K
}
在STM32CubeMX生成的工程中,system_stm32f4xx.c
中的SystemInit()
函数,由main()
之前的启动代码调用,将向量table地址寄存器重置为开始闪存的。
/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
/* -- snip -- */
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
您可以直接编辑此文件(而不是再次在项目上 运行 STM32CubeMX,因为它 appears to overwrite this file),或者只需在 main()
中再次设置正确的值,然后再启用中断。