最近做的一个项目需要做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(); } }