制限キューは、一定の項目数によって制限されたキューであり、通常、定期的にデータを処理するときに必ず使用されます。制限キューは、所望のデータブロックサイズに等しい、「エントリ」の固定長キューを作成することによって構成されます。エントリサイズはアプリケーションに固有な値です。また、最も近いページ消去の境界に切り上げる必要があります。注:消去することのできる最小サイズは2ページ/ワードです。データフラッシュは、アプリケーションの要件に応じて、さまざまな方法で分割することが可能ですが、データフラッシュには2ページ消去の制限があるため、エントリは2ページの倍数に限定されます。たとえば、512 x 16のデータフラッシュは16ワードの32エントリに分けることが可能であり、結果として、表4のようなメモリマップになります。
; This routine is callable by C code using the following prototype
; u16 flashWrite(u16 *pDest, u16 *pSrc);
;
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], ACC
move ACC, @DP[0] ; Retrieve the address of the routine.
push DP[1] ; Save Frame Pointer on the stack.
move DP[0],A[0] ; Move argument 0(dest address) to DP[0].
move DP[1],A[1] ; Move argument 1(src address) to DP[1].
call ACC ; Execute the routine.
pop DP[1] ; Restore Frame Pointer.
ret ; Status returned in A[0].
; This routine is callable by C code using the following prototype
; u16 flashErasePage(void *pAddress);
;
flashErasePage:
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], ACC
move ACC, @DP[0] ; Retrieve the address of the routine.
call ACC ; Execute the routine.
ret ; Status returned in A[0].
; 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], ACC
move ACC, @DP[0] ; Retrieve the address of the routine.
call ACC ; Execute the routine.
ret
; This routine is callable by C code using the following prototype
; u16 flashRead(u16 *pAddress);
;
flashRead:
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 #3 ; Add the index to the moveDP0 routine.
move DP[0], ACC
move ACC, @DP[0] ; Retrieve the address of the routine.
push DP[1] ; Save Frame Pointer on the stack.
move DP[0],A[0] ; Move argument 0(src address) to DP[0].
call ACC ; Execute the routine.
pop DP[1] ; Restore Frame Pointer.
move A[0],GR
ret ; Data word returned in A[0].
; 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 #15 ; Add the index to the flashEraseSector routine.
move DP[0], ACC
move ACC, @DP[0] ; Retrieve the address of the routine.
call ACC ; Execute the routine.
ret ; Status returned in A[0].
; This routine is callable by C code using the following prototype
; u16 dataFlashWrite(void *pAddress, u16 iData);
;
dataFlashWrite:
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 #16 ; Add the index to the flashWrite routine.
move DP[0], ACC
move ACC, @DP[0] ; Retrieve the address of the routine.
call ACC ; Execute the routine.
ret ; Status returned in A[0].
; This routine is callable by C code using the following prototype
; u16 dataFlashErasePage(void *pAddress);
;
dataFlashErasePage:
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 #18 ; Add the index to the dataFlashErasePage routine.
move DP[0], ACC
move ACC, @DP[0] ; Retrieve the address of the routine.
call ACC ; Execute the routine.
ret ; Status returned in A[0].
; This routine is callable by C code using the following prototype
; u16 dataFlashEraseSector(void *pAddress);
;
dataFlashEraseSector:
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 #19 ; Add the index to the dataFlashEraseSector routine.
move DP[0], ACC
move ACC, @DP[0] ; Retrieve the address of the routine.
call ACC ; Execute the routine.
ret ; Status returned in A[0].
; This routine is callable by C code using the following prototype
; void dataFlashEraseAll(void);
;
dataFlashEraseAll:
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 #20 ; Add the index to the flashEraseAll routine.
move DP[0], ACC
move ACC, @DP[0] ; Retrieve the address of the routine.
call ACC ; Execute the routine.
ret
typedef struct {
u16 iSize; // The size of the application in words
u32 iCRC; // The CRC of the application
u8 ID[8]; // ID string for current application
} APPLICATION_HEADER;
/*
// VerySimpleReFlash()
// As simple as it gets.
// Step 1. Wait for erase command, then erase flash.
// Step 2. Wait for program command, program flash one word at a time.
*/
void VerySimpleReFlash()
{
u16 iStatus; // The status returned from flash utility ROM calls
s32 iSize; // The size of the main code to program
u16 *pAddress = 0x2000; // The starting address of the main application
u16 i;
InitializeCOMM(); // Can be CAN or UART.
WaitForEraseCommand();
// Assume that application starts at the beginning of a sector.
for (i=C_START_SECTOR;i 0)
{
u16 iData[32];
Get32WordsFromCOMM(iData);
iStatus = flashWrite(pAddress, iData);
if (iStatus)
break;
pAddress += 32;
iSize -= 32;
UpdateWatchdog(); // Prevent timeout
}
SendFlashWriteResponse(iStatus);
ResetMicro();
}