stm32通过串口IAP

         

        首先申明一点,我这个不是什么原创,但也不是转载。以正点原子的战舰开发板的资料和神州IV号以及广大网友的资料为基础来做的。

          我使用的硬件神州IV号开发板,stm32f107系列的芯片,256K flash。IAP在线升级的确是个好东西,对于那些已经安装好的设备来说,真是一大利器。IAP的核心理论其实比较简单:总共有两个程序,一个叫bootloader  ,一个叫app。其中bootloader 、是一个引导程序,通过串口、usb、或者其他通讯接口,将app的代码(也是一个完整的程序,但是稍有一点不同),接收,然后存储到指定的flash处,最后跳转到存储app的地址,执行app。 app也是一个完整的程序只是他的堆zha地址往后移到,存储app的位置。下面我就截取一下原子的用户资料。

     注:此图是从STM32开发指南是截取。

     这就是这bootloader和app的整个执行过程。其中可以看出,bootloader是一个正常的程序,只是最后转到APP而已。app就稍有不同了他的中断复位地址要改变一下了。就是bootloader将其存储的位置。这些待会再说。

    现在让我们来屡一下,其中bootloader,要的模块就是串口、和flash。所以函数就只要,串口中断接收、flash存储、跳转app。

   下面就是我的bootloader的部分代码,很多是移植了原子哥的

 

这里是main.c里面的

#define FLASH_APP1_ADDR  0x08010000   //第一个应用程序起始地址(存放在FLASH)
           //保留0X08010000~0X0800FFFF的空间为IAP使用

USART2_Init();

 while (1)
  {  
     if(USART_RX_CNT)
    {
      if(oldcount==USART_RX_CNT)//新周期内,没有收到任何数据,认为本次数据接收完成.
   {
    applenth=USART_RX_CNT;
    oldcount=0;
    USART_RX_CNT=0;
    printf("用户程序接收完成!\r\n");
    printf("代码长度:%dBytes\r\n",applenth);
    flag=1;
   }else oldcount=USART_RX_CNT;
    }
    t=6553;
  while(t)
  {t--;}
    if(flag)
    {
//         printf("\n\r 这是buffrx  %s",USART_RX_BUF); 
//   flag=0;
            printf("\n\r 开始更新固件") ;
   if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
    { 
    iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,applenth);//更新FLASH代码  
//     delay_ms(100);
//     LCD_ShowString(60,210,200,16,16,"Copy APP Successed!!");
     printf("固件更新完成!\r\n");
     USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);//开启中断 
    }else
    {
    // LCD_ShowString(60,210,200,16,16,"Illegal FLASH APP!  ");   
     printf("非FLASH应用程序!\r\n");
    }

   if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
   { 
    iap_load_app(FLASH_APP1_ADDR);//执行FLASH APP代码
   }else
   {
    printf("非FLASH应用程序,无法执行!\r\n");
   // LCD_ShowString(60,210,200,16,16,"Illegal FLASH APP!");   
   }         
    }

USART.C里面的

u8 USART_RX_BUF[USART_REC_LEN]  __attribute__ ((at(0X20001000)));//接收缓冲,最大xx字节,起始地址  这一段比较重要,这是把某一个数组指定存储到某一个位置

u16 USART_RX_STA=0;        //接收状态标记  
u16 USART_RX_CNT=0;   //接收的字节数

void USART2_IRQHandler(void)                 //
{
       //printf("\n\r wo ok la!");
     //  rx=0;
  u8 res;
       if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
    {
     //
   res=USART_ReceiveData(USART2);
   //flag =1;
  if(USART_RX_CNT<USART_REC_LEN)
  {
   USART_RX_BUF[USART_RX_CNT]=res;
  // USART_RX_BUF[USART_RX_CNT++]  =   USART_ReceiveData(USART2);
   USART_RX_CNT++;                 
  }

}

以上两个文件里面的函数,就可以实现相应的功能了。

接下来就是app程序了。app程序和普通程序是一样的但是要注意,两点

1、需要使用 SCB->VTOR = FLASH_BASE | 0x10000;这条语句将堆栈偏移到bootloader的存储位置与之相对应

2、107的空间是0x8000000到0x804000,其中0x8000000到0x8010000留给了bootloader,剩下的就是app的了。

对了app要。bin格式的,可以通过串口助手,直接发送到mcu。

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值