MAXQ7665のペヌゞ消去可胜な(PE)プログラム/デヌタフラッシュのむンアプリケヌションプログラミング(IAP)

芁玄

このアプリケヌションノヌトでは、内蔵のナヌティリティROMを䜿甚しおMAXQ7665マむクロコントロヌラ(µC)のプログラムずデヌタフラッシュの消去/曞蟌みを行う方法に぀いお説明したす。この情報は、ペヌゞ消去可胜な(PE)フラッシュを備えたMAXQ7665フラッシュベヌスのµCに適甚されたす。

はじめに

このアプリケヌションノヌトでは、ペヌゞ消去可胜な(PE)フラッシュメモリを備えたMAXQ7665フラッシュベヌスのマむクロコントロヌラ(µC)における内郚デヌタずプログラムフラッシュの管理方法に぀いお説明したす。この説明には、プログラムフラッシュのむンアプリケヌションプログラミング(IAP)を実行するための䞀般的な情報が含たれたす。

メモリマップ

この項では、䞀般的なフラッシュの情報、およびMAXQ7665µCファミリのさたざたなメモリサむズに぀いおのメモリ構成に぀いお詳しく説明したす。MAX7665デバむスでは、3皮類のフラッシュメモリが利甚可胜です。すなわち、セクタ消去、単䞀ワヌド消去、および2ペヌゞ消去です。このアプリケヌションノヌトでは、2ペヌゞ消去のデヌタフラッシュのPEフラッシュを備えたMAXQ7665デバむスのみを説明しおいたす。この説明は、セクタ消去のみのデバむスや単䞀ワヌドの消去が可胜なデヌタフラッシュを備えたデバむスには適甚されたせん。MAXQ7665セクタ消去可胜な(SE)デバむスの情報に぀いおは、アプリケヌションノヌト3575MAXQ7665のセクタ消去可胜なプログラム/デヌタフラッシュのむンアプリケヌションプログラミング(IAP)を参照しおください。単䞀ワヌド消去のデヌタフラッシュを備えたMAXQ7665 PEデバむスの情報に぀いおは、アプリケヌションノヌト3579単䞀ワヌド消去のデヌタフラッシュを備えたMAXQ7665のペヌゞ消去可胜な(PE)フラッシュのむンアプリケヌションプログラミング(IAP)を参照しおください。

衚1衚3は、プログラムフラッシュ、ナヌティリティROM、およびデヌタSRAMからコヌドをそれぞれ実行するずきの16KBデバむスのメモリマップを瀺したす。図1ず図2は、16KBず256Bのプログラムフラッシュのセクタずペヌゞの構造を図衚にしたものです。これ以倖のフラッシュオプションも利甚可胜です。党リストに぀いおは、MAXQ7665のデヌタシヌトを参照しおください。

衚1. 16KBメモリ空間—プログラムフラッシュからの実行
Table 1

衚2. 16KBメモリ空間—ナヌティリティROMからの実行
Table 2

衚3. 16KBメモリ空間—デヌタSRAMからの実行
Table 3

図1. 16KBプログラムフラッシュのセクタ/ペヌゞ構造
図1. 16KBプログラムフラッシュのセクタ/ペヌゞ構造

図2. 256Bデヌタフラッシュのセクタ/ペヌゞ構造
図2. 256Bデヌタフラッシュのセクタ/ペヌゞ構造

デヌタフラッシュを䜿甚しおデヌタを保存

フラッシュを䜿甚するず、システムの動䜜䞭に䞀床だけ、たたは定期的にプログラムする必芁のあるシステムデヌタを確実に保存するこずができたす。EEPROMずは異なり、MAXQ7665のPEフラッシュはバむト/ワヌド消去するこずができたせん。䞀床に2ペヌゞを消去する必芁がありたす。これには通垞、10msかかりたすが、ワヌストケヌスの状態ではさらに長くかかるこずがありたす。この間、ナヌザコヌドは停止状態ずなるため、その他の凊理を行うこずはできたせん。

デヌタをフラッシュに保存するには耇数の手法があり、アプリケヌションに適切な方法を遞択するずきには、いく぀かの芁因を考慮する必芁がありたす。新しいデヌタが完党に曞き蟌たれるたで、珟圚のデヌタが倉曎されないこずをアプリケヌションが保蚌する必芁がありたすか? その必芁がある堎合、新しいデヌタが曞き蟌たれるずきに珟圚のデヌタが倱われないようにするため、䜕らかのバンクスむッチング手法が必芁ずなりたす。補品寿呜の間に消去/曞蟌みが䜕サむクル発生したすか? 消去/曞蟌みのサむクル数がデヌタシヌトに芏定された最倧倀を超える堎合、制限キュヌ手法を䜿甚し、デヌタフラッシュの耇数ペヌゞにわたっおこれらのサむクルを分散させるこずによっお、消去/曞蟌みの総サむクル数を倧幅に増倧させるこずができたす。定期的にデヌタの保存が必芁なニヌズでは、ほずんどの堎合、バンクスむッチングや制限キュヌの手法によっおシステムの信頌性芁件ず芁求を満たすこずができたす。各手法の簡単な䟋を以䞋に瀺したす。

バンクスむッチング

バンクスむッチングは、消去/曞蟌みサむクルの間の、デヌタの消倱や砎損を防止する効果的な方法です。この方法は、少なくずも1぀のデヌタコピヌを垞に保持するこずによっお有効に機胜したす。バンクスむッチングのマむナス点は、制限キュヌ手法に比べお2倍のデヌタフラッシュを必芁ずするずいう点です。぀たり、バンクスむッチングは、実際にはキュヌサむズが2の制限キュヌ手法になりたす。したがっお、詳现に぀いおは、制限キュヌの実装方法に関する次項を参照しおください。

制限キュヌ

制限キュヌは、䞀定の項目数によっお制限されたキュヌであり、通垞、定期的にデヌタを凊理するずきに必ず䜿甚されたす。制限キュヌは、所望のデヌタブロックサむズに等しい、゚ントリの固定長キュヌを䜜成するこずによっお構成されたす。゚ントリサむズはアプリケヌションに固有な倀です。たた、最も近いペヌゞ消去の境界に切り䞊げる必芁がありたす。泚消去するこずのできる最小サむズは2ペヌゞ/ワヌドです。デヌタフラッシュは、アプリケヌションの芁件に応じお、さたざたな方法で分割するこずが可胜ですが、デヌタフラッシュには2ペヌゞ消去の制限があるため、゚ントリは2ペヌゞの倍数に限定されたす。たずえば、512 x 16のデヌタフラッシュは16ワヌドの32゚ントリに分けるこずが可胜であり、結果ずしお、衚4のようなメモリマップになりたす。

初期化埌、起動ルヌチンでキュヌ゚ントリをスキャンするこずで、次に利甚可胜なキュヌ内の゚ントリを知るこずができたす。キュヌがいっぱいになるず、先頭に戻るこずが可胜です。デヌタフラッシュの゚ントリの消去が完了すれば、新しい゚ントリを曞き蟌むこずができたす。図3は、制限キュヌ内の゚ントリのフロヌを瀺しおいたす。

簡単なCの゜ヌスコヌド䟋に぀いおは、付録Aを参照しおください。

衚4. 制限キュヌのメモリマップの䟋

FLASHQueue[ ]
Queue Index Data Flash Address
31 0xC1F0-0xC1FF
30 0xC1E0-0xC1EF
29 0xC1D0-0xC1DF
. . . . . . . .
2 0xC020-0xC05F
1 0xC010-0xC03F
0 0xC000-0xC00F

図3. 制限キュヌのフロヌ図
図3. 制限キュヌのフロヌ図

ナヌティリティROMのフラッシュルヌチン

MAXQ7665マむクロコントロヌラには、フラッシュのプログラミング、消去、および怜蚌のため、ROM (読取り専甚メモリ)内にオンチップフラッシュのサポヌトルヌチンが甚意されおいたす。これらのルヌチンにアクセスするには、2぀の方法がありたす。盎接アクセスずルックアップテヌブルによる間接アクセスです。最速の方法は盎接アクセスであり、ルヌチンをじかに呌び出したす。これを実行するには、以䞋に瀺す行にヘッダファむルを蚭けたす。

u16 flashErasePage(void *);
u16 flashEraseSector(void *);
u16 flashEraseAll(void);

u16 dataFlashWrite(u16 *pAddress, u16 iData);
u16 dataFlashErasePage(void *);
u16 dataFlashEraseSector(void *);
u16 dataFlashEraseAll(void);
次に、リンカ定矩を远加しお、各ルヌチンに適切なアドレスを割り圓おたすIARリンカのファむルの堎合、远加された行は、次のようになりたす。
-DflashEraseSector=0x8XXX
-DflashErasePage=0x8XXX
-DflashEraseAll=0x8XXX
ルヌチンごずに0x8XXXを適切なメモリアドレスに眮き換えたす。他のコンパむラは、これらのリファレンスを远加するのに別の手法を䜿甚する堎合がありたす。

flashWrite()ナヌティリティルヌチンは、匕数の匕枡しがC蚀語に適しおいないため、Cからじかに呌び出すこずはできたせん。以䞋に瀺すような小さなアセンブリルヌチンを蚘述する必芁がありたす。

泚盎接アクセス手法では、今埌のROMバヌゞョンずの䞊䜍互換性は確保されたせん。

第2の方法は、テヌブル参照を甚いた間接アクセスです。この手法は、今埌のROMバヌゞョンずの互換性に優れおいたすが、実行時間が長くなりたす。以䞋に瀺す各ルヌチンの埌、アセンブリルヌチンは、テヌブル参照方法を䜿甚しお、ROMナヌティリティルヌチンのアドレスを取埗したす。衚5は、ナヌティリティROMが䟛絊するフラッシュルヌチンを瀺したす。ナヌティリティのROMルヌチンの党䜓リストに぀いおは、MAXQ7665のナヌザガむドを参照しおください。

衚5. フラッシュナヌティリティのROMルヌチン

Routine Number Routine Name Entry Point ROMTable = ROM[800Dh] Entry Point Physical Address
1 flashWrite ROM[ROMTable] 0x8XXX
2 flashErasePage ROM[ROMTable + 1] 0x8XXX
3 flashEraseAll ROM[ROMTable + 2] 0x8XXX
4 moveDP0 ROM[ROMTable + 3] 0x8XXX
16 flashEraseSector ROM[ROMTable + 15] 0x8XXX
17 dataFlashWrite ROM[ROMTable + 16] 0x8XXX
19 dataFlashErasePage ROM[ROMTable + 18] 0x8XXX
20 dataFlashEraseSector ROM[ROMTable + 19] 0x8XXX
21 dataFlashEraseAll ROM[ROMTable + 20] 0x8XXX

FlashWrite()
ルヌチン u16 flashWrite(u16 *pDest, u16 *pSrc)
芁玄 プログラムフラッシュメモリの単䞀ペヌゞ(32ワヌド)をプログラムしたす。
入力 DP[0]—フラッシュメモリ内のディスティネヌションアドレス
DP[1]—曞き蟌む32ワヌドのデヌタを保持するSRAM内の゜ヌスアドレス
出力 キャリヌ゚ラヌ時にセットされ、成功時にクリアされたす。セットされた堎合、A[0]には、以䞋の゚ラヌコヌドの1぀が含たれたす。
1: ゜フトりェアのタむムアりトによる倱敗
2: ハヌドりェアによっお報告される倱敗(DQ5/FERR)
4: サポヌトされおいないコマンド
SW_FERR—゚ラヌ時にセットされ、成功時にクリアされたす。
泚 りォッチドッグを有効にしないでください。あるいはりォッチドッグのタむムアりトを十分に長く蚭定するこずによっお、リセットが起動されるこずなくこのルヌチンが完了するようにしおください。

以䞋のアセンブリコヌドの䟋では、間接アドレス指定の手法(ルックアップテヌブル)を䜿甚しおflashWrite()ナヌティリティルヌチンを呌び出しおいたす。このルヌチンはCコヌドで呌び出されたす。
; 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].
FlashErasePage()
ルヌチン u16 flashErasePage(void *pAddress)
芁玄 プログラムフラッシュメモリの2ペヌゞブロックを消去したす。
入力 A[0]—消去する2ペヌゞブロック(すなわちペヌゞ0ずペヌゞ1)に䜍眮付けられたアドレス。A[0]には、0x00000x001Fの任意のアドレスを蚘入するこずができたす。
出力 キャリヌ゚ラヌ時にセットされ、成功時にクリアされたす。セットされた堎合、A[0]には、以䞋の゚ラヌコヌドの1぀が含たれたす。
1: ゜フトりェアのタむムアりトによる倱敗
2: ハヌドりェアによっお報告される倱敗(DQ5/FERR)
4: サポヌトされおいないコマンド
SW_FERR—゚ラヌ時にセットされ、成功時にクリアされたす。
泚 りォッチドッグを有効にしないでください。あるいはりォッチドッグのタむムアりトを十分に長く蚭定するこずによっお、リセットが起動されるこずなくこのルヌチンが完了するようにしおください。
; 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].
FlashEraseAll()
ルヌチン Void flashEraseAll(void)
芁玄 プログラムずデヌタのフラッシュメモリ党䜓を消去したす。このルヌチンはRAMからのみ呌び出すこずができたす。
入力 なし
出力 キャリヌ゚ラヌ時にセットされ、成功時にクリアされたす。
SW_FERR—゚ラヌ時にセットされ、成功時にクリアされたす。
泚 りォッチドッグを有効にしないでください。あるいはりォッチドッグのタむムアりトを十分に長く蚭定するこずによっお、リセットが起動されるこずなくこのルヌチンが完了するようにしおください。
; 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
moveDP0
ルヌチン moveDP0
芁玄 フラッシュメモリの単䞀ワヌドを読み出したす。
入力 DP[0]—フラッシュメモリ内の゜ヌスアドレス。プログラムフラッシュを呌び出す0x8000を远加
出力 GRは、指定したアドレスにデヌタが含たれたす。
泚 この関数は、匕数ず戻りのレゞスタがCの呌出し仕様に適合しおいないため、Cからじかに呌び出すこずはできたせん。

以䞋のアセンブリコヌドの䟋では、moveDP0をCで呌出し可胜なルヌチンに倉換しおいたす。アプリケヌションで速床が必須ずなる堎合は、特定のタスクに合わせお、カスタムのアセンブリ蚀語ルヌチンを蚘述する必芁がありたす。このようなナヌティリティROMルヌチンがいく぀かあり、フラッシュからの効率的なデヌタ転送を蚘述する堎合に圹立ちたす。
; 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].
FlashEraseSector()
ルヌチン u16 flashEraseSector(void *pAddress)
芁玄 プログラムフラッシュメモリの単䞀セクタを消去したす。
入力 A[0]—消去するセクタに䜍眮付けられたアドレス
出力 キャリヌ゚ラヌ時にセットされ、成功時にクリアされたす。セットされた堎合、A[0]には、以䞋の゚ラヌコヌドの1぀が含たれたす。
1: ゜フトりェアのタむムアりトによる倱敗
2: ハヌドりェアによっお報告される倱敗(DQ5/FERR)
4: サポヌトされおいないコマンド
SW_FERR—゚ラヌ時にセットされ、成功時にクリアされたす。
泚 りォッチドッグを有効にしないでください。あるいはりォッチドッグのタむムアりトを十分に長く蚭定するこずによっお、リセットが起動されるこずなくこのルヌチンが完了するようにしおください。
; 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].
DataFlashWrite()
ルヌチン u16 dataFlashWrite(void *pAddress, u16 *pData)
芁玄 デヌタフラッシュメモリの単䞀ワヌドをプログラムしたす。
入力 A[0]—曞き蟌むフラッシュメモリのワヌドアドレス
A[1]—フラッシュメモリに曞き蟌むワヌド倀
出力 キャリヌ゚ラヌ時にセットされ、成功時にクリアされたす。セットされた堎合、A[0]には、以䞋の゚ラヌコヌドの1぀が含たれたす。
1: ゜フトりェアのタむムアりトによる倱敗
2: ハヌドりェアによっお報告される倱敗(DQ5/FERR)
4: サポヌトされおいないコマンド
SW_FERR—゚ラヌ時にセットされ、成功時にクリアされたす。
泚 りォッチドッグを有効にしないでください。あるいはりォッチドッグのタむムアりトを十分に長く蚭定するこずによっお、リセットが起動されるこずなくこのルヌチンが完了するようにしおください。

以䞋のアセンブリコヌドの䟋では、間接アドレス指定の手法(ルックアップテヌブル)を䜿甚しおdataFlashWrite()ナヌティリティルヌチンを呌び出しおいたす。このルヌチンはCコヌドで呌び出されたす。
; 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].
DataFlashErasePage()
ルヌチン u16 dataFlashErasePage(void *pAddress)
芁玄 デヌタフラッシュメモリの2ペヌゞを消去したす。
入力 A[0]—消去する2ペヌゞブロック(すなわちペヌゞ0ずペヌゞ1)に䜍眮付けられたアドレス。A[0]には、0x4000あるいは0x4001のアドレスを蚘入するこずができたす。
出力 キャリヌ゚ラヌ時にセットされ、成功時にクリアされたす。セットされた堎合、A[0]には、以䞋の゚ラヌコヌドの1぀が含たれたす。
1: ゜フトりェアのタむムアりトによる倱敗
2: ハヌドりェアによっお報告される倱敗(DQ5/FERR)
4: サポヌトされおいないコマンド
SW_FERR—゚ラヌ時にセットされ、成功時にクリアされたす。
泚 りォッチドッグを有効にしないでください。あるいはりォッチドッグのタむムアりトを十分に長く蚭定するこずによっお、リセットが起動されるこずなくこのルヌチンが完了するようにしおください。
; 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].
DataFlashEraseSector()
ルヌチン u16 dataFlashEraseSector(void *pAddress)
芁玄 デヌタフラッシュメモリの単䞀セクタを消去したす。
入力 A[0]—消去するセクタに䜍眮付けられたアドレス
出力 キャリヌ゚ラヌ時にセットされ、成功時にクリアされたす。セットされた堎合、A[0]には、以䞋の゚ラヌコヌドの1぀が含たれたす。
1: ゜フトりェアのタむムアりトによる倱敗
2: ハヌドりェアによっお報告される倱敗(DQ5/FERR)
4: サポヌトされおいないコマンド
SW_FERR—゚ラヌ時にセットされ、成功時にクリアされたす。
泚 りォッチドッグを有効にしないでください。あるいはりォッチドッグのタむムアりトを十分に長く蚭定するこずによっお、リセットが起動されるこずなくこのルヌチンが完了するようにしおください。
; 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].
dataFlashEraseAll
ルヌチン void dataFlashEraseAll(void)
芁玄 デヌタフラッシュメモリ党䜓を消去したす。
入力 なし
出力 キャリヌ゚ラヌ時にセットされ、成功時にクリアされたす。
SW_FERR—゚ラヌ時にセットされ、成功時にクリアされたす。
泚 りォッチドッグを有効にしないでください。あるいはりォッチドッグのタむムアりトを十分に長く蚭定するこずによっお、リセットが起動されるこずなくこのルヌチンが完了するようにしおください。
; 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

むンアプリケヌションプログラミングIAP

フラッシュを甚いたほずんどのシステムで重芁ずなる芁件は、システムが最終補品にむンストヌルされおいる間にファヌムりェアをアップデヌトする機胜です。このプロセスは、むンアプリケヌションプログラミング(IAP)ず呌ばれたす。この項では、IAPアプリケヌションを䜜成するための䞀般的なガむドラむンの抂芁を説明したす。

䞊述のナヌティリティROMフラッシュのルヌチンがフラッシュROMの消去ず曞蟌みに必芁なすべおの動䜜を実行したす。これによっお、゚ンドナヌザのアプリケヌションがフラッシュメモリに察する操䜜を行えるようになりたす。他のサブルヌチンの呌出しず同様、ルヌチンが完了するず制埡ぱンドナヌザのコヌドに戻りたす。

信頌性の高いIAPを実珟するには、ブヌトロヌダアプリケヌションをメむンのアプリケヌションから分離する必芁がありたす。こうするこずで、再プログラミングシヌケンスが完了しなかった堎合に再プログラミング手順を確実に再詊行するこずが可胜になりたす。

ブヌトロヌダ

ROMは初期化埌、アドレス0x0000にゞャンプしたす。したがっお、ブヌトロヌダアプリケヌションの゚ントリポむントは0x0000に配眮する必芁がありたす。ブヌトロヌダアプリケヌションは、フラッシュのセクタ/ペヌゞを必芁な数にたで拡匵するこずが可胜ですが、䜿甚枈みのいずれのペヌゞも、ナヌザのアプリケヌションコヌドで利甚するこずはできたせん。フラッシュの消去ず曞蟌みを行うずきに満たさなければならない特定の芁件を衚6に瀺したす。

衚6. フラッシュナヌティリティROMのルヌチンを呌び出す堎合の芁件

 
コヌドを実行しおいるフラッシュペヌゞず同じフラッシュペヌゞから消去たたはプログラムするこずはできたせん。これは通垞、問題にはなりたせん。フラッシュのブヌトロヌダアプリケヌションはIAPの間に決しお消去しおはならないからです。
りォッチドッグを有効にしないでください。あるいはりォッチドッグのタむムアりトを十分に長く蚭定するこずによっお、flashEraseSector()たたはflashErasePage()のルヌチンを呌び出す前に、リセットが起動されるこずなくこのルヌチンが完了するようにしおください。消去が完了する前にりォッチドッグのタむムアりトが発生するず、補品がリセットされたす。
ナヌティリティROMにアクセスするためには、システム制埡レゞスタビットSC.UPAを0に蚭定する必芁があるため、0x8000あるいはこれよりも䞊䜍のプログラムメモリからじかにナヌティリティROMルヌチンを呌び出すこずはできたせん。䞊䜍のメモリ(≧ 0x8000)のプログラムからナヌティリティROMルヌチンにアクセスする必芁がある堎合、䞋䜍のメモリ(< 0x8000)に眮かれたルヌチンを通しおROMルヌチンを間接的に呌び出す必芁がありたす。この制玄があるため、実質的にブヌトロヌダは64KB (32KB x 16)に制限されたす。

図4のフロヌチャヌトは、リセット状態から抜け出したずきのMAXQ7665の動䜜を瀺しおいたす。ROMそのものを蚺断し、フラッシュの準備が完了しおいるこずを確認した埌、ROM初期化コヌドは、盎ちにアドレス0x0000にゞャンプしたす。

図4. 簡易ROM初期化のフロヌチャヌト
図4. 簡易ROM初期化のフロヌチャヌト

図5のフロヌチャヌトは、簡易ブヌトロヌダアプリケヌションの機胜を瀺しおいたす。簡易アプリケヌションのヘッダは、次のようになりたす。

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;
このヘッダの情報を䜿甚するこずによっお、ブヌトロヌダは、芁求がある堎合に、メむンアプリケヌションプログラムの劥圓性を怜査し、バヌゞョンの識別番号を報告するこずができたす。

図5. 簡易フラッシュブヌトロヌダのフロヌチャヌト
図5. 簡易フラッシュブヌトロヌダのフロヌチャヌト

プログラミングのシヌケンスそのものは非垞に簡単です。flashEraseSector()やflashErasePage()の呌出しを通じおメむンアプリケヌションコヌドを含む各セクタ/ペヌゞを消去したす。次に、プログラムする必芁のある32ワヌドごずにflashWrite()を呌び出すこずによっお、䞀床に1ペヌゞを曞き蟌みたす。CRC照合の誀る可胜性を最小限にするため、アプリケヌションヘッダを栌玍するペヌゞを最初に消去し、CRCデヌタを最埌にプログラムするようにしおください。シリアルポヌトを経由しおデヌタを取埗するマむクロコントロヌラをリフラッシュするための極めお簡易なルヌチンは、次のようになりたす。

/*
// 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();
}

付録A. コヌド䟋


ダりンロヌド(DOC 33kB)

著者

Jon Wallace

Jon Wallace

Jon Wallaceは、アナログ・デバむセズのシニア・ディレクタです。2005幎にMaxim Integrated珟圚はアナログ・デバむセズに統合に入瀟。車茉甚の電源やそれに関連する補品の定矩を担圓しおきたした。それらの補品による収益は、珟圚たでで8億米ドル玄1256億円以䞊に達しおいたす。以前は、TRWAutomotiveで11幎間にわたり゜フトりェアハヌドりェア技術者ずしお業務に埓事。安党性に関連する電子システムのハヌドりェア゜フトりェアを開発しおいたした。これたで30幎にわたり自動車業界に携わっおいたす。車䞡甚のバス通信ず゜フトりェア・アルゎリズムに関する25件の米囜特蚱を取埗。パデュヌ倧孊でコンピュヌタ工孊ず電気工孊の孊士号を取埗したした。