Jarecki napisał(a):
Szofer napisał(a):
A to dlatego aby przerwanie mogło jeszcze zmodyfikować stan pinu/portu przed zapisem
ProgramistaAVR czy to dobra odpowiedź? Śledzę ten wątek i uważam, że jest mega ważny i interesujący ale nie wiem czy wszystko dobrze rozumiem a bardzo bym chciał rozumieć
![Szczęśliwy :)](https://forum.atnel.pl/images/smilies/icon_e_smile.gif)
Zła.
Chodzi właśnie o coś dokładnie odwrotnego, aby ewentualne przerwanie nie mogło się wykonać. Przeważnie rozkazy wykonują się od razu. Gdyby tak było to sekwencja:
SEI
ZAPIS PORTU
byłaby ryzykowna, po po SEI mogłoby wykonać się przerwanie, które mogłoby zmodyfikować stan portu. Błąd byłby ciężki do znalezienia to rzadki ale w AVR, zaraz po SEI nie może wykonać się przerwanie, dopiero w kolejnym rozkazie co gwarantuje, ze przerwanie nie zmodyfikuje stanu portu przed jego zapisem. W praktyce zadział to jak sekwencjia
ZAPIS PORTU
SEI
w innych CPU ale nie pytaj jakich bo nie pamiętam wiele z dawnych CPU. Coś tam mi świta, że w Z-80 zaraz po DI (blokada przerwań) modło być wykonanie przerwanie (nie wiem czy we wszystkich trybach czy tylko w IM2 - wektoryzowane) a 6502 odblokowanie przerwań miało skutek natychmiastowy.
Kiedyś zabieg z wykonaniem rozkazu zaraz po odblokowaniu przerwań był używany w pracy krokowej. Na NMI wymuszało się L. CPU prawie cały czas był w przerwaniu. Wykonanie kroku to opuszczenie przerwania gdzie w po przywróceniu znacznika przerwania (W 6502 był on na stosie, w rejestrze stanu, umieszczany sprzętowo, w Z-80 osobny przerzutnik) musiał wykonać się jeden rozkaz po którym program ponownie skakał w przerwanie. Nie pamiętam czy przypadkiem nie taki mechanizm był w CA-80 ale naprawdę wiele lat minęło.
------------------------ [ Dodano po: 34 minutach ]Od siebie jeszcze dodam, ze w ARM nie używam ATOMIC_BLOCK. Blokuję w NVIC tylko przerwania, które mogłyby przeszkadzać. W AVR takie rozwiązanie raczej się nie przyda. Przerwania są blokowane głównie po to, aby nie zakłócić jakiś krytycznych czasowo funkcji np generowania bitu dla WS2812. Przy czasie impulsu 400ns przerwanie trwające kilka us rozwali wszystko. Nawet wolna transmisja 1-Wire też będzie szwankować. W ARM z reguły to nie problem, bo jest dziesiątki jak nie setki razy szybszy od AVR (taki H743 może być taktowany nawet 480MHz a są i takie co 600MHz mają). W ARM przerwania się blokuje gdy np i w przerwaniu i w programie głównym modyfikuje się np rejestry UART. W takiej sytuacji wystarczy jednak zablokować przerwania od UART.
W AVR też może być podobna sytuacja np licznik wielo bajtowy w przerwaniu. Aby go odczytać w programie głównym trzeba zatrzymać przerwania ale zamiast wyłączać wszystkie wystarczy zablokować przerwanie od timera modyfikującego licznik.
Jest też prosta metoda aby One Wire czy WS2812 na AVR obsłużyć w przerwaniu. Tak jak w przypadku One Wire są dwa rozwiązania czyli timer albo UART tak w przypadku WS2812 SPI lub UART. W necie można znaleźć przykłady a dla One Wire przez UART to nawet Maxim wydał odpowiednią notę katalogową. Szczegóły można tam przeczytać a w skrócie, to ustawia się UART na 9600 Zapisuje FF i sprawdza co wróciło (TX-RX jest zapętlone przez bufor OC). Jak FF to nie zgłosił się slave, jak inna wartość to było zgłoszenie. Komunikacja podobnie tyle, że na 115200. Wysłanie 1 to zapis FF, zera to zapis 0. Odczytanie bitu to zapis FF i odczyt, jak FF to slave zwraca 1, jak <> od FF to zwrócił 0.
Proste a działa na każdym mikrokontrolerze. Próbowałem na AVR, ARM wiem, że działa na porcie COM PC powinno na konwerterze USB-UART ale nie próbowałem. Można sobie zorganizować komunikację w tle (na przerwaniach). WS2812 zarówno na AVR jak i ARM próbowałem na SPI i UART. Działa na przerwaniach ale na AVR lepiej robić to na UART.