Hlavní navigace

Architektura mikrořadičů s jádry ARM Cortex-M3

6. 10. 2015
Doba čtení: 19 minut

Sdílet

Na článek z předchozího týdne, v němž jsme si popsali nejmenší jádra ARM s názvem Cortex-M0 a Cortex-M0+, navážeme článkem dnešním, který je věnován výkonnějším mikroprocesorovým a mikrořadičovým jádrům. Ta nesou označení Cortex-M3 a nalezneme je například v čipu, který pohání populární Arduino Due.

Obsah

1. Architektura mikrořadičů s jádry ARM Cortex-M3

2. Instrukční sada podporovaná jádry Cortex-M3

3. Instrukce SDIV a UDIV

4. Přerušení běhu instrukcí LDM, STM, PUSH, POP atd.

5. Instrukční sada Thumb-2

6. Podmínky v instrukcích (CBZ, CBNZ)

7. Prefix IT aneb řešení mnoha problémů s podmíněnými skoky

8. Bitové operace (Booleovský procesor)

9. Booleovský procesor implementovaný v jádrech Cortex-M3

10. Jednotka MPU

11. Procesory Atmel založené na technologii ARM

12. Odkazy na Internetu

1. Architektura mikrořadičů s jádry ARM Cortex-M3

V předchozím článku jsme se zabývali popisem nejdůležitějších vlastností jader Cortex-M0 a Cortex-M0+, které tvoří základ řady Cortex-M (architektura ARM pro mikrořadiče). Připomeňme si, že se jedná (alespoň prozatím) o nejmenší procesorová jádra s architekturou ARM, která byla navržena takovým způsobem, aby dokázala cenově, z pohledu spotřeby elektrické energie, dostupností vývojových a ladicích prostředků atd. konkurovat některým typům osmibitových a šestnáctibitových mikrořadičů. Tato snaha vedla k cílenému omezení některých vlastností jader M0 a M0+, především se to týká zjednodušení instrukční sady (podmnožina instrukční sady Thumb), neexistence hardwarové děličky a samozřejmě též absence dalších koprocesorů (matematický koprocesor, NEON apod.). Pro ty aplikace, kde je vyžadován přece jen větší výpočetní výkon, jsou však určena jiná jádra navržená ve společnosti ARM. Další v pořadí (na škále od nejméně výkonných až po nejvýkonnější CPU) jsou jádra Cortex-M3, která se díky vyváženosti mezi výpočetním výkonem, cenou a spotřebou stala poměrně populární a nalezneme je například v čipech SAM3×.

Mezi základní cíl při návrhu jader Cortex-M3 patřilo vytvoření CPU s co nejmenší latencí, což znamená, že reakce na přerušení by měla proběhnout ideálně v jediném taktu. Navíc měly mít tyto procesory relativně dobrý výpočetní výkon, čehož bylo dosaženo hned několika způsoby. Především mají jádra Cortex-M3 Harvardskou architekturu umožňující mj. provádět současné čtení další instrukce společně se čtením či zápisem dat (zde ovšem závisí na konkrétním výrobci čipu, jak bude koncipovat interní sběrnice připojené k pamětem). Dále je použita pipeline se třemi řezy (klasické RISCové fetch, decode, execute) a nalezneme zde i modul určený pro dopředné čtení instrukcí (PFU – Prefetch Unit) a další modul pro pozdržení zápisu jednoho slova do datové paměti (ovšem pouze pro ty regiony paměti, které jsou označeny příznakem „bufferable“). Vlastní jádro Cortex-M3 je v případě potřeby rozšiřitelné o další moduly, zejména pak o modul MPU (Memory Protection Unit) popsaný níže, dále pak o modul DWT (Data Watchpoint and Trace Unit) usnadňující ladění či NVIC (Nested Vectored Interrupt Controller), o němž se taktéž zmíníme v navazujícím textu.

2. Instrukční sada podporovaná jádry Cortex-M3

Před podrobnějším popisem instrukční sady jader Cortex-M3 si zopakujme tabulku, s níž jsme se seznámili již minule:

# Jádro Architektura ARM Architektura CPU/MCU MPU
1 Cortex-M0 ARMv6-M Von Neumann ne
2 Cortex-M0+ ARMv6-M Von Neumann volitelná
3 Cortex-M1 ARMv6-M Von Neumann ne
4 Cortex-M3 ARMv7-M Harvardská volitelná
5 Cortex-M4 ARMv7E-M Harvardská volitelná
6 Cortex-M7 ARMv7E-M Harvardská volitelná

Z této tabulky mj. vyplývá, že jádra Cortex-M3 jsou založena na architektuře ARMv7-M a nikoli na architektuře ARMv6-M, jako je tomu u Cortex-M0(+). To s sebou přináší změny zejména v instrukční sadě, protože jádra Cortex-M3 plně podporují jak instrukční sadu Thumb s 16bitovými operačními kódy, tak i instrukční sadu Thumb-2, v níž nalezneme i instrukce s 32bitovým slovem (jedná se však o odlišný formát, než jaký je použit v původní RISCové instrukční sadě A32).

Přímo jsou podporovány i instrukce vykonávané hardwarovou násobičkou, která dokáže provést vlastní operaci vynásobení za jediný takt (viz též diskuzi o rozdílných vlastnostech násobičky u jader Cortex-M0 a Cortex-M0+). Tyto instrukce umožňují vynásobit dva 32bitové operandy (volitelně bez znaménka či se znaménkem) a získat 32bitový popř. 64bitový výsledek, popř. provést po vynásobení operaci součtu či rozdílu, čehož lze využít například při zpracování signálu:

# Instrukce Operandy Výsledek Operace
1 MUL 32bit×32bit 32bit násobení
2 MAL 32bit×32bit 32bit násobení a přičtení výsledku (Multiply and Accumulate)
3 MLS 32bit×32bit 32bit násobení a odečtení výsledku (Multiply and Subtract)
4 SMULL 32bit×32bit 64bit násobení hodnot se znaménkem
5 SMLAL 32bit×32bit 64bit Multiply and Accumulate
6 UMULL 32bit×32bit 64bit násobení hodnot bez znaménka
7 UMLAL 32bit×32bit 64bit Multiply and Accumulate

3. Instrukce SDIV a UDIV

Na rozdíl od jednodušších jader Cortex-M0 a Cortex-M0+ se u jader Cortex-M3 setkáme se i s hardwarovou děličkou. Ta však pracuje relativně pomalu, protože operace dělení je v závislosti na konkrétních hodnotách operandů dokončena ve dvou až šestnácti cyklech (a je přerušitelná, viz též další kapitolu):

# Instrukce Operandy Výsledek Operace
1 SDIV 32bit×32bit 32bit operace dělení hodnot se znaménkem
2 UDIV 32bit×32bit 32bit operace dělení hodnot bez znaménka

Mimochodem, absence hardwarové děličky je u mnoha jader řady Cortex-M a dokonce i Cortex-A poměrně běžná, což nám názorně přibližuje následující tabulka:

# Jádro DIV (Thumb) DIV (A32)
1 Cortex-M0 ne nedostupné
2 Cortex-M0+ ne nedostupné
3 Cortex-M1 ne nedostupné
4 Cortex-M3 ano nedostupné
5 Cortex-M4 ano nedostupné
6 Cortex-R4 ano ne
7 Cortex-R5 ano jen s registrem r1
8 Cortex-R7 ano ano
9 Cortex-A5 ne ne
10 Cortex-A7 ano ano
11 Cortex-A8 ne ne
12 Cortex-A9 ne ne
13 Cortex-A15 ano ano
14 Cortex-A53 ano ano
15 Cortex-A57 ano ano

4. Přerušení běhu instrukcí LDM, STM, PUSH, POP atd.

Instrukční sada Thumb obsahuje i instrukce typu LDM a STM, pomocí nichž je možné uložit či naopak načíst celou řadu vybraných pracovních registrů, nikoli pouze registr jediný. Pro seznam registrů platí některá omezení, například že adresa pro ukládání či načítání nesmí být specifikována v registru PC, seznam ukládaných/načítaných registrů nesmí obsahovat SP, u STM nesmí seznam obsahovat ani PC a u LDM nesmí obsahovat PC v případě, že obsahuje LR (tato pravidla jsou však vcelku pochopitelná, když si uvědomíme, jak RISCový procesor uvnitř pracuje). Druhým typem instrukcí určených pro současný přenos dat do/z většího počtu registrů jsou instrukce typu PUSH a POP, které mohou v případě instrukční sady Thumb pracovat nikoli pouze s jediným registrem, ale s libovolnou kombinací (ve skutečnosti jsou PUSH a POP pouze často používaným aliasem pro jednu z variant instrukcí LDM a STM).

O těchto instrukcích se explicitně zmiňuji především z toho důvodu, že v případě příchodu přerušení či výjimky musí procesor co nejdříve pozastavit běh hlavního programu a umožnit spuštění rutiny pro obsluhu přerušení/výjimky. Pro mnoho aplikací, v nichž se používají mikrořadiče, je však neakceptovatelné čekat tak dlouho, až se dokončí výše zmíněné instrukce (či taktéž dlouhotrvající operace dělení UDIV a SDIV). To ve skutečnosti ani není zapotřebí, protože tyto operace jsou přerušitelné, takže se na přerušení reaguje s velmi nízkou latencí (1–2 takty). Tato jádra navíc podporují i takzvaný tail-chaining, který urychluje zpracování většího množství výjimek (vynechá se operace se zásobníkem na konci rutiny).

5. Instrukční sada Thumb-2

V úvodních kapitolách jsme si řekli, že procesorová jádra řady Cortex-M3 podporují kromě 16bitové instrukční sady Thumb i instrukční sadu Thumb-2. Na základě zveřejněných měření se ukazuje, že díky použití Thumb-2 se na jedné straně dosahuje jak velké hustoty kódu (code density), tak i velkého výpočetního výkonu. Thumb-2 sice může vypadat problematicky (nejedná se o čistý RISC), ovšem sami konstruktéři mikroprocesorů ARM se vyjádřili k tomu, z jakého důvodu vlastně instrukční sada Thumb-2 vznikla. Při jejím návrhu měli na mysli čtyři parametry, které se navzájem ovlivňují a vylepšení jednoho z parametrů většinou v důsledku vede ke zhoršení zbývajících třech parametrů. Jedná se o následující parametry:

  1. Cenu vlastního procesoru, která je kromě jiných okolností ovlivněna i jeho složitostí (existence branch prediktorů, spekulativního provádění instrukcí, …), počtem aritmeticko-logických jednotek (obecně zda jde o skalární či superskalární procesor), velikostí potřebných vyrovnávacích pamětí atd.
  2. Dosahovaný výpočetní výkon v reálných aplikacích. V praxi to znamená, že hodnota udávaná v jednotkách MIPS nebo MFLOPS nemusí být vždy směrodatná: je to právě příklad jednodušších instrukcí Thumb v porovnání s obecně výkonnějšími instrukcemi ARM.
  3. Nutný energetický příkon procesoru (závisí na technologii výroby, napájecím napětí, hodinové frekvenci, počtu ALU, velikosti vyrovnávacích paměti, struktuře pipeline, dekódovací tabulky atd.).
  4. Cenu za vývoj a optimalizaci aplikací (tu ovlivňuje složitost instrukční sady, nedostatky v instrukční sadě: například nutnost provádění neefektivních skoků, složitost při načítání konstant do pracovních registrů atd.).

Za povšimnutí stojí především skutečnost, že snaha o vylepšení jednoho parametru skutečně ve většině případů vede ke zhoršení ostatních parametrů. Například zvýšení výpočetního výkonu pomocí větších vyrovnávacích pamětích ovlivní jak cenu mikroprocesoru, tak i energetický příkon atd. Zajímavý je ale především význam posledního parametru: cena za vývoj a optimalizaci aplikací. Při zavádění instrukční sady Thumb (zde bez dvojky) se totiž předpokládalo, že většina kódu bude překládána právě do této sady, což zmenší počet výpadků vyrovnávacích pamětí pro srovnatelný program (binární kód), a jen přibližně deset procent kritických částí kódu bude napsáno s využitím instrukcí ARM (jedná se tedy o aplikaci známého pravidla 90:10 či 80:20). To sice může na první pohled velmi dobře fungovat, ovšem zjištění, které jsou vlastně ony kritické části kódu, se muselo mnohdy provádět až v pozdních fázích vývoje, což vedlo mj. i k rostoucí ceně za vývoj (i když popravdě řečeno se to týká skutečně oněch částí kódu, s nimiž si někdo dal tu práci a optimalizoval je ručně s využitím výsledků získaných například z profileru).

Navíc není přepínání mezi instrukcemi ARM a Thumb zcela „zadarmo“, což poněkud zmenšuje možnosti neustálého přepínání, takže se hledal způsob, jak stávající stav ještě vylepšit. Výsledkem této snahy je instrukční sada nazvaná Thumb-2. Její vznik byl umožněn postupným vylepšováním technologie výroby integrovaných obvodů (zjednodušeně řečeno tím, že bylo možné na čipu implementovat větší množství tranzistorů bez razantního nárůstu ceny a/nebo spotřeby) a navíc byl „vynucen“ tím, že se stále zvětšoval rozdíl mezi rychlostí mikroprocesorů a dobou přístupu k pamětem DRAM či u mikrořadičů do Flash ROM. Cílem tedy byl menší binární kód (instrukce s větší hustotou) a současně stále dobrá výkonnost dosažená tím, že ne všechny instrukce Thumb-2 jsou tak jednoduché či jednoúčelové, jako instrukce Thumb.

Důvodů pro vznik nové instrukční sady tedy bylo více než dost, takže se podívejme na to, co se jejím tvůrcům podařilo splnit a co nikoli. V následujícím textu budou uvedeny výsledky měření prezentované samotnou společností ARM (takže je nutné je brát s rezervou :-). V první tabulce je porovnána „hustota“ binárního strojového kódu měřená jeho délkou. Ve všech případech se jednalo o stejný algoritmus, který byl poprvé implementován s využitím instrukční sady ARM, podruhé s pomocí sady Thumb a potřetí byla použita instrukční sada Thumb-2. Za základ je přitom brána délka původního kódu používajícího instrukce ARM (tento kód odpovídá sto procentům, čím menší číslo, tím menší je i výsledný binární program a tím lepší je využití I-cache či rychlejší přístup do Flash ROM):

Instrukční sada Délka kódu
ARM 100%
Thumb 70%
Thumb-2 74%

Ve druhé tabulce je uveden relativní výpočetní výkon přeloženého binárního programu, přičemž 100% odpovídá nejrychlejší implementaci a 75% implementaci nejpomalejší:

Instrukční sada Relativní výpočetní výkon
ARM 100%
Thumb 75%
Thumb-2 98%

Z výsledků, které jsou prezentovány v předešlých dvou tabulkách tedy vyplývá, že pro testovanou aplikaci se díky použití instrukční sady Thumb-2 podařilo zmenšit velikost kódu na tři čtvrtiny původní velikosti a přitom výpočetní výkon poklesl pouze o zhruba 2% (zde se samozřejmě projevila i nižší pravděpodobnost výpadku instrukční cache, která ovšem byla nižší i u implementace využívající instrukce Thumb).

Poznámka: jako u všech podobných měření je samozřejmě nutné mít na paměti, že se jedná pouze o (reprezentativní) vzorek, který může ale taktéž nemusí odpovídat jinému typu algoritmu. Vždy záleží jen na konkrétní aplikaci, konkrétním vývojáři, jeho rozpočtu a času, zda si podobné měření udělá i v případě jím vyvíjené aplikace, nebo zda se spolehne na cizí statistiku :-) (to ovšem platí i pro výběr procesoru: opět záleží na mnoha okolnostech, včetně dosavadních zkušeností vývojáře, ceně za vývojové nástroje atd.).

6. Podmínky v instrukcích (CBZ, CBNZ)

Jednou z předností instrukční sady Thumb-2 je zavedení nových instrukcí umožňujících v programovém kódu implementovat podmínky. Ty se totiž v mnoha případech ukazují být kritickou částí kódu, protože zejména podmíněné skoky mohou přerušit jinak plynulý tok zpracovávaných instrukcí, takže se z ideálního stavu, kdy RISCové jádro díky existenci pipeline dokončí v každém cyklu jednu instrukci (v případě superskalárních čipů Cortex-A i více instrukcí) můžeme dostat do stavu, kdy podmíněný skok způsobí nutnost přerušit již zpracovávané instrukce a začít znovu (samozřejmě s latencí).

Při analýze reálných aplikací si tvůrci instrukční sady Thumb-2 všimli si, že se v programech velmi často vyskytuje sekvence instrukcí, které nejdřív porovnají obsah vybraného pracovního registru s nulou a posléze provedou podmíněný skok na základě toho, zda je onen pracovní registr skutečně nulový nebo naopak nenulový. Poměrně velké frekvenci této sekvence instrukcí se nelze ani divit, protože podobným způsobem mohou být implementovány například testy na hodnotu NULL, počítané smyčky, smyčky typu do-while v nichž je pravdivostní hodnota vyjádřena celým číslem, práce s ASCIIZ řetězci atd. Aby bylo možné zmenšit velikost binárního kódu programu a současně ho i urychlit, byly do instrukční sady Thumb-2 přidány dvě nové instrukce, které nejprve provedou porovnání pracovního registru s nulou a poté provedou skok, pokud je registr nulový či naopak není nulový. Součástí instrukčního slova je přitom i krátký offset umožňující provést skok do vzdálenosti PC+4 až PC+130.

První z těchto instrukcí provede skok, pokud je vybraný pracovní registr nulový:

CBZ Rn, offset   ; compare and branch if zero

Tato instrukce je ekvivalentní delší sekvenci:

CMP Rn, #0
BEQ label

Druhá instrukce provádí skok v přesně opačném případě, tj. tehdy, když má registr nenulovou hodnotu:

CBNZ Rn, offset   ; compare and branch if non zero

Ekvivalentní zápis:

CMP Rn, #0
BNE label

7. Prefix IT aneb řešení mnoha problémů s podmíněnými skoky

Tvůrci instrukční sady Thumb-2 se taktéž snažili nějakým způsobem nahradit kdysi populární kombinaci příznakových bitů, které byly součástí většiny instrukcí klasické RISCové instrukční sady A32. Z tohoto důvodu do Thumb-2 přidali jednu z nejzajímavějších instrukcí, které kdy pro RISCové mikroprocesory vznikly. Jedná se vlastně o instrukční prefix nazvaný IT podle sousloví if-then. Tento prefix může být aplikován na jednu až čtyři instrukce následující za prefixem. Ihned za prefixem IT se (bez mezery) udává, zda má být daná instrukce provedena při splnění podmínky (T – then) či naopak při jejím nesplnění (E – else). U první instrukce je automaticky předpokládáno T, tudíž se uvádí maximálně tři kombinace znaků T/E. Samozřejmě je taktéž nutné zapsat i testovanou podmínku – může se jednat o kódy používané jak u podmíněných skoků, tak i v podmínkových bitech:

Kód Význam Předchozí operace porovnání
EQ Z==1 (rovno) signed i unsigned
NE Z==0 (nerovno) signed i unsigned
CS C==1 (větší nebo rovno) unsigned
CC C==0 (menší než) unsigned
MI N==1 (záporný výsledek) signed
PL N==0 (kladný nebo nulový výsledek) signed
VS V==1 (přetečení) signed
VC V==0 (nedošlo k přetečení) signed
HI C==1 & Z==0 (vetší než) unsigned
LS C==0 | Z==1 (menší nebo rovno) unsigned
GE N==V (větší nebo rovno) signed
LT N!=V (menší než) signed
GT Z==0 & N==V (větší než) signed
LE Z==1 N!=V (menší nebo rovno) signed

V praxi to může znamenat, že zápis:

ITEEE EQ

značí, že pokud je nastaven příznak zero (rovnost), je provedena jen první instrukce následující za prefixem, kdežto další tři instrukce nebudou provedeny (třikrát „else“).

Pokud by se měly provést tři instrukce v případě kladného výsledku předchozího porovnání, použil by se zápis:

ITTT PL

Porovnejme si nyní tři identické algoritmy. První z nich je implementovaný s využitím instrukcí A32 s podmínkovými bity:

        LDREQ r0,[r1]      ; if EQ then LDR
        LDRNE r0,[r2]      ; if NE then LDR
        ADDEQ r0, r3, r0   ; if EQ then ADD
        ADDNE r0, r4, r0   ; if NE then ADD

V případě použití instrukční sady Thumb musíme využít podmíněné skoky se všemi nepříjemnostmi, které z toho plynou:

        BNE L1             ; opačná podmínka - přeskočení instrukce
        LDR r0, [r1]
        ADD r0, r3, r0     ; máme štěstí: můžeme prohodit pořadí instrukcí
        B L2
L1
        LDR r0, [r2]
        ADD r0, r4, r0
L2

U instrukční sady Thumb-2 lze v tomto případu s výhodou použít prefixovou instrukci IT:

        ITETE EQ
        LDR r0, [r1]
        LDR r0, [r2]
        ADD r0, r3, r0
        ADD r0, r4, r0

Na závěr si ještě všechny tři implementace pro zajímavost porovnáme, a to jak z hlediska velikosti programového kódu, tak i z hlediska celkové doby trvání výpočtu:

Instrukční sada Velikost kódu Počet cyklů
ARM (RISC) 16 bajtů 4 cykly
Thumb 12 bajtů 4–20 cyklů
Thumb-2 10 bajtů 4–5 cyklů

Výsledek: pokud máme kvalitní překladač, bude instrukční sada Thumb-2 s velkou pravděpodobností lepší, než snaha o implementaci A32. Tento rozdíl bude ještě více patrný na mikrořadičích a tedy i jádrech Cortex-M3, protože zde může být program uložen v relativně pomalé Flash ROM.

8. Bitové operace (Booleovský procesor)

V oblasti mikrořadičů se již od dob slavného čipu Intel 8051 (MCS-51) můžeme setkat s implementací takzvaného Booleovského procesoru. Tímto poněkud nadneseným jménem se označuje sada instrukcí, které dokážou pracovat na úrovni jednotlivých bitů a nikoli celých slov, a to (většinou) dokonce takovým způsobem, že i přístup do paměti či do řídicích registrů periferních zařízení je prováděn po jednom bitu (například negace jediného bitu je rozdílná operace od přečtení bajtu/slova do akumulátoru, negace vybraného bitu a zápis celého bajtu/slova zpět). Jen pro zajímavost: na již zmíněném mikrořadiči MCS-51 je implementován úplný Booleovský procesor s jednobitovým akumulátorem (tím je příznak C/carry), 128 bitovou oblastí RAM a 128 bitovou oblastí speciálních řídicích registrů (SFR). Tento Booleovský procesor měl k dispozici sedmnáct instrukcí:

# Operace S příznakem C S bitem v RAM či SFR
1 Vynulování bitu CLR C CLR bit
2 Nastavení bitu SETB C SETB bit
3 Negace bitu CPL C CPL bit
4 Logický součin ANL C,bit ANL C,/bit  
5 Logický součet ORL C,bit ORL C,/bit  
6 Přesun bitu MOV C,bit MOV bit,C
7 Skok při bit=1 JC JB
8 Skok při bit=0 JNC JNB
9 Skok + vynulování   JBC

9. Booleovský procesor implementovaný v jádrech Cortex-M3

Nyní nám již zbývá popsat, jakým způsobem je Booleovský procesor implementován na jádrech Cortex-M3. Tvůrci zvolili odlišný přístup, než tomu bylo v případě mikrořadiče 8051: namísto použití speciálních instrukcí pro manipulaci s jednotlivými bity nedošlo ke změně instrukční sady, ale k vyhrazení několika paměťových regionů, k nimž se přistupuje po bitech. Tyto regiony leží na adresách 0×20000000–0×200FFFFF a 0×40000000–0×400FFFFF. Jak je ze zadaného rozsahu patrné, má každý region velikost 1MB. Pro tento jeden megabajt existují adresové aliasy 0×22000000–0×23FFFFFF a 0×42000000–0×43FFFFFF. Ty mají zdánlivou velikost 32MB, ovšem jen z toho důvodu, že při čtení slova se ve skutečnosti přečte pouze jediný bit, takže se do registru načte hodnota 0×00000000 nebo 0×00000001. Při zápisu se naopak zapisuje pouze nejnižší bit uložený v registru, takže hodnota 0×00000000, 0×FFFFFFFE či 0×44444444 má stejný význam, stejně jako hodnoty 0×00000001, 0×FFFFFFFF atd. Jednotka pro přístup do paměti automaticky přepočte zadanou aliasovou adresu 0×22000000–0×23FFFFFF na reálnou adresu 0×20000000–0×200FFFFF a provede zápis či čtení jediného bitu.

Poznámka: ve skutečnosti je první paměťový region uložen v SRAM (a to hned na jejím začátku), kdežto druhý region je mapován do oblasti periferních zařízení. Opět se zde reflektuje situace mikrořadiče 8051, kde bylo provedeno totéž rozdělení, ovšem v mnohem menším měřítku (128 bitů SRAM a 128 bitů pro periferní zařízení versus 1 MB SRAM a 1 MB pro periferní zařízení). Další zajímavostí je fakt, že operace čtení či zápisu bitů jsou atomické a nepřerušitelné.

10. Jednotka MPU

Mezi další zajímavé prvky, kterými mohou být jádra Cortex-M3 doplněny, patří jednotka MPU neboli Memory Protection Unit. Tato jednotka neslouží k virtualizaci paměti (jako MMU), ale „pouze“ k definování až osmi paměťových regionů, u nichž lze nastavovat různá práva, zejména právo XN (Execute Never, zákaz spouštění kódu z daného regionu). Zajímavé je, že se tyto regiony dokonce mohou překrývat, v tomto případě se práva převezmou z nastavení regionu s vyšším indexem (0–7). Kromě práv je možné nastavit, zda se daná oblast má sdílet s dalšími jádry (což u většiny implementací Cortex-M3 bude postrádat význam) a zda mají být zápisy do paměti provedeny vždy v takovém pořadí, jak to odpovídá sekvenci instrukcí (to má význam především při komunikaci s periferními zařízeními).

11. Procesory Atmel založené na technologii ARM

Nastal čas podívat se na nějaký reálný mikrořadič či SoC založený na technologii Cortex-M3. Aby to bylo zajímavější, zaměříme se na čipy SAM3× vyráběné firmou Atmel. Proč se jedná o zajímavé téma? Společnou Atmel totiž některými svými dalšími čipy, zejména pak řadou AVR32, vlastně ARMovským jádrům poměrně zdárně konkuruje, nicméně ani to jí nezabraňuje, aby dokázala realizovat jedny z nejlepších integrovaných obvodů s jádrem Cortex-M3. Má to vlastně svoji logiku, protože Atmel vyniká i v implementaci periferních zařízení, které jsou pro mikrořadiče většinou nezbytné. Kombinací jádra Cortex-M3 a periferií od Atmelu (A/D převodníky, USART, SPI, CAN, I2C atd.) tak zákazníci dostávají k dispozici velmi zajímavý čip, který je navíc navržen takovým způsobem, aby jednotlivé periferie spolu dokázaly komunikovat přímo a nechat tak procesor v režimu sleep. Čipy SAM3× za sebou mají relativně dlouhý vývoj, což je patrné i z následující tabulky:

UX DAy - tip 2

# Čip Rok uvedení do výroby
1 SAM3U 2009
2 SAM3S 2009
3 SAM3N 2010
4 SAM3A 2012
5 SAM3X 2012

Například na čipu Atmel SAM3X8E s hodinovou frekvencí 84 MHz použitém v populárním Arduinu Due kromě jádra Cortex-M3 nalezneme i:

  1. 2 × 256 kB Flash ROM
  2. 64 + 32 kB SRAM
  3. 16 kB ROM (obsahuje především bootloader rutiny pro UART a USB)
  4. 54 I/O pinů (12 z nich vyhrazeno pro PWM)
  5. 16 kanálový ADC (12 bitů), jeden rezervován pro vnitřní senzor teploty
  6. 2 DAC (taktéž 12bitů)
  7. 3× USART
  8. 9 kanálový 32bitový čítač
  9. 2 TWI (Two Wire Interface, varianta I2C)
  10. USB Device/Mini host
  11. Ethernet MAC 10/100 + podpora pro přenos dat přes DMA (to je důležité, viz problémy s Raspberry)
  12. True Random Number Generator (TRNG), dokáže každých 32 taktů vrátit 32bitové náhodné(?) číslo

Tento čip je použit i v počítači UDOO, s nímž se seznámíme někdy příště.

12. Odkazy na Internetu

  1. A tour of the Cortex-M3 core:
    http://community.arm.com/grou­ps/processors/blog/2013/11/04/a-tour-of-the-cortex-m3-core
  2. Five things you may not know about ARM Cortex-M:
    http://community.arm.com/docs/DOC-6912
  3. Divide and Conquer:
    http://community.arm.com/docs/DOC-8059
  4. MCU market turns to 32-bits and ARM
    http://www.eetimes.com/do­cument.asp?doc_id=1280803
  5. Cortex-M0 Processor (ARM Holdings)
    http://www.arm.com/produc­ts/processors/cortex-m/cortex-m0.php
  6. Cortex-M0+ Processor (ARM Holdings)
    http://www.arm.com/produc­ts/processors/cortex-m/cortex-m0plus.php
  7. ARM Processors in a Mixed Signal World
    http://www.eeweb.com/blog/arm/arm-processors-in-a-mixed-signal-world
  8. ARM Architecture (Wikipedia)
    https://en.wikipedia.org/wi­ki/ARM_architecture
  9. Cortex-M0 (Wikipedia)
    https://en.wikipedia.org/wi­ki/ARM_Cortex-M0
  10. Cortex-M0+ (Wikipedia)
    https://en.wikipedia.org/wi­ki/ARM_Cortex-M#Cortex-M0.2B
  11. Improving ARM Code Density and Performance
    New Thumb Extensions to the ARM Architecture Richard Phelan
  12. The ARM Processor Architecture
    http://www.arm.com/produc­ts/processors/technologies/in­struction-set-architectures.php
  13. Thumb-2 instruction set
    http://infocenter.arm.com/hel­p/index.jsp?topic=/com.ar­m.doc.ddi0344c/Beiiegaf.html
  14. Introduction to ARM thumb
    http://www.eetimes.com/dis­cussion/other/4024632/Intro­duction-to-ARM-thumb
  15. ARM, Thumb, and ThumbEE instruction sets
    http://www.keil.com/suppor­t/man/docs/armasm/armasm_CEG­BEIJB.htm
  16. An Introduction to ARM Assembly Language
    http://dev.emcelettronica­.com/introduction-to-arm-assembly-language
  17. Processors – ARM
    http://www.arm.com/produc­ts/processors/index.php
  18. The ARM Instruction Set
    http://simplemachines.it/doc/ar­m_inst.pdf

Byl pro vás článek přínosný?