STM32 ota跳转关闭全部中断

解决stm32 ota程序跳转异常:

ota升级分启动程序BootLoader与跳转的应用程序app,但跳转APP程序后有些中断不关闭,会导致app程序异常重启,所以防止app跳转程序异常需要关闭所有的中断。

解决办法:

  1. 在BootLoader跳转前关闭所有的中断。
  2. 在BootLoader跳转后app程序刚启动关闭所有的中断。

我更倾向与方法2,可以解决与BootLoader程序的耦合性。不用管BootLoader是否关闭中断了.


  //关闭所有中断,清除所有中断挂起标志
  int i = 0;
  for ( i = 0; i < 8; i++)
  {
    NVIC->ICER[i]=0xFFFFFFFF;
    NVIC->ICPR[i]=0xFFFFFFFF;
  }
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个基本的STM32 Bootloader例程,用于使用USART通信协议对STM32芯片进行固件升级。 ```c #include "stm32f1xx_hal.h" // Bootloader会在这个地址开始执行 #define APPLICATION_ADDRESS 0x08004000 // Bootloader会选择的升级文件的最大长度 #define MAX_APP_SIZE 0x4000 // 16KB // Bootloader UART通信参数 #define BAUD_RATE 115200 #define USART USART1 #define USART_PORT GPIOA #define TX_PIN GPIO_PIN_9 #define RX_PIN GPIO_PIN_10 // Bootloader的命令字 #define CMD_ERASE 0x43 // C #define CMD_WRITE 0x57 // W #define CMD_CHECK 0x4B // K #define CMD_EXEC 0x58 // X // Bootloader的命令缓冲区 #define CMD_BUFFER_SIZE 256 uint8_t cmd_buffer[CMD_BUFFER_SIZE]; uint32_t cmd_size = 0; // 启动应用程序 void bootloader_jump_to_app(){ // 关闭所有中断 HAL_NVIC_DisableIRQ(SysTick_IRQn); __disable_irq(); //清除所有挂起的中断 NVIC->ICER[0] = 0xFFFFFFFF; NVIC->ICER[1] = 0xFFFFFFFF; NVIC->ICER[2] = 0xFFFFFFFF; // 启动应用程序 typedef void (*pFunction)(void); pFunction app_reset_handler; uint32_t msp_value = *(volatile uint32_t *) APPLICATION_ADDRESS; __set_MSP(msp_value); app_reset_handler = (pFunction) (*(volatile uint32_t *)(APPLICATION_ADDRESS + 4)); app_reset_handler(); } // 擦除Flash void bootloader_erase_flash() { HAL_FLASH_Unlock(); FLASH_Erase_Sector(FLASH_SECTOR_2, FLASH_VOLTAGE_RANGE_3); HAL_FLASH_Lock(); } // 写Flash void bootloader_write_flash(uint8_t *buffer, uint32_t size) { uint32_t i = 0; uint32_t address = APPLICATION_ADDRESS; HAL_FLASH_Unlock(); for (i = 0; i < size; i += 4) { HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address + i, *((uint32_t*)(buffer + i))); } HAL_FLASH_Lock(); } // 校验Flash uint8_t bootloader_check_flash(uint8_t *buffer, uint32_t size) { uint32_t i = 0; uint32_t address = APPLICATION_ADDRESS; for (i = 0; i < size; i += 4) { if (*((uint32_t *)(buffer + i)) != (*(volatile uint32_t *)(address + i))) { return 0; } } return 1; } // 读取命令缓冲区 void bootloader_read_cmd_buffer(uint8_t *buffer, uint32_t size) { int i = 0; for(i = 0; i < size; i ++) { buffer[i] = cmd_buffer[i]; } } // 清空命令缓冲器 void bootloader_clear_cmd_buffer() { cmd_size = 0; } // 解析和执行命令 void bootloader_parse_cmd() { uint8_t cmd = cmd_buffer[0]; uint8_t status = 0; switch (cmd) { case CMD_ERASE: bootloader_erase_flash(); status = 1; break; case CMD_WRITE: if (cmd_size > 4) { bootloader_write_flash(cmd_buffer + 1, cmd_size - 1); status = 1; } break; case CMD_CHECK: if (cmd_size > 4) { status = bootloader_check_flash(cmd_buffer + 1, cmd_size - 1); } break; case CMD_EXEC: bootloader_jump_to_app(); break; default: break; } // 回复命令执行的结果 HAL_UART_Transmit(&USART, &status, sizeof(status), HAL_MAX_DELAY); bootloader_clear_cmd_buffer(); } // 接收和处理命令 void bootloader_uart_rx_handler() { static uint8_t rx_data = 0x00; if (__HAL_UART_GET_FLAG(&USART, UART_FLAG_RXNE) != RESET) { HAL_UART_Receive(&USART, &rx_data, sizeof(rx_data), 0); if (cmd_size >= CMD_BUFFER_SIZE || rx_data == '\n') { bootloader_parse_cmd(); } else { cmd_buffer[cmd_size++] = rx_data; } } } // 初始化UART通信 void init_uart() { GPIO_InitTypeDef gpioInit; USART_PORT->CRH &= ~(GPIO_CRH_CNF9 | GPIO_CRH_CNF10 | GPIO_CRH_MODE9 | GPIO_CRH_MODE10); gpioInit.Pin = TX_PIN; gpioInit.Mode = GPIO_MODE_AF_PP; gpioInit.Pull = GPIO_NOPULL; gpioInit.Speed = GPIO_SPEED_FREQ_HIGH; gpioInit.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(USART_PORT, &gpioInit); gpioInit.Pin = RX_PIN; gpioInit.Mode = GPIO_MODE_INPUT; gpioInit.Pull = GPIO_PULLUP; gpioInit.Speed = GPIO_SPEED_FREQ_HIGH; //gpioInit.Alternate = GPIO_AF7_USART1; HAL_GPIO_Init(USART_PORT, &gpioInit); USART->BRR = (uint16_t)(SystemCoreClock / BAUD_RATE); USART->CR1 = USART_CR1_RE | USART_CR1_TE | USART_CR1_RXNEIE | USART_CR1_UE; HAL_NVIC_EnableIRQ(USART1_IRQn); } // 主函数 int main(void) { HAL_Init(); SystemClock_Config(); init_uart(); while (1); } void USART1_IRQHandler(void) { bootloader_uart_rx_handler(); } ``` 需要注意的是,此处的例程仅适用于使用USART通信协议进行固件升级的场景。您可能需要根据您的具体应用场景进行一些修改。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值