A tudástár ezen cikkében az Arduino alatti programozásról, a bootloader működéséről és beprogramozásáról lesz szó. Ehhez felhasználjuk az Arduino mintaalkalmazások közül az ArduinoISP mintakódot, a tartalék áramköri lapokat és néhány kábelt, LED-et és ellenállást. Lépésenként taglalja a cikk a megvalósítást és a buktatókat is. Számos kifejezésre is magyarázat található, amik eddig elvétve fordultak elő és számos internetes cikk triviális, magától értetődőnek tekintette a használatát. De hogy mi is az a bootloader, miben segíti az Arduino működését és hogyan kerül bele a chipbe a működéshez? Ezt járja körbe ez a cikk…
Mi is az az Arduino és miért jó nekünk?
Az Arduino (mint hardware eszköz) számos dolog miatt jól használható – de a legfontosabb ezek közül, hogy nagyon könnyen programozható az Arduino szoftverből. Elég a számítógéphez csatlakoztatni az USB porton keresztül és csak megnyomjuk az Upload/Feltöltés gombot – a sketch programunkat lefordítja és a kontroller flash memóriájába is feltölti a háttérben a szerkesztőprogram.
A bootloader
A könnyű feltöltés (amikor csak a PC-re csatlakoztatjuk az eszközt és rátöltjük a programot) egy speciális kódrészletnek köszönhető. Ezt a kódrészletet a mikrokontroller minden egyes indulásakor végrehajtja, és amely program egy külső eszközön (itt a PC-n levő) lefordított programot (shetchből készült processzor által futtatható kódot) keres az USB(soros) porton egy adott protokoll és kommunikációs sebesség szerint.
Ha a kapcsolat nem épül fel, akkor a korábban feltöltött sketch program kezd el futni a mikrokontrolleren. Ezt a kis (általában 512 byte hosszú) kódrészletet „Bootloader”-nek hívják, és a mikrovezérlő memóriájának egy olyan területén található amely nem programozható át a programok feltöltése során. Ez egy olyan speciális programterület, melyet eredetileg a bekapcsoláskor, a főprogram futása előtt elinduló program céljára tervezték.
A bootloader programozásához és ezen keresztül az Arduino szoftverrel (IDE) való kompatibilitás biztosításához a mikrovezérlőbe ezt az indítóprogramot valahogyan bele kell tölteni. Ez történhet:
- gyárilag, előreprogramozottan – ahogyan a gyártósorról lejön a kontroller (AVR esetén nagyon ritka megoldás), vagy
- a chipen kialakított ún. programozó felületen keresztül.
A gyári programozófelület használatára az AVR mikrokontroller család esetén többféle módszer is van – a leggyakoribb az ún. ISP (In System Programming) felületen keresztül történő programozás. Az ISP felület a kontroller adott lábain keresztül érhető el és adott protokoll szerint lehet a programozás menetét elvégezni (a részletes folyamatleírást a mikrokontroller adatlapja tartalmazza). A programozás során nem csak a nemfelejtő programmemóriát (Flash), hanem az írható-olvasható adatmemóriát (EEPROM) és a chip működési paramétereit beállító ún. biztosítékbitjeit is lehet módosítani/újraírni.
Az ISP eljárás segítségével a chip – szinte teljes területéhez hozzá lehet férni. Kezdőként kb. olyan ez a lehetőség, mintha kibiztosított fegyver lenne – sokmindent meg lehet tenni a segítségével: akár a chip halálát is okozva!
Az ISP programozási eljárás magában foglalja a biztosítékok írását is: egy olyan speciális bitkészletet, amely meghatározza a mikrokontroller működését adott körülmények között, például az órajelének forrását illetve – a programmemória felosztását a bootloader és a főprogram memória közt.
Arduino, mint programozó
A bootloader kód beprogramozását, a biztosítékbitek megfelelő beállítását – azaz az ATMega mikrokontroller „Arduino”-vá alakításának teljes folyamatát – az Arduino Software (IDE) integráltan, beépítve kezeli: önálló menüpontban elérhető a teljes folyamat kezelése. A programozók közül számos fajtát támogat a keretrendszer – ez is egyszerűen menüből kiválasztható.
A programozók közül az „Arduino as ISP” a legolcsóbb és legpraktikusabb megoldás a bootloader írására: ekkor egy Arduino lapot használunk programozóvá alakítva (az Arduino lapka ATMega2560, ATmega328P vagy akár ATMega32U4 chip köré is épülhet (egyéb lapkák támogatása folyamatosan bővül)).
A programozási folyamat a céláramkör alábbi kivezetéseit használja: VCC, GND, MISO, MOSI, SCK és a RESET.
A programozóvá dedikált lapka és a céláramkör összekötése
A következő táblázat megmutatja, hogy mely lapok hol tartalmazzák a programozó kivezetésket és a rendszer mekkora feszültségen üzemel:
Arduino lapka | MOSI | MISO | SCK | Feszültség |
Uno/Duemilanove | 11 / ICSP-4 | 12 / ICSP-1 | 13 / ICSP-3 | 5V |
Mega | 51 / ICSP-4 | 50 / ICSP-1 | 52 / ICSP-3 | 5V |
Leonardo | ICSP-4 | ICSP-1 | ICSP-3 | 5V |
Due | ICSP-4 | ICSP-1 | ICSP-3 | 3.3V |
Zero | ICSP-4 | ICSP-1 | ICSP-3 | 3.3V |
101 | 11 / ICSP-4 | 12 / ICSP-1 | 13 / ICSP-3 | 3.3V |
Az SPI kommunikációs kivezetések azonosak a programozáshoz használt kivezetéssel. Ezek jellemzően dedikáltan megtalálhatóak az áramköri lapokon – ICSP csatlakozóként. Az ICSP csatlakozó szabványos lábkiosztása és elhelyezkedése miatt sok esetben a shield-ek is ezt a csatlakozósort használják az SPI kommunikációra. (Az SPI kommunikáció a MOSI, MISO és SCK funkcióval rendelkező kivezetéseket jelenti.) Tipp: a leírásokban gyakran az ICSP (azaz In Circuit Serial Programming – Soros áramköri programozó-kivezetés) elnevezéssel illetik az ISP (In System Programming) kivezetést. Gyakorlatilag mind a kettő rövidítés ugyanazt jelenti.
A szabványos ISP/ICSP csatlakozó kiosztása:
A következő képen az Arduino Uno lapkán pirossal kerültek jelölésre az SPI busz kivezetései, míg sárgával a központi ATMega328P-hez csatlakozó ICSP. Az Uno lapokon az USB illesztésért felelős ATMega16U2 chip programozását a külön kivezetett ICSP2 csatlakozón át lehet elvégezni.
Egyes Arduino lapokon (lásd a fenti táblázatot) a MOSI, a MISO és az SCK kivezetések megegyeznek a digitális 11, 12 és 13 kivezetésekkel (D11, D12 és D13 jelölés). Sok interneten található leírás úgy tálalja, hogy a programozást (programozóeszközként használva a lapot!) ezen kivezetések segítségével végezzük el. Azonban ez a kijelentés csak az Uno/Diecimila és Nano lapok esetén igaz! Ha például a Mega, Leonardo, stb. lapokon is ezen kivezetéseket szeretnénk használni programozásra, akkor a mintaprogramban az USE_OLD_STYLE_WIRING lehetőséget engedélyezni kell! (Uno esetén erre nincs szükség). A Leonardo, Mega stb. lapokon a 10-12-13 kivezetések nem az SPI felület kivezetett csatlakozásai!
A fenti képen két Uno alaplapot csatlakoztatunk össze a bootloader írásához a „régi stílusú” kapcsolattal: a felső lap a céláramkör (Target), az alsó lap a programozó (Programmer). Szükséges még a működéshez a programozó lapon a kinevezett „céláramköri reset” kivezetést (jellemzően D10) összekötni a céláramkör Reset kivezetésével (sárga vezetékkel jelölve). Valamint a tápfeszültségeket is közösíteni kell.
Az Arduino Nano programozása az ICSP/ISP kivezetésén át az Uno D10..D13 programozófelületével is egyszerűen megoldható:
Az következő ábrán egy Arduino Mega segítségével kerül egy Arduino Uno felprogramozásra. A trükk, hogy az Arduino Mega közvetlen SPI kivezetésére kerül az Uno rákötésre – az összekötött kivezetések Mega-Uno között:
- D51-D11,
- D50-D12,
- D52-D13,
- GND-GND,
- 5V-5V és
- D10 a RESET-re.
Tipp: az Arduino lap a működése miatt a soros/USB kapcsolat megnyitásakor a kontrollert újraindítja (reseteli) – (gyakorlatilag minden induláskor, soros kapcsolat megnyitásakor megtörténik az újraindulás, – hogy a programok feltöltése a bootloader segítségével egyszerűen megtörténhessen). Ezt a programozásra kijelölt lapka esetén meg kell akadályozni, hogy a programozószoftver folyamatosan futhasson rajta és ne induljon minden adatkapcsolat megnyitásakor újra állandóan. (Természetesen csak azután, ha már a programozó szoftver rátöltésre került!) A megoldás kulcsa, hogy a reset funkciót valami módon meg kell gátolni. Erre több megvalósítási lehetőség is kínálkozik:
- a GND és a Reset kivezetés közt 10uF kondenzátor beépítésével, vagy
- a Reset és a tápfeszültség kis (pl. 100R ellenálláson át) összekötésével.
A soros/USB kapcsolat megnyitásakor fellépő reset-működés elve az, hogy egy 100nF kondenzátoron át a Reset kivezetés egy negatív resetimpulzust kap. A 10uf kondenzátor illetve a 100R ellenállás ezt akadályozza meg (Az ábrán pirossal jelölve az Uno kapcsolási rajz részletén).
A programozó lapon a RESET és a GND közti kondenzátor csak azokon a lapokon szükséges, amelyek rendelkeznek külön illesztővel a kontroller és a USB port közt (például Mega, Uno, Nano). Az olyan lapok esetén nem szükséges, amelyek beépített USB-vel rendelkeznek (Leonardo, Esplora, Micro) mivel a programozáskori resetet a kontroller maga végzi.
És hogyha a Digistump – Digispark T85 (ATTiny85 chipre épülő) áramkörét kell újraprogramozni, akkor is az ISP felületen át történik az átprogramozás/bootloader feltöltés:
Persze itt sem maradhat el az ArduinoISP használata a járulékos kondenzátorral. Tipp: bizonytalan programozás esetén az Uno lapon a Reset kivezetés és a +5V összekötése sokat javít a helyzeten.
A „Digispark használata Arduino alatt” is megér egy olvasását: →Digispark T85 (ATTiny85) használata.
Feszültségszintek
Az Arduino lapka-család 5V és 3,3 V rendszerfeszültségű-eszközöket is tartalmaz. Ha olyan Arduino lap lett kiválasztva programozónak, amelyik 3.3V-os I/O feszültségű (Due, Zero, 101, MKR1000…), akkor ügyelni kell arra, hogy a programozó kivezetésein nehogy külső 5V-ot kapjon! Ennek egyszerű módja, hogy a teljes rendszer (mind a programozó, mind a céláramkör is!) 3,3V tápellátásról működjön.
A fenti képen az MKR1000 és az Uno közötti huzalozás látható: speciális megoldás, hogy minden 3.3V-on fut. Az MKR1000 Vcc-jéből és GND -jéből véve az Uno 5V belső tápfeszültségére a 3,3V rendszertáp lett kötve és természetesen a GND-GND összekötés sem maradhat el. Ugyanez a kapcsolat létesíthető az Uno ICSP felületén keresztül is a korábban írt lábkiosztás alapján. Az egyes kivezetések funkcióit a kábelezk színe is megjeleníti: az összes képen így könnyebben átlátható a régi és az új huzalozás.
Fontos! Az MKR család esetén a céláramkör felé menő Reset kivezetés tényleges azonosítását át kell írni a kódban: az alapértelmezett D10 helyett a D6-ot kell megnevezni (a D10 eredeti funkciója MKR1000 esetén a MISO!)
Megjegyzés: Az USB-ről vagy önálló tápellátást csak a kábelezés-összekötés után kapjon az összeállított áramkör! Szükséges – még az összeköttetés előtt – a Programozónak kinevezett lapra a programozószoftver feltöltését megtenni!
Programozószoftver feltöltése
A programozószoftvert az Arduino keretrendszer tartalmazza, a File – Minták – 11. ArduinoISP – ArduinoISP elérési úton.
A vázlatot megnyitva, a programban számos paraméter található. Ezek működését a programkódban levő megjegyzések magyarázzák meg – csak akkor szabad megváltoztatni ezeket a paramétereket, ha felmértük a hatását a program működésére! A program három visszajelző LED-et is támogat, amelyek vizuális információt adnak a programozási folyamatról.
Az ArduinoISP program feltöltését a Programozónak kinevezett lapkára ugyanúgy lehet végrehajtani, mint bármilyen más program feltöltését. A lapka és a port kiválasztása után fordítás és feltöltés következik.
Fontos! A program feltöltése után a korábban írt 10uF kondenzátort és/vagy 100R ellenállást is be kell rakni a lapka megfelelő kivezetésére!
Felkészülés a programozásra: ArduinoISP kiválasztása
A működéshez szükséges még, hogy az Arduino keretrendszerben a programozó legyen pontosan kiválasztva – ugyanis nem a beépített bootloadert használjuk a program át/feltöltésére (hiszen azt írjuk be a céláramköri mikrokontrollerbe). A céláramkör és a számítógép közt a programozónak kinevezett és már ennek megfelelően felprogramozott áramkörünket kell megadni a keretrendszernek, hogy ezt használja majd a programozásra. Ezt az Eszközök – Programozó alatt lehet megtenni: az ArduinoISP kiválasztásával.
Bootloader programozása
A rendszerbetöltő (bootloader) feltöltése hasonlóan történik, mint bármely más szoftver feltöltése az Arduino lapra. A különbség, hogy a feltöltés nem a standard módon, hanem külső programozóval történik.
Ha minden vezeték már be van kötve a korábbi leírásoknak megfelelően, akkor a bootloader programozása már egyszerűen végrehajtható:
- Az Eszközök-Alaplap alatt ki kell választani a programozandó lapka típusát (nem az ArduinoISP programozó-szoftvert már tartalmazó lap típusát!) és ha szükséges a processzor illetve órajel is pontosítandó (nem minden lapnál jelennek meg ezek a paraméterek). Ez a beállítás határozza meg a céláramkörhöz szükséges bootlooader típusát, a processzorbeállításokat jelentő biztosítékbitek beállításait, a célkontroller típusának (chip) meghatározását. A programozási eljárás (függetlenül, hogy a standard belső folyamattal, vagy külső programozóval történik a chip beprogramozása) minden írási művelet előtt ellenőrzésre kerül a mikrokontroller típusa is. De sok Arduino lapka ugyanazt a mikrokontrollert használja és minden alaplap-típusnak kissé eltérő működésű bootloadere van.
- A PC oldali portként azt kell megadni, ahová az ArduinoISP szoftvert tartalmazó, azaz a programozást végző lapka van csatlakoztatva.
- A tényleges programozási folyamathoz ki kell választani az Eszközök – Bootloader égetése menüpontot.
- Az Arduino keretrendszer megkezdi a programozást, amit az alsó státuszmezőben lehet nyomon követni (ehhez a Fájl – Beállítások alatt a Bővebb kimenet mutatása eközben: fordítás, feltöltés paraméterek legyenek kipipálva.) Ha a LED-ek is csatlakoztatva vannak a programozóra, akkor a folyamat vizuálisan is követhető.
SPI-Soros programozási mód
A programozási folyamat a három SPI kivezetésen át történik (MISO, MOSI és SCK) a szabványos SPI programozási protokoll szerint. A protokoll ugyanaz, mint amit az SD/uSD memóriakártyák olvasására és írására használunk. Az egyetlen különbség a memóriakártyákkal való kommunikációhoz képest, hogy a chip programozásakor a /CS (/Chip select) funkció nincsen használva. Az AVR mikrovezérlők esetén a RESET folyamat speciális funkcióját használjuk, amely leállítja a processzorban futó programot (akár a boot-, akár a főprogramot), és a mikrokontrollert olyan állapotba hozza, ahol a kontroller figyeli az SPI felület felől érkező parancsokat. A legelső parancs, amelyet a protokoll alapján a kontroller vár, hogy melyik programozási módba lépjen be.
Ha ez a specifikus programozási mód aktívvá válik, akkor már írható és olvasható a mikrokontroller minden programozható területe: Flash, EEPROM és biztosítékbitek. A Flash memória címterének végén van a bootloader rendszerbetöltő részére fenntartott kódterület (ahogyan ez a cikk elején lévő képen is látszik). A „Burn Bootloader” (Bootloader égetése) eljárás során a kiválasztott lap paramétereinek megfelelően beállításra kerülnek a mikrovezérlő biztosítékbitjeit is. Ez az egyik oka annak, hogy pontosan kell kiválasztani a pontos céláramkör típusát.
A programozás technikai oldala
A mikrokontroller programozására használt nyílt forráskódú szoftver eszköz az avrdude névre hallgat. A szoftver segítségével végzett programozási folyamat négy fő lépésre bontható:
- a mikrokontroller azonosítása és tartalmának törlése,
- a biztosítékbitek beállítása a kiválasztott lapkának megfelelően,
- a bootloader kód feltöltése,
- a mikrokontroller bootloaderének felülírás elleni védelméhez a biztosítékbitek beállítása.
A biztosítékbitek beállításai minden egyes lapka paraméter-fájljában került tárolásra – elkerülve a hibás megadásából származó működési problémákat.
A rendszer-biztosítékbitek általában három byte-ból állnak – alacsony (Low), magas (High) és kiterjesztett (Extend). Ez a 3 byte-nyi adat beírása a programozás legkritikusabb aspektusa: a rossz biztosítékbit-beállítások tönkretehetik a mikrokontrollert és az alaplapot. Ennek oka, hogy a biztosítékbitek a mikrokontroller funkcióinak számos alapműködését határozzák meg, mint például: különböző órajel-források kiválasztása és a chip sebességének finomhangolása (CKSEL, SUR, DIVCK8), a chip programfuttatásához szükséges minimális rendszer-feszültség beállítása (védelmi leállás küszöbfeszültsége (BOD level)), a bootloader használatának engedélyezése/tiltása (BootEN), a Flash memóriából a bootloader méretének meghatározása (512..4096 bájt), a Reset kivezetés illetve az SPI módú soros programozás letiltása (RESET EN, ISP disable, dW enable), illetve az EEPROM tartalom adatmegőrzésének engedélyezése programozáskor (EESAVE).
A biztosítékbitek részletes leírása megtalálható az egyes mikrovezérlők adatlapjában. Minden beállításnak megvan a maga átgondolt funkciója – például a fejlesztő lezárhatja a chipet, és megvédheti a tartalmát illetéktelen kiolvasástól (és másolástól). De előfordulhat, hogy tévesen rossz módon sikerül beállítani a mikrokontroller biztosítékbitjeit, és az ISP csatlakozón keresztüli programozás nem érhető el többé („kizárja a chipből magát”). De ha sikeresen a mikrokontroller tetszhalott állapotba került a programozás után, akkor sincs még veszve minden: a mikrokontroller helyreállításához ún. nagyfeszültségű soros vagy nagyfeszültségű párhuzamos programozót kell használni. Ezzel a biztosítékbitek újra hozzáférhetőek lesznek és a hibás beállítás kijavítható. De ennek az eljárásnak az ismertetése túlmutat a mostani tudáscikk keretein…
A biztosítékbitekről bővebben: → AVR Biztosítékbitek
Összefoglalásként: Bootloader égetésének lépései
Az Arduino keretrendszerben a példák közül az ArduinoISP-t meg kell nyitni.
Tipp: az Arduino 1.0.x sorozatú Arduino szoftver használata esetén esetében: a heartbeat ()
függvényben a delay (40);
utasítást módosítani kell delay (20);
-ra.
- Az Eszközök – Alappanel és az Eszközök – Port menükben be kell állítani a programozóként használt alaplap típusát és a kapcsolódási portját.
- Az ArduinoISP programot fel kell tölteni a Vázlat – Feltöltés menüt kiválasztva a Programozónak kinevezett lapra.
- A programozónak kinevezett lapka áramellátásának megszüntetése után, össze kell kötni a programozandó lapkával (lásd: cikk eleje)
- A cél-lapkát kell kiválasztani az Eszközök – Alappanel menüben, amely megfelel annak a lapnak, amelyen a bootloadert szeretnénk írni (nem a programozóként használt lap típusát kell megadni!).
- A programozó kiválasztását az Eszközök – Programozó menüben kell megtenni. A kiválasztandó programozó: ArduinoISP.
- Az Eszközök – Bootloader égetése menüt választva a programozás megtörténik.
Felhasznált források