本文原創(chuàng)作者: 少占魚大神
關(guān)于8051的bootloader實現(xiàn)方式
一, 基本硬件需求
要實現(xiàn)IAP功能,需要51單片機可以在程序里修改代碼空間的Flash,或者至少可以修改用戶程序區(qū)的Flash,新出的51大部分都能滿足這個要求
二,空間劃分
一般bootloader位于單片機代碼空間的起始地址,用戶程序在后面。這個需要根據(jù)實際的需求來決定,bootloader功能簡單,就少占用一些,bootloader功能復(fù)雜的就多占用一些。除此之外,一般還要根據(jù)Flash的頁為界線劃分。附帶的工程模板里,bootloader使用0x0000-0x0fff區(qū)間,用戶程序使用0x1000以后的空間。
三,中斷的處理
51單片機的中斷入口一般位于0地址開始的區(qū)間,無法修改,但是根據(jù)上面的空間劃分方式,這個區(qū)間位于bootloader的范圍,是不能隨意更改的。所以代碼里用了一個軟件的方式對中斷入口做了重映射處理,后面將結(jié)合具體的代碼介紹實現(xiàn)方式。
四,Bootloader的處理
1, 建立工程的時候,選擇把Startup.a51添加到工程
2, 在Startup.a51里添加如下代碼:
ORG 0003H
LJMP 2003H
ORG 000BH
LJMP 200BH
ORG 0013H
LJMP 2013H
ORG 001BH
LJMP 201BH
ORG 0023H
LJMP 2023H
………………………….
根據(jù)具體型號的中斷數(shù)量和地址,添加中斷跳轉(zhuǎn)代碼,格式為ORG XXH LJMP 2000+XXH,這樣做,是為了將中斷映射到用戶程序區(qū)的0x2000開始的空間,在用戶程序里,還要做一些對應(yīng)的設(shè)置,后面將介紹。
3, Bootloader的處理流程。Bootloader的主要作用一般是開機初始化,自檢和升級用戶程序,以及引導(dǎo)用戶程序。因為上面已經(jīng)把中斷映射到用戶程序空間,所以bootloader里最好就不要用中斷了。
五, 用戶程序的處理。
1, 用戶程序的Startup.a51無特殊需求,可以根據(jù)需要選擇添加到工程,然后自己做修改,也可以不添加到工程,由編譯器連接一個默認的startup.a51
2, 用戶程序的所有普通函數(shù)和中斷函數(shù)也沒有特殊要求,可以按正常的方式編寫
3, 用戶程序的工程設(shè)置。因為用戶程序不再是從0地址開始,所以需要在工程設(shè)置里做定位處理:設(shè)置用代碼的范圍,定位用戶代碼入口地址。具體設(shè)定如下圖:
因為用戶代碼規(guī)劃到0x1000以后的空間,所以設(shè)置code range從0x1000開始
為了讓bootloader能準確跳到用戶程序入口,所以需要將C_C51STARTUP定位到0x1000位置。(C_STARTUP位于startup.a51里,它才是程序的真正入口,而不是main函數(shù);另外,入口也并不是必須定位在這個位置,只要位于用戶代碼空間就可以)
51hei.png (128.16 KB, 下載次數(shù): 101)
下載附件
2020-4-12 16:23 上傳
4, 中斷映射。在bootloader里,將中斷入口定位在了0x2000開始的空間,在用戶程序里,也必須做一個對應(yīng)的設(shè)置。方法如下:
51hei.png (168.63 KB, 下載次數(shù): 97)
下載附件
2020-4-12 16:23 上傳
這樣處理之后,便完成了中斷的映射。當中斷發(fā)生時,會先進入位于bootloader里的硬件中斷入口,然后在那里跳轉(zhuǎn)到0x2000開始的一個軟件重定義的向量表,再跳轉(zhuǎn)到中斷入口函數(shù)。和沒有bootloader的方式比起來,這樣做會多一次LJMP跳轉(zhuǎn),但是一般情況下影響不大。
關(guān)于bootloader存放位置:
備注:其實,最好是將bootloader程序放到最后,這樣,應(yīng)用程序起始地址,中斷地址等不用設(shè)置,默認程序從0x0000h開始執(zhí)行,然后用函數(shù)指針跳轉(zhuǎn)到bootloader 程序起始地址,讓其先執(zhí)行。通過bootloader內(nèi)部程序選擇是否升級應(yīng)用程序還是直接跳轉(zhuǎn)回應(yīng)用程序區(qū)執(zhí)行。
若升級,就讀寫flash的應(yīng)用程序部分。若不升級,就跳轉(zhuǎn)回應(yīng)用程序繼續(xù)運行。
BOOTLOADER 程序舉例:
#include<reg52.h>
//用戶程序起始地址
#define USER_APP_ADDR 0x1000
char power_on_test(void);
char check_upgrade_request(void);
char upgrade(void);
void main(void)
{
//定義一個函數(shù)指針,用于跳轉(zhuǎn)到用戶程序
void (*boot)() = USER_APP_ADDR;
//bootloader里不能開啟中斷
EA = 0;
//添加系統(tǒng)初始化代碼
if(power_on_test()){//開機自檢
upgrade();
}
else if
(check_upgrade_request()){//檢查是否有升級需求
upgrade();
}
//如果不需要升級,或者升級已經(jīng)完成,執(zhí)行下面的代碼進入用戶程序
(*boot)();
//正常情況下不會運行到這里,以防萬一
while(1);
}
char power_on_test(void)
{
//添加開機自檢代碼,如果自檢錯誤,進入升級模式
return 0;
}
char check_upgrade_request(void)
{
//添加檢查用戶是否有升級要求的代碼,例如輸入命令或按下按鍵,如果有,則進入升級模式
return 0;
}
char upgrade(void)
{
//添加傳輸升級文件和升級用戶程序區(qū)的代碼
return 1;
}
用戶程序:
#include<reg52.h>
//main函數(shù)無特殊要求
void main(void)
{
while(1);
}
//中斷函數(shù)無特殊需求,可根據(jù)需求隨意添加
void UART_ISR(void) interrupt 4
{
return;
}
工程配置如下
51hei.png (194.48 KB, 下載次數(shù): 88)
下載附件
2020-4-12 16:24 上傳
51hei.png (99.6 KB, 下載次數(shù): 106)
下載附件
2020-4-12 16:24 上傳
六,關(guān)于升級文件
升級文件的傳輸可以根據(jù)需要使用任何方式,例如串口,網(wǎng)絡(luò),USB,存儲卡等。升級文件的傳輸可以做在bootloader里,也可以做在用戶程序里,或者兩種方式都有。一般來說,bootloader的代碼比較簡單,不適合做復(fù)雜的傳輸方式。如果傳輸方式比較復(fù)雜,可以在用戶程序里傳輸升級文件,暫存到一個外部存儲器,然后跳轉(zhuǎn)到bootloader,讓bootloader從外部存儲器讀出并升級用戶程序。升級的時候要注意用戶代碼的范圍。
為了傳輸?shù)目煽啃裕壩募话氵會添加一個文件頭,里面包含一些基本的文件信息,例如長度,校驗等,這些可以通過編寫一些簡單的工具來完成。
另外,推薦一些升級文件的傳輸方式,做bootloader的時候可以考慮
1, 串口。可以考慮使用XMODEM協(xié)議傳輸升級文件,因為這是一個比較標準的傳輸協(xié)議,很多現(xiàn)成的軟件可以支持,例如Windows下自帶的超級終端就可以實現(xiàn)(XP以后的系統(tǒng)沒有超級終端,但是也有一些別的軟件可以代替,例如SecureCRT)
2, USB主機。可以用U盤方式升級。升級文件取一個特定文件名,放在特定位置,主機讀取到文件后自動升級
3, USB從機。可以讓從機虛擬成一個U盤,PC把文件復(fù)制到這個虛擬U盤就完成升級。這樣就不需要編寫專門的升級軟件
4, 以太網(wǎng)。
a) TFTP,這是標準的文件傳輸命令,Windows自帶,而且協(xié)議簡單
b) Web。用網(wǎng)頁的方式,界面有好直觀,用網(wǎng)頁瀏覽器就可以實現(xiàn),也不用單獨開發(fā)專用的升級軟件。
全部程序51hei下載地址:
關(guān)于8051的bootloader實現(xiàn)方式.rar
(2.99 KB, 下載次數(shù): 109)
2020-4-12 09:38 上傳
點擊文件名下載附件
下載積分: 黑幣 -5
|