STM32 SD bootloader實現(xiàn)
前幾天在網(wǎng)上看到了一個sd bootloader,但是下載需要積分。于是想著自己寫個簡單的sd卡的bootloader,實際上就是stm32的iap功能了。簡單介紹一下stm32的iap吧,以下內(nèi)容摘抄自網(wǎng)絡。
IAP是In Application Programming的首字母縮寫,IAP是用戶自己的程序在運行過程中對User Flash的部分區(qū)域進行燒寫,目的是為了在產(chǎn)品發(fā)布后可以方便地通過預留的通信口對產(chǎn)品中的固件程序進行更新升級。
通常在用戶需要實現(xiàn)IAP功能時,即用戶程序運行中作自身的更新操作,需要在設計固件程序時編寫兩個項目代碼,第一個項目程序不執(zhí)行正常的功能操作,而只是通過某種通信管道(如USB、USART)接收程序或數(shù)據(jù),執(zhí)行對第二部分代碼的更新;第二個項目代碼才是真正的功能代碼。這兩部分項目代碼都同時燒錄在User Flash中,當芯片上電后,首先是第一個項目代碼開始運行,它作如下操作:
1)檢查是否需要對第二部分代碼進行更新
2)如果不需要更新則轉到4)
3)執(zhí)行更新操作
4)跳轉到第二部分代碼執(zhí)行
第一部分代碼必須通過其它手段,如JTAG或ISP燒入;第二部分代碼可以使用第一部分代碼IAP功能燒入,也可以和第一部分代碼一道燒入,以后需要程序更新是再通過第一部分IAP代碼更新。
對于STM32來說,因為它的中斷向量表位于程序存儲器的最低地址區(qū),為了使第一部分代碼能夠正確地響應中斷,通常會安排第一部分代碼處于Flash的開始區(qū)域,而第二部分代碼緊隨其后。
在第二部分代碼開始執(zhí)行時,首先需要把CPU的中斷向量表映像到自己的向量表,然后再執(zhí)行其他的操作。
如果IAP程序被破壞,產(chǎn)品必須返廠才能重新燒寫程序,這是很麻煩并且非常耗費時間和金錢的。針對這樣的需求,STM32在對Flash區(qū)域實行讀保護的同時,自動地對用戶Flash區(qū)的開始4頁設置為寫保護,這樣可以有效地保證IAP程序(第一部分代碼)區(qū)域不會被意外地破壞。
stm32的iap功能,官方也有com,i2c以及基于USB的DFU,大致原理都是前面所說的那樣。對于sd的bootloader,也就是前面所說的第一部分代碼實現(xiàn)的主要過程是使用fatfs系統(tǒng)讀取sd卡上的bin文件,并把數(shù)據(jù)寫到第二部分代碼的向量表起始位置,我的設定是0x8003000處。寫完后讀取flash校驗。就是如此的簡單,廢話不多說上代碼!
/*******************************************************************************
*FunctionName:main.
*Description:mainroutine.
*Input:None.
*Output:None.
*Return:None.
*******************************************************************************/
intmain(void)
{
DFU_Button_Config();
/*CheckiftheKeypush-buttononSTM3210x-EVALBoardispressed*/
if(DFU_Button_Read()!=0x00)
{/*Testifusercodeisprogrammedstartingfromaddress0x8003000*/
if(((*(__IOuint32_t*)ApplicationAddress)&0x2FFE0000)==0x20000000)
{/*Jumptouserapplication*/
JumpAddress=*(__IOuint32_t*)(ApplicationAddress+4);
Jump_To_Application=(pFunction)JumpAddress;
/*Initializeuserapplication'sStackPointer*/
__set_MSP(*(__IOuint32_t*)ApplicationAddress);
Jump_To_Application();
}
}/*OtherwiseentersDFUmodetoallowusertoprogramhisapplication*/
UsartInitilize();
RCC_HSICmd(ENABLE);
NVIC_Initilize();
ComPrint("**********************************n");
ComPrint("*STM32SDBootloader*n");
ComPrint("*V1.0*n");
ComPrint("**********************************n");
ComPrint("nSD-LODER:startflashprogram......n");
if(SD_Initilize()==SD_OK)
{
FRESULTstatus=FR_OK;
uint8_tflashProgramSuccess=0;
uint8_tcheckSum=0;
uint32_tsize=0;
uint32_tlength=0;
uint32_tsectorAddr=0;
uint32_ti=0,j=0,k=0,numberOfPage=0;
f_mount(0,&fsrc);
status=f_open(&fp,"upload.bin",FA_READ+FA_OPEN_EXISTING);
if(status==FR_OK&&(size=f_size(&fp))!=0)
{
ComPrint("nSD-LODER:openupload.binsuccess,size=%dKBnn",size/1024);
numberOfPage=size/FLASH_PAGE_SIZE+1;
Hal_Unlock();
for(i=0;i { ComPrint("*"); sectorAddr=ApplicationAddress+i*FLASH_PAGE_SIZE; Hal_Erase(sectorAddr); for(j=0;j { memset(MAL_Buffer,0x0,wTransferSize); status=f_read(&fp,MAL_Buffer,wTransferSize,&length); if(status!=FR_OK||length==0) { ComPrint("SD-LODER:nreadfilefailedwhenprogrampage%d!n",i); gotoEnd_Flash; }