Obsah
1. Programovatelné IO na mikrořadičích RP2040
2. Jednodeskové mikropočítače Raspberry Pi Pico
3. Mikrořadiče RP2040 a RP2350
4. Důvody pro existenci PIO na Raspberry Pi Pico
5. Realizace PIO na čipu RP2040
6. Interní struktura stavových strojů tvořících PIO
7. Výstupní FIFO (fronta) a posuvný registr OSR
8. Vstupní FIFO (fronta) a posuvný registr ISR
9. Čítače počtu posunů registrů ISR a OSR
14. Instrukce čekání na událost (WAIT)
1. Programovatelné IO na mikrořadičích RP2040
Společnost Raspberry Pi Ltd. pravděpodobně není nutné čtenářům Roota podrobně představovat, protože se s jejími jednodeskovými mikropočítači setkal prakticky každý. Po hlavičkou této společnosti vzniklo poměrně velké množství různých desek s mikrořadiči nebo mikroprocesory, z nichž nejznámější je řada Raspberry Pi (od Modelu-A z roku 2012 až k Raspberry Pi 5 vydané předloni). Neméně zajímavá je i řada Raspberry Pi Zero a taktéž Raspberry Pi Pico.
V dnešním článku nás bude zajímat především poslední zmíněná řada, tedy Raspberry Pi Pico, která je založená na mikrořadičích RP2040, resp. RP2350. Interně se sice tyto mikrořadiče od sebe odlišují (mají například odlišná procesorová jádra), ovšem jednu vlastnost mají společnou – obsahují totiž takzvané PIO (Programmable IO), což je označení popisující bloky ovládající vstupně-výstupní piny, na které se můžeme dívat jako na samostatně programovatelné (i když velmi jednoduché) procesory s vlastní instrukční sadou a během nezávislým na hlavním jádru.
V dnešním článku se nejdříve ve stručnosti seznámíme s celou řadou Pi Pico a následně si popíšeme jak funkcionalitu PIO, tak i způsob jejich programování. Přitom použijeme programovací jazyk Python, resp. přesněji řečeno jeho variantu nazvanou MicroPython, kterou lze na Pi Pico bez problémů provozovat. I s MicroPythonem jsme se na stránkách Roota již ve stručnosti seznámili a to konkrétně v článcích [1] [2] [3] [4] a (i když nutno připomenout, že ve zcela odlišném kontextu) i v [5].
2. Jednodeskové mikropočítače Raspberry Pi Pico
Původní jednodeskový mikropočítač řady Pico se jmenoval jednoduše Raspberry Pi Pico. Jeho oficiální cena byla čtyři dolary a založen byl na mikrořadiči RP2040 s 264kB RAM (SRAM) a 2MB paměti Flash. Mikrořadič RP2040 má jádro ARM Cortex-M0+ s taktovací frekvencí 133MHz, ovšem na Pico je frekvence snížena na 125MHz. Jak kapacita RAM, tak i Flash paměti společně s poměrně vysokým výpočetním výkonem umožňují běh MicroPythonu, i když mnoho projektů se píše v céčku, Rustu nebo dokonce i ve FreePascalu. Dnes nás bude zajímat i to, že původní Pi Pico má 26 GPIO pinů (varianta Pico H je prakticky totožná, až na odlišné piny pro debugging).
O rok později vznikla varianta „W“, přičemž toto písmeno naznačuje, že byl přidán modul pro Wifi. Konkrétně se jedná o čip Infineon CYW43439, díky němuž bylo možné Pico W použít v těch aplikacích, v nichž se nasazovaly konkurenční produkty ESP8266 a ESP32 (ale i mnoho dalších).
Naproti tomu modely Pico 2 a Pico 2 W jsou poněkud odlišné. Především jsou založeny na odlišném čipu, protože RP2040 nahradil výkonnější čip RP2350 a dostupná je i větší kapacita RAM i Flash (u obou se dosahují prakticky dvojnásobné hodnoty kapacity). Ovšem po SW stránce zůstala zachována kompatibilita na úrovni zdrojových kódů s původní řadou Pico, která se navíc stále používá (Pico 2 je dražší a výkon původního Pico pro mnoho aplikací více než dostačuje).
V následující tabulce jsou jednotlivé jednodeskové mikropočítače (mikrořadiče) Pico porovnány:
Označení | Vydáno | Mikrořadič | Wifi | RAM | Flash |
---|---|---|---|---|---|
Raspberry Pi Pico | 2021 | RP2040 | ne | 264kB | 2MB |
Raspberry Pi Pico W | 2022 | RP2040 | ano | 264kB | 2MB |
Raspberry Pi Pico 2 | 2024 | RP2350 | ne | 520kB | 4MB |
Raspberry Pi Pico 2 W | 2024 | RP2350 | ano | 520kB | 4MB |
3. Mikrořadiče RP2040 a RP2350
Již z tabulky uvedené ve druhé kapitole je zřejmé, že modely Pi Pico (bez číslovky) a Pi Pico 2 se od sebe v několika ohledech odlišují, což je do značné míry způsobeno použitím odlišných mikrořadičů. Rozdílů je však ještě větší množství a vzhledem k tomu, že se dotýkají i problematiky probírané v dnešním článku (PIO), si tyto rozdíly taktéž vypíšeme. Zajímat nás budou především údaje o PIO:
Čip | RP2040 | RP2350 | Poznámka |
---|---|---|---|
Jádra | 2×ARM Cortex-M0+ | 2×ARM Cortex-M33 + 2×Hazard3 RISC-V | volba jader při bootu |
FPU | ne | ano (ARM) | pouze jednoduchá přesnost |
Frekvence | 133 MHz | 150 MHz | |
(S)RAM | 264 kB | 510 kB | |
OTP paměť | × | 8 kB | používáno například pro klíče při bootu atd. |
DMA | 12 kanálů | 16 kanálů | přímý přístup do paměti |
IRQ pro DMA | 2 | 4 | HW přerušení používaná při DMA |
PIO | 2 (8 stavových strojů) | 3 (12 stavových strojů) | bude popsáno dále |
PWM | 16 | 24 | pulsní šířková modulace |
ADC | 4 kanály, 12bitů | 4 kanály, 12 bitů (popř. 8 kanálů) | analogově-digiální převodník |
DAC | × | × | digitálně-analogový převodník |
4. Důvody pro existenci PIO na Raspberry Pi Pico
Samotné mikrořadiče RP2040 a RP2350 jsou poměrně rychlé, takže mj. umožňují provozovat i interpretované programovací jazyky typu MicroPython (i když i zde lze zařídit překlad vybraných funkcí). Ovšem i přes samotnou rychlost mikrořadičových jader je mnohdy nutné v reálném čase pracovat se vstupně-výstupními piny. Příkladem může být například implementace vlastního sériového přenosu dat bez použití k tomu dedikovaných bloků mikrořadiče.
Samozřejmě je možné napsat subrutiny s realizací tohoto sériového přenosu. Používá se k tomu technika zvaná bit banging, tedy programové ovládání obecných vstupně-výstupních pinů (GPIO). Nicméně se mnohdy jedná o operace, které musí být přesně načasovány a v takových případech nám nemusí hrubá rychlost jader postačovat – záviset budeme (možná) na systému přerušení, na tom, jaké další činnosti jádra provádí, zda se činnost jader nepřerušuje kvůli DMA atd. A už vůbec není možné v těchto případech použít zmíněný MicroPython; vše by muselo být naprogramováno v jazyce C nebo přímo v assembleru.
Řešení spočívá právě ve využití programovatelných IO, kdy se samotná logika ovládání pinů (tj. v tom nejjednodušším případě jejich čtení či zápis) buď kompletně nebo alespoň částečně naprogramuje v PIO tak, že poběží nezávisle na jádrech mikrořadiče. Díky tomu, že v tomto případě přesně známe délku trvání hodinových cyklů, může být časování provedeno tím nejtriviálnějším způsobem – použitím instrukcí nop. V extrémním případě tak jádra nebudou moci vykonávat prakticky žádnou činnost, protože vstupně-výstupní operace poběží přes PIO.
5. Realizace PIO na čipu RP2040
Podívejme se nyní, jakým způsobem jsou PIO realizovány na čipu RP2040. Tento mikrořadič obsahuje dvojici bloků PIO (RP2350 má tyto bloky tři). Každý blok je tvořen čtveřicí stavových strojů (state machine), které dokážou, nezávisle na ostatních subsystémech, vykonávat krátké specializované programy. Ty jsou uloženy v samostatné paměti (Instruction Memory), která má kapacitu pro až 32 instrukcí. Do stavových strojů se přivádí hodinový signál, který synchronizuje prováděné operace: přečtení, dekódování a vykonání instrukcí. Samotný repertoár dostupných instrukcí je ve skutečnosti velmi krátký, protože obsahuje jen devět instrukcí. Konkrétně se jedná o instrukce IN, OUT, PUSH, PULL, MOV, JMP, WAIT, SET a IRQ. Vstupně-výstupní instrukce mohou pracovat s jakýmkoli GPIO pinem, kterých je na RP2040 celkem 30 (jsou označeny symboly GP0 až GP29, teoreticky je ovšem k dispozici celkem 32 GPIO). Stavové stroje musí komunikovat i se zbytkem mikrořadiče, což je realizováno přes FIFO (fronty) a systém přerušení.
Interně vypadá propojení stavových strojů s GPIO na straně jedné a s jádry mikrořadiče na straně druhé následovně:

Obrázek 1: Jeden z bloků PIO (druhý má totožnou strukturu)
Zdroj: datasheet k čipu RP2040, dostupné na https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf.
6. Interní struktura stavových strojů tvořících PIO
Z prvního obrázku je patrné, že každý blok PIO interně obsahuje čtveřici stavových strojů, které jsou přes celkem osm FIFO připojeny k mikrořadiči a přes mapovací obvod k vybraným GPIO (tedy obecným vstupně-výstupním pinům). Na PIO se můžeme dívat jako na samostatnou výpočetní jednotku (CPU), která je zvláštní tím, že neobsahuje plnohodnotnou aritmeticko-logickou jednotku (a nelze tedy jednoduše realizovat například součet atd.). Interně stavový stroj obsahuje následující bloky:
- dva 32bitové posuvné registry ISR a OSR (shift registers) s volitelným směrem posunu
- dva 32bitové registry X a Y nazývané scratch registers, ovšem ve skutečnosti mají význam univerzálních registrů
- registr PC obsahující index instrukce uložené v paměti nazývané instruction memory
- 32bitové fronty (FIFO) pro čtení i zápis dat
- dělič hodinového signálu (16+8 bitů)
- mapování na GPIO
- rozhraní pro DMA
- rozhraní pro IRQ (přerušení)
7. Výstupní FIFO (fronta) a posuvný registr OSR a ISR
Pro komunikaci mezi mikrořadičem a stavovými stroji se používá dvojice posuvných registrů označovaná zkratkami OSR a ISR, jejichž způsob zapojení i ovládání přes instrukce PIO je nutné znát.
OSR neboli Output Shift Register slouží pro čtení dat posílaných z mikrořadiče do stavového stroje. Pro manipulaci s OSR slouží dvojice PIO instrukcí s mnemotechnickými zkratkami PULL a OUT. Instrukce PULL přečte 32bitové slovo z výstupní FIFO (fronty) a zapíše je do OSR. A instrukce OUT dokáže provést posun bitů v posuvném registru s jejich vysunutím (zápisem) na GPIO, do scratch registrů atd. Funkci si tedy můžeme graficky znázornit následovně:

Obrázek 2: Výstupní FIFO a registr OSR
Zdroj: datasheet k čipu RP2040, dostupné na https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf.
8. Vstupní FIFO (fronta) a posuvný registr ISR
Posuvný registr ISR neboli Input Shift Register naopak slouží pro (postupné) čtení dat dostupných ve stavovém stroji (GPIO atd.) s jejich posíláním do vstupní FIFO (fronty). Pro ovládání této části se používají PIO instrukce s mnemotechnickými zkratkami IN a PUSH. Instrukce IN do posuvného registru zapíše 1 až 32 bitů (s posunem zbytku) a instrukce PUSH pošle celý obsah ISR do FIFO. Opět platí, že pojmenování jak registru, tak i fronty je provedeno na základě toho, jak se jejich činnost jeví z pohledu mikrořadiče (a nikoli stavového stroje):

Obrázek 3: Vstupní FIFO a registr ISR
Zdroj: datasheet k čipu RP2040, dostupné na https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf.
9. Čítače počtu posunů registrů ISR a OSR
Při posílání dat do nebo z posuvných registrů ISR a OSR instrukcemi IN a OUT se obnovují i takzvané čítače posunů. Jedná se o další pomocné registry, které mohou obsahovat celočíselné hodnoty v rozsahu 0..32 (tedy v rozsahu „žádný posun“ až „posun o celých 32 bitů“). Po každé operaci s posuvným registrem se změní i příslušný čítač. Navíc se může provést jedna z následujících operací:
- Registr OSR je automaticky naplněn novou hodnotou (32bitovým slovem) ve chvíli, kdy jeho čítač dosáhne hodnoty 32.
- Registr ISR je automaticky vyprázdněn ve chvíli, kdy jeho čítač (odlišný od čítače předchozího) taktéž dosáhne hodnoty 32.
Hodnoty čítačů posunů se nulují operacemi PUSH, resp. PULL, ovšem taktéž instrukcemi MOV OSR, …, resp. MOV ISR, … – to je logické a očekávané chování.
10. Pracovní registry X a Y
V každém stavovém stroji (což je, jak již víme, vlastně malý specializovaný CPU), lze manipulovat s dvojicí 32bitových registrů pojmenovaných X a Y. V dokumentaci se tyto registry označují termínem scratch register, což by mohlo naznačovat, že je jejich obsah jen dočasný. Ovšem tyto registry jsou z pohledu stavového stroje plnohodnotnými registry, i když repertoár operací, které s nimi lze provádět, je omezený. Je tomu tak mj. i z toho důvodu, že stavové stroje neobsahují plnohodnotnou ALU, takže například není možné registry X a Y sečíst atd. (na druhou stranu je možné například snížit obsah registru o jedničku, takže lze realizovat počítané programové smyčky).
Tyto registry mohou sloužit jako zdroj nebo naopak cíl dat pro instrukce IN, OUT, SET a MOV. Taktéž mohou sloužit pro vyhodnocení podmínky u skoků, tedy u instrukce JMP.
11. Dvojice front (FIFO)
S frontami (FIFO) jsme se již ve stručnosti setkali v předchozím textu. Připomeňme si tedy, že každý stavový stroj obsahuje dvojici front, přičemž jedna fronta je typicky určena pro posílání dat z mikrořadiče do stavového stroje (TX fronta – transmit) a druhá fronta naopak slouží pro posílání dat ze stavového stroje do mikrořadiče (RX fronta – receive). Na straně mikrořadiče je zápis do fronty prováděn například přes DMA. Díky použití front bylo možné činnost mikrořadiče prakticky zcela oddělit od činnosti jednotlivých stavových strojů a do značné míry zajistit jejich nezávislou činnost (souběh či v tomto případě prakticky plný paralelismus). FIFO navíc dokážou generovat signál DREQ, který společně s DMA může zajistit přenosy dat bez toho, aby se musela na straně mikrořadiče spouštět přerušovací subrutina.
Každá z front má kapacitu na čtyři 32bitová slova, což umožňuje nezávislou a nepřerušovanou činnost I/O subsystému i v případě, že mikrořadič provádí jiné činnosti. Ovšem může se stát, že je zapotřebí přes PIO implementovat rychlé přenosy (displej atd.). V takovém případě lze obě fronty spojit a vytvořit jedinou FIFO s kapacitou osmi slov. Taková FIFO ovšem bude jednosměrná – tedy výstupní pro ovládání displeje a naopak vstupní, pokud se například bude přijímat video signál.
12. Instrukční sada PIO
Instrukční sada PIO obsahuje pouze devět instrukcí, ovšem již nyní je nutné upřesnit, že některé z těchto instrukcí jsou poměrně univerzální. Například instrukce JMP díky možnosti zakódování podmínky vlastně odpovídá hned několika instrukcím z jiných instrukčních sad. Totéž platí například i o instrukci MOV, která taktéž dokáže během přenosu dat provádět jednoduché operace. Všechny instrukce mají jednotnou šířku šestnácti bitů, přičemž první tři bity obsahují operační kód instrukce a dalších pět bitů pak počet zpožďovacích cyklů. Do zbylých osmi bitů jsou zakódovány operandy instrukcí, řídicí bity atd.:
# | Instrukce | Parametry | Stručný popis |
---|---|---|---|
1 | JMP | podmínka, adresa | skok, skok s podmínkou |
2 | WAIT | polarita, zdroj | čekání na splnění podmínky (stav pinu, IRQ) |
3 | IN | zdroj, počet bitů | zápis bitů ze zdroje do posuvného registru ISR |
4 | OUT | cíl, počet bitů | vysunutí bitů z posuvného registru ISR do cíle |
5 | PUSH | blokující zápis | uložení hodnoty z posuvného registru ISR do RX fronty (FIFO) |
6 | PULL | blokující zápis | přečtení hodnoty z TX fronty (FIFO) se zápisem do posuvného registru OSR |
7 | MOV | cíl, operace, zdroj | přenos dat s provedením zvolené operace (negace či otočení bitů) |
8 | IRQ | nastavit/smazat, čekání | nastavení nebo vymazání příznaku přerušení |
9 | SET | cíl, data (pět bitů) | zápis dat do zvoleného cíle |
13. Instrukce skoku (JMP)
Podrobnější popis instrukčního souboru začneme instrukcí nazvanou JMP, kterou je možné realizovat nepodmíněný nebo i podmíněný skok. Instrukční slovo této instrukce má délku dva bajty (16 bitů) a je rozděleno do čtyř bitových polí:
+-15-14-13-12-11-10--9--8--7--6--5--4--3--2--1--0--+ | 0 0 0 | delay |condition| address | +---------+--------------+---------+---------------+
O bitovém poli delay si řekneme podrobnosti příště, takže nás nyní budou zajímat pole nazvaná address a condition. Bitové pole address obsahuje adresu cíle skoku. Vzhledem k omezené velikosti paměti pro PIO instrukce je pět bitů dostačujících. Mnohem zajímavější je bitové pole condition, ve kterém je zakódována podmínka, která se vyhodnocuje. Toto pole má šířku tří bitů, což znamená, že lze rozlišit osm podmínek:
# | Condition bity | Podmínka, která se testuje |
---|---|---|
1 | 000 | bez podmínky (skok se vždy provede) |
2 | 001 | X==0 |
3 | 010 | X!=0 před snížením X o jedničku |
4 | 011 | Y==0 |
5 | 100 | Y!=0 před snížením Y o jedničku |
6 | 101 | X!=Y |
7 | 110 | PIN==1 (libovolný dopředu zvolený GPIO) |
8 | 111 | registr OSR je posunut o nastavený počet bitů |
14. Instrukce čekání na událost (WAIT)
Pro subsystém PIO zcela typická je instrukce nazvaná WAIT. Tato instrukce umožňuje čekat na určitou událost, kterou může být změna stavu sledovaného pinu nebo vznik přerušení (jeho zdrojem je typicky externí událost). Vzhledem k tomu, že u pinů můžeme chtít čekat buď na změnu stavu z nuly na jedničku či naopak, obsahuje instrukční slovo i bit nazvaný pol, resp. celým jménem polarity. V případě, že je tento bit nastavený na nulu, čeká se na událost, která vynuluje příslušný pin (nebo signál přerušení) a pokud je nastavený na jedničku, čeká se (logicky) na přechod pinu do stavu 1 nebo na příchod přerušení. Dále instrukční slovo obsahuje dva bity se specifikací sledovaného zdroje a taktéž pětibitový index:
+-15-14-13-12-11-10--9--8--7--6--5--4--3--2--1--0--+ | 0 0 1 | delay |pol|source| index | +---------+--------------+---+-----+---------------+
# | Source (bity) | Použitý zdroj |
---|---|---|
1 | 00 | libovolný GPIO pin určený bitovým polem index |
2 | 01 | PIN získaný mapováním a poté určený bitovým polem index |
3 | 10 | IRQ určené bitovým polem index |
4 | 11 | rezervováno, na RP2040 nepoužito |
15. Instrukce IN
Další PIO instrukce, s níž se v dnešním článku setkáme, se jmenuje IN. Tato instrukce přečte zadaný počet bitů z vybraného zdroje (source) a pošle je do posuvného registru ISR (jen pro připomenutí – tento registr je připojen na RX FIFO a tedy slouží pro čtení dat z PIO do mikrořadiče). Kromě počtu bitů 0..31, které se mají nasunout do registru ISR se ještě ve třech bitech specifikuje zdroj (source), takže instrukční slovo vypadá následovně:
+-15-14-13-12-11-10--9--8--7--6--5--4--3--2--1--0--+ | 0 1 0 | delay | source | bit count | +---------+--------------+---------+---------------+
# | Source (bity) | Použitý zdroj data |
---|---|---|
1 | 000 | GPIO piny |
2 | 001 | registr X |
3 | 010 | registr Y |
4 | 011 | budou se nasouvat nulové bity |
5 | 100 | rezervováno, na RP2040 nepoužito |
6 | 101 | rezervováno, na RP2040 nepoužito |
7 | 110 | registr ISR (což znamená formu rotace bitů) |
8 | 111 | registr OSR |
16. Instrukce OUT
Logickým opakem výše popsané instrukce IN je pochopitelně instrukce OUT. Tato instrukce vysune specifikovaný počet bitů z posuvného registru OSR a uloží je do zvoleného cíle (destination). Instrukční slovo má velmi podobný formát, jako je tomu u instrukce IN:
+-15-14-13-12-11-10--9--8--7--6--5--4--3--2--1--0--+ | 0 1 1 | delay | dest | bit count | +---------+--------------+---------+---------------+
Opět si uveďme, jaké cíle pro vysunovaná data je možné zvolit:
# | Destination (bity) | Použitý cíl pro data |
---|---|---|
1 | 000 | GPIO piny |
2 | 001 | registr X |
3 | 010 | registr Y |
4 | 011 | bity se jen vysunou a zahodí |
5 | 100 | GPIO piny (odlišné mapování) |
6 | 101 | registr PC (čítač instrukcí) |
7 | 110 | registr ISR |
8 | 111 | EXEC (viz poznámka níže) |
17. Instrukce PUSH a PULL
Další dvojice instrukcí, s nimiž je možné v PIO pracovat, jsou instrukce nazvané PUSH a PULL. Tyto instrukce slouží pro přenos dat mezi posuvným registrem ISR a RX FIFO (frontou), resp. naopak mezi TX FIFO (frontou) a posuvným registrem OSR (opět si připomeňme, že jména front RX a TX i jména posuvných registrů ISR a OSR jsou odvozena z pohledu mikrořadiče, nikoli z pohledu PIO).
Konkrétně to znamená, že instrukce PUSH přesune obsah registru ISR do RX fronty. Přitom se bude pracovat se všemi 32 bity registru a po provedení této operace bude registr ISR vynulován. Instrukce PULL naopak pošle 32bitové slovo z TX fronty do registru OSR.
Instrukční slova obou těchto instrukcí vypadají podobně:
+-15-14-13-12-11-10--9--8--7---6---5--4--3--2--1--0--+ | 1 0 0 | delay | 0 |IfF|Blk| 0 0 0 0 0 | +---------+--------------+---+---+---+---------------+ +-15-14-13-12-11-10--9--8--7---6---5--4--3--2--1--0--+ | 1 0 0 | delay | 1 |IfF|Blk| 0 0 0 0 0 | +---------+--------------+---+---+---+---------------+
Musíme se však zmínit o významu bitů IfF a Blk. První z těchto bitů může přenos dat přeskočit tehdy, dokud čítač posunů nedosáhl nastaveného limitu. A druhý bit řídí způsob čekání na uvolnění fronty. Konkrétně to znamená, že tyto bity ovlivňují instrukce PUSH a PULL následovně:
Instrukce | IfF | Blk |
---|---|---|
PUSH | přeskok, dokud čítač nedosáhl limitu SHIFTCTRL_PUSH_THRESH | čekání, dokud se neuvolní RX FIFO (fronta) |
PULL | přeskok, dokud čítač nedosáhl limitu SHIFTCTRL_PULL_THRESH | čekání, pokud je TX FIFO (fronta) prázdná |
18. Instrukce MOV
Předposlední PIO instrukcí, se kterou se dnes setkáme, je instrukce určená pro přenos dat. Tato instrukce se jmenuje, jak je ve světě assemblerů zvykem, MOV. Ovšem v případě PIO se nemusí jednat o pouhý přenos dat mezi zdrojem (source) a cílem (destination), protože s daty lze provést i jednoduchou operaci specifikovanou v instrukci. Instrukční slovo vypadá následovně:
+-15-14-13-12-11-10--9--8--7--6--5--4--3--2--1--0--+ | 1 0 1 | delay | dest | op | source | +---------+--------------+---------+----+----------+
Popsat si v tomto případě musíme všechna tři bitová pole, tedy source, destination i op. Začneme zdrojem dat:
# | Source (bity) | Použitý zdroj data |
---|---|---|
1 | 000 | GPIO piny |
2 | 001 | registr X |
3 | 010 | registr Y |
4 | 011 | přesunou se nulové bity (vynulování cíle) |
5 | 100 | rezervováno, na RP2040 nepoužito |
6 | 101 | registr STATUS (ještě nepopsán) |
7 | 110 | registr ISR |
8 | 111 | registr OSR |
Cíle dat mohou být následující:
# | Destination (bity) | Použitý cíl pro data |
---|---|---|
1 | 000 | GPIO piny |
2 | 001 | registr X |
3 | 010 | registr Y |
4 | 011 | rezervováno, na RP2040 nepoužito |
5 | 100 | EXEC (data se spustí) |
6 | 101 | registr PC (čítač instrukcí) |
7 | 110 | registr ISR (příslušný čítač se vynuluje) |
8 | 111 | registr OSR (příslušný čítač se vynuluje) |
Zbývá nám popis operací, která lze s daty provádět v průběhu jejich přesunu:
# | Operation (bity) | Vykonaná operace |
---|---|---|
1 | 00 | přesun dat bez jejich modifikace |
2 | 01 | inverze všech bitů |
3 | 10 | otočení všech bitů v 32bitovém slovu |
4 | 11 | rezervováno, na RP2040 nepoužito |
19. Instrukce SET
Poslední dnes popsanou instrukcí je instrukce SET. Tato instrukce slouží pro uložení dat do zvoleného cíle, kterým může být buď pracovní registr X či Y nebo, což je taktéž velmi užitečné, zvolený GPIO pin nebo piny (musí být dopředu namapovány). Díky této instrukci tedy můžeme přímo ovládat výstupní piny. Šířka ukládaných dat je pět bitů, což znamená, že do pracovních registrů lze uložit jen hodnoty 0..31, což však pro mnoho účelů může dostačovat. Pokud je nutné registry inicializovat většími hodnotami, musí se tyto hodnoty přenést přes FIFO (což už vlastně známe).
Formát instrukčního slova vypadá takto:
+-15-14-13-12-11-10--9--8--7--6--5--4--3--2--1--0--+ | 1 1 1 | delay | dest | data (5 bitů) | +---------+--------------+---------+----+----------+
Cíle dat mohou být následující:
# | Destination (bity) | Použitý cíl pro data |
---|---|---|
1 | 000 | GPIO piny |
2 | 001 | registr X (nejnižších pět bitů, ostatní bity jsou vynulovány) |
3 | 010 | registr Y (nejnižších pět bitů, ostatní bity jsou vynulovány) |
4 | 011 | rezervováno, na RP2040 nepoužito |
5 | 100 | GPIO piny (bude popsáno příště) |
6 | 101 | rezervováno, na RP2040 nepoužito |
7 | 110 | rezervováno, na RP2040 nepoužito |
8 | 111 | rezervováno, na RP2040 nepoužito |
20. Odkazy na Internetu
- Zápis funkcí obsahujících instrukce Thumb a Thumb-2 v MicroPythonu
https://www.root.cz/clanky/zapis-funkci-obsahujicich-instrukce-thumb-a-thumb-2-v-micropythonu/ - Zápis funkcí obsahujících instrukce Thumb a Thumb-2 v MicroPythonu (2)
https://www.root.cz/clanky/zapis-funkci-obsahujicich-instrukce-thumb-a-thumb-2-v-micropythonu-2/ - Zápis funkcí obsahujících instrukce Thumb a Thumb-2 v MicroPythonu (dokončení)
https://www.root.cz/clanky/zapis-funkci-obsahujicich-instrukce-thumb-a-thumb-2-v-micropythonu-dokonceni/ - Překlad funkcí přímo do nativního kódu MicroPythonem
https://www.root.cz/clanky/preklad-funkci-primo-do-nativniho-kodu-micropythonem/ - MicroPython ve webovém prohlížeči: lehkotonážní varianta k Pyodide
https://www.root.cz/clanky/micropython-ve-webovem-prohlizeci-lehkotonazni-varianta-k-pyodide/ - Programmable IO
https://docs.micropython.org/en/latest/rp2/tutorial/pio.html - Introduction to the PIO (Programmable Input Output) of the RP2040
https://tutoduino.fr/en/pio-rp2040-en/ - MicroPython examples: PIO
https://github.com/raspberrypi/pico-micropython-examples/tree/master/pio - PIO: Wikipedia CZ (pozor: jedná se o něco jiného!)
https://cs.wikipedia.org/wiki/PIO - RP2040 (Wikipedia)
https://en.wikipedia.org/wiki/RP2040 - Maximising MicroPython speed
https://docs.micropython.org/en/latest/reference/speed_python.html - Online ARM converter
https://armconverter.com/?disasm - The 3 different code emitters
https://www.kickstarter.com/projects/214379695/micro-python-python-for-microcontrollers/posts/664832 - The 3 different code emitters, part 2
https://www.kickstarter.com/projects/214379695/micro-python-python-for-microcontrollers/posts/665145 - Fast Filters for the Pyboard
https://github.com/peterhinch/micropython-filters - How to load 32 bit constant from assembler with @micropython.asm_thumb
https://forum.micropython.org/viewtopic.php?f=21&t=12931&sid=25de8871fa9cfcf8cafb6318f9d8ba3a - Pi pico, micropython.asm_thumb: ADR Rd, <label> and LDR Rd, <label> not implemented?
https://github.com/orgs/micropython/discussions/12257 - MicroPython documentation
https://docs.micropython.org/en/latest/index.html - Inline assembler for Thumb2 architectures
https://docs.micropython.org/en/latest/reference/asm_thumb2_index.html - Inline assembler in MicroPython
https://docs.micropython.org/en/latest/pyboard/tutorial/assembler.html#pyboard-tutorial-assembler - MCU market turns to 32-bits and ARM
http://www.eetimes.com/document.asp?doc_id=1280803 - Cortex-M0 Processor (ARM Holdings)
http://www.arm.com/products/processors/cortex-m/cortex-m0.php - Cortex-M0+ Processor (ARM Holdings)
http://www.arm.com/products/processors/cortex-m/cortex-m0plus.php - ARM Processors in a Mixed Signal World
http://www.eeweb.com/blog/arm/arm-processors-in-a-mixed-signal-world - RISCové mikroprocesory s komprimovanými instrukčními sadami
https://www.root.cz/clanky/riscove-mikroprocesory-s-komprimovanymi-instrukcnimi-sadami/ - RISCové mikroprocesory s komprimovanými instrukčními sadami (2)
https://www.root.cz/clanky/riscove-mikroprocesory-s-komprimovanymi-instrukcnimi-sadami-2/ - ARM Architecture (Wikipedia)
https://en.wikipedia.org/wiki/ARM_architecture - Cortex-M0 (Wikipedia)
https://en.wikipedia.org/wiki/ARM_Cortex-M0 - Cortex-M0+ (Wikipedia)
https://en.wikipedia.org/wiki/ARM_Cortex-M#Cortex-M0.2B - Improving ARM Code Density and Performance
New Thumb Extensions to the ARM Architecture Richard Phelan - The ARM Processor Architecture
http://www.arm.com/products/processors/technologies/instruction-set-architectures.php - Thumb-2 instruction set
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0344c/Beiiegaf.html - Introduction to ARM thumb
http://www.eetimes.com/discussion/other/4024632/Introduction-to-ARM-thumb - ARM, Thumb, and ThumbEE instruction sets
http://www.keil.com/support/man/docs/armasm/armasm_CEGBEIJB.htm - An Introduction to ARM Assembly Language
http://dev.emcelettronica.com/introduction-to-arm-assembly-language - Processors – ARM
http://www.arm.com/products/processors/index.php - The ARM Instruction Set
http://simplemachines.it/doc/arm_inst.pdf - The Thumb instruction set
http://apt.cs.manchester.ac.uk/ftp/pub/apt/peve/PEVE05/Slides/05_Thumb.pdf - Why Learn Assembly Language?
http://www.codeproject.com/Articles/89460/Why-Learn-Assembly-Language - Is Assembly still relevant?
http://programmers.stackexchange.com/questions/95836/is-assembly-still-relevant - Why Learning Assembly Language Is Still a Good Idea
http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html - Assembly language today
http://beust.com/weblog/2004/06/23/assembly-language-today/ - Assembler: Význam assembleru dnes
http://www.builder.cz/rubriky/assembler/vyznam-assembleru-dnes-155960cz - Assembler pod Linuxem
http://phoenix.inf.upol.cz/linux/prog/asm.html - AT&T Syntax versus Intel Syntax
https://www.sourceware.org/binutils/docs-2.12/as.info/i386-Syntax.html - Linux Assembly website
http://asm.sourceforge.net/ - Raspberry Pi Pico Variants – A Detailed Comparison
https://circuitdigest.com/article/raspberry-pi-pico-variants-comparison - Raspberry Pi Pico 2 vs Original Pico: What’s New?
https://www.digikey.cz/en/maker/blogs/2024/raspberry-pi-pico-2-vs-original-pico-whats-new - pio-uart
https://github.com/Sympatron/pio-uart - Datasheet čipu RP2040
https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf