跳转到应用程序时中断不起作用(STM32)

Posted

技术标签:

【中文标题】跳转到应用程序时中断不起作用(STM32)【英文标题】:Interrupts Not Working When I Jump to Application (STM32) 【发布时间】:2019-08-02 19:22:46 【问题描述】:

更新:也许更好的问题是我应该如何调试这个问题?我将 VS Code 与 OpenOCD 调试器一起使用。我总是清理构建。 JumpToApplication() 后,我能做的最好的事情就是查看当我暂停/步入时调试器停止的地址。

我可以将程序刷入分区 A (@address 0x8060000) 并通过 CRC 校验对其进行验证。该程序在while循环中运行任何东西(LED3切换,UART);但是,基于定时器中断的 LED2 切换不起作用。当我正常刷新程序(即不使用我的引导加载程序)时,它可以 100% 工作,包括 LED2 切换。

以下是我处理的一些资源(1、2、3、AN2606)。如何让中断为我的第二个应用程序工作?资源建议我清除挂起的中断,但我不知道解决这个问题的最佳方法。在我的引导加载程序应用程序中,我使用 ETH、UART 和 GPIO 外围设备,因此我将阅读手册并读取寄存器以清除中断标志,但其他中断(如 NMI、HardFault)呢?我是否必须弄清楚如何清除这些中断?好吧?通过我的谷歌搜索,我没有找到任何方便的功能来清除所有挂起的中断,它存在吗?

下面我在 0x8000000 处包含引导加载程序应用程序的跳转函数/链接器文件,在 0x8060000 处包含应用程序的 main.c/链接器文件:

引导加载程序中的跳转功能位于 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

【问题讨论】:

您的“引导加载程序”代码似乎禁用了所有中断。您的主要“应用程序”代码是否再次启用中断? 我将 __enable_irq() 添加为我的闪烁程序中 main 的第一行。现在两个 LED 都不会切换。 仅供参考:arm KEIL:ARM:如何编写引导加载程序:keil.com/support/docs/3913.htm 【参考方案1】:

在STM32CubeMX生成的工程中,system_stm32f4xx.c中的SystemInit()函数被main()之前的启动代码调用,将向量表地址寄存器复位到FLASH的开头。

/* #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() 中再次设置正确的值。

【讨论】:

我添加了 SCB->VTOR = 0x8060000;到我的应用程序,它的工作原理!谢谢@berendi。知道为什么调试器在我跳转后没有更新查看器中的 VTOR 寄存器吗?我一直在看这个。

以上是关于跳转到应用程序时中断不起作用(STM32)的主要内容,如果未能解决你的问题,请参考以下文章

如何跳转到 UIPageViewController 中的特定页面,setViewControllers 不起作用

STM32F103ZET6外部中断不起作用,不知道程序哪里错了?

如果 sscanf 在代码中的任何位置,STM32 USB CDC 虚拟 COM 将不起作用

STM32:自己的功能不起作用。我该如何解决?

PROTUSE 仿真STM32按键控制LED,按键不起作用

STM32F4 SPI接收中断不起作用