***************************************2017.6.6***************************************
最近在研究開發板遠程升級的事情,稍微記錄一下而已。功能大概是這樣的:一台放在室外的板子,需
要通過服務器給開發板上的4G模塊下發指令來進行遠程升級。
看了網上好多資料,多數人的方法和串口IAP在線升級是一個套路。大致就是如下:上電,從boot區啟動檢測有沒有新
的新用戶程序,有就跳入處理,沒有就跳到用戶代碼。具體的是,給開發板一個升級命令,下載升級包(注意校驗),置更
新升級標志,將升級包寫入到flash,清除更新升級標志,復位啟動。我說的太簡單,具體實現我還是有許多問題不知道怎
么實現,還需要在研究。
公司大牛前輩有給我指導,我也詢問了一些問題。首先,他建議我先實現串口在線升級。他說的過程大致如下,先給一
個開發板一個升級指令,開發板收到命令之后,跳轉到bootloader,置升級標志位,開始接收數據,校驗正確寫入RAM,一
包接收成功給外界一個回應,外界收到正確回應之后,繼續發送下一包數據......收到全部數據之后,寫入flash,清除升級標
志位,復位啟動。下面我說一些我的疑問和需要解決的問題。
(串口在線升級可以參考STM32F10x_AN2557_FW_V3.3.0示例代碼)
1.主要還是接收數據包的問題,怎么傳輸,校驗用什么方法校驗?
STM32F103串口升級用的是YModem這個文件傳輸協議,傳輸還是自擬協議好了,需要帶ACK;校驗的話我本來准備
用CRC16校驗,前輩建議我用XOR校驗。
2.怎么跳轉到相應的地址以及bootloader的地址是什么?
#define jump(TargetAddr ) (*((void(*)())(TargetAddr))()
bootloader是哪個地址?
3.怎么擦除flash,寫入flash?
4.RTC里面有個備份程序區,可以把更新升級標志位放在那里,不會因為斷電重啟而改變。
......姑且就這么多,一步一步解決吧。明天繼續
***************************************2017.6.7***************************************
1./*軟復位*/
NVIC_SystemReset(void);
2.stm32在線升級中的主要函數如下:
void Main_Menu(void)
{
uint8_t key = 0;
/* Get the number of block (4 or 2 pages) from where the user program will be loaded */
BlockNbr = (FlashDestination - 0x08000000) >> 12;
/* Compute the mask to test if the Flash memory, where the user program will be
loaded, is write protected */
#if defined (STM32F10X_MD) || defined (STM32F10X_MD_VL)
UserMemoryMask = ((uint32_t)~((1 << BlockNbr) - 1));
#else /* USE_STM3210E_EVAL */
if (BlockNbr < 62)
{
UserMemoryMask = ((uint32_t)~((1 << BlockNbr) - 1));
}
else
{
UserMemoryMask = ((uint32_t)0x80000000);
}
#endif /* (STM32F10X_MD) || (STM32F10X_MD_VL) */
/* Test if any page of Flash memory where program user will be loaded is write protected */
if ((FLASH_GetWriteProtectionOptionByte() & UserMemoryMask) != UserMemoryMask)
{
FlashProtection = 1;
}
else
{
FlashProtection = 0;
}
while (1)
{
SerialPutString("\r\n================== Main Menu ============================\r\n\n");
SerialPutString(" Download Image To the STM32F10x Internal Flash ------- 1\r\n\n");
SerialPutString(" Upload Image From the STM32F10x Internal Flash ------- 2\r\n\n");
SerialPutString(" Execute The New Program ------------------------------ 3\r\n\n");
if(FlashProtection != 0)
{
SerialPutString(" Disable the write protection ------------------------- 4\r\n\n");
}
SerialPutString("==========================================================\r\n\n");
key = GetKey();
if (key == 0x31)
{
/* Download user application in the Flash */
SerialDownload();
}
else if (key == 0x32)
{
/* Upload user application from the Flash */
SerialUpload();
}
else if (key == 0x33)
{
JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
/* Jump to user application */
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) ApplicationAddress);
Jump_To_Application();
}
else if ((key == 0x34) && (FlashProtection == 1))
{
/* Disable the write protection of desired pages */
FLASH_DisableWriteProtectionPages();
}
else
{
if (FlashProtection == 0)
{
SerialPutString("Invalid Number ! ==> The number should be either 1, 2 or 3\r");
}
else
{
SerialPutString("Invalid Number ! ==> The number should be either 1, 2, 3 or 4\r");
}
}
}
}
3.flash的地址(看datesheet)
program flash start_address:0x0000_0000 end_address:0x0007_FFFF
***************************************2017.6.8***************************************
1.前面的細節好像還沒有解決,先實現通過串口向開發板傳輸bin文件,大小是80KB,怎么分包傳輸,怎么校驗?
一包數據1.2KB,大概需要60包左右。我思考的是,70KB的文件怎么分包方便,怎么校驗
校驗部分:
uint8_t xor(char* source)
{
int j;
int slen=strlen(source);
uint8_t tmpstr = 0;
for(j=0;j<slen;j++)
{
tmpstr=tmpstr^source[j];
if(!tmpstr)
tmpstr=source[j];
}
source[j] = tmpstr;
return tmpstr;
}
上面參考的是網上的,下面是我自己調試可用的異或校驗:
uint8_t xor(uint8_t* source, uint16_t length)
{
uint16_t j;
uint8_t tmpstr = 0;
for(j=0;j<length-2;j++)
{
tmpstr=tmpstr^source[j];
tmpstr=source[j];
}
return tmpstr;
// if(tmpstr == source[length-3])//去掉0D,0A的幀尾
// return true;
// else
// return false;
}
分包部分:最大預算80包,每包1260個字節,開通的全局buffer是boot_array[80][1300];
接下來是分包組包,寫入flash。
***************************************2017.6.8***************************************
1.定義的buffer不能是boot_array[80][1300];,網上查了一下,好像是超過128KB的ram允許的范圍了,改為boot_array[75][1300];
網上說的原因:由於Kinetis K系列芯片使用的是ARM Cortex M4內核,其使用哈弗架構,內部的SRAM被分成了兩部分,通過不同的總線訪問。也就是說,SRAM分成了兩部分,雖然邏輯地址是連續的,但是這兩部分SRAM不能當成一個連續空間來使用。因此,請避免將heap大小設置超過1/2 SRAM大小,否則在使用過程中會產生錯誤。
2.定義分包協議
包頭:2個字節,包括總包數和現在第幾包。
內容:1250個字節
校驗:(XOR) 1個字節
幀尾:0x0D,0x0A
3.使用串口工具將bin文件發給板子,存在boot_arrat中,第1包就放在boot_array[0]中,第2包放在boot_array[1]中,第13包放在boot_array[12]中,類似存入buffer中。
*****問*****
怎么判定最后一包,且之前的每一包都正確收到???
————>每一包正確收到之后,會有反饋,收到反饋之后繼續發送下一包。如果某一包不成功,那就重新發送這一包。等能夠收到總包數和現在的包數一樣時,不就證明是最后一包了嗎,收到反饋之后,擦除flash,寫入falsh。
4.研究怎么擦除flash,怎么寫入flash
網上查資料和跑官網上給的flash例程。知道了怎么擦出一個大小是2KB的扇區,怎么檢驗是不是被擦除,怎么寫入一個扇區。
知道了flash扇區的每一塊的地址和總的地址范圍。
***************************************2017.6.16***************************************
這么多天沒寫,第一個就是突然插入支持其他的項目,然后每次調試的時候,flash擦除,讀寫有問題,一直拖到現在。剛才把flash讀寫搞定,發現擦除,寫入還是有一些講究的,擦出多大,寫入多少。。。