Tag Archives: STM32F

ARM:0016 pertraukimai WTF?

Kartas nuo karto, kai būna laiko vis paknibinėju ARM procesoriuką. Bet kuo toliau, tuo labiau jis mane nervuoja. Šį kartą pašnekėsim apie pertraukimus dėl PIO kojų lygio pasikeitimo…

Biški veikia ir biški veikia keistai…

Susikonfiguruoji koją kaip input:

AT91F_PIO_CfgInput( AT91C_BASE_PIOA, RTC_INT );

Pagalvoji, kad kojai reikėtu pull-up:

AT91F_PIO_CfgPullup( AT91C_BASE_PIOA, RTC_INT );

… pyst neveikia iškarto. Nebereaguoja. Tai šitą eilutę užkomentuojam.

Dėl šito nežinau ar reikia, bet eksperimente panaudojau:

AT91F_PIO_CfgInputFilter( AT91C_BASE_PIOA, RTC_INT );

Dabar konfiguruojam pačio pertraukimo valdymą:

//* configure PIO interrupt and handler
AT91F_AIC_ConfigureIt ( AT91C_BASE_AIC,
AT91C_ID_PIOA,	// pertraukimo tipas.
INT_LEVEL,	// pertraukimo lygis
//AT91C_AIC_SRCTYPE_EXT_LOW_LEVEL , 	// nesuprantu kas sukelia pertraukima
AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE , // nes visi sitie veikia vienodai
//AT91C_AIC_SRCTYPE_POSITIVE_EDGE, // visiskai. Nesamone.
ISR_PIO_handler); // paprograme atliekanti INT apdorojimą

Ir kaip parašyta komentaruose, visiškai pofig ką ten konfiguruoji- ar low_level ar external negative edge ar positive edge pertraukimas iššauna visada. Į RTC_INT koją padaviau 1Hz signalą kuris ateina iš nepriklausomo šaltinio. Taigis pertraukimas šaudo ir kai būna LH ir HL perjungimas. Ir visiškai dzin ką ten rašai.

Kita pastebėta nesamonė- nesugebu išjungti pertraukimo. Pas AVR procesoriuką, vieną asemblerio komanda ir pertraukimai išjungti. Čia jau ne. Tačiau yra “makro” komandos:

//AT91F_AIC_DisableIt (AT91C_BASE_AIC, AT91C_ID_PIOA);
//AT91F_AIC_EnableIt (AT91C_BASE_AIC, AT91C_ID_PIOA);

Atrodo kaip tik tas- išjungia pertraukimus pagal PIO. Praktiškai viskas žymiai blogiau. Ta išjungimo komanda susideda iš kelių komandų. O procesorius taigi dirba “asinchroniškai” (pipeline). Ir taip gaunasi, kad kažkuriuo momentu kažkas susimaišo protelyje pas ARMą ir pertraukimas nebeveikia.
Programa tokia: sukasi amžinas ciklas kuris ant spalvoto LCD ekranėlio paišo mažus kvadratėlius ar linijas (tai ne žaidimas), o pertraukimas, kas 1 sekundę parašo- atnaujiną laiką ant to pačio ekrano. Grafinio ekrano paišymo subtilybė- kad nupaišyti primityva atliekamos kelios komandos. Ir jų seka svarbi. Todėl, teoriškai grafinio paišymo metu pertraukimas turi būti išjungtas. Išjungia pertraukimą, nupaiš0 kvadratėlį, įjungia pertraukimą. Ir kai pertraukimas suveikia, ant to pačio ekrano parašo laiką. Ką jus manot? Ogi figuški- per mažiausiai 10 sekundžių, daugiausiai per porą minučių pertraukimas sugenda. Jei nejungti pertraukimo blokavimo, viskas veikia ilgai, tik ant ekrano atsiranda artefaktų dėl nekorektiško valdymo. Programėlę reikia rašyti kitaip, nei įprasta pas ATMEGAs…

Laukių komentarų žmonių kurie žaidė su SAM7 čipu.

Beja, int handleris:

__ramfunc void ISR_PIO_handler(void)
{
volatile unsigned int pin_mask = AT91C_BASE_PIOA->PIO_ISR;
// Int patvirtinimas-isvalymas. Be jo neveikia.

	if(pin_mask & RTC_INT)
	{
	if ( (AT91F_PIO_GetInput(AT91C_BASE_PIOA) & RTC_INT) == 0 )
		{
			AT91F_PIO_ClearOutput( AT91C_BASE_PIOA, _BV(15));
			AT91F_PIO_SetOutput( AT91C_BASE_PIOA,_BV(15));
		}
	}
AT91F_AIC_ClearIt(AT91C_BASE_AIC,AT91C_ID_PIOA); // clear interrupt
AT91F_AIC_AcknowledgeIt(AT91C_BASE_AIC);	// acknowledge interrupt
}

gal čia kažką neteisingai parašiau?

ARM:0015 LCD ILI9341

Greitas portas iš AVR versijos į ARM SAM7S kodą. Čia iškilo smulkių problemų ir nesusipratimų. Tačiau buvo nustatyta, kad ILI9341 datašytas biški meluoja:
Serial Clock Cycle (Write) min 100 – ns (10MHz)
Serial Clock Cycle (Read) min 150 – ns (6.66MHz)

Tačiau man kažkodėl visas SPI puikiausiai veikia su 24MHz SPI CLK!

ARM SAM7 and ILI9341 color LCD SPI
Tekstinis LCD čia beveik nereikalingas, nes jis buvo naudojamas kaip DEBUG, kad pamatyti ar praėjo softas per tam tikrus etapus.

Ko aš nepadariau. SAM7 moka per SPI transliuoti daugiau nei 8 bitus. Tačiau man nepavyko iššifruoti “buferio” persiuntimo per SPI (DMA). Daugelis komandų susideda iš 8 bitų komandos ir 8, 16 ar daugiau bitų duomenų. Tačiau kiek supratau (gal klaidingai), kad pakeisti 8-16-24-32 bitų transliacijas reikia perkonfiguruoti SPI. Tačiau man gi reikia dažnai daryti 8+16 siuntimą ir tada perkonfiguruoti SPI? Nesamonė. Kitas metodas- aprašyti buferį ir nurodyti hardwarei ką ir kaip perduoti. Deja tas man nesigavo.
Todėl teko vietoje “navarotnų” metodų panaudoti tą pačia strategiją kaip ir AVR kontroleryje.

Nu ir aišku source kodas bei kompiliuotas hex kodas, hexas sukompiliuotas Atmel AT91SAM7S256AU serijos čipui

P.S. projektų numeracija atitinka numeriams mano kietam diske. Tai visiškai nesusije su straipsnių seka. Pvz. 14 projektas yra tuščias projektas su minimalia konfiguracija- kad pradedant naują projektą per daug nevargti. Imi 14 projektą, kopijuoji ir darai naują. Template vienu žodžiu.

ARM:0012 ADC

Prisikasėm prie šio procesoriuko ADC (analog to digital converter). Čia irgi biški iškilo problemų. Pagrindinė- rodos nereikia nurodinėti, kad ADC koja priskiriama specialiai periferijai, o ne standartiniam PIO. Tipo jei pasirenki ADC kanalą, tai viskas susikonfiguruoja automatiškai. Kažkas man čia neaišku.
Dar dėl ADC periferijos clock, tai tipo jis visada įjungtas ir neišsijungia. Rodos taip parašyta datasheete.

Nu nėra ką čia daugiau pridurti. Veikimo principas panašus kaip ATMEGOJE, tik papildomai yra ne tik paskutinio nuskaityto ADC kanalo registras, bet ir kiekvienas ADC kanalas turi savo “asmeninį” registrą kurį galima vėliau nuskaityti.

Nu ir aišku source kodas bei kompiliuotas hex kodas, hexas sukompiliuotas Atmel AT91SAM7S256AU serijos čipui.

ARM:0011 PWM

Vėl nuo “sudėtingų” einam link pačių paprasčiausių. Šį kartą pabandysim pasileisti hardwarinį PWMą. Dabar viskas tupi vėl pagrindiniam, main.c faile.

Atmel ARM SAM7S PWM

Mano LCD kontrastas valdomas su programiniu PWM. Reikėtu taip kvailai nedaryti, o panaudoti tikrą hardwarinį (kalbainiškai- aparatinį) PWM. Internete susiradau pavyzduką su PWM. Ten naudojamas PWM0 kanalas, ir jo galimos išėjimo kojos labai toli nuo mano LCD lizdo. Tuo tarpu PWM1 kanalo galimo kojos visai patogios. Todėl, kad palengvinti būsimos, pataisytos PCB projektavimą, nutariau užprogramuoti PWM1 kanalą. Source kode yra viskas palikta ir PWM0 kanalo programavimui. O peržvelgus abu variantus, iškarto pasidaro aišku kaip užprogramuoti likusius.
Programoje kiek tai bandoma paaiškinti kaip skaičiuojasi vienas ar kitas parametras- tikslas buvo 2kHz PWM signalas. Bet vistiek rekomenduoju pasiskaityti datašytą.

Kada padarys tokį kontrolerį kurio kojytės bus dar labiau nepririštos prie periferijos?

Aišku:
Atmel ARM SAM7S PWM example with source code and hex, hexas sukompiliuotas Atmel AT91SAM7S256AU serijos čipui.

ARM:0010 grafinis LCD

Tai palengvinta grafinio displėjau valdymo programa. Ji neturi daugybės opcijų ir šiaip ribota. Tai pagrinde lenko Radosław Kwiecień programa, aš ja kiek adaptavau mano stiliui ir prirašiau minimalistinę paprogramę proporciniam šriftui. Deja, šriftas tik 8 pikselių aukščio ir pozicionuojasi Y ašyje kas 8 pikseliai. X ašyje viskas gerai- galima pastumti per vieną pikselį.
Proporcinis šriftas nupaišytas pagal originalų tekstinių LCD šriftų vaizdelį, tik perdarytas proporciniui variantui. Čia man padėjo java programa iš AVR grafinių LCD paketo. Ten viduje failo yra nuorodos.

ARM SAM7S graphic LCD
Kadangi SAM7 turi daug kojų, tai pajungtas ir grafinis ir tekstinis LCD.

Mano turimas LCD tai pats pigiausias kiniškas LCD su KS0108 kontroleriu. Jo vaizdelis invertuotas, todėl jau ne kartą minėtąpenis harder” paveiksliuką teko invertuoti.

Horse penis harder on small LCD LOL
Kadangi sumažinto teksto neįmanoma perskaityti, šukį be kurio paveiksliukas negalioja perrašiau naudodamas savo teksto rašymo paprogrames. Dar viršuje rodomas laikas nuskaitytas iš RTC mikroschemos.

Šio posto source code ir hexas:
Grafinio LCD ARM SAM7S source code ir hex, hexas sukompiliuotas Atmel AT91SAM7S256AU serijos čipui.

ARM:0009 RTC HT1381

Čia tos keistos Holteko HT1381 mikroschemos, kur prisilupinėjau iš šroto. Viskas tas pats kaip ir AVR versijoje, tik perrašyta taip, kad suprastu SAM7 mikroschema. Nieko stebūklingo.

ARM SAM7 HT1381 RTC

Ten per viduriuką rodo laiką kiek turi savyje holtekas. Čia ką tik įjungta, tai tik 00:01:48.

Source kodas ir kompiliuotas hex failas:
ARM SAM7S ir Holteko RTC HT1381 source code ir hex, hexas sukompiliuotas Atmel AT91SAM7S256AU serijos čipui.

ARM:0008 taimeris

Pagaliau prisikasiau prie taimerio ir pertraukimo pagal taimerį. Tai bene dažniausiai naudoja taimerio funkcija- gi tereikia kas kažkiek laiko apsiklausti visokios periferijas ir apdoroti rezultatus. O kitą laiką kontroleriukas miega ir taupo elektrą. Šiame pavyzdyje MCU elektros dar netaupo, tačiau taimeris veikia.
Programa sulipdyta iš interneto lobių. Tik kiek pakeistos kai kurios vietos, kad man būtų suprantamiau.

ARM SAM7S timer
Čia matosi, kaip softas bando organizuoti 1ms (1000Hz) pertraukimą. Pertraukimo metu invertuojama viena koja ir ją galima pamatuoti su oscilografu. Nežinau kas kaltas, bet gavosi 984.4μs (1016Hz). Kas kaltas dar nežinau- aš nuskaitau vidinį MCU dažnį ir perskaičiuoju automatiškai dalinimo koeficientus. Vartotojui-programuotojui tereikia tik įvesti norimo intervalo dažnį hercais.

Source kodas pasidarė dar labiau modulinis- pertraukimas pagal taimerį faile “timeris.c”, o PIO kojų pertraukimą perkėliau į “pioint.c”. Taip lengviau man bus “klijuoti” būsimas programas.

Viskas kompiliuojasi per GCC toolchainą Yagarto, make failas dar sugeba per J-Linką suprograminti į mikroschemą.

ARM SAM7S taimerio pertraukimo source code ir hex failas, hexas sukompiliuotas Atmel AT91SAM7S256AU serijos čipui.

Dar galima pastebėti, kad daug kas persikraustė į pertraukimus.

ARM:0007 I2C ir LM75 ar FM75

Dar vienas atmintinukas- SAM7 ir I2C. Šį kartą visas I2C softas drožtas nuo Sun Microsystems. Jį pasirinkau, nes viskas labai gražiai suprogramuota, yra padaryti avariniai taimautai ir panašiai. Kiti internete prieinami sourcai buvo labai kreivi ir be taimautu- jei I2C sleivas nerastas ar neatsiliepia, tai SAM7 paprasčiausiai užsikemša. Aišku čia viskas labai paprastai padaryta, jokių fancy efektų.

ARM SAM7 I2C
Čia vėl netolygus ekranas dėl per dažno perpaišymo. Dar pastebėjimas- LM75 ir FM75 negalima per dažnai klausinėti apie temperatūrą. Vienas iš jų pradeda visada sakyti tą pačia temperatūrą, kitas išviso prabyla 0xFF skaičiais. Dar negalima labai eksperimentuoti su I2C (TWI) greičiais.

ARM SAM7 I2C debug
Buvau pajungęs defektuotą LM75 mikroschemą, tai ilgai knisausi. Net teko pajungti sniferį ir žiūrėti kas ten dedasi. Ta, ore pakibusi plokštelė yra LM75 slave board nulupta nuo plazminio teliko matricos. Jos ten monitorina ar neperkaito telikas.

Nu ir aišku:
ARM SAM7 I2C source code ir hex, hexas sukompiliuotas Atmel AT91SAM7S256AU serijos čipui.

ARM:0006 SPI ir eprom

Dar vienas atminties rezervas. Šį kartą, prie esamo softo kur buvo pertraukimai dėl kojų pridėtos papildomos paprogramės leidžiančios skaityti-valdyti 25XXXX serijos SPI mikroschemas. Softas tiesiog trauktas dalinai iš interneto, dalinai iš senų mano AVR bibliotekų. Softas išbandytas tik su viena mikroschema ir tik skaitymo režime. Tačiau spėju, kad viskas turi veikti.

Taigi, brain dump, Atmel SAM7 ir SPI.
ARM SAM7 SPI
Eilutė ADR rodo EPROM adresą ir reikšmę tame adrese. Vaizdelis toks pas LCD “brukšniuotas” dėl to, kad LCD per dažnai perpaišomas.
Status ir info eilutės liko iš ankstesnio posto softo.

Nu ir aišku:
ARM SAM7 SPI source code ir sukompiliuotas hexas, hexas aišku sukompiliuotas Atmel AT91SAM7S256AU čipui.

ARM:0005 arba paprastas PIO kojų pertraukimas

Gali kas nors paklausti, kam aš rašau šituos trumpus straipsnius. Ogi pirmiausia, čia yra mano “brain dump” -papildoma atmintis. O antriausia, pilnas internetas tų pačių straisnių apie šitą reikalą… bet visi arba rašo apie tą patį pavyzdį nuo atmelio arba jau šneka apie labai advanced versijas.
Ir net pavyzdys nagrinėja iškarto keletą pertraukimų, o norisi suprasti kur kas eina kiekvienam atskirai. Taigi pertraukimas (interrup) pagal PIO. Nu tipo pagal kojas bendrai.

PIO Int handling in ARM MCU
Viskas iš pradžių pasirodė paprasta, bet neveikė :). Todėl ilgai ir nuobodžiai guglinau ir bandžiau. LCD ekraniukas rodo minimalistinę informaciją: pirmoje eilutėje šiaip pavadinimas. Antroja, kur “STATUS”, rodo kintamojo reikšmę kuri keičiasi tik pertraukime. Trečioje eilutėje- širdelė. Tai pagrindiniam cikle, po įvairiausiu skaičiavimu paišomos mažesnės ir didesnės širdelės. Jei širdelė pulsuoja, reiškia, kad pagrindinis ciklas dar dirba ir softas neužstrigo.
Ir paskutinė eilutė, kur “INFO”. Čia paprasčiausiai nuskaitoma informacija iš visų MCU kojų ir parodoma. Kaip diagnostika.

Softas paprastas- pagrindiniam cikle sukasi daug pauzių, pulsuojama širdelė, nuskaitoma porto būklė ir parodoma per LCD ekraniuką, ir rodoma kintamojo reikšmė.
Tuo tarpu, trys kontrolerio kojos suprogramuotos kaip mygtukai į žemę kai nuspausta. Normalioje būklėje daroma pull-up. SW0 didina skaičiaus reikšmę, SW1 mažina reikšmę, o SW3 nulina.
Nuspaudus bet kurį iš SW mygtukų, iššaukiamas pertraukimas kuris ir atlieką darbą. Puikiausiai skaičiuoja kontaktų drebėjimo skaičių. Todėl nenustebkit, kad paspaudus mygtuką skaičius pasikeičia keliais vienetais ar šimtais- čia taip turi būti.

Pagrindiniai atradimai šioje programoje- kad negalima pasirinkti bet kokio pertraukimo tipo. Nes nuo “edge” trigerių kažkodėl pertraukimo softas užspringsta.
Ir dar sužinota, kad LCD paprogrames reikia patobulinti… ir jos patobulintos. Dabar teoriškai lygtai LCD veikimas nebeiškraipo kitų MCU kojų konfiguracijų. Čia ypač liečia “direct drive” ir “pull-up”.

ARM PIO INT testo source code ir hex failas, hexas aišku sukompiliuotas Atmel AT91SAM7S256AU čipui.