[STM32F0] 笔记---基于HAL库的M0在应用升级IAP

[复制链接]
 楼主| Larm1 发表于 2019-4-17 09:55 | 显示全部楼层 |阅读模式
       虽然之前看过STM32的在应用升级IAP,但是一直没有亲自实验过,最近心血来潮准备体验一下。具体的实现原理这里就不再描述,网上的资料很多。因为M0的APP实现方式不同于M0+、M3、M4等内核的实现方式,所以在这里做个笔记。

       实验平台:
       硬件: STM32F072 Nucleo开发板
       软件: HAL库
       工具: IAR
       参考: STSW-STM32116————官方提供的F0例程(AN4065)

一、IAP工程功能
       上电后执行IAP,在跳转到APP之前,使用PC6控制LED翻转5次,再检测APP跳转条件,满足后跳转到APP。
       使用CubeMx生成工程之后。增加FLASH_If_Init函数,以初始化Flash,具体代码如下:
  1. void FLASH_If_Init(void)
  2. {
  3.   /* Unlock the Program memory */
  4.   HAL_FLASH_Unlock();

  5.   /* Clear all FLASH flags */  
  6.   __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP|FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR );
  7. }
具体main函数如下:
  1. int main(void)
  2. {
  3.   uint8_t  num = 0;
  4.   uint32_t tmp=0;
  5.   
  6.   FLASH_If_Init();
  7.   HAL_Init();

  8.   SystemClock_Config();
  9.   MX_GPIO_Init();
  10.   
  11.   for ( num=0; num<5; num ++)
  12.   {
  13.     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);
  14.    
  15.     for (tmp=0; tmp<300000; tmp ++);
  16.    
  17.     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
  18.    
  19.     for (tmp=0; tmp<300000; tmp ++);
  20.   }
  21.   
  22.          //// 判断APP的地址处是否已经下载了APP程序
  23.   if ( ((*(__IO uint32_t *)APP_ADDR)&0x2FFE0000)==0x20000000 )
  24.   {
  25.     JumpAddr = *(__IO uint32_t *)(APP_ADDR + 4); //// 设置APP复位中断入口地址
  26.     JumpApp = (pFunction)JumpAddr;
  27.     __set_MSP(*(__IO uint32_t *)APP_ADDR); //// 设置APP栈顶地址
  28.     JumpApp(); //// 跳转到APP
  29.   }
  30.   
  31.   while (1);
  32. }
二、APP工程功能
       由于在网上看见之前有在验证APP时,有各种现象——外部中断、串口中断和定时器中断等不响应,所以设计的工具比较多一下,看看具体有没有问题。
       功能1、外部中断——PA0上升沿触发外部中断,在中断内翻转PC9;
       功能2、TIM3定时中断——在中断内翻转PC7;
       功能3、串口1空闲中断——接收到的数据正确后,翻转PC8;
       功能4、主函数循环执行以下功能——开启串口DMA接收数据、串口发送数据、PC6状态翻转、延时。
       PC6~PC9输出控制LED灯。

       F0属于M0内核,不同于M0+、M3和M4等内核,没有专门的中断向量控制寄存器,中断向量的设置只能采用拷贝到SRAM方式。具体实现方式——定义一个位于SRAM首地址全局数组变量,将M0的所有中断入口地址拷贝到该变量内,再将SRAM的地址映射到地址0x00000000,发生中断后,MCU自动从地址0x00000000对应的偏移处寻找中断入口,如下:
  1. ///// 定义全局数组以存储中断向量表,M0共48个
  2. #if (defined (__CC_ARM) ) //// for keil MDK compiler
  3. __IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));
  4. #elif (defined (__ICCARM__) ) //// for IAR compiler
  5. #pragma location=0x20000000
  6. __no_init __IO uint32_t VectorTable[48];
  7. #elif (defined ( __GNUC__) ) //// for GNU compiler
  8. __IO uint32_t VectorTable[48] attribute__((section(".RAMVectorTable")));
  9. #elif (defined ( __TASKING__) ) //// for TASKING compiler
  10. __IO uint32_t VectorTable[48] at(0x20000000);
  11. #endif

  12. //// interrupt vector remapping
  13. void AppVectorTblRemap(void)
  14. {
  15.   uint8_t     tmp;
  16.   uint32_t    tmpCfgr=0;
  17.   
  18.         //// copy interrupt vector
  19.   for (tmp=0; 48>tmp; tmp++)
  20.   {
  21.                 //// because size of interrupt vector's address is 4, so tmp+=4(be equal to
  22.                 //// tmp<<=2);
  23.     VectorTable[tmp] = *( __IO uint32_t *)(APP_FLASH_ADDR + (tmp<<2));
  24.   }
  25.   
  26.   __HAL_RCC_SYSCFG_CLK_ENABLE();
  27.   tmpCfgr = SYSCFG->CFGR1;
  28.   tmpCfgr &= (uint32_t)(~SYSCFG_CFGR1_MEM_MODE_Msk);
  29.   tmpCfgr |= (uint32_t)0x03; //// embedded SRAM mapped at 0x0000 0000
  30.   SYSCFG->CFGR1 = tmpCfgr;
  31. }
      其余代码实现如下:
  1. void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
  2. {
  3.   if (TIM3==htim->Instance)
  4.   {
  5.     TimerBitSta ^= 1;
  6.     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_7, (GPIO_PinState)TimerBitSta);
  7.   }
  8. }

  9. void Exit0IrqCb(void)
  10. {
  11.   if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_0))
  12.   {
  13.     ExitBitSta ^= 1;
  14.     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, (GPIO_PinState)ExitBitSta);
  15.     __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_0);
  16.   }
  17. }

  18. void Usart1IrqCb(void)
  19. {
  20.   if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE))
  21.   {
  22.     USART1->ISR;
  23.     USART1->RDR;
  24.       
  25.     if ( (1==TestUartRcvBuf[0]) && (5==TestUartRcvBuf[4]) )
  26.     {
  27.       UsartBitSta ^= 1;
  28.       HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, (GPIO_PinState)UsartBitSta);
  29.       TestUartRcvBuf[0] = 0;
  30.       TestUartRcvBuf[4] = 0;
  31.     }
  32.    
  33.   }
  34.   HAL_UART_AbortReceive_IT(&huart1);
  35.   HAL_UART_DMAStop(&huart1);
  36.   __HAL_UART_CLEAR_IT(&huart1, UART_FLAG_IDLE);
  37. }
     中断服务程序:
  1. void EXTI0_1_IRQHandler(void)
  2. {
  3.   
  4.   Exit0IrqCb();
  5. }



  6. /**
  7.   * [url=home.php?mod=space&uid=247401]@brief[/url] This function handles TIM3 global interrupt.
  8.   */
  9. void TIM3_IRQHandler(void)
  10. {
  11.   /* USER CODE BEGIN TIM3_IRQn 0 */

  12.   /* USER CODE END TIM3_IRQn 0 */
  13.   HAL_TIM_IRQHandler(&htim3);
  14.   /* USER CODE BEGIN TIM3_IRQn 1 */

  15.   /* USER CODE END TIM3_IRQn 1 */
  16. }


  17. void USART1_IRQHandler(void)
  18. {
  19.   /* USER CODE BEGIN USART1_IRQn 0 */
  20.   Usart1IrqCb();
  21.   /* USER CODE END USART1_IRQn 0 */
  22.   HAL_UART_IRQHandler(&huart1);
  23.   /* USER CODE BEGIN USART1_IRQn 1 */

  24.   /* USER CODE END USART1_IRQn 1 */
  25. }
     主程序:
  1. int main(void)
  2. {
  3.   /* USER CODE BEGIN 1 */
  4.   uint32_t tmp;
  5.   
  6.   AppVectorTblRemap();
  7.   /* USER CODE END 1 */

  8.   /* MCU Configuration--------------------------------------------------------*/

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

  11.   /* USER CODE BEGIN Init */

  12.   /* USER CODE END Init */

  13.   /* Configure the system clock */
  14.   SystemClock_Config();

  15.   /* USER CODE BEGIN SysInit */

  16.   /* USER CODE END SysInit */

  17.   /* Initialize all configured peripherals */
  18.   MX_GPIO_Init();
  19.   MX_DMA_Init();
  20.   MX_USART1_UART_Init();
  21.   MX_TIM3_Init();
  22.   HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
  23.   
  24.   /* USER CODE BEGIN 2 */
  25.   HAL_TIM_Base_Start_IT(&htim3);
  26.   __HAL_UART_ENABLE_IT(&huart1, UART_IT_IDLE);
  27.   __set_PRIMASK(0); //// close interrupt in IAP, so open
  28.   
  29.   /* USER CODE END 2 */

  30.   /* Infinite loop */
  31.   /* USER CODE BEGIN WHILE */
  32.   while (1)
  33.   {
  34.     HAL_UART_Receive_DMA(&huart1, TestUartRcvBuf ,UART_BUF_LEN);
  35.     HAL_UART_Transmit(&huart1, TestUartSndBuf ,UART_BUF_LEN, UART_BUF_LEN);
  36.    
  37. ////          HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);
  38. ////    HAL_GPIO_WritePin(GPIOC, GPIO_PIN_8, GPIO_PIN_SET);
  39.    
  40. ////    for (tmp=0; tmp<600000; tmp ++);
  41.    
  42.    
  43.     WhileBitSta ^= 1;
  44.     HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, (GPIO_PinState)WhileBitSta);
  45.     for (tmp=0; tmp<600000; tmp ++);
  46.    
  47.     /* USER CODE END WHILE */

  48.     /* USER CODE BEGIN 3 */
  49.   }
  50.   /* USER CODE END 3 */
  51. }
       两个工程编译通过后,使用仿真器将执行文件烧录到MCU,程序运行正常。TIM3定时中断你控制的灯一直亮,但是亮度没有其余的灯亮,因为占空比不是100%;测试串口时,使用镊子或者金属片将串口连个引脚短接起来后,在串口中断内控制翻转控制的LED均正常没有出现网上说的中断不响应等问题。
       整个工程代码见附件。
       F072TestApp.rar (1.05 MB, 下载次数: 49)
       F072TestIap.rar (487.8 KB, 下载次数: 76)

mmuuss586 发表于 2019-4-18 09:44 | 显示全部楼层
感谢分享
晓伍 发表于 2019-5-8 08:34 | 显示全部楼层
非常感谢楼主分享
观海 发表于 2019-5-8 08:41 | 显示全部楼层
非常感谢楼主分享
guanjiaer 发表于 2019-5-8 08:50 | 显示全部楼层
非常感谢楼主分享
heimaojingzhang 发表于 2019-5-8 08:57 | 显示全部楼层
非常感谢楼主分享
keaibukelian 发表于 2019-5-8 08:59 | 显示全部楼层
非常感谢楼主分享
labasi 发表于 2019-5-8 09:04 | 显示全部楼层
非常感谢楼主分享
paotangsan 发表于 2019-5-8 09:47 | 显示全部楼层
非常感谢楼主分享
renzheshengui 发表于 2019-5-8 09:55 | 显示全部楼层
非常感谢楼主分享
wakayi 发表于 2019-5-8 10:10 | 显示全部楼层
非常感谢楼主分享
wowu 发表于 2019-5-8 10:16 | 显示全部楼层
非常感谢楼主分享
木木guainv 发表于 2019-5-8 10:38 | 显示全部楼层
非常感谢楼主分享
wangjiahao88 发表于 2019-5-8 11:04 | 显示全部楼层
这个 之前使用过,STM32F046的,没有成功……不知道为什么,,,,,,
djz1992 发表于 2019-5-13 20:42 | 显示全部楼层
感谢分享,后面深入研究一下,主要想做GPRS的远程升级
letflying 发表于 2020-11-5 11:11 | 显示全部楼层
楼主只是实现了IAP到APP的跳转,并没有实现falsh_if的HAL库函数的读写操作,以及Ymodem的协议啊
 楼主| Larm1 发表于 2021-5-17 11:59 | 显示全部楼层
letflying 发表于 2020-11-5 11:11
楼主只是实现了IAP到APP的跳转,并没有实现falsh_if的HAL库函数的读写操作,以及Ymodem的协议啊 ...

真正做产品的话我觉得不会使用Ymodem协议,而是使用自定义的代码,使用该协议的都是用现成的上下位机代码做研究,这种升级协议使用通用协议不完全...
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:大爱无疆

53

主题

389

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部