Egy tipikus Cortex-M firmware-ben a fő ciklus szenzoradatot dolgoz fel, miközben egy UART-vevő megszakításkérés (interrupt request, IRQ) érkezik, egy timer lejár, és egy hiba miatt buszhitelesítési kivétel keletkezik. A processzornak el kell döntenie, melyik eseményt szolgálja ki először, melyik szoríthatja háttérbe a többit, és mi történik a megszakított kód regisztereivel. Ez a döntés nem a C kódban, hanem a Cortex-M kivételmodelljében (exception model) születik meg: a vektortábla (vector table) rögzíti, hova kell ugrani, a prioritásrendszer (priority) pedig azt, hogy egyszerre érkező események közül melyik nyer. A következő alfejezet ezt a két mechanizmust rendszerezi. Az itt tanultakra épül a következő alfejezet NVIC-konfigurációja, és erre támaszkodik az ISR-írás is.
A Cortex-M szóhasználatában a kivétel (exception) minden olyan esemény, amely a processzort arra készteti, hogy a normál utasításfolyamot megszakítsa, és egy előre kijelölt kezelőrutinba (handler) ugorjon. A reset is kivétel: az első utasítás végrehajtása előtt a mag egy kezelőbe kerül. Az ARMv7-M architektúra a kivételeket két nagy csoportra osztja:
A kivételszám (exception number) egy egész szám, amely az egyes kivételeket azonosítja. Az 1-es a Reset, a 2-es az NMI, a 3-as a HardFault, a 4–6 a MemManage/BusFault/UsageFault, a 11 az SVCall, a 14 a PendSV, a 15 a SysTick. A 16-tól kezdődnek az IRQ-k: a 16-os az IRQ0, a 17-es az IRQ1, és így tovább. A 0-s kivételszám nem kivételhez tartozik: ez a vektortábla 0. szava, a kezdeti veremmutató.
A vektortábla (vector table) a címtér elején elhelyezkedő, 4 bájtos bejegyzésekből álló tömb. A 0. bejegyzés a kezdeti veremmutató (initial stack pointer), az 1. bejegyzés a Reset-hez tartozó kezelő címe, a 2. az NMI-é, és így tovább. A vektortábla indexe és a kivételszám közötti kapcsolat egyszerű:
Ez azért igaz, mert a 0. index foglalja el a veremmutatót, és az 1. indextől kezdődnek a kivételvektorok. Az IRQ0 tehát a 16. indexű bejegyzés, az IRQn a (16 + n)-edik. Ez a látszólag apró eltolás a gyakori hibák egyik fő forrása: ha valaki az IRQ0-t a 0. indexre teszi, akkor a kezdeti veremmutatót írja felül, és a rendszer már a reset után hibás állapotba kerül.
A vektortábla első 16 bejegyzésének fix sorrendjét az előző alfejezet már bemutatta. Itt annyi a kiegészítés, hogy a tábla nem áll meg a 16. bejegyzésnél: az IRQ-k számára fenntartott bejegyzések a 16. indextől kezdődnek, és addig tartanak, ameddig a konkrét implementáció IRQ-t támogat. Egy adott IRQ-hoz tartozó kezelő címét tehát a (16 + IRQ-szám) indexű szó tartalmazza.
A kivételtípusok és vektortábla-pozícióik összefoglalása:
| Kivételszám | Név | Vektortábla index | Prioritás típusa |
|---|---|---|---|
| 1 | Reset | 1 | fix, -3 |
| 2 | NMI | 2 | fix, -2 |
| 3 | HardFault | 3 | fix, -1 |
| 4 | MemManage | 4 | konfigurálható |
| 5 | BusFault | 5 | konfigurálható |
| 6 | UsageFault | 6 | konfigurálható |
| 7–10 | fenntartott | 7–10 | — |
| 11 | SVCall | 11 | konfigurálható |
| 12 | Debug Monitor | 12 | konfigurálható |
| 13 | fenntartott | 13 | — |
| 14 | PendSV | 14 | konfigurálható |
| 15 | SysTick | 15 | konfigurálható |
| 16 + n | IRQn | 16 + n | konfigurálható |
A táblázatban a „fenntartott” (reserved) bejegyzések helyére a
linkerscriptnek is bejegyzést kell tennie, különben a tábla elcsúszik. A
gyakorlatban ezeket nullával vagy egy Default_Handler
címével szokás kitölteni.
A Cortex-M prioritásrendszerének legfontosabb szabálya: a kisebb prioritásszám magasabb prioritást jelent. A Reset prioritása -3, az NMI-é -2, a HardFaulté -1. Ezek fix, negatív értékek; nem konfigurálhatók, és minden konfigurálható kivételnél magasabb rendűek. A konfigurálható kivételek prioritásszáma 0 és egy felső határ között mozog. A 0 a legmagasabb konfigurálható prioritás.
A prioritásszám nem feltétlenül használja ki a teljes 8 bites
tartományt. Hogy hány bitet valósít meg a mag, az implementációs
választás: az Armv7-M 3 és 8 bit között engedi meg, és a
Cortex-M3-at beépítő gyártó dönti el (sok mikrokontrolleren 3 vagy 4
bit). Ez tehát nem általános Cortex-M3-tulajdonság, hanem a konkrét
futtatókörnyezet paramétere. CMSIS-ben a
__NVIC_PRIO_BITS, ebben a könyvben a
LAB_NVIC_PRIO_BITS laborparaméter rögzíti, és a NVIC-konfiguráció visszaolvasásos próbája méri meg.
A könyv két futtatókörnyezete eltér. A QEMU stable-8.2
mps2-an385 NVIC-modellje Armv7-M-en 8
bitet valósít meg (ott a 0xFF visszaolvasva
0xFF); ezt a QEMU forrásából tudjuk, a laborban a
visszaolvasás igazolja. A könyv számpéldái és a
tools/cm-run.py alapértelmezése egy 3
bites modellt követnek, amely sok mikrokontrolleren valós érték. Az
alábbi táblázat mindkettőt mutatja. Négy dolgot kell külön kezelni:
| Fogalom | Mi ez | Példa (LAB_NVIC_PRIO_BITS = 3, 3 bites modell) |
Példa (LAB_NVIC_PRIO_BITS = 8, QEMU 8.2
mps2-an385) |
|---|---|---|---|
| nyers prioritásbájt | a regiszterben tárolt 8 bites érték | 0xA0 |
0xA0 |
| megvalósított bitek | a bájt felső LAB_NVIC_PRIO_BITS bitje; a többi
olvasáskor 0, írása hatástalan |
a 7:5 bitek; 0xFF visszaolvasva 0xE0 |
mind a 8 bit; 0xFF visszaolvasva 0xFF |
| logikai prioritás | a megvalósított bitek értéke:
nyers >> (8 − LAB_NVIC_PRIO_BITS) |
0xA0 >> 5 = 5 |
0xA0 >> 0 = 160 |
| csoport- és alprioritás | az AIRCR.PRIGROUP (0–7) kettévágja a bájtot: a
[7 : PRIGROUP+1] bitek a csoportprioritás, a
[PRIGROUP : 0] bitek az alprioritás (mindkettő a
megvalósított bitekből) |
PRIGROUP = 4 (vagy kisebb): a 3 bit mind
csoportprioritás, csoport = 5, alprioritás = 0;
PRIGROUP = 5: csoport = 0xA0 >> 6 = 2,
alprioritás = (0xA0 >> 5) & 1 = 1 |
PRIGROUP = 4: csoport =
0xA0 >> 5 = 5, alprioritás =
0xA0 & 0x1F = 0; PRIGROUP = 5: csoport =
0xA0 >> 6 = 2, alprioritás =
0xA0 & 0x3F = 32 |
| legalacsonyabb konfigurálható prioritás | a visszaolvasott maszk (0xFF írása után olvasott
érték) |
0xE0 |
0xFF |
A csoportprioritás tehát a két esetben azonos, mert ugyanazokból a felső bitekből jön; az alprioritás és a logikai érték viszont a megvalósított bitek számától függ. A sorrend (melyik kivétel előbb) mindkét esetben ugyanaz, amíg a nyers bájtok csak megvalósított biteket használnak.
A 0xA0 tehát csak ismert bitszám
mellett jelent „5”-öt: 3 megvalósított bitnél a felső három bit
101. Ha ugyanaz a mag 8 bitet valósítana meg, a
0xA0 logikai prioritása 160 lenne, 4 bitnél pedig
0xA0 >> 4 = 10. A nyers bájt és a logikai érték
összekeverése a másik gyakori félreértés.
A preemptálásról csak a csoportprioritás dönt: egy
futó kezelőt az a kivétel szakíthat meg, amelynek csoportprioritása
szigorúan magasabb rendű (kisebb szám). Az alprioritás és a kivételszám
csak azt dönti el, hogy több egyidejűleg függő kivétel közül melyik
kerül sorra először. Reset után PRIGROUP = 0, ami 3
megvalósított bit mellett azt jelenti, hogy mindhárom bit
csoportprioritás.
A prioritások közötti döntés menete:
SHPR1–3 regiszterei csak a MemManage, BusFault,
UsageFault, SVCall, DebugMonitor, PendSV és SysTick prioritását
tartalmazzák. A „mindig kiszolgálható” állításnak azonban vannak
korlátai. A PRIMASK nem maszkolja a HardFaultot, a
FAULTMASK = 1 viszont a végrehajtási prioritást −1-re
emeli, így a HardFault sem tud belépni (csak az NMI). Ha pedig HardFault
vagy NMI kezelése közben (−1 vagy −2 prioritáson) újabb szinkron hiba
keletkezik, nincs magasabb kezelő, ahová eszkalálódhatna: a mag
lockup állapotba kerül, és nem hajt végre több
utasítást.A prioritásszám tehát nem „erősség”, hanem rangsor: minél kisebb, annál előrébb van a sorban. Ezt a szemléletet érdemes a C kód prioritásdefinícióiban is következetesen alkalmazni.
A Cortex-M két végrehajtási módot ismer. Thread
módban fut a normál alkalmazáskód: a fő ciklus, a
segédfüggvények, a háttérlogika. Handler módban futnak
a kivételkezelők. A mag a kivétel belépésekor automatikusan Handler
módba vált, és a kivételkezelőből való visszatéréskor tér vissza Thread
módba. Handler módban a végrehajtás mindig privilegizált szintű; Thread
módban lehet privilegizált vagy nem privilegizált, attól függően, hogyan
konfiguráltuk a CONTROL regisztert.
A visszatérés mechanizmusa a Cortex-M sajátossága, és két réteget érdemes szétválasztani.
A hardveres réteg: EXC_RETURN. A
kivétel belépésekor az LR (link register) egy speciális
EXC_RETURN értéket kap (például
0xFFFFFFF9). Ez nem visszatérési cím, hanem kódolt érték,
amely megmondja a magnak, melyik verem keretét kell visszatölteni, és
milyen módba kell visszatérni. A kivétel-visszatérést az váltja ki, hogy
Handler módban egy EXC_RETURN-mintájú érték kerül a
PC-be egy erre megengedett utasítással. Ilyen a
BX LR, de ugyanígy a POP {..., PC}, az
LDM a PC-vel a listában, vagy egy
LDR PC, [...], ha a visszatöltött érték az EXC_RETURN.
A fordítói réteg: a C-függvény prológusa és
epilógusa. Egy C-ben írt kezelő a fordító szemében
közönséges void f(void) függvény. Ha nem
hív mást, jellemzően BX LR-rel zárul. Ha hív, a prológus
PUSH {..., LR}-rel menti az LR-ben lévő EXC_RETURN-t, az
epilógus pedig POP {..., PC}-vel tölti vissza, és ez maga a
kivétel-visszatérés. A kezelőt tehát nem kell kézzel
BX LR-rel zárni, és nem kell külön attribútum sem. A
feltétel csak az, hogy az LR-ben kapott értéket a kód ne írja felül
végleg, és változatlanul juttassa a PC-be. A GCC
__attribute__((interrupt)) Armv7-M-en érvényes, de mást
jelent, mint A-profile-on: a kivételtípust figyelmen kívül hagyja, és
azt jelzi, hogy a függvény csak 4 bájtra igazított SP-vel is
meghívódhat, ezért a fordító a prológusban 8 bájtra igazítja a vermet.
Ha a mag a belépéskor maga igazít (CCR.STKALIGN = 1, ami a
Cortex-M3 r2p0-tól a reset utáni alapállapot), a sima
void f(void) is AAPCS-helyes.
Amikor egy kivétel belép, a hardver automatikusan elmenti a megszakított program legfontosabb regisztereit a jelenlegi verembe. Ez a context-mentés (context save) nyolc szót érint. Az elrendezést az architektúra rögzíti: a belépés után az SP a keret legalacsonyabb címére (R0) mutat, és innen mérve az offsetek mindig ugyanazok:
| Offset az új SP-től | Regiszter | Megjegyzés |
|---|---|---|
+0x00 |
R0 | |
+0x04 |
R1 | |
+0x08 |
R2 | |
+0x0C |
R3 | |
+0x10 |
R12 | |
+0x14 |
LR | a megszakított kód link registere |
+0x18 |
PC | a folytatási cím (lásd lent) |
+0x1C |
xPSR | állapotjelzők; a 9. bit jelzi az igazítási szót |
+0x20 |
(igazítási szó, opcionális) | csak ha a belépés előtti SP nem volt 8 bájtra igazított |
Ha a belépés előtti SP nem volt 8 bájtra igazított, a mag egy igazítási szót hagy ki. Ez a szó a keret fölött, a magasabb címen, az xPSR és a belépés előtti SP között van, nem a keret alatt. A regiszterek offsetjei ezért nem változnak, a visszatérés pedig a mentett xPSR 9. bitjéből tudja, hogy vissza kell-e adnia a +4 bájtot.
A mentett PC általánosan a folytatási cím: az az
utasítás, amellyel a kivétel-visszatérés után a végrehajtás folytatódik.
Aszinkron megszakításnál ez a következő, még végre nem hajtott utasítás.
SVC-nél az SVC utáni utasítás. Szinkron
hibáknál (például UsageFault, precíz BusFault) jellemzően maga a hibát
okozó utasítás, de nem minden hibatípusnál: egy pontatlan (imprecise)
BusFault mentett PC-je egy később végrehajtott utasításra mutathat. A
hibakeresésnél tehát a mentett PC a kiindulópont, nem automatikusan a
hibás utasítás címe.
A Cortex-M3 nem tartalmaz FPU-t, ezért nála mindig ez a 8 szavas alapkeret jön létre. A lebegőpontos regisztereket is mentő, kiterjesztett keret csak FPU-s magokon (például Cortex-M4F, Cortex-M7) jelenik meg, és külön profilváltást igényel; ebben a fejezetben nem foglalkozunk vele.
A veremmutató a mentés során csökken, és a nyolc szó (szükség esetén az igazítási szóval együtt) bekerül a verembe. A megszakított program regiszterei tehát megőrződnek; a kezelő saját kódja szabadon használhatja őket. A visszatéréskor a hardver a nyolc szót visszatölti, és a megszakított utasításfolyam pontosan ott folytatódik, ahol abbamaradt. Ez a mechanizmus az alapja annak, hogy a C-ben írt ISR-ek látszólag „ingyen” megkapják a regisztermentést.
A context-mentés a jelenleg aktív veremmutatót használja. Thread módban ez általában a fő veremmutató (MSP) vagy a folyamat veremmutatója (PSP); Handler módban mindig az MSP. A veremhasználat és a PSP/MSP váltás részletei a következő alfejezetek témái; itt a fogalmi szint a lényeg: a hardver a kivétel belépésekor automatikusan ment, a visszatéréskor automatikusan visszaállít.
Munkakönyvtár: ~/arm-labor/cm/a068/ —
az alfejezet minden laborfájlja ide kerül, és minden parancs innen
futtatandó (a könyvtárrendet a Labor-alapkörnyezet alfejezet írja le).
mkdir -p ~/arm-labor/cm/a068
cd ~/arm-labor/cm/a068A következő példa egy külső IRQ-t konfigurál a QEMU
mps2-an385 machine-en. A konkrét IRQ-számot szimbolikusan
kezeljük, mert annak pontos értéke a QEMU machine és a CMSDK periféria
leírásából ellenőrizendő. A regisztercímek az ARMv7-M System Control
Space dokumentált címei.
A NVIC prioritásregiszterei (IPR) bájtonként címezhetők: az IRQ
n prioritásbájtja a 0xE000E400 + n címen
található. Az engedélyezés az ISER0 regiszteren keresztül történik, a
0xE000E100 címen.
/* Thumb-2 / Armv7-M, Cortex-M3, QEMU mps2-an385 */
.equ NVIC_ISER0, 0xE000E100
.equ NVIC_IPR_BASE, 0xE000E400
.syntax unified
.thumb
/* Laborparaméter: a megvalósított prioritásbitek száma (CMSIS: __NVIC_PRIO_BITS).
A futtatókörnyezethez kell rögzíteni, az a069 visszaolvasásos próbája szerint:
3 a könyv 3 bites modelljében (tools/cm-run.py alapértelmezés), 8 a QEMU 8.2
mps2-an385-ön. Az alábbi várható értékek a 3 bites modellre szólnak. */
.equ LAB_NVIC_PRIO_BITS, 3
.equ LAB_IRQ12_PRIO, 5 /* logikai prioritás */
/* Az IRQ12 prioritásának beállítása: a logikai értéket a megvalósított
felső bitekbe toljuk. 3 bitnél: 5 << 5 = 0xA0. */
ldr r0, =NVIC_IPR_BASE + 12
mov r1, #(LAB_IRQ12_PRIO << (8 - LAB_NVIC_PRIO_BITS))
strb r1, [r0]
/* Az IRQ12 engedélyezése: ISER0 bit 12. */
ldr r0, =NVIC_ISER0
mov r1, #(1 << 12)
str r1, [r0]
A hozzá tartozó ISR C-ben, a vektortábla pedig a 16 + 12 = 28. indexű bejegyzést tartalmazza. Az IRQ12 itt szimbolikus példa: az AN385-ön ez a UART0–2 összevont túlcsordulási vonala, nem egy egyszerű perifériakérés (a070 1. feladata a tényleges UART0 RX vonalat használja).
/* Thumb-2 / Armv7-M, Cortex-M3 */
void IRQ12_Handler(void)
{
/* A periféria megszakításjelzőjének törlése itt történik. */
/* ... */
}A vektortábla megfelelő részlete assemblyben. Ez
rövidített szemléltetés: a kihagyott bejegyzéseknek
valódi szavaknak kell lenniük, különben az IRQ12_Handler
nem a 28. indexre kerül. A teljes, kitöltött mintát a Megszakítás-vezérelt I/O kidolgozott példája és a
Záróprojekt II vektortáblája adja.
/* Thumb-2 / Armv7-M, Cortex-M3 */
.section .vectors, "a", %progbits
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
/* ... a 16. indexig ... */
.word 0 /* 16: IRQ0 */
.word 0 /* 17: IRQ1 */
/* ... */
.word IRQ12_Handler /* 28: IRQ12 */
Várható állapot GDB-vel ellenőrizve, a konfiguráló kód lefutása után,
a 3 bites modellben (LAB_NVIC_PRIO_BITS = 3). QEMU 8.2
alatt a paramétert 8-ra kell állítani, ekkor ugyanez a sor a nyers
0x05-öt írja be, és a visszaolvasás is
0x05:
x/1xb 0xE000E40C → 0xA0
(0xE000E400 + 12)x/1xw 0xE000E100 → 0x00001000 (bit
12)x/1xw a vektortábla 28. szavára (0x70) →
az IRQ12_Handler címe, páratlan értékkel (a bit0 a
Thumb-állapotot jelzi).A 0xA0 logikai prioritása
0xA0 >> (8 − 3) = 5. A reset utáni
PRIGROUP = 0 mellett ez teljes egészében csoportprioritás,
tehát egy másik kezelőt akkor preemptál, ha annak csoportprioritása
5-nél nagyobb szám. Ha a paramétert nem igazítjuk a futtatókörnyezethez,
és a 8 bites QEMU-n is a 3-as értékkel számolunk, a beírt nyers
0xA0 ott 160-as logikai prioritást jelent; ezért kell a
bitszámot a visszaolvasás alapján rögzíteni.
objdump -s -j .vectors a firmware binárison; a
0. szó SRAM-cím, a 16. szó az IRQ0 kezelő címe.0xA0 3 megvalósított bitnél 5-ös, 4
bitnél 10-es, 8 bitnél 160-as logikai prioritás. Tünet: egy „alacsony
prioritásúnak” szánt IRQ megelőz egy „magasat”, vagy két, különbözőnek
szánt prioritás egybeesik. Ellenőrzés: a LAB_NVIC_PRIO_BITS
összevetése a visszaolvasásos próbával (a069),
és az AIRCR.PRIGROUP értéke: a preemptálásról csak a
csoportprioritás dönt.ISER együttes
vizsgálata.ISER bit
beállítása nélkül a függőben lévő kérés nem indul el. Tünet: a periféria
jelez, de kezelő nem fut. Ellenőrzés: ISPR és
ISER regiszterek.A hibakeresés menete mindig ugyanaz: tünet → hipotézis → adatgyűjtés
(GDB, objdump, NVIC-regiszterek) → egy változtatás →
ellenőrzés.
LAB_NVIC_PRIO_BITS = 3 mellett, és azt is, hogy 4 bitnél mi
lenne a helyes bájt.ISER megfelelő bitje be van állítva.
Milyen hipotéziseket vizsgálnál? Milyen regisztereket és
memóriaterületeket ellenőriznél GDB-vel?Megoldás. Reset: kivételszám 1, vektortábla index 1, prioritás fix -3. NMI: kivételszám 2, index 2, prioritás fix -2. HardFault: kivételszám 3, index 3, prioritás fix -1. IRQ0: kivételszám 16, index 16, prioritás konfigurálható. Az index minden esetben megegyezik a kivételszámmal, mert a 0. index a kezdeti veremmutatóé.
Megoldás. Az IRQ3 prioritásbájtja a
0xE000E400 + 3 = 0xE000E403 címen van. A 2-es logikai
prioritás LAB_NVIC_PRIO_BITS = 3 mellett
2 << 5 = 0x40 (8 bitnél, QEMU 8.2 alatt
0x02) (a felső 3 bitbe írva 010 →
0100 0000); 4 bitnél 2 << 4 = 0x20
lenne. Az engedélyezés az ISER0 0xE000E100
címén, a 3-as bit beállításával történik.
/* Thumb-2 / Armv7-M, Cortex-M3 */
ldr r0, =0xE000E403
mov r1, #0x40
strb r1, [r0]
ldr r0, =0xE000E100
mov r1, #(1 << 3)
str r1, [r0]
PRIMASK (vagy FAULTMASK,
BASEPRI) regiszterrel; (b) a kérés függőben van, de egy
magasabb prioritású kezelő blokkolja; (c) a periféria nem generál
megszakítást, csak státuszbitet állít; (d) a vektortábla bejegyzése
rossz címre mutat; (e) a kezelő neve nem egyezik a linkerscriptben
használt szimbólummal. Ellenőrzés: PRIMASK,
ISPR, ISER, a prioritásregiszter és a
vektortábla 16+IRQ indexű szava. A periféria oldalán a
megszakítás-engedélyező és jelző regiszterek vizsgálata szükséges.A Cortex-M kivételmodellje a kivételszám és a vektortábla index
közötti 1:1 megfelelést használja: a 0. index a kezdeti veremmutató, az
1. a Reset, a 3. a HardFault, a 16. pedig az IRQ0. A prioritásszám
fordítottan arányos a tényleges prioritással: a kisebb szám magasabb
rendet jelent, a Reset/NMI/HardFault fix negatív prioritású. A
megvalósított prioritásbitek száma implementációs paraméter
(LAB_NVIC_PRIO_BITS), a nyers bájtból ebből adódik a
logikai prioritás, a preemptálásról pedig a PRIGROUP
szerinti csoportprioritás dönt. A kivétel belépésekor a hardver
automatikusan nyolc szót ment a verembe (szükség esetén egy igazítási
szóval a keret fölött), és Handler módba vált. A visszatérést egy
EXC_RETURN-értéknek a PC-be töltése váltja ki; egy C-függvény epilógusa
(BX LR vagy POP {..., PC}) ezt külön teendő
nélkül elvégzi.
Továbbhasznált definíciók: - kivételszám (exception number): a kivételt azonosító egész szám; a vektortábla indexével egyezik meg. - prioritásszám (priority number): a kivétel rangsorát kódoló érték; kisebb szám = magasabb prioritás. - automatikus context-mentés (automatic context save): a hardver által kivétel belépésekor a verembe mentett nyolc regiszter.
Az alábbiak dokumentációs kiindulópontok (forrásállapot: nem megnyitott, lásd az Olvasói útmutató jelöléseit):
mps2-an385 machine és a CMSDK
perifériák leírása; az IRQ-számok és a periféria-regiszterek pontos
értéke itt ellenőrizendő..section, .word és
szimbólumkezelés nyelvi eszközei.Ellenőrzési hiányok: a QEMU mps2-an385
machine-en az egyes CMSDK perifériákhoz tartozó IRQ-számok pontos értéke
ebben a folyamatban nem került ellenőrzésre; a példában ezért
szimbolikus IRQ-számot használtunk. A megvalósított prioritásbitek száma
az Armv7-M implementációs opciója; a könyv laborparamétere
(LAB_NVIC_PRIO_BITS = 3) munkafeltételezés, amelyet konkrét
eszközön a gyártói dokumentáció vagy a a069
visszaolvasásos próbája (0xFF írása, visszaolvasás) dönt el. A
HardFault-korlátok (FAULTMASK, lockup), a keretigazítás és
a CCR.STKALIGN alapállapota az Armv7-M ARM és a Cortex-M3
műszaki leírás szerinti állítás, ebben a munkafolyamatban nem futtattuk
le.