Operace nad flash prováděné za běhu aplikace v mikrokontroleru MC9S08x
Několik funkcí v C a v Asembleru do předmětu Mikroprocesorové a vestavěné systémy, které implementují některé operace prováděné s pamětí flash mikrokontrolérů rodiny MC9S08 firmy Freescale. Na požádání k nim můžu zaslat i česky psané vývojové diagramy.
POZN.: Všechny uvedené funkce předpokládají na začátku programu správně inicializovanou paměť Flash nastavením správné frekvence hodin paměti v registru FCDIV.
Funkce nejsou řádně otestované přímo na kontroléru a kód uvedený v této zprávě se může lišit od kódu v odevzdaných zdrojových souborech, protože jej často bylo nutno krátit či pro názornost jinak upravit.
Ověření prázdnosti (BlankCheck)
Funkce vykoná příkaz ověření prázdnosti nad pamětí Flash a nastaví příslušný bit stavového registru Flash jako výsledek. Hodnota tohoto bitu je předána volajícímu programu jako návratová hodnota a jedná se tak o jedinou funkci s návratovou hodnotou jinou než udávající, zda došlo k chybě či nikoliv.
Funkce nemá žádné parametry a žádné specifické počáteční podmínky pro své volání. Při operaci se sice zapisuje do bufferu paměti, ale adresa ani data nemají vliv na průběh operace.
Návratová hodnota je buď paměť je prázdná nebo paměť není prázdná nebo chyba. V jazyce symbolických instrukcí je návratová hodnota předána volajícímu programu skrze střadač.
byte BlankCheck(void) { if (FSTAT_FACCERR) FSTAT_FACCERR = 1; while (!FSTAT_FCBEF); *((word *)0xDD00) = 0; FCMD = mBlank; FSTAT_FCBEF = 1; _asm NOP; // 4x if (FSTAT_FACCERR || FSTAT_FPVIOL) return FAILURE; while (!FSTAT_FCCF); return FSTAT_FBLANK; }
blank_check: lda #(mFSTAT_FPVIOL+mFSTAT_FACCERR) sta FSTAT ldhx #$AFBE sta 0,x lda #mBlank sta FCMD lda #mFSTAT_FCBEF sta FSTAT nop brset FSTAT_FACCERR, FSTAT, error brset FSTAT_FPVIOL, FSTAT, error done: lda FSTAT lsla bpl done error: RTS
Programování bytu (ByteProgram)
Funkce zapisující právě jeden byte do paměti Flash vykonáním specifického příkazu. Zápis je možný pouze do nechráněné části paměti. Také není dovoleno přepsat jakýkoliv byte paměti, aniž by zápis nepředcházelo jeho smazání k tomu určenou operací.
První ze dvou parametrů udává adresu ve Flash, kam se mají data uložit, zatímco druhým parametrem jsou právě tato data.
V asemblerovské verzi rutiny je adresa místa v paměti předána v registru H:X. Byte dat určený k zápisu je předán přes zásobník.
Návratovou hodnotou funkce je úspěšnost operace zápisu.
byte ByteProgram(byte*addr,byte data) { if (FSTAT_FACCERR FSTAT_FACCERR = 1; while (!FSTAT_FCBEF); *addr = data; FCMD = mByteProg; FSTAT = 0x80; _asm NOP; // 4x if (FSTAT_FACCERR || FSTAT_FPVIOL) return FAILURE; while (!FSTAT_FCCF); return SUCCESS; }
byte_program: lda #(mFSTAT_FPVIOL+mFSTAT_FACCERR) sta FSTAT lda 3,SP sta ,X lda #mByteProg sta FCMD lda #mFSTAT_FCBEF sta FSTAT nop brset FSTAT_FACCERR, FSTAT, error brset FSTAT_FPVIOL, FSTAT, error done: lda FSTAT lsla bpl done error: RTS
Smazání stránky (PageErase)
U kontrolérů řady MC9S08 je nejmenší možná jednotka pro operaci mazání Flash paměti jedna stránka, tedy 512 bytů. Je-li požadováno smazání jednoho bytu, není jiná možnost než smazat celou stránku, ve které se tento byte nachází. Funkce PageErase vymaže obsah stránky identifikované adresou jakéhokoli bytu, který obsahuje. Není možno smazat stránku v chráněném bloku paměti.
Parametrem funkce je adresa libovolné slabiky nacházející se ve stránce, která je určena ke smazání.
V jazyce symbolických instrukcí je adresa předána uložením do registru H:X před rozvětvením do rutiny.
Návratová hodnota udává úspěšnost operace mazání stránky.
byte PageErase(byte*addr) { if (FSTAT_FACCERR FSTAT_FACCERR = 1; while (!FSTAT_FCBEF); *addr = 0; FCMD = mPageErase; FSTAT_FCBEF = 1; _asm NOP; // 4x if (FSTAT_FACCERR || FSTAT_FPVIOL) return FAILURE; while (!FSTAT_FCCF); return SUCCESS; }
page_erase: lda #(mFSTAT_FPVIOL+mFSTAT_FACCERR) sta FSTAT sta 0,X clr ,X lda #mPageErase sta FCMD lda #mFSTAT_FCBEF sta FSTAT nop brset FSTAT_FACCERR, FSTAT, error brset FSTAT_FPVIOL, FSTAT, error done: lda FSTAT lsla bpl done error: RTS
Smazání celé FLASH (MassErase)
Operace smazání celé paměti Flash.
Nejsou specifikovány žádné vstupní parametry. Součástí operace je sice také zápis do paměti, ale podobně jako u ověření prázdnosti tento zápis nijak neovlivní její obsah ani průběh operace.
Funkce vrací úspěšnost operace jako návratovou hodnotu.
byte MassErase(void) { if (FSTAT_FACCERR FSTAT_FACCERR = 1; while (!FSTAT_FCBEF); *((word*)0xDD00) = 0; FCMD = mMassErase; FSTAT_FCBEF = 1; _asm NOP; // 4x if (FSTAT_FACCERR || FSTAT_FPVIOL) return FAILURE; while (!FSTAT_FCCF); return SUCCESS; }
mass_erase: lda #(mFSTAT_FPVIOL+mFSTAT_FACCERR) sta FSTAT ldhx #$AFBE sta 0,X lda #mMassErase sta FCMD lda #mFSTAT_FCBEF sta FSTAT nop brset FSTAT_FACCERR, FSTAT, error brset FSTAT_FPVIOL, FSTAT, error done: lda FSTAT lsla bpl done error: RTS
Programování v burst režimu (BurstProgram)
Obdobně jako u ByteProgram se jedná o funkci zprostředkující zápis do paměti Flash, avšak s tím rozdílem, že je možno zapsat více bytů během jednoho volání. Zapisovaná data musí ležet v paměti za sebou. Funkce je složitější o smyčku, ve které jsou zapisovány jednotlivé byty tak, jak jdou za sebou. Počet iterací je dán parametrem length.
Funkce má tři parametry a všechny jsou předány přes zásobník (i v asembleru). Těmito parametry jsou počáteční adresa zdroje dat, počáteční adresa místa paměti Flash, kam se data mají uložit a počet zapisovaných bytů.
Návratová hodnota je stejná jako u funkce zápisu jednoho bytu, tedy úspěch či případný neúspěch operace.
byte BurstProgram(byte*addr, byte*data, word length) { if (FSTAT_FACCERR FSTAT_FACCERR = 1; do { while (!FSTAT_FCBEF); *addr = *data++; FCMD = mBurstProg; FSTAT_FCBEF = 1; _asm NOP; // 4x if (FSTAT_FACCERR||FSTAT_FPVIOL) return FAILURE; addr++; } while (--length); while (!FSTAT_FCCF); return SUCCESS; }
burst_program: lda #(mFSTAT_FPVIOL+mFSTAT_FACCERR) sta FSTAT loop: lda FSTAT and #mFSTAT_FCBEF beq loop ldhx 5,SP lda ,X aix #1 sthx 5,SP ldhx 3,SP lda ,X aix #1 sthx 3,SP lda #mBurstProg sta FCMD lda #mFSTAT_FCBEF sta FSTAT nop brset FSTAT_FACCERR, FSTAT, error brset FSTAT_FPVIOL, FSTAT, error lda 7,SP deca sta 7,SP cmp #0 bne loop done: lda FSTAT lsla bpl done error: RTS
Vypnutí zabezpečení paměti (DisengageSecurity)
Paměť Flash u kontrolérů řady MC9S08 má svou vlastní ochranu před neoprávněným přepsáním. Tato ochrana se dá vypnout pouze buď v režimu background debug nebo za běžného chodu aplikace zadáním bezpečnostního kódu. Jedná se o osmi-bytový bezpečnostní kód uložený programátorem na jistém místě v paměti. Umožňuje-li aplikace uživateli vypínat ochranu paměti Flash, musí uživatel zadat bezpečnostní kód přes nějaké vstupní rozhraní. V této implementaci funkce vypnutí ochrany je použito rozhraní SCI, které po zavolání funkce očekává jednotlivé byty bezpečnostního kódu a pokud je všech osm slabik kódu správně zadáno, je zabezpečení vypnuto až do následujícího resetu.
Funkce nepřebírá žádné parametry, ale má specifické podmínky použití. Pokud není nastaven bit KEYEN registru FOPT paměti Flash, nemůže být zabezpečení vypnuto. Dále musí být umožněn uživatelský vstup přes rozhraní SCI.
Funkce nic nevrací, proto jediným způsobem, jak programově poznat, zda je ochrana vypnuta, je kontrola bitů SEC01:SEC00 registru NVOPT, které jsou vypnutím zabezpečení automaticky nastaveny na 1:0.
void DisengageSecurity(void) { if (FOPT_KEYEN == 0) return; _asm { mov #$00, SCI1BDH mov #$34, SCI1BDL mov #$04, SCI1C2 } FCNFG_KEYACC = 0x1; while (SCI1S1_RDRF != 1); *(byte *)0xFFB0 = SDI1D; // . . . 0xFFB1 – 0xFFB6 . . . while (SCI1S1_RDRF != 1); *(byte *)0xFFB7 = SDI1D; FCNFG_KEYACC = 0x0; }
disengage_security: lda NVOPT and #mNVOPT_KEYEN beq error mov #$00, SCI1BDH mov #$34, SCI1BDL mov #$04, SCI1C2 bset FCNFG_KEYACC,FCNFG brclr 5,SCI1S1,* lda SCI1D sta NVBACKKEY0 ; . . . NVBACKKEY1 - NVBACKKEY6 brclr 5,SCI1S1,* lda SCI1D sta NVBACKKEY7 bclr FCNFG_KEYACC,FCNFG RTS
Ochrana bloků paměti (FlashBlockProtection)
Programátor může zabezpečit určitou část paměti Flash, avšak vždy se jedná o část paměti od určité, programátorem zadané adresy, po konec adresového prostoru (adresa FFFF). Dá se tedy určit pouze začátek chráněného bloku paměti a to adresou. Funkce tuto adresu vezme, upraví na adresu posledního nechráněného bytu, z ní vezme nejvyšších osm bitů, přičemž jejich nejnižší bit vynuluje a takto upravenou adresu uloží do registru FPROT, čímž se ochrana aktivuje.
Jako parametr do funkce vstupuje adresa začátku chráněného bloku paměti Flash.
Funkce nemá žádnou návratovou hodnotu.
Kód v jazyce C void FlashBlockProtection(byte*addr) { byte tmp; --addr; tmp=(byte)(((word)addr&0xFE00)>>8); FPROT = tmp; }
flash_block_protection: ;address is in H:X register decx pshh pula and #%11111110 sta FPROT RTS