STM32 IAP采用Ymodem協定更新固件
公司最近軟體需要通過IAP來更新所有闆卡的固件,其中闆卡有2塊,一塊主要闆卡,一塊子控闆卡。其中,主要闆卡與子控闆卡之間采用RS485通信,PC與主要闆卡采用RS232通信。
具體架構:
一、PC端與主要闆卡
首先,PC端與主要闆卡之間的更新采用正常的 Ymodem 協定傳輸,IAP 更新。可以參考ST官方的IAP工程
另外安福萊硬漢哥進行了整理可具體可參考 STM32-V5開發闆序列槽IAP操作說明
1.工作流程:
這裡,使用的STM32的型号為STM32F407ZET6 ,其FLASH大小是512KB,0x08000000為其FLASH被映射的位址,程式被燒寫到的就是這個位址。此處,我們的IAP程式燒寫到這個位址,根據IAP程式的大小,我們在keil裡可以設定合适的IAP結束位址。
2. 工程說明:
本項目用到的兩個工程可按照文末的方式擷取,其中IAP工程移植至ST官方例程。下面對兩個工程進行簡單的說明
IAP工程:
(1)需要在target頁籤裡設定我們IAP程式的起始位址與大小,如:
這裡我們的IAP程式起始位址設為0x08000000,大小設為0x4000,即IAP所能用的FLASH空間為16KB。其中IAP所能占的占空間的大小可根據IAP的實際大小進行修改。
(2)需要修改程式中我們需要跳轉到的應用程式的位址(即IAP程式的結束位址):
APP工程:
(1)需要在target頁籤裡設定我們LED程式的起始位址與大小,如:
這裡我們的APP程式起位址設為0x08004000,大小設為0x7C000,即APP所能用的FLASH空間為496KB(總容量為512K,IAP占用16K)。其中結束位址可根據APP應用程式的實際大小進行修改。
(2). 設定中斷向量表的偏移(依據實際情況設定)
(3). bin檔案生成。
3.IAP軟體流程
代碼:
while (1)
{
if(!Check_App_Flag())
{
SerialDownload();
}
else if (RTC_ReadBackupRegister(RTC_BKP_DR0) == UPDATA_APP)
{
updata_fpga_flag = RTC_ReadBackupRegister(RTC_BKP_DR0);
RTC_WriteBackupRegister(RTC_BKP_DR0,0);
SerialDownload();
}
else if (RTC_ReadBackupRegister(RTC_BKP_DR0) == UPDATA_FPGA)
{
updata_fpga_flag = RTC_ReadBackupRegister(RTC_BKP_DR0);
RTC_WriteBackupRegister(RTC_BKP_DR0,0);
SerialDownload();
}
else if (RTC_ReadBackupRegister(RTC_BKP_DR0) == UPDATA_DRIVER)
{
updata_fpga_flag = RTC_ReadBackupRegister(RTC_BKP_DR0);
RTC_WriteBackupRegister(RTC_BKP_DR0,0);
printf("\r\nUpdata Driver open USART_IT_RXNE and USART_IT_IDLE\n\r");
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);/* 使能接收完成中斷 */
USART_ITConfig(USART1,USART_IT_IDLE,ENABLE); //開啟序列槽空閑中斷
while (1)
{
//判斷資料是否進入驅動闆APP
if(g_ucDriverUpdataSuccess == 1)
{
printf("exit yi ci \r\n");
break;
}
LED4_Out() = 1;
delay_ms(500);
LED4_Out() = 0;
delay_ms(500);
}
USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);/* 關閉接收完成中斷 */
USART_ITConfig(USART1,USART_IT_IDLE,DISABLE); //關閉序列槽空閑中斷
USART_ITConfig(RS485_USART, USART_IT_TC, DISABLE);
USART_ITConfig(RS485_USART, USART_IT_RXNE, DISABLE);
}
else
{
printf("\r\nLoad APP");
Iap_Load_App(APPLICATION_ADDRESS);
}
}
其中判斷校驗位置處是否有APP應用程式,采用 flash 位址的最後4個位元組作為校驗位,正常燒錄正确以後,在 flash 位址的最後4個位元組處寫入 0x5A5A。
然後開機的時候 首先讀取該位址處的校驗位是否正确,不正确,則表示上一次燒錄錯誤,需要重新更新。正确則判斷是否有更新标志。
這裡的更新标志采用“備份域寄存器”中讀取資料。“備份域寄存器”是 可以用于存儲掉電不丢失的資料(需要RTC紐扣電池支援)。當我們從APP中接收到需要更新APP的指令,這個時候,我們往“備份域寄存器”中寫入 0x5050 表示需要更新APP。如果是接收到更新FPGA的指令,則寫入0x7070。然後執行軟體複位操作,從APP跳轉IAP。IAP中判斷“備份域寄存器”的值,然後執行響應的更新操作。
-------------------------------------------------------------------------------------------------------------------------------------------
二、PC端與子控制闆卡
pc端更新子控闆卡有2種方案:
- Ymodem協定校驗發生在PC端與子控闆卡,這個時候,主要闆卡訓示做一個資料的轉發,說白了:序列槽1從PC端接收到了什麼資料,就通過序列槽2發生出去給子控制闆。序列槽2從子控制闆中接收到什麼資料,就從序列槽1發送給PC端。
- Ymodem協定校驗發生在PC端與主要闆卡。主要闆卡接收到正确的一幀資料後,啟動485 發送給子控闆卡。子控闆卡接收以後直接寫入flash。
方案一:
我們先來說說第一種情況,具體框圖如下:
這裡有一個點需要注意的地方就是,主要闆卡與子控闆卡通信是采用485通信,是以需要嚴格的控制 RS485_EN 使能引腳的時序。否則會導緻資料發送錯誤。
目前,我采用的方案是通過開啟幾個中斷來控制 RS485_En 使能引腳的時序,
開啟主要闆卡序列槽1 的接收完成中斷,和序列槽1的空閑中斷。
開啟子控制闆卡的接收完成中斷,和發送完成中斷。
主要闆卡中,序列槽1接收到一個位元組後,進入中斷,使能RS485_En引腳,控制發送,将資料轉發給序列槽2發送出去,并且清零标志。
當檢測到序列槽空閑中斷後,485資料發送完成标志置1。
在子控制闆卡中,發送完成中斷用來将 RS485_En 使能切換為接收模式。其中,前提是需要判斷接收完成标志是否置一。
子控制闆的接收完成中斷,是用來判斷,子控制闆是否燒錄完成進入 APP。進入APP以後,會發送指令“$Load Driver”。
主要闆接收到指令後,标志置一。跳出IAP 。進入APP。
經過測試,第一種方案可行。并且穩定性還可以,協定發生需要寫入的控制闆卡中,這樣不容易出現資料丢失的問題。
方案二:
Ymodem 協定傳輸校驗發生在PC端與控制闆卡之間,校驗通過後,将解析出的一幀資料包,通過啟動485發生給子控制闆卡,子控制闆卡接收後,寫入flash。
這種方案的好處是,控制闆卡 與 子控制闆卡之間沒有校驗,是以可以同時燒錄多個子控制闆卡。