„Hello, ARM“ ir truputukas teorijos

Posted: 2014-01-09 in Darbeliai
Žymos:, , ,

Kadangi pavyko sujungti J-Link ir mažą ARM devborduką, tai reikia ir „Hello, World“ atitikmenį padaryti. Mikrovaldikliams „Hello, World“ yra, be abejo, mirksintis šviesos diodas.

Bet pradžiai aš truputuką surašysiu teorines žinias, kurias sukaupiau skaitydamas apie STM32 procesorius. Mano pasirinkimą dėl šių procesorių nulėmė dar ir kodo pernešamumas (portability).

ARM procesorių yra visokiems taikymams. Cortex-M yra skirti mikrovaldikliams. Na, kaip PIC ar AVR kontroleriukai. Tik ARM yra 32 bitų. Yra atskiros šių valdiklių šeimos: Cortex-M0, Cortex-M0+, Cortex-M1 (šios šeimos procesorių nėra, yra tik architektūra FPGA mikroschemoms), Cortex-M3 (kuriuos tyrinėsiu ir aš) bei Cortex-M4.

Internetuose žmonės skundžiasi, kad, tarkim, LPC valdikliukai tarp skirtingų lygių (M0, M3 ir t.t.) yra tarpusavy prastai susiję. Vienam parašius programą ją pernešti į kitą nepavyks, arba tai bus sudėtinga. STM32 — priešingai, sako, kad kodas pernešamas lengvai. Aš, aišku, viso šito nežinau, tai tik internetiniai paistalai. Bet, spėju, kad ne be pagrindo 🙂

Antras navarotas. Aš buvau užmatęs, kad LPC procesoriukai gali būti programuojami per serijinę jungtį. Na, panašiai, kaip AVR procesoriai su Optiboot įkelties programėle — tas pats Arduino būtent taip ir veikia. Nereikia programatoriaus, reikia tik USB UART keitiklio. Taip galima ir sutaupyti. Pasirodo, STM32 ARM procesoriai dar gamykloje gauna įkelties programėlę, kuri gali padaryti tą patį. Vienas nepatogumas: procesorių reikia nuresetinti mygtukais — o jie ARM procesorių plokštėse yra iš esmės privalomi. Šiaip spėju, kad reset laiduką prijungus prie UART keitiklio irgi suveiktų. Iš to išplaukia išvada, kad JTAG zondas yra nebūtinas. Tiesa, su juo viskas kur kas patogiau, o be to, galima aparatūriškai debuginti kodą. Kadangi aš jau su AVR’ais esu privargęs šiek tiek, tai aparatinio debuginimo perspektyva mane smarkiai džiugina. O ir kodą įkelti per JTAG paprasčiau, nereikia tų mygtukų spaudinėti.

Ateityje būtinai pabandysiu programos įkėlimą su savo turimu USB UART keitikliu ir apie tai papasakosiu. Be to, su kažkokia (gal ir gamykline, dar neišsiaiškinau) įkelties programėle galima ARM procesorius ir iš viso tiesiai per USB kojas programuoti — visiškas patogumas. Bet USB programavimas ant klaustuko, aš dar apie jį nieko tikslaus nežinau.

Trečias reikalas. Aš kol kas Cortex-M3 procesoriuką ruošiuosi naudoti kaip papimpintą AVR. Na, 32 bitai, didesnis veikimo gretis, daugiau RAM… bet čia tik pradžia ir mokymasis. Nepatikėsite, bet šitas mažylis su 20 kb RAM gali pavežti… nedidukę OS ir netgi su grafiniu ekranu. Taip taip. Na, bet aš kol kas ten nelinkstu, pradžiai aiškinsiuos aparatinę dalį ir žemesnio lygio kodijimą.

Ketvirtas linksmumas: taktinis dažnis. Na, jau sakiau, kad STM32F103C8T6 procesoriukas gali veikti dažniu iki 72 MHz. Bajeris: parsisiųstoje plokštėje kvarcas yra 8 MHz. Iš pradžių pagalvojau, kad vatafak… paskui pagalvojau, kad pabandymui bus gerai… o paskui paskaičiau ir supratau, kad jo — per akis.

Kvarcas ARM procesoriuose naudojamas ne procesoriaus taktinio dažnio generatoriui valdyti, o PLL’ui. PLL — toks sudėtingas prietaisas faziniam sinchronizavimui — kad skirtingų aparatų taktiniai dažniai sutaptų ties impulsų pradžiomis, tiksliau, fazės pokyčiams. PLL’as savo ruožtu sinchronizuoja tikrojo procesoriuko taktinio dažnio generatorių su kvarcu. Programiškai nurodomas kvarco dažnio daugiklis. Pavyzdžiui, 8 MHz kvarcui nurodom daugiklį 9 ir… procesoriukas sukasi 72 MHz taktiniu dažniu. PLL’as užtikrina, kad kas devinto taktinio impulso fazė sutaptų su kvarcu. Na, kad dažnis „neplaukiotų“. Taigi, dėl to ir nereikia didelio dažnio kvarco. Tiesa, su Ethernet susijusiems projektams privalu įdėti 25 MHz kvarcą, kad normaliai sutaptų dažniai.

Penktas džiugesys: konkrečiai šiame procesoriuke yra vidinis RTC (laikrodis, taip sakant). Yra ir baterijos įvado koja, ir atskiras laikrodžio 32768 Hz kvarciukas (kuo šitas dažnis ypatingas — nežinau, nesidomėjau). Taip pat yra atskiros kojelės USB komunikacijai.

Šeštas mažas nuliūdimas: konkrečiai šitie procesoriukai neturi jokios vidinės EEPROM atminties. Lyginant su AVR tai šioks toks trūkumas. Rūpinantis kokių nors parametrų išsaugojimu teks papildomą mikroschemą įdėti.

Septintas gerumas/blogumas: priklauso nuo požiūrio. ARM procesoriai yra maitinami 3,3 V įtampa. AVR — paprastai 5 V, nors su 3,3 V irgi gali veikti. Aš jau buvau pradėjęs galvoti apie AVR projektėlį su 3,3 V įtampa, nes turiu visokios periferijos, kuri su 5 V nedirba. O ir Raspberry Pi yra 3,3 V logikos (na, juk ARM). Tiesa, gerumas tas, kad beveik visi ARM procesoriai turi dalį kojų, tolerantiškų 5 V logikai.

Aštuntas gėris didysai. ARM procesoriuose galima kaitalioti kojų paskirtis. Na, tarkim, AVR procesoriuose RX/TX (UART jungtis) yra priskirta tam tikroms kojoms ir viskas. Nepakeisi. O ARM procesoriuose galima „permesti“ kojų paskirtį. Tai yra gerai tuo, kad projektuojant plokštes galima kiek laisviau dėliotis įvairias jungteles ir komponentus. Reikia RX/TX kitoj pusėj? Prašom! Šitą būtinai reikės išbandyti.

Tiek teorijos. O toliau — bandymas suderinti Eclipse programavimo aplinką, kad būtų galima koduoti kodą ARM procesoriams. Aš Eclipse pažįstu gerai, naudoju jau seniai, tai ir toliau viską stengiuosi su šia programa daryti. Turiu keletą Eclipsių: viena darbinė ir nejudinama, viena skirta viskam, ką šiaip terlioju su krūva visokių plėtinių C++, Python, PHP ir dar šiam bei tam. Dar viena yra atskirai Java kalbai, nes JDT kažkodėl pjaunasi su PHPDev. Na, o ARM procesoriams irgi paskyriau atskirą, nes nebuvau įsitikinęs, kaip viskas pavyks. Tad parsisiunčiau jau C++ paruoštą Kepler CDT.

Apskritai, daug kas pakeiksnoja ARM procesorius dėl to, kad jiems sunku susirankioti progamavimo įrankius į veikiantį komplektą (toolchain). Buvo toks Yagarto projektas, bet, panašu, kad numiręs jau.

Parsisiuntęs Eclipse parsisiunčiau ir arm-none-eabi-gcc kompiliatorių. Buvo ten tar.bz2 diegimo archyvas Linux’ui, juo ir pasinaudojau.

Tade Eclipse programoje per Help > Install New Software prisidėjau GNU ARM Eclipse: http://gnuarmeclipse.sourceforge.net/updates

Parvažiavo įskiepis, pabandžiau sukurti naują C++ projektą. Geras, yra visos priemonės STM32F10x procesoriams! Matyt, jie visgi labai populiarūs… Taip pat dar yra STM32F4xx bibliotekos. Kitiems reikėtų parsisiųsti bibliotekas iš gamintojų. Sukūriau projektėlį su reikiamomis bibliotekomis, o ten standartiškai pirmas pavyzdėlis — mirksiuko kodas. Labai gera pradžia žaliam ARM dundukui.

Ką gi, OpenOCD GDB serverį pasileisti išmokau. Dabar parodysiu, kaip sukūriau projektėlį, kaip jį mažumėlę paredagavau ir kaip pavyko įkelti mirksiuko kodą.

Projektą sukurti paprasta: New Project ir renkamės C++ Project. Spaudžiam Next ir kitam langelyje renkamės projekto tipą su STM32F10x bibliotekomis bei Cross ARM GCC kompiliavimo/derinimo priemonėmis:

ARM Toolchaino pasirinkimas Eclipse | Darau, blė

Toliau renkamės procesoriaus tipą. STM32F103C8T6 procesoriukas yra Medium Density (ne per didelis ir ne per galingas), turi 64 kB flash atminties ir 20 kB RAM. Taip ir suvedu:

Procesoriaus density, flash atminties ir RAM pasirinkimas STM32F10x šeimai Eclipse | Darau, blė

Paskui du langelius paspaudžiu Next nežiūrėdamas, o paskutiniame renkuosi toolchain’ą „GNU Tools for ARM Embedded Processors (arm-none-eabi-gcc)“:

GNU Tools for ARM Embedded Processors (arm-none-eabi-gcc) toolchain'o pasirinkimas Eclipse | Darau, blė

Valio, projektas sukurtas, o jo kode — pavyzdinis mirksiukas:

Pavyzdinis mirksiuko projektas „Hello, World“ ARM procesoriui Eclipse | Darau, blė

Laikas susikrapštyti kokią nors schemutę pabandymui. Pavyzdinis projektėlis siūlo GPIOC dvyliktą koją, aš prijungsiu prie GPIOA nulinės:

Šviesos diodas prijungtas prie nulinės GPIOA STM32F103C8T6 ARM procesoriaus kojos | Darau, blė

Diodą prijungiau kaip active low, t.y. jis turėtų užsidegti GPIOA0 elektrodą nustačius į loginį nulį. Na, tuo metu elektrodas prijungiamas prie „žemės“. Tai raudonas laidas (pliusas) prijungtas prie 3,3 V. Kodą pakeičiau paprastai:

#define BLINK_PORT GPIOA
#define BLINK_PIN 0
#define BLINK_RCC_BIT RCC_APB2Periph_GPIOA

Dabar Eclipse reikia susikurti tinkamą Debug profilį, kuris sukompiliuotų kodą ir per J-Link (tiksliau tai per GDB serverį) jį įkeltų į valdiklį. Taigi spaudžiu Run > Debug Configurations… ir prie GDB Hardware Debugging pridedu naują profiliuką:

GDB Hardware Debugging profilis Eclipse, skirtas OpenOCD ARM J-Link debuginimui | Darau, blė

Debugger skirtukyje reikia įrašyti arm-none-eabi-gdb komandą bei OpenOCD serverio prievadą (šis yra 3333):

Debugger arm-none-eabi-gdb Eclipse | Darau, blė

Toliau Startup skirtukyje reikia surašyti GDB serverio komandas, kurios perkrautų valdiklį ir įkeltų sukompiliuotą programos atvaizdą. Man kažkodėl neveikė su santykiniu keliu, tai teko įrašyti pilną kelią iki sukompiliuoto .elf atvaizdo:

GDB serverio komandos .elf atvaizdo įkėlimui į ARM per JTAG, Elipse | Darau, blė

Va ir viskas. Dabar pat jau galima spausti Debug ir įvyks bandymas įkelti failą į valdiklį. Taip ir buvo, o atskiroje konsolėje paleistas OpenOCD GDB serveris išspjovė draugišką žinelę:

Info : accepting 'gdb' connection from 3333
Warn : acknowledgment received, but no packet pending
Info : JTAG tap: stm32f1x.cpu tap/device found: 0x3ba00477 (mfg: 0x23b, part: 0xba00, ver: 0x3)
Info : JTAG tap: stm32f1x.bs tap/device found: 0x16410041 (mfg: 0x020, part: 0x6410, ver: 0x1)
target state: halted
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x08001564 msp: 0x20005000
auto erase enabled
wrote 11264 bytes from file /media/VIETA/Dokumentai/Advanced/workspace/ARM_HELLO/Debug/ARM_HELLO.elf in 0.692682s (15.880 KiB/s)

Reiškia, atvaizdas į valdiklį perkeltas sėkmingai! Eclipse, tiesa, paklausė, ar nenorėčiau persijungti į Debug perspektyvą, ką aš ir padariau. Pavyzdinėje programėlėje kažkur pridėliota breakpointų, tad mirksiukas iš karto nepradėjo mirksėti. Programa buvo sustabdyta:

Su breakpoint'u sustabdyta ARM programėlė su JTAG, Elipse | Darau, blė

Kelis kartus pamaigius Resume mygelį programa pasiekė pagrindinį ciklą:

Pagrindinį ciklą pasiekusi ARM programa, JTAG, Eclipse | Darau, blė

Tiesa, spaudinėjant Resume OpenOCD konsolėje pabyrėjo krūvelė va tokių klaidelių:

Error: JTAG-DP STICKY ERROR
Error: MEM_AP_CSW 0x23000050, MEM_AP_TAR 0xfffff000
Error: Failed to read memory at 0xfffff000
Error: JTAG-DP STICKY ERROR
Error: MEM_AP_CSW 0x23000050, MEM_AP_TAR 0xfffff000
Error: Failed to read memory at 0xfffff000

Internete neradau nieko blogo, dauguma pasiūlymų buvo „nekreipti dėmesio“. Kol kas, kol dar nieko rimto nedarau ir tie errorai niekam netrukdo, aš į juos irgi nesigilinsiu. Debugeris, šiaip ar taip, veikia.

O mirksiukas pradėjo mirksėti! Štai nuotraukėlė viso mano setupo:

„Hello, World“ ARM programėlė-mirksiukas, STM32F103C8T6 procesorius, Eclipse, JTAG, J-Link, OpenOCD | Darau, blė

O čia ir mirksiuko filmukas:

Tiek šiam kartui. Kitu bandymu pažiūrėsiu, kaip mirksiuką paleisti su laikmačio pertraukimu ir kaip prijungti aparatinį mirksėjimą. Intensyviai skaitau Savelio ARM bandymus, manau, kad dar kitu bandymu ir remdamasis ano pavyzdžiu bandysiu 1602 ekranėlį prišriubuoti. Iš pradžių prie procesoriaus kojų, paskui ir per I²C.

Komentarai
  1. a parašė:

    Laikrodinis kvarcas yra ~32kHz todėl, kad:
    * 2^15 ir yra tasai kvarco dažnis, tad paimk 15 bitų skaitiklį, paduok į jį 32 768Hz dažnį ir skaitiklis persipildys tiksliai kas sekundę.
    Aišku kyla klausimas – kodėl 15bitų, o ne 16, 8 ar dar kiek? Čia jau tiksliai nepamenu, bet atrodo nuo kažkur 30kHz prasideda kvarco stabilumo zona ir 14 bitų atveju kvarcas būtų žymiai mažiau stabilus, nei 15bitų atveju. 16 bitų atveju stabilumas būtų panašus, bet laikrodinio kvarco standartas įsigalėjo tada, kai skaitikliai buvo tranzistoriniai ar tai tiesiog 15 ir 16 bitų taimeriai skyrėsi savo kaina/sudėtingumu. Dėl to ir liko 32 768Hz.

    • Darau, Blė parašė:

      Manau, kad 15 bitų pasirinkta dėl to, jog 16-as bitas dažniausiai žymi ženklą. Bet čia tik spėjimas, iš aparatūros pusės skaitliukui neturėtų būti įdomu.

  2. […] praeitame įraše tobulinti mirksiuką, bet šiek tiek persigalvojau. Visgi pradžiai nusprendžiau pasigilinti į […]

  3. Ignas parašė:

    Labas, programavau ant atmel serijos valdikliu ir nusprendžiau pamėginti išbandyti ARM cortex serijos valdiklius bei mikroprocesorius, gal galėtum parašyti, kur ir ko reikia ir kur nusipirkai viską ir už kokią kainą? 🙂

    • Darau, Blė parašė:

      Na, variantų yra milijonai. Mano rinkinys yra toks:

      Visa kita, ką naudoju ir kaip dirbu, esu plius/minus aprašęs. Toolchain’as kartu su Eclipse, ARM GCC — iš internetų. Kad tik būtų noro, bet dabar biškį tingiu, o ir savos gamybos plokštė sufeilino 😦

      • Ignas parašė:

        Na pripratęs buvau aš ant 32 ir 328 atmegu, bet pastebėjau naują ARM valdiklių tendenciją, sakau reikia išmėginti. Reiks susirasti by step by ko reikia, kad pradėčiau ir soft ir pan. 🙂 Nes kaip suprantu vienas iš didžiausių ARM valdiklių privalumų programuotojui yra jų funkcijų bibliotekos, t.y bibliotekos kuriose jau viskas yra aprašyta, lyginant su atmel kur reikia po datasheetus knistis…. 🙂

        • Darau, Blė parašė:

          Tamsta kažką painiojate. Sakyčiau, kad kaip tik priešingai. Yra visas AVR Freaks tinklapis, bile kiek Arduino bibliotekų ir viskas ten veikia. Su ARM kaip tik sudėtingiau, nes priklauso dar ir nuo gamintojo: ar tai bus STM32 ARMas, ar NXP, ar irgi Atmel SAM kuris nors…

          Man atrodo, didžiausias ARM privalumas yra sąlyginai mažesnė pačių procesorių kaina ir gerokai didesnė galia. Krapštytis po datasheetus reikia lygiai taip pat, tik tai kur kas sudėtingiau, nes reikia kažką pasižiūrėti konkrečiai ARM architektūros, paskui gamintojo referencus, o paskui dar ir softo bibliotekas. Taip kad ARM už AVR, bent jau mano galva, tikrai sudėtingiau — ypač iš pradžių ir visokiems mėgėjiškiems užsiėmimams.

  4. n\a parašė:

    Sveikas, gal pavyko trace outputa iskakoti i konsole ? Pats darau bandymus su stm32f103c8t6 + Eclipse + GNU Tools for ARM Embedded Processors + GNU ARM C/C++ Cross Compiler ir niekaip nepavyksta outputinti info i konsole..

  5. Andrius parašė:

    4:24:12 **** Build of configuration Debug for project Mirksius ****
    make all
    Cannot run program “make“: Launching failed

    Error: Program “make“ not found in PATH
    PATH=[D:\Projektai\STM32_Toolchain\gcc-arm-none-eabi-5_3-151225\arm-none-eabi\bin;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files (x86)\Skype\Phone\;D:\Projektai\Coreutils\bin\;D:\Projektai\Coreutils\bin\]

    14:24:12 Build Finished (took 96ms)

    darau visak pagal tave, poto ziurejau keleta video youtuveje, galvojau gal ka praleidau bet kaip nepavyksta build padaryti, ne per kur.

    gal kokiu ideju ka reik nustatyt?

    • Darau, Blė parašė:

      Hmmmz… nu, klaida tai aiški, neranda „make“ komandos. Tamstai reikėtų susidėti make for Windows ir bandyti padėti į PATH’ą. Nes pagal Eclipse CDT dokumentaciją yr taip:

      „The CDT relies on an external make utility, such as GNU make, to build a project. The CDT can generate makefiles automatically when you create a Managed Make C project or a Managed Make C++ project. You have the option of creating a Standard Make C project or a Standard Make C++ project and providing the makefile yourself.“

Parašykite komentarą

Brukalų kiekiui sumažinti šis tinklalapis naudoja Akismet. Sužinokite, kaip apdorojami Jūsų komentarų duomenys.