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?