在應用編程MAXQ微控制器中可分區(qū)擦除的程序和數
以下匯編代碼實例采用間接尋址方法(查表)調用flashWrite()應用例程。該例程可由C代碼調用。
; This routine is callable by C code using the following prototype; u16 flashWrite(u16 *pAddress, u16 iData);;flashWrite:move APC, #0 ; No auto inc/dec of accumulator.move AP, #2 ; Set ACC to A[2]move DP[0], #0800Dh ; This is where the address of the table is stored.move ACC, @DP[0] ; Get the location of the routine table.add #14 ; Add the index to the flashWrite routine.move DP[0], ACCmove ACC, @DP[0] ; Retrieve the address of the routine.call ACC ; Execute the routine.ret ; Status returned in A[0]flashEraseSector
Routine | u16 flashEraseSector(void *pAddress) |
Summary | Erases a single sector of flash memory |
Inputs | A[0] - Address located in the sector to erase. |
Outputs | Carry: Set on error and cleared on success. If set, then A[0] contains one of the following error codes: 1 : failure due to software timeout 2 : failure reported by hardware (DQ5/FERR) 4 : command not supported SW_FERR - Set on error, cleared on success. |
Notes | The watchdog must not be active, or the watchdog timeout must be set long enough to complete this routine without triggering a reset. |
; This routine is callable by C code using the following prototype; u16 flashEraseSector(void *pAddress);;flashEraseSector:move APC, #0 ; No auto inc/dec of accumulator.move AP, #1 ; Set ACC to A[1]move DP[0], #0800Dh ; This is where the address of the table is stored.move ACC, @DP[0] ; Get the location of the routine table.add #1 ; Add the index to the flashEraseSector routine.move DP[0], ACCmove ACC, @DP[0] ; Retrieve the address of the routine.call ACC ; Execute the routine.ret ; Status returned in A[0]flashEraseAll
Routine | void flashEraseAll(void) |
Summary | Erases the entire program and data flash memory, including the boot loader sector. This routine is not normally used for IAP, as great care must be taken to ensure that the erase/programming sequence is not interrupted. |
Inputs | None |
Outputs | Carry: Set on error and cleared on success.SW_FERR: Set on error, cleared on success. |
Notes | The watchdog must not be active, or the watchdog timeout must be set long enough to complete this routine without triggering a reset. |
; This routine is callable by C code using the following prototype; void flashEraseAll(void);;flashEraseAll:move APC, #0 ; No auto inc/dec of accumulator.move AP, #0 ; Set ACC to A[0]move DP[0], #0800Dh ; This is where the address of the table is stored.move ACC, @DP[0] ; Get the location of the routine table.add #2 ; Add the index to the flashEraseAll routine.move DP[0], ACCmove ACC, @DP[0] ; Retrieve the address of the routine.call ACC ; Execute the routine.ret
在應用編程
大多數基于閃存的系統(tǒng)要求,當系統(tǒng)安裝到終端產品上以后,其固件必須具備升級的能力。這種功能稱為在應用編程(IAP)。本節(jié)概述了創(chuàng)建一個IAP應用程序的要領。上面列出的應用ROM閃存例程,可完成閃存ROM所需要的所有擦除和寫入操作,從而允許用戶代碼對閃存進行操作。與其他子程序調用相似,程序執(zhí)行完成之后,控制將返回到用戶代碼。
要實現(xiàn)可靠的IAP,引導裝載程序必須與主程序分開。這樣可以確保在經歷一次未竟編程之后,可以重新啟動編程過程。
引導裝載程序
初始化以后,由于ROM跳轉至地址0x0000,因此,引導裝載程序的入口應為0x0000。不同的MAXQ器件,其引導閃存分區(qū)的大小也不相同。可以根據需要,將引導程序擴展至多個閃存分區(qū),用戶應用程序代碼不能使用已被占用的任何分區(qū)。擦除和寫入閃存時必須滿足的特定要求見表6。
表6. 調用應用ROM閃存例程的要求
You cannot erase or program from the same flash sector from which you are executing code. This is not normally a problem since the flash Boot Sector should never be erased during IAP. |
The watchdog must not be enabled or the watchdog timeout must be set long enough to complete this routine without triggering a reset before the flashEraseSector() routine is called. If the watchdog time out occurs before the erase is complete, it will reset the part. Erasing a sector typically takes 0.7 seconds; it can take up to 15 seconds under worst case conditions. |
Since the System Control Register bit SC.UPA must be set to 0 to access the Utility ROM, a ROM Utility routine cannot be called directly from program memory addresses = 0x8000. If access to a Utility ROM routine is required from a program in upper memory (= 0x8000), the program must indirectly call the ROM routine through a routine residing in lower memory (0x8000). This effectively limits the boot loader to = 64kB (32kB x 16). |
圖4中的流程說明了脫離復位狀態(tài)后MAXQ的操作。ROM進行自診斷并確定閃存已經準備好以后,ROM初始化代碼直接跳轉到地址0x0000。請閱讀相關的數據手冊和用戶指南,確定您的MAXQ微控制器是否按照這個啟動順序運行。
圖4. ROM初始化流程示意
圖5給出了一個簡單的引導裝載程序的流程圖。當使用引導裝載程序實現(xiàn)IAP時,對于16kB (8K x 16)的引導裝載程序,主應用程序的入口通常位于地址0x2000 + 標題偏移,對于32kB (16K x 16)的引導裝載程序,則位于地址0x4000 + 標題偏移。一個簡單的應用程序標題如下所示:
typedef struct {u16 iSize; // The size of the application in wordsu32 iCRC; // The CRC of the applicationu8 ID[8]; // ID string for current application} APPLICATION_HEADER;引導裝載程序可以利用此標題所提供的信息確定主程序的有效性,如果需要,還可以報告其版本標識。
圖5. 閃存引導裝載流程示意圖
編程過程本身非常簡單。首先調用flashEraseSector(),擦除含有主程序代碼的每個分區(qū)。然后調用flashWrite()逐字寫入要編程的代碼字。應最先擦除含有應用程序標題的塊,而最后編程CRC數據,以便將出現(xiàn)錯誤CRC匹配的概率降到最低。下面給出通過串口獲取數據來刷新微控制器的一個簡單例程:
/*// VerySimpleReFlash()// As simple as it gets.// Step 1. Wait for erase command, then erase flash.// Step 2. Wait for program command, then program flash one word// at a time.*/void VerySimpleReFlash(){u16 iStatus; // The status returned from flash utility ROM callsu16 iSize; // The size of the main code to programu16 *pAddress = 0x2000; // The starting address of the main applicationInitializeCOMM(); // Can be CAN or UARTWaitForEraseCommand();SlowDownWatchdog(); // If watchdog enabled set update > 15siStatus = flashEraseSector(C_ADDRESS_SECTOR_1);if (iStatus == 0)iStatus = flashEraseSector(C_ADDRESS_SECTOR_2);UpdateWatchdog(); // Prevent watchdog timeoutSendFlashErasedResponse(iStatus);if (iStatus)ResetMicro();iSize = WaitForProgramCommand();while (iSize--){u16 iData = GetWordFromCOMM();iStatus = flashWrite(pAddress, iData);if (iStatus)break;++pAddress;UpdateWatchdog(); // Prevent watchdog timeout}SendFlashWriteResponse(iStatus);ResetMicro();}那些引導裝載程序沒有使用的程序空間,可用于其他例程和/或常數的存儲。一個很好的例子是將間接調用應用ROM例程的所有子程序保存在這里,例如上面“應用ROM閃存例程”中所給出的一些子程序。在引導程序分區(qū)存儲其他信息時需要注意:除非部分或全部擦除引導裝載程序自身,否則無法將其擦除。
采用基于RAM的閃存例程實現(xiàn)IAP
當不要求故障恢復時,可采用基于RAM的閃存
評論