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