在應(yīng)用編程MAXQ微控制器中可分區(qū)擦除的程序和數(shù)
以下匯編代碼實例采用間接尋址方法(查表)調(diào)用flashWrite()應(yīng)用例程。該例程可由C代碼調(diào)用。
; 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
在應(yīng)用編程
大多數(shù)基于閃存的系統(tǒng)要求,當(dāng)系統(tǒng)安裝到終端產(chǎn)品上以后,其固件必須具備升級的能力。這種功能稱為在應(yīng)用編程(IAP)。本節(jié)概述了創(chuàng)建一個IAP應(yīng)用程序的要領(lǐng)。上面列出的應(yīng)用ROM閃存例程,可完成閃存ROM所需要的所有擦除和寫入操作,從而允許用戶代碼對閃存進(jìn)行操作。與其他子程序調(diào)用相似,程序執(zhí)行完成之后,控制將返回到用戶代碼。
要實現(xiàn)可靠的IAP,引導(dǎo)裝載程序必須與主程序分開。這樣可以確保在經(jīng)歷一次未竟編程之后,可以重新啟動編程過程。
引導(dǎo)裝載程序
初始化以后,由于ROM跳轉(zhuǎn)至地址0x0000,因此,引導(dǎo)裝載程序的入口應(yīng)為0x0000。不同的MAXQ器件,其引導(dǎo)閃存分區(qū)的大小也不相同??梢愿鶕?jù)需要,將引導(dǎo)程序擴(kuò)展至多個閃存分區(qū),用戶應(yīng)用程序代碼不能使用已被占用的任何分區(qū)。擦除和寫入閃存時必須滿足的特定要求見表6。
表6. 調(diào)用應(yīng)用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中的流程說明了脫離復(fù)位狀態(tài)后MAXQ的操作。ROM進(jìn)行自診斷并確定閃存已經(jīng)準(zhǔn)備好以后,ROM初始化代碼直接跳轉(zhuǎn)到地址0x0000。請閱讀相關(guān)的數(shù)據(jù)手冊和用戶指南,確定您的MAXQ微控制器是否按照這個啟動順序運行。
圖4. ROM初始化流程示意
圖5給出了一個簡單的引導(dǎo)裝載程序的流程圖。當(dāng)使用引導(dǎo)裝載程序?qū)崿F(xiàn)IAP時,對于16kB (8K x 16)的引導(dǎo)裝載程序,主應(yīng)用程序的入口通常位于地址0x2000 + 標(biāo)題偏移,對于32kB (16K x 16)的引導(dǎo)裝載程序,則位于地址0x4000 + 標(biāo)題偏移。一個簡單的應(yīng)用程序標(biāo)題如下所示:
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;引導(dǎo)裝載程序可以利用此標(biāo)題所提供的信息確定主程序的有效性,如果需要,還可以報告其版本標(biāo)識。
圖5. 閃存引導(dǎo)裝載流程示意圖
編程過程本身非常簡單。首先調(diào)用flashEraseSector(),擦除含有主程序代碼的每個分區(qū)。然后調(diào)用flashWrite()逐字寫入要編程的代碼字。應(yīng)最先擦除含有應(yīng)用程序標(biāo)題的塊,而最后編程CRC數(shù)據(jù),以便將出現(xiàn)錯誤CRC匹配的概率降到最低。下面給出通過串口獲取數(shù)據(jù)來刷新微控制器的一個簡單例程:
/*// 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();}那些引導(dǎo)裝載程序沒有使用的程序空間,可用于其他例程和/或常數(shù)的存儲。一個很好的例子是將間接調(diào)用應(yīng)用ROM例程的所有子程序保存在這里,例如上面“應(yīng)用ROM閃存例程”中所給出的一些子程序。在引導(dǎo)程序分區(qū)存儲其他信息時需要注意:除非部分或全部擦除引導(dǎo)裝載程序自身,否則無法將其擦除。
采用基于RAM的閃存例程實現(xiàn)IAP
當(dāng)不要求故障恢復(fù)時,可采用基于RAM的閃存
評論