想想來這個論壇挺久了,也在這學了不少東西,本著回饋論壇,回饋網(wǎng)友的心態(tài),發(fā)一篇關(guān)于OTA的貼,不喜勿噴,隨著現(xiàn)在科技的發(fā)展,市面上出現(xiàn)很多帶wifi,藍牙等智能產(chǎn)品,為滿足人們對產(chǎn)品可以不斷完善,誕生了這種遠程升級的技術(shù)。 在此之前呢,做過一個stm32遠程升級的項目,這種片子的代碼地址偏移性很好,load程序和應(yīng)用程序劃分好就可以,后來就想51這種便宜的mcu,能不能也實現(xiàn)這個功能呢,這就有了這次的實驗。
廢話不多說,先說說原理,OTA主要就三部分,一個是load程序,一個是應(yīng)用程序,還有帶升級的程序,三個分別存儲在不同地址,我以flash 32K為例。如下圖
捕獲.PNG (5.19 KB, 下載次數(shù): 123)
下載附件
2020-2-15 17:15 上傳
為什么要這樣劃分地址呢。主要是因為51單片機的中斷地址不能發(fā)生偏移(至少我不知道怎么偏移),所以我運行的程序必須在起始地址0x0.吧bootload程序放在了0x6000的位置。
1,bootload程序設(shè)計,程序功能主要是判斷有沒有升級標志,有升級標志把APP2的文件拷貝到APP1,然后跳轉(zhuǎn)到app1位置運行。如果沒有升級標志直接跳轉(zhuǎn)到app1.
keil中設(shè)置1,BL51 locate 啟動文件 ?C_C51STARTUP(0x6100) 需要特殊放置,這樣才能保證每次啟動后跳轉(zhuǎn)的位置準確;
設(shè)置2,target EProm 0x6000;
load_keil_set2.PNG (16.11 KB, 下載次數(shù): 127)
下載附件
2020-2-15 17:42 上傳
load_keil_set.PNG (21.29 KB, 下載次數(shù): 124)
下載附件
2020-2-15 17:42 上傳
這樣編譯出來的 hex文件 就是下面這個樣子。
捕獲2.PNG (4.4 KB, 下載次數(shù): 107)
下載附件
2020-2-15 17:53 上傳
這個時候bootload程序算設(shè)計好了,可以直接燒錄到MCU中。
2,應(yīng)用程序 APP1設(shè)計,程序功能主要實現(xiàn)我們自己產(chǎn)品功能,以及接收保存遠程發(fā)過來的程序。
keil中設(shè)置1,BL51 locate 啟動文件 ?C_C51STARTUP(0x1000) 需要特殊放置,這樣才能保證每次啟動后跳轉(zhuǎn)的位置準確;
設(shè)置2,target EProm 0x0;
捕獲3.PNG (16.49 KB, 下載次數(shù): 124)
下載附件
2020-2-15 17:58 上傳
捕獲4.PNG (27.1 KB, 下載次數(shù): 131)
下載附件
2020-2-15 18:00 上傳
這樣就可以確保每次程序跳轉(zhuǎn)正確。關(guān)鍵的在這里,因為每次要先運行bootload 所以需要在0x0 位置 跳轉(zhuǎn)到bootload地址是0x6100,再有boot程序跳轉(zhuǎn)到我們的0x1000 這樣成正常運行,看起來很復(fù)雜,其中只有兩個關(guān)鍵地址,0-->0x6100 -->0x1000 , 就這兩步驟。
3,然后再來說說升級文件的打包制作,首先呢需要把 02 10 00 改成 02 61 00.
在bin文件前面插入256個字節(jié),升級文件信息。
a,0-3字節(jié) 文件版本號
b 4-7字節(jié) 文件長度
c 8-11字節(jié) 文件類型
d 12-13字節(jié) 文件的CRC校驗(校驗只對程序文件,不包括插入的信息)
e 10-255 0xff
我這里用C#寫了一個小工具和一個模擬云服務(wù)器發(fā)送的 工具。
捕獲5.PNG (4.02 KB, 下載次數(shù): 111)
下載附件
2020-2-15 18:17 上傳
捕獲6.PNG (20.83 KB, 下載次數(shù): 109)
下載附件
2020-2-15 18:19 上傳
這樣就完成了51 遠程升級的全部工作。不喜勿噴,附上代碼僅供學習參考。
//-------------------------------bootload----------------------------------------
#include "hal_clock.h"
#include "hal_gpio.h"
#include "hal_pwm.h"
#include "hal_timer.h"
#include "hal_interrupt.h"
#include "hal_adc.h"
#include "hal_uart.h"
#include "WIFI_JD780.h"
#include "IR.h"
#include "Buzz.h"
#include "hal_ssp.h"
#include "stdio.h"
#define USAR_APP_ADDR 0x1000
typedef void (*boot_fun)(void) ;//= USAR_APP_ADDR;
int cnt_500ms;
char goto_flag;
int i;
char str[10];
char temp1,temp2;
void main(void)
{
system_clock_set(0);
_hal_gpio_init();
_MCU_TIMER_Init();
_mcu_uart1_init();
EA = 0;
uart1_send("boot run .. \r\n");
uart1_send("boot addr 0x6000 main addr 0x6100..\r\n");
uart1_send(__DATE__);
uart1_send("\r\ngo to app run addr:0x1000 \r\n");
uart1_send("-----------------------------------\r\n");
// Ssp_WriteByte(EEPOM_ADDR,0xaa,mFLASH);
i = Read_FlashByte(EEPOM_ADDR);//檢查是否有升級
if(i==0xaa)
{
uart1_send("Updata......\r\n");
for( i=0;i<10;i++)
{
Ssp_EraseBlock(APP_ADDR + i*0x400,mFLASH);
}
uart1_send("EraseBlock OK \r\n");
for(i=0;i<0x2800;i++)
{
Ssp_WriteByte(i,Read_FlashByte(APP_BACK_ADDR+i),mFLASH);
}
uart1_send("WriteBlock OK \r\n");
Ssp_EraseBlock(EEPOM_ADDR,mFLASH);
Ssp_WriteByte(EEPOM_ADDR,0,mFLASH);
for(i=0;i<0x2800;i++)
{
temp1 = Read_FlashByte(APP_BACK_ADDR+i);
temp2 = Read_FlashByte(APP_ADDR+i);
if( temp1 != temp2)//APP_ADDR
{
uart1_send("index: ");
sprintf(str,"%d",i);
uart1_send(str);
uart1_send("Updata Error.....\r\n");
while(1);
}
}
}
((void(code*)(void))USAR_APP_ADDR)();
while(1);
}
//-----------------------app1---------------------------------------------------
#include "hal_clock.h"
#include "hal_gpio.h"
#include "hal_pwm.h"
#include "hal_timer.h"
#include "hal_interrupt.h"
#include "hal_adc.h"
#include "hal_uart.h"
#include "WIFI_JD780.h"
#include "IR.h"
#include "Buzz.h"
#include "hal_ssp.h"
//0x0000-0x27ff app main 0x1000 10K
//0x2800-0x4fff app-back 10K
//0x5000-0x5fff eerom 2 k
//0x6000-0x7fff boot main 0x6100 8 k
//?C_C51STARTUP(0x1000)
code unsigned char mcu_sf_ver[5] ="1.09";
code unsigned char mcu_hw_ver[5] ="1.00";
int send_time;
void main(void)
{
system_clock_set(0);
_hal_gpio_init();
_MCU_PWM_Init();
_MCU_TIMER_Init();
_mcu_uart1_init();
_MCU_IRQ_Init();
_wifi_init();
IR_ExtInit();
_mcu_adc_init();
BUZ_Init();
BUZ_PLAY_OFF();
EA = 0;
uart1_send("-----------------------------------\r\n");
uart1_send("welcome to app world ..............\r\n");
uart1_send(__DATE__);
uart1_send("-----------------------------------\r\n");
uart1_send("software ver :");
uart1_send(mcu_sf_ver);
uart1_send("\r\n");
EA = 1;
while(1)
{
_MCU_TIMER_Driver();
if(F_10ms)
{
F_10ms =0;
IR_Process();
_user_wifi_data_drives();
if(IR_KeyCode.bits.Power)
{
IR_KeyCode.bits.Power = 0;
BUZ_PLAY_KEY();
//SBUF = 'C';
SBUF = Read_FlashByte(0x2800);
Ssp_EraseBlock(0x2800,mFLASH);
SBUF = Read_FlashByte(0x2800);
}
if(IR_KeyCode.bits.Auto)
{
IR_KeyCode.bits.Auto = 0;
BUZ_PLAY_KEY();
SBUF = 'W';
//ssp_write_flash_nbyte(APP_BACK_ADDR,"1234567890",10);
//ssp_write_flash_nbyte(APP_BACK_ADDR+20,"1234567890",10);
}
BUZ_Run();
//ADC_GetAD_12bit(1);
}
}
}
全部資料51hei下載地址:
bin+fifo.zip
(50.72 KB, 下載次數(shù): 144)
2020-2-15 18:26 上傳
點擊文件名下載附件
C# 下載積分: 黑幣 -5
tool.zip
(14.3 KB, 下載次數(shù): 111)
2020-2-15 18:22 上傳
點擊文件名下載附件
工具 下載積分: 黑幣 -5
|