ARM: GPIO galimybės

Posted: 2014-02-08 in Darbeliai
Žymos:, ,

Žadėjau praeitame įraše tobulinti mirksiuką, bet šiek tiek persigalvojau. Visgi pradžiai nusprendžiau pasigilinti į ARM GPIO galimybes, kurios smarkiai platesnės už AVR. Ir, tiesą sakant, tiek platesnės, kad kelia milžinišką pagarbą STMicroelectronics inžinieriams. Na, o gal ARM projektuotojams, nežinau, kurie čia atsakingi už visą tą gėrį.

Pradžiai truputuką apie dokumentaciją. AVR atveju užtenka pasiimti atitinkamo „kauliuko“ specifikacinį lakštą (datasheet) ir ten knaisiotis. STM32 procesorių atveju viskas yra kur kas sudėtingiau. Specifikaciniuose lakštuose aprašyti konkretūs egzemplioriai su nupaišytomis mikroschemų kojytėmis ir priskirtais elektrodais. Kur kokius registrus siuntinėti ir ką procesoriai gali, reikia skaityti visos didelės šeimynos (STM32F101xx, STM32F102xx, STM32F103xx, STM32F105xx ir STM32F107xx) informaciniame lakšte (reference manual). Dar yra bendrinė ARM Cortex-M3 informacija iš pačių „ARM Holdings“, bet ten tik bendram supratimui, nes skirtingi gamintojai vis tiek kažko papildomo prisigalvoja. Informacijos daug (tarkim, informacinis lakštas yra daugiau, nei tūkstančio puslapių), skaityti sudėtinga, atrasti internete konkrečios problemos sprendimą irgi nelengva (arba bent jau man nelabai sekasi). Bet viskas po truputuką kruta į priekį. Taigi.

Trumpai prisimenam, kas yra AVR. AVR procesoriuose elektrodai gali būti įvesties arba išvesties režime. Taip pat kai kurie turi antrinę paskirtį. Pavyzdžiui, I²C ar RX/TX. Šeši elektrodai dar gali būti analoginiais įvadais. Taip pat įvesties arba „neapibrėžtos būsenos“ elektrodams galima įjungti vidinius „patempiančiuosius“ rezistorius.

Tuo tarpu STM32 Cortex-M3 procesoriukų elektrodai gali turėti štai tokias paskirtis ir su tokiomis savybėmis:

  • Didelio impedanso (tariamosios varžos) įvestis
  • Įvestis su „patempiančiuoju“ (pull-up) loginio vieneto rezistoriumi
  • Įvestis su „įžeminančiuoju“ (pull-down) loginio nulio rezistoriumi (AVR tokio nėr)
  • Analoginis įvadas. Skirtumas nuo AVR toks, kad bet kuris GPIO elektrodas gali būti analoginis
  • Išvestis su atvira santaka (drain). Na, elektrodas arba „užtrumpinamas“ į žemę arba paliekamas „plaukioti“ su dideliu impedansu. Gali praversti modeliuojant išvestį su išoriniais patempiančiaisiais rezistoriais
  • Išvestis su nustatyta įtampa (push-pull, kaip ir išvestis AVR)
  • Alternatyvios funkcijos, kurių yra nemažai ir jos gali būti laisviau kaitaliojamos, nei AVR. Alternatyvios funkcijos gali veikti nustatytos įtampos arba atvirosios santakos režimu

Taip pat dalis GPIO yra tolerantiški 5 V įtampai ir dėl šios priežasties ARM procesorius lengva sujungti su įvairia 5 V įranga, nereikia įtampos konverterių ir kitų nesąmonių.

Taigi ARM „kauliuko“ galimybės vien įvesties/išvesties srityje yra gerokai pažangesnės už AVR. Kaip tą panaudoti — kitas klausimas, bet neabejoju, kad prigalvoti tikrai galima. GPIO režimai ir jų blokinės schemos pateiktos informaciniame lakšte (nuorodos pabaigoje).

Dabar truputuką apie bibliotekas. Bet kuris ARM projektas turi turėti bibliotekų rinkinį. Aš kol kas susidariau tokį įspūdį, kad kartu būna CMSIS biblioteka (bendrinė, sukurta „ARM Holdings“ ir pritaikyta prie konkretaus „kauliuko“ jau gamintojo), bei paties gamintojo viską „palengvinančios“ bibliotekos — kad nereikėtų su CMSIS po registrus knaisaliotis. O visą šitą GPIO ūkį valdo padori krūvelė įvairių registrų — jų įsisavinimui reikia graužti informacinį lakštą.

Štai keli trumpi pasiknaisiojimai.

Prievadai ARM procesoriuke šešiolikos bitų (AVR, palyginimui, prievadai yra aštuonių bitų). Vienai prievado kojai valdyti skirti 4 bitai, taigi visam prievadui — 64. Šiam reikalui konfigūruoti yra registrų pora GPIOx_CRH:GPIOx_CRL, o duomenys saugomi GPIOx_IDR ir GPIOx_ODR registruose. Yra 32 bitų atominių veiksmų registras GPIOx_BSRR ir 16 bitų registras GPIOx_BRR. Be to, dar yra 32 bitų užrakinimo registras GPIOx_LCKR — su juo sukonfigūruotą koją galima „užrakinti“ ir apsaugoti nuo tolimesnių modifikacijų. Tarkim, saugantis nuo to, kad užsikrovus pagrindinei programai išvadai išliktų fiksuotos paskirties.

Apie konfigūraciją. GPIOx_CRL 32 bitų registras valdo 0–7 prievado kojas, o GPIOx_CRH atitinkamai 8–15. Čia paveiksliukas iš informacinio lakšto, kur parodytas GPIOx_CRL registras ir jame išskirti bitukai prievado kojų konfigūravimui:

GPIOx_CRL ARM registras | Darau, blė

MODE bitai nurodo įvestį arba išvestį, o CNF — konkretų režimą.

CNF režimai įvesčiai (MODE[1:0]=00):

  • 00: analoginė įvestis
  • 01: neapibrėžta įvestis („plaukiojantis“ didelio impendanso režimas)
  • 10: įvestis su patempimu arba įžeminimu
  • 11: nenaudojama

CNF režimai išvesčiai (MODE[1:0]>00):

  • 00: bendros paskirties išvestis su nustatyta įtampa
  • 01: bendros paskirties išvestis su atvira santaka
  • 10: alternatyvioji išvestis su nustatyta įtampa
  • 11: alternatyvioji išvestis su atvira santaka

MODE išvesties režimai:

  • 01: maksimali 10 MHz sparta
  • 10: maksimali 2 MHz sparta
  • 11: maksimali 50 MHz sparta

Viskas taip pat nustatoma ir GPIOx_CRH registre.

Ką gi, norint pamirksėti diodu reikia kažkurią koją nustatyti į išvesties režimą ir į išvesties registrą įrašyti tinkamą reikšmę. Išvesties registrai yra GPIOx_ODR. Kas ten papuola — papuola ir į atitinkamai sukonfigūruotą koją. Jeigu koja su nustatyta įtampa, tai 1 įrašymas joje padarys 3,3 V įtampą, o nuliukas — įžemins. Jeigu kojos konfigūracija — atvira santaka, tai 1 įrašymas paliks tą koją „kaboti ore“, ji bus aukšto impedanso būsenoje. Nuliukas ją įžemins.

Su GPIOx_ODR reikia elgtis panašiai, kaip su AVR PORTx. Vienetuką įrašinėti su loginiu „arba“, o nuliuką su loginiu „ir“ papildomai „apverčiant“ reikšmę. Šias operacijas atliekant sunaudojami keli procesoriaus taktai. „arba“ bei „ir“ operacijoms pirmiausia registras nuskaitomas, atliekama aritmetika ir paskui įrašoma reikšmė — iš viso trys veiksmai. Jeigu netyčia tarp jų įsiterpia pertraukimo paprogramė — visas reikalas gali susiknisti.

Va tam yra specialūs atominių operacijų registrai GPIOx_BSRR ir GPIOx_BRR. Į juos įrašinėjami kojos numeriai ir atitinkama koja nustatoma į 1 arba 0. Nereikia jokių „ir“ ar „arba“. Reikia penktą koją nustatyti į vienetuką — į GPIOxBSRR rašom skaičių 32 (du penktuoju). Reikia nustatyti nuliuką — 32 rašom į GPIOx_BRR. Ir viskas. Išvesties operacija atliekama vienu veiksmu.

Pabandysiu savo pirmąjį mirksiuką perrašyti be ST bibliotekų, o naudodamasis CMSIS registrų operacijomis. Truputuką daugiau pisnios, bet užtat šiek tiek daugiau supratimo apie tai, kaip ten viskas veikia.

ARM procesoriai dar sudaryti iš įvairių taktinių magistralių. Nesigilinsiu per daug, bet esmė tame, jog taktų generavimas pagal nutylėjimą būna išjungtas. Todėl jo neįjungus GPIO neveiks, net jei ir teisingai sustatysime registrų reikšmes. GPIO taktavimas valdomas APB2 magistralės, kuri konfigūruojama RCC_APB2ENR registro. Labai nesigilinsim, bet tinkamo bituko nustatymas į vienetuką įjungia taktavimą konkrečiam GPIO prievadui. Gerai, kad CMSIS bibliotekoje visam tam reikalui yra konstantos…

Taigi štai mirksiuko programėlė su registrų valdymu iš mano „Hello, ARM“ projekto:

#include "stm32f10x.h"

#define BLINK_LOOPS     250000

int main(void) {
  // Įjungiamas taktavimas GPIOA prievadui
  RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
  // Nulinis išvadas konfigūruojamas į push-pull režimą
  GPIOA->CRL &= ~GPIO_CRL_CNF0;
  // Nulinis išvadas konfigūruojamas į 50 MHz išvestį
  GPIOA->CRL |= (GPIO_CRL_MODE0_0 | GPIO_CRL_MODE0_1);

  while (1) {
      // Jungiam nulinę koją į loginį nuliuką
      GPIOA->BRR = GPIO_BRR_BR0;

      uint32_t i;
      i = 2 * BLINK_LOOPS;
      while (--i);

      // Jungiam nulinę koją į loginį vienetuką
      GPIOA->BSRR = GPIO_BSRR_BS0;

      i = BLINK_LOOPS;
      while (--i);
  }
  return 0;
}

Va kaip ir tiek. Programa be ST konstrukcijų ir paprastesnė. Teoriškai turėtų veikti su bet kokiu Cortex-M procesoriumi, nes CMSIS yra bendrinė biblioteka. Tiesa, includas viršuje turėtų būti pakeistas į atitinkamo gamintojo, bet tik tiek — nes gali skirtis registrų adresacija.

Kam aš čia apie tai rašau? Ogi tam, kad mokantis kažką naujo visada verta pradėti iš giliau kapstyti. Galima ir ST bibliotekas naudoti su visomis gražiomis struktūromis ir lengvai skaitomais pavadinimais. Tada vartant informacinį lakštą galima kodą rašyti kur kas greičiau ir jis suprantamesnis. Be to, kiek žiūrėjau, manipuliavimo registrais biblioteka gan paprasta, ten tik debuginio kodo biškį prikišta, kad pradedantis programuotojas kažko neprisidirbtų be galo. Inicializavimo procedūros tai truputį baisios, panašios į Arduino kodą, bet kadangi prievadai nėra inicializuojami labai dažnai, didelių našumo problemų dėl to neturėtų kilti. Visgi, pasidomėti registrais ir jų veikimu visuomet sveika ir naudinga, ar ne? 🙂

Apie kitus režimus šiandien nerašysiu, kol kas pakrapščiau paprasčiausią I/O, išvestį su mirksiuku. Žiūrėsim, kas bus kitam kartui. Nors nujaučiu, kad reikės LCD ekraniuko valdymą pasidaryt, nes dabar be mirksiuko neturiu jokios išvesties. Debuginis spausdinimas į GDB serverio konsolę kažko neveikia, tai taip truputuką neaišku, kas ir kur vyksta.

Nuorodos:

Reklama
Komentarai
  1. giedriuszzz parašė:

    Kad parašyti programėlę reik gana daug barškinti klaviatūra, rašau kaip arduinininkas mėgėjas 🙂

    • Darau, Blė parašė:

      Nu argi taip jau daug 🙂 Kelios eilutės… tiesa, nelabai lengvai skaitomos. Bet čia žemas lygis, bandymas susipažinti su keliais registrais. AVR kodas su registrų valdymu irgi ne kažką geriau… Arduino bibliotekos viską gražiai užmaskuoja, tik ne visada tas gerai. Prireikia kokios nors bjauresnės bibliotekos, žiū, jau atmintis ant ribos… tiesa, labai retais ir ekstremaliais atvejais.

      • Ignas parašė:

        Labas dirbu ant atmega32 328 ir kt. tiesiog ant avr 8 bitų valdiklių. Pastebėjau, kad norinti ant arm uždegti ir užgesinti led reikia nemažai prirašyti, norėjau paklausti koks esminis skirtumas būtų tarp arm ir 8 bitų valdiklių programavimo. Nes 8 bitams reikia žinoti daug registrų, o kai būtų su arm? Jų daugiau yra ar mažiau?

        • Darau, Blė parašė:

          ARM yra iš principo sudėtingesnė architektūra, tad atsakymas yra toks: visko yra daugiau ir viskas yra sudėtingiau. Tas „nemažai“ prirašyti yra sąlyginis, kai žinai, kaip veikia pats procesorius, tai rašosi savaime 🙂 Na, pavyzdžiui, Atmegose viskas įsijungia iš karto. Jei nori taupyt energiją, reikia, pavyzdžiui, specialiai išjungti ADC ar GPIO. Su ARM atvirkščiai: kai procesorius įjungiamas, jame visos magistralės būna išjungtos. Nori GPIO padegiot, reikia pirma įsijungti magistralę, prie kurios konkretus kojų bankas prikabintas, paskui užduoti taktavimą, paskui užduoti režimą (push-pull, active low ir t.t.), o jau tik tada gali degiot.

          Esminis skirtumas tarp programavimo… na, viskas skiriasi. Skiriasi registrų pavadinimai, jų valdymas, žongliravimas būsenomis ir pan. Tik ta pačia C ar C++ kalba galima programuot. Bet suvokiant pagrindinius mikrovaldiklių programavimo principus galima dalį tų žinių panaudot. Na, sakykim, paimsi I²C magistralę, tai žinosi, kaip joje reikia bitukus siuntinėt (nebent naudojaisi Wire ar kokia kita biblioteka ir „vidurių“ visai nesupranti). Tai, sakykim, tvarkingai programuojant galima pasidaryti bendrines, sakykim, LCD ekranėlio valdymo bibliotekas, o I²C „draiverį“ konkrečiam mikrovaldikliui pasirašyti atskirai, su tokiu pačiu interfeisu. Tai tada „aukšto lygio“ programavimas ir AVR, ir ARM bus panašus. Na, juk yra, sakykim, tiek AVR, tiek ARM pagrįsti Arduino modeliai su tomis pačiomis „komandomis“ GPIO ar ADC valdymui, bet pasiknisus giliau „draiveriai“ skiriasi kapitaliai…

          Nu va kažkaip taip maždaug, galvoju…

          • Ignas parašė:

            Klausiu dėl to, kad darausi vieną projektą, nemažai esu jo padaręs, naudoju multiple adc kanalo nuskaityma, naudoju uart duomenimis isvesti, kad galeciau juos stebeti vizualiai ir viska darau ant 32 atmegos, ir pradedu jausti, kad visa valdikli po truputi jau baigiu uzkrauti, dar nesu sujunges timeriu ir PWM kuriu tikrai man reikes. Tai pagalvojau, kad tiesiog reiketu pereiti prie arm… Bet cia toks retoriskas klausimas, nes kaip suprantu viska reiketu keisti programatoriu stk 500 isp pacia plokste ir baigiant programavimo kodu.
            Aisku mazai as kazka domejausi tuo klausimu bet kaip pvz su resursais, t.y saltiniu, kodo pvz ir projektu ir pan, gausu ar ne? Jauciu tai ka padares esu reiketu knistis ir perrasytineti kokius metus ant 32 bitu. 😀

            • Darau, Blė parašė:

              Nu kodėl, galima nusipirkti pigų kinišką devboarduką ir USB-TTL konverterį už pusę dolco. Galima tiems STM32 ARM’ams įkėlinėt kodą per serial, rašiau kitam straipsnely apie tai. Pasižaidimui investicijos tikrai minimalios.

              Dėl perrašinėjimo, kaip sakiau, priklauso nuo kodo tvarkingumo. Jei tiesiai funkciniame kode yra prikaišiota žaidimų su registrais, tai perrašinėjimas bus ilgas ir nuobodus. Jei buvo daryta tvarkingiau, tai užteks perrašyti tik tam tikras dalis. Sakykim, aš išbandžiau porą C bibliotekų, kuriose užteko pakeisti tik antraštes ir porą funkcijų, o visa kita važiavo laisvai iškart.

              Šiaip nežinau, ką patart. Jei procesoriuko resursų tikrai pradeda trūkti, tai du variantai: investuoti į galingesnę Atmegą arba pereiti prie ARM. Pereiti prie STM32 finansiškai bus tikrai pigiau, bet atsieis daug pisvalandžių (toks darbo laiko matavimo vienetas).

            • Darau, Blė parašė:

              Ai beje, reikia nepamiršti, kad ARM bus 3.3 V logika (išskyrus kai kurias 5 V tolerantiškas kojas). Tad apie šitą irgi reikia pagalvoti ir pažiūrėti, ar tamstos projekte nėra per daug priklausomybių nuo maitinimo įtampos.

              • Ignas parašė:

                Aisku privalumas butu tame, kad anksciau ar veliau gyvenime tikrai pereisiu prie arm ir viskas daug solydziau atrodys, kai galimybes yra kelis kartus geriau, vien pasiziurejus toki paprasta dalyka kaip kvarcini rezonatoriu kurio intervalas jau zenkliai skyriasi nuo 8 bitu architekturos. 🙂 Reikes man tikriausiai pasiziureti ir uzsisakyti kaip tu sakai pasizaidimui bent uzdegsiu led. 😀
                Taip kode daug reigistru pas mane kolkas artmetiniu funkciju nera tik kruvos visokiu jutikliu, temperaturos, sviesos apsviestumo, akselerometras ir pan. 🙂 Galvojau dar apie 328 kuriu turiu namie bet tikriausiai arm geresnis sprendimas butu bent pameginimui. 🙂

  2. Ignas parašė:

    Žėk dar turiu viena klausima, jei noriu pradeti programuoti su arm cortex m3 ar m4 procu tai man yra reikalingas programatorius ir breadbord kazkokios tai firmos kaip suprantu. Gal kazka savotisko galetum rekomenduoti, kad nebutu per daug ten pisnios surisant pc su programatoriu ir tuo breadbordu? Galetum ir kazka konkretaus pamineti tuo klausimu, buciau dekingas. Pats priprates esu prie avr studio 6, tai noretusi, kad palaikytu ir tai, nes daznai buna, kad programatorius vienoks ar kitoks to nepalaiko. Bandau kazka googlinti bet cia nelabai turiu patirties, siuo klausimu, tai geriausia butu jei kazka parekomenduotum.

    • Darau, Blė parašė:

      Tiesiogiai vėl neatsakysiu. Aš pats programavimui naudoju Eclipse ir ARM toolkito pluginą. Mano turimi devboardukai yra tokie. Jie man patinka tuo, kad turi ne tik taktinį, bet ir laikrodžio kvarcą bei pilną JTAG kaladę. Bet gali įsigyti ir tokią, ji turi SWD išvadą debuginimui/programavimui.

      Programatorius nebūtinas, nes, kaip sakiau, HEX ar BIN failą gali įsikelti ir per serial jungtį, pavyzdžiui, naudodamas tokį niekutį.

      Jeigu nori debugintis ir kelti softą be trumpiklių mainymo, tai gali įsigyti ir JTAG zondą, aš naudoju J-Link kloną.

      Paskui debuginimui užsikūrinėjau OpenOCD — tai buvo papildomos pisnios pareikalavęs dalykas. Tačiau visgi viskas veikia. Na, trumpai tariant, mano ARM skiltyje yra daugmaž aprašytas visas tyrinėjimų ir bandymų kelias. Dabar aš tik pasikrapštau su viena ar kita ARM savybe, kokiu nors PWM ten ar RTOS, bet tik tiek. Apie RTOS gal kada papezėsiu daugiau.

      STM32 procesoriai yra pigiausi, be to, labiausiai tarpusavy suderinami tarp atskirų šeimų (M0, M3, M4). NXP, sakykim, kodo iš M3 į M4 lengvai neperneši, bus vargo. Atmel ARM man pasirodė brangokoki. Tai kaip ir tiek.

  3. Ignas parašė:

    Ok dėkui mėginsiu kažką pirkti iš tavo nurodytų nuorodų ir žiūrėti. 🙂 Jaučiu, kad ten su tuo J-link daug knisnios…. 🙂

    • Darau, Blė parašė:

      Ai, nu… man irgi iš pradžių kažkaip baisoka atrodė, bet iš kitos pusės gi čia savo asmeniniam tobulėjimui 🙂 Reikėtų komercijai, būtų kiti įrankiai ir kitos galimybės.

Parašykite komentarą

Įveskite savo duomenis žemiau arba prisijunkite per socialinį tinklą:

WordPress.com Logo

Jūs komentuojate naudodamiesi savo WordPress.com paskyra. Atsijungti / Keisti )

Twitter picture

Jūs komentuojate naudodamiesi savo Twitter paskyra. Atsijungti / Keisti )

Facebook photo

Jūs komentuojate naudodamiesi savo Facebook paskyra. Atsijungti / Keisti )

Google+ photo

Jūs komentuojate naudodamiesi savo Google+ paskyra. Atsijungti / Keisti )

Connecting to %s