Instrukcja AVR SEI

13

Instrukcja AVR SEI ( http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_SEI.html ) czeka na zakończenie kolejnej instrukcji przed włączeniem przerwań.

Jeśli użyję innej instrukcji, aby ustawić flagę I w SREG, czy to również czeka 1 instrukcję?

Innymi słowy: czy czekanie jest cechą instrukcji SEI lub rejestru statusu?

Jeśli jest to cecha instrukcji SEI, to w którym momencie faktycznie ustawiana jest flaga, w cyklu wykonującym SEI lub z następną instrukcją?

jayjay
źródło
To świetne pytanie, ale testowanie i upewnienie się nie powinno być zbyt trudne.
Vorac
1
@Vorac Czy możesz podać przykład, w jaki sposób można to przetestować? To na pewno moja zaakceptowana odpowiedź.
jayjay,
1
Może to być cecha implementacji architektury AVR i gdzie można obsłużyć przerwania. IIRC, architektura AVR wykorzystywała potrójny etap. Tak więc następna instrukcja może być już „w locie” (tj. Na etapie pierwszego etapu rurociągu lub dalej), zanim zmiana flagi I będzie mogła zostać użyta do sprawdzenia przerwania. Dawno nie szukałem, ale nie sądzę, aby projektanci architektury AVR zbyt mocno się ograniczali. Zatem testowanie przerwania dla instrukcji w etapie 1 potoku, a nie przed kolejną instrukcją (w etapie 2), daje im pewną elastyczność.
żaglowiec

Odpowiedzi:

8

Wyniki empiryczne!

Podczas gdy inne odpowiedzi są przemyślane i dobrze uzasadnione, wszystkie są niekompletne lub jedynie domysł. Tam, gdzie dokumentacja jest niejednoznaczna, musimy eksperymentować i testować każdy przypadek.

To pytanie zasługuje na rozstrzygającą odpowiedź, więc wyciągnijmy AVR i zacznijmy ustawiać trochę bitów!

Procedura

Aby przetestować, stworzyłem mały program Arduino (ATMEGA328P), który ...

  1. ustaw ISR, który nigdy nie zwróci ( while (1))
  2. przypisałem ISR do źródła, które mogłem uruchomić w oprogramowaniu ( INT0niski poziom)
  3. wyłączone przerwania
  4. włącza i wyzwala przerwanie, aby było w toku

Użyłem łóżka testowego, które włączałoby diodę LED w pojedynczej instrukcji po włączeniu przerwań. Próbując różnych sposobów włączania przerwań w łóżku testowym i sprawdzania diody LED, mogłem stwierdzić, czy instrukcja po instrukcji aktywującej została wykonana, czy nie.

Jeśli dioda LED nie zapaliła się, to wiem, że ISR wykonał (i zablokował) natychmiast po włączeniu przerwań.

Jeśli dioda LED się zapaliła, to wiem, że następna instrukcja mogła zostać wykonana przed wywołaniem ISR.

Wyniki

SEI instrukcja (skrzynka podstawowa)

Kod:

sei

Wynik: dioda LED włączona. Wykonano instrukcję.

OUT instrukcja

Kod:

in  r16,0x3f   // Get SREG
ori r16,128    // Set I bit 
out 0x3f,r16   // Save back to SREG

Wynik:

LED włączone. Wykonano instrukcję.

ST instrukcja

Kod:

   clr r29        // Clear Y high byte
   ldi r28,0x5f   // Set Y low byte to point to SREG
   ld r16, Y      // Get SREG
   ori r16,128    // Set I bit 
   st Y,r16       // Put SREG

Wynik:

LED włączone. Wykonano instrukcję.

Wniosek!

P: Czy oczekiwanie jest funkcją instrukcji SEI lub rejestru statusu?

Odp .: Wygląda na to, że zmiana Ibitu in SREGz a 0na a 1pozwoli następnej instrukcji na wykonanie następnej, nawet jeśli występuje oczekujące przerwanie, niezależnie od instrukcji użytej do ustawienia bitu.

Notatki

To faktycznie przerodziło się w bardzo interesujące pytanie z wieloma komplikacjami. Jeśli jesteś zainteresowany szczegółami, sprawdź ...

http://wp.josh.com/2016/01/05/different-ways-to-set-i-bit-in-avr-sreg-besides-sei/

bigjosh
źródło
2
Gdy specyfikacja jest niejednoznaczna, występuje problem z „wynikami empirycznymi”. Po prostu dlatego, że konkretny testowany sprzęt działa w określony sposób, nie oznacza to, że inne części będą działać w ten sposób. Atmel może dowolnie zmieniać implementację, pod warunkiem że nie zmienia ona specyfikacji. Tak więc „tam, gdzie dokumentacja jest niejednoznaczna ...” pozostaje dokładnie to, że po eksperymentach i testach jest nadal niejednoznaczna.
żaglowiec
@gbulmer Zgadzam się w 100%. Ten, kto korzysta z nieudokumentowanych funkcji w produkcji, z pewnością będzie smutny. Wciąż interesujące pytanie empiryczne (i odpowiedź) i prawdopodobnie ok, aby polegać na jednorazowym osobistym projekcie.
bigjosh
Tak, przeprowadziłeś fascynujące śledztwo.
żaglowiec
4

Z mojej dokumentacji wynika, że ​​wykonanie seiinstrukcji nie różni się niczym od bezpośredniego wpisania 1 do bitu I SREG. Zaletą instrukcji jest to, że nie trzeba najpierw ładować wartości 1<<Ido działającego rejestru, aby zmienić SREG, co oszczędza czas.

Aby rozwinąć, używając sei:

sei ; One cycle

Ustawienie bitu za pomocą sbi(działałoby tylko, jeśli SREG znajdował się w dolnych 32 bajtach mapy rejestrów, ale wydaje się, że w większości, jeśli nie wszystko, nie jest).

sbi SREG,7 ; Two cycles

Piszę do I bit bezpośrednio w SREG:

in  r24,SREG ;
ori r24,0x80 ;
out SREG,r24 ; Three cycles

IBit powinien być ustawiony w SREG jak tylko seiinstrukcją (lub sbilub out) zakończy. Jednak wszelkie oczekujące przerwania nie będą obsługiwane, dopóki nie zakończy się kolejna instrukcja - bit zostanie ustawiony, ale włączenie przerwań wymaga dodatkowego cyklu. Ponieważ przerwanie nie może być obsługiwane w połowie instrukcji, a niektóre instrukcje wymagają więcej niż jednego cyklu do wykonania, określają czas potrzebny do włączenia jako jedna instrukcja. Tak powinno być w przypadku wszystkich wersji kodu - tzn. Każda z powyższych spowoduje opóźnienie instrukcji.


Po kilku poszukiwaniach znalazłem ten wątek na forum Arduino, na którym przeprowadzono kilka różnych testów w celu zweryfikowania zachowania. Wydaje się, że zgadza się z tym, co powiedziałem powyżej.

Ponadto, zgodnie z tym wątkiem, jeśli Iflaga jest już ustawiona, wówczas nie ma opóźnionej odpowiedzi przerwania, przez seico implikuje się, że opóźniona odpowiedź nie jest spowodowana przez samą instrukcję, ale raczej w wewnętrznym sprzęcie kontrolowanym przez Iflagę - więc każdej operacji, która zmienia flagę w SREG, czy to seilub outczy stsbędzie miał dokładnie takie samo zachowanie.

Tom Carpenter
źródło
Więc nie ma aspektu opóźniania operacji, specyficznego dla SEI, ale nie OUT, który pozwala na wykonanie poniższej instrukcji?
Brian Drummond
W przypadku drugiego przykładu, kiedy obsługiwane jest oczekujące przerwanie? Czy występuje opóźnienie cyklu jak w pierwszym?
jayjay,
@jayjay zobacz moją aktualizację.
Tom Carpenter
1
Zauważ, że SBInie można go użyć do ustawienia Ibitu, SREGwięc każdy kod, który to robi, prawdopodobnie nie został przetestowany w prawdziwym życiu, ponieważ nawet się nie zgromadzi. SBImoże działać tylko na niższych 32 rejestrach, a SREG znajduje się w slocie 63.
bigjosh
@bigjosh Przykład SBI był tym, o którym myślałem później - outtego, którego użyłem pierwotnie. Myślałem, że natknę się na AVR (może być ATTiny), który ma SREG w niższych 32 rejestrach, ale mogę sobie to wyobrazić.
Tom Carpenter
1

IMHO zapisuje do SREG nadal opóźnia 1 instrukcję można przetestować w ten sposób (pseudokod):

ISR() { PORTA = 0; while(1); }
main() 
{
    cli();
    DDRA = 0xff;
    configure_isr_for_level_interrupt_that_will_trigger_immediately();
    SREG = 0xff;
    cli();
    PORTA = 0xff;
    while(1);
}

Niestety brakuje mi czasu na zrobienie tego :(

Vorac
źródło
0

To nie tak mówi. Dokumentacja mówi

Instrukcja po SEI zostanie wykonana przed wszelkimi oczekującymi przerwaniami.

nie że czeka na następną instrukcję. Przeczytałem to, ponieważ flaga jest ustawiana natychmiast, ale nawet jeśli jest włączona, żadne przerwania nie będą obsługiwane, dopóki następna instrukcja nie zostanie wykonana.

patthoyts
źródło
To wszystko prawda, ale moje pytanie brzmi: czy to zachowanie jest specyficzne dla SEI?
jayjay
@jayjay Podejrzewam, że wynika to z długości potoku instrukcji
krytyczny