OTA升级实现方案

时间:2024-03-12 16:47:30

最近做的一个项目需要做OTA升级,使用的芯片是stm32f103c8t6,从阿里云获取固件包,并写入内部flash中,实现在线升级。

 

由于c8t6的内部flash只有64K,sram只有16K,没办法在从阿里云接收数据的过程中同时进行md5值的校验和写入内部flash的操作,所以就使用了一个外部flash做缓存,即先将从阿里云获得的数据(包括bin文件,文件大小,md5校验值)写入外部flash中,然后再将外部flash里面的bin文件1K,1K的读出来进行md5值的计算,最终与外部flash里的md5值进行比较,如果一致,说明数据没错,则将外部flash的bin文件写入内部flash,再实现程序的跳转;否则重新向阿里云请求获得数据包。以上即为我实现OTA升级的大致逻辑,如果哪位大佬觉得有更好的方案可以一起讨论!下面介绍下实现md5值计算和程序跳转的内容吧。

 

md5值计算

 

 

 以上代码为md5运算过程的主要计算,全是数学方面的知识,鄙人才疏学浅,原理不是太懂,拿来能用就行啦,哈哈

 

 

 这串代码的作用是将从外部flash里面读出的bin文件以4个字节为一组,总共16组的方式填充进x里面,相当于C语言里面的函数fread(&x,4,16,fp),只不过这里的fp不是指向文件,而是读出来的bin文件的首地址

 

 

 此函数即为实现从外部flash获取数据进行计算的主要逻辑,首先是将外部flash的数据分别1K,1K的拿出来进行md5()计算,再将最后不足1K的进行计算,不过最后计算的时候需要补上10000000,以及文件长度的二进制,最终即得到文件的md5值,如果对计算出来的结果是否正确存在担心时,可以利用notepad++计算该bin文件的md5值,进行对比即可

 

 

 

 

最后在简单说说stm32的IAP是怎么做的

首先在上面计算出md5值之后,如果校验成功,那么将该bin文件写入内部flash的指定位置,我是写到了0x8004000这个位置的,因为stm32的flash的起始地址是0x08000000,则我中间留出了16K的大小写我的bootloader,在bin文件完全正确的写入指定地址后,可以使用以下代码进行程序跳转

 

 

 

 

 

 不过怎样去看自己的bin文件是否写入正确呢?这里推荐使用软件 ,通过stlink与stm32成功相连后,可以使用这个软件查看内部flash的值,借此与bin文件进行比较,当然这款软件不止这一个功能,比如全片flash擦除的等等功能啦

 

 

 

这里再讲一个关于待升级的固件程序的配置问题,首先需要将设定为你程序需要跳转的地方,其次是的将SystemInit()函数里的SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;进行修改,其中VECT_TAB_OFFSET代表了你固件程序中断向量表的偏移地址;如果不修改,你固件程序中的中断将无法使用,之前我就遇到过这个问题,对于一个串口接收和发送的程序,在程序跳转后,能够发送东西,但是无法收到我传过去的东西,应该是串口接收中断没有起作用。

 

 

最后附上我工程里的一些关键性代码

 

 

  1 #include "md5.h"
  2 
  3 unsigned int A=0x67452301,B=0xefcdab89,C=0x98badcfe,D=0x10325476,a,b,c,d,flen[2],x[16]; 
  4 u16 i = 0;
  5 u16 j = 0;
  6 u16 k = 0;
  7 
  8 u8 Temp_Ex_Flash[1025]  __attribute__((at(0X20001000)));//¶¨ÒåÔÝʱ´æ´¢1KÍⲿflashÄÚbinÎļþ
  9 
 10 void md5(void){                 //MD5Ö÷Òª¼ÆËã
 11 
 12   a=A,b=B,c=C,d=D;
 13 
 14   FF (a, b, c, d, x[ 0],  7, 0xd76aa478); 
 15   FF (d, a, b, c, x[ 1], 12, 0xe8c7b756); 
 16   FF (c, d, a, b, x[ 2], 17, 0x242070db); 
 17   FF (b, c, d, a, x[ 3], 22, 0xc1bdceee); 
 18   FF (a, b, c, d, x[ 4],  7, 0xf57c0faf); 
 19   FF (d, a, b, c, x[ 5], 12, 0x4787c62a); 
 20   FF (c, d, a, b, x[ 6], 17, 0xa8304613); 
 21   FF (b, c, d, a, x[ 7], 22, 0xfd469501); 
 22   FF (a, b, c, d, x[ 8],  7, 0x698098d8); 
 23   FF (d, a, b, c, x[ 9], 12, 0x8b44f7af); 
 24   FF (c, d, a, b, x[10], 17, 0xffff5bb1); 
 25   FF (b, c, d, a, x[11], 22, 0x895cd7be); 
 26   FF (a, b, c, d, x[12],  7, 0x6b901122); 
 27   FF (d, a, b, c, x[13], 12, 0xfd987193); 
 28   FF (c, d, a, b, x[14], 17, 0xa679438e); 
 29   FF (b, c, d, a, x[15], 22, 0x49b40821); 
 30 
 31 
 32   GG (a, b, c, d, x[ 1],  5, 0xf61e2562); 
 33   GG (d, a, b, c, x[ 6],  9, 0xc040b340); 
 34   GG (c, d, a, b, x[11], 14, 0x265e5a51); 
 35   GG (b, c, d, a, x[ 0], 20, 0xe9b6c7aa); 
 36   GG (a, b, c, d, x[ 5],  5, 0xd62f105d); 
 37   GG (d, a, b, c, x[10],  9, 0x02441453); 
 38   GG (c, d, a, b, x[15], 14, 0xd8a1e681); 
 39   GG (b, c, d, a, x[ 4], 20, 0xe7d3fbc8); 
 40   GG (a, b, c, d, x[ 9],  5, 0x21e1cde6); 
 41   GG (d, a, b, c, x[14],  9, 0xc33707d6); 
 42   GG (c, d, a, b, x[ 3], 14, 0xf4d50d87); 
 43   GG (b, c, d, a, x[ 8], 20, 0x455a14ed); 
 44   GG (a, b, c, d, x[13],  5, 0xa9e3e905); 
 45   GG (d, a, b, c, x[ 2],  9, 0xfcefa3f8); 
 46   GG (c, d, a, b, x[ 7], 14, 0x676f02d9); 
 47   GG (b, c, d, a, x[12], 20, 0x8d2a4c8a); 
 48 
 49 
 50   HH (a, b, c, d, x[ 5],  4, 0xfffa3942); 
 51   HH (d, a, b, c, x[ 8], 11, 0x8771f681); 
 52   HH (c, d, a, b, x[11], 16, 0x6d9d6122); 
 53   HH (b, c, d, a, x[14], 23, 0xfde5380c); 
 54   HH (a, b, c, d, x[ 1],  4, 0xa4beea44); 
 55   HH (d, a, b, c, x[ 4], 11, 0x4bdecfa9); 
 56   HH (c, d, a, b, x[ 7], 16, 0xf6bb4b60); 
 57   HH (b, c, d, a, x[10], 23, 0xbebfbc70); 
 58   HH (a, b, c, d, x[13],  4, 0x289b7ec6); 
 59   HH (d, a, b, c, x[ 0], 11, 0xeaa127fa); 
 60   HH (c, d, a, b, x[ 3], 16, 0xd4ef3085); 
 61   HH (b, c, d, a, x[ 6], 23, 0x04881d05); 
 62   HH (a, b, c, d, x[ 9],  4, 0xd9d4d039); 
 63   HH (d, a, b, c, x[12], 11, 0xe6db99e5); 
 64   HH (c, d, a, b, x[15], 16, 0x1fa27cf8); 
 65   HH (b, c, d, a, x[ 2], 23, 0xc4ac5665); 
 66 
 67 
 68   II (a, b, c, d, x[ 0],  6, 0xf4292244); 
 69   II (d, a, b, c, x[ 7], 10, 0x432aff97); 
 70   II (c, d, a, b, x[14], 15, 0xab9423a7); 
 71   II (b, c, d, a, x[ 5], 21, 0xfc93a039); 
 72   II (a, b, c, d, x[12],  6, 0x655b59c3); 
 73   II (d, a, b, c, x[ 3], 10, 0x8f0ccc92); 
 74   II (c, d, a, b, x[10], 15, 0xffeff47d); 
 75   II (b, c, d, a, x[ 1], 21, 0x85845dd1); 
 76   II (a, b, c, d, x[ 8],  6, 0x6fa87e4f); 
 77   II (d, a, b, c, x[15], 10, 0xfe2ce6e0); 
 78   II (c, d, a, b, x[ 6], 15, 0xa3014314); 
 79   II (b, c, d, a, x[13], 21, 0x4e0811a1); 
 80   II (a, b, c, d, x[ 4],  6, 0xf7537e82); 
 81   II (d, a, b, c, x[11], 10, 0xbd3af235); 
 82   II (c, d, a, b, x[ 2], 15, 0x2ad7d2bb); 
 83   II (b, c, d, a, x[ 9], 21, 0xeb86d391); 
 84 
 85   A += a;
 86   B += b;
 87   C += c;
 88   D += d;
 89 
 90 }
 91 
 92 unsigned int sample_index = 0; //´ÓTEST_data²É¼¯64λ¸ö×Ö½Ú
 93 unsigned int data_index = 0;   //binÎļþ×Ö·ûË÷Òý,¹Ì¼þbinÎļþ´óС²»Òª³¬¹ý65K
 94 unsigned int read_times = 0;
 95 unsigned int BIN_location = 0;
 96 
 97 void Read_Group_TEMPBUF(void)
 98 {
 99     memset(x,0,64);    
100     sample_index = 0;
101     for(j = 0;j < 16;j++)//fread(&x,4,16,fp) ÒÔ4×Ö½ÚΪһ×飬¹²16×éÍùxдÈëÊý¾Ý
102     {
103         for(k = 0;k < 4;k++)
104         {
105             if((read_times >= BINLEN/1024)&&(data_index >= BINLEN%1024)) break;//µ±¶Ô×îºóÒ»²¿·ÖСÓÚ1KµÄbinÎļþ´¦Àí
106             
107             ((char*)x)[sample_index] = Temp_Ex_Flash[data_index];
108             data_index++;
109             sample_index++;
110         }
111     }
112 }
113 
114 
115 
116 void Get_Bin_Md5(void)
117 {
118     u16 i = 0;
119     
120     for(read_times = 0;read_times < BINLEN/1024;read_times++)//¶ÔÕûK½øÐÐmd5¼ÆËã
121     {
122         W25QXX_Read(Temp_Ex_Flash,EX_FLASH_SIZE-100*1024+BIN_location,1024);//ÿ´ÎÖ»¶ÁÈ¡1KµÄbinÎļþ
123         BIN_location += 1024;
124         
125         for(i = 0;i < 16;i++)//¸ÕºÃ¶Ô¶Á³öµÄ1KbinÎļþ½øÐÐmd5¼ÆËã 
126         {
127             Read_Group_TEMPBUF();
128             md5();    
129         }
130         data_index = 0;//×î´óÖ»µ½1023
131     }
132     memset(Temp_Ex_Flash,0,1025);
133     W25QXX_Read(Temp_Ex_Flash,EX_FLASH_SIZE-100*1024+BIN_location,BINLEN%1024);
134     
135     
136     Read_Group_TEMPBUF();
137     for(i = 0;i < (BINLEN%1024)/64;i++)
138     {
139         md5();
140         Read_Group_TEMPBUF();
141     }
142     ((char*)x)[BINLEN%64]=128;//Îļþ½áÊø²¹1,0²Ù×÷ 10000000
143     
144     flen[1]=BINLEN/0x20000000;   //ת»»¶þ½øÖÆÎļþ´óС£¨byte->bit£©
145     flen[0]=(BINLEN%0x20000000)*8;
146     
147     if(BINLEN%64>55) md5(),memset(x,0,64);
148     memcpy(x+14,flen,8);
149     md5();
150     printf("MD5 Code:%08x%08x%08x%08x\n",PP(A),PP(B),PP(C),PP(D));
151     
152 }
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "stmflash.h"
#include "iap.h"
#include "md5.h"
#include "w25qxx.h"

iapfun jump2app; 
u16 iapbuf[1024];   
u8 iap_temp_buf[2048];

void iap_write_appbin(u32 appxaddr,u32 appsize)//³¯ÄÚ²¿flashÖ¸¶¨µØַдÈëbinÎļþ
{
    u16 i = 0;
    u16 t = 0;
    u16 m = 0;
    u16 temp;
    u16 Binlocation;
    u32 fwaddr=appxaddr;//µ±Ç°Ð´ÈëµÄµØÖ·

    
    for(i = 0;i < appsize/2048;i++)
    {
        W25QXX_Read(iap_temp_buf,EX_FLASH_SIZE-100*1024+Binlocation,2048);//ÿ´ÎÖ»¶ÁÈ¡2KµÄbinÎļþ        
        for(t = 0;t < 2048;t = t+2)//×é³É1KµÄIAPBUF
        {
            temp = (u16)iap_temp_buf[t+1]<<8;
            temp += (u16)iap_temp_buf[t];
            iapbuf[m++] = temp;            
        }
        
        STMFLASH_Write(fwaddr,iapbuf,1024);
        Binlocation += 2048;
        fwaddr+=2048;
        m = 0;
    }
    
    memset(iap_temp_buf,255,2408);
    
    W25QXX_Read(iap_temp_buf,EX_FLASH_SIZE-100*1024+Binlocation,appsize%2048);
    for(t = 0;t < appsize%2048;t = t+2)
    {
        temp = (u16)iap_temp_buf[t+1]<<8;
        temp += (u16)iap_temp_buf[t];
        iapbuf[m++] = temp;    
    }
    STMFLASH_Write(fwaddr,iapbuf,m);    
}


//Ìøתµ½Ó¦ÓóÌÐò¶Î
//appxaddr:Óû§´úÂëÆðʼµØÖ·.
void iap_load_app(u32 appxaddr)
{
    if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)    
    { 
        jump2app=(iapfun)*(vu32*)(appxaddr+4);        
        MSR_MSP(*(vu32*)appxaddr);                 
        jump2app();                                    
    }
}