Szczerze mówiąc chciałem tego uniknąć, bo to trochę pisania jest... Liczyłem, że po prostu spróbujesz czy to pomoże, nie wnikając w szczegóły.
No ale spróbuję w miarę możliwości krótko. Zmienna globalna
ascii_line jest modyfikowana zarówno w programie głównym, jak i w procedurze obsługi przerwania. Operacja
ascii_line--; nie odbywa się w jednym takcie zegara, ponieważ jest zapisana w pamięci RAM, a nie mikrokontroler nie może wykonywać operacji bezpośrednio na komórkach pamięci. Wymagane więc jest:
- wczytanie zmiennej z pamięci RAM do rejestru,
- wykonanie operacji pomniejszenia wartości rejestru,
- zapisanie wartości rejestr z powrotem do RAM.
Jeśli w trakcie tej operacji (po wczytaniu zmiennej do rejestru) wystąpi przerwanie i zmodyfikuje wartość zmiennej, to program główny o tym nie wie, i nie wczyta ponownie zmiennej do rejestru, tylko wykona operację na rejestrze i zapisze wynik operacji z rejestru do zmiennej w RAM, czyli przykładowo:
- program główny wczytuje do rejestru wartość zmiennej ascii_line równą 3,
- występuje przerwanie i procedura jego obsługi zmienia wartość zmiennej ascii_line na 4,
- po zakończeniu procedury obsługi program główny wraca do miejsca, w którym skończył, i wykonuje następną instrukcję, czyli zmniejsza wartość rejestru z 3 na 2,
- po wykonaniu operacji zapisuje wartość z rejestru (czyli 2, a powinno być 3) do zmiennej ascii_line w pamięci RAM.
W efekcie wartość zmiennej po tej operacji jest nieprawidłowa, bo nie uwzględnia tego, co doliczyła w międzyczasie procedura obsługi przerwania. W ten sposób w buforze zawsze zostaną dane nie uwzględnione przez zmienną
ascii_line, przez co prędzej czy później bufor się przepełni. Jaki będzie tego efekt to jest uzależnione od tego, jak masz zorganizowaną resztę programu (szczególnie chodzi o obsługę bufora, czyli zadbanie o to, by nie szło go przepełnić).
Prawdopodobieństwo "trafienia" nie jest wprawdzie duże, ale jakieś jest, dlatego program może przez jakiś czas pozornie pracować prawidłowo, a czas ten będzie losowy, choć w pewnej mierze zależny np. od częstotliwości i długości przesyłanych pakietów danych (u Ciebie ciągów znaków oddzielonych znakiem '\r', jeśli dobrze rozumiem). Im więcej krótkich pakietów w jednostce czasu, tym ryzyko problemów będzie większe.
EDIT:
kamilo0 napisał(a):
Bibliotekę tą zmodyfikowałem dla własnych potrzeb tak, abym mógł odbierać całe stringi
...
Zmodyfikowałem sobie funkcję uart_get_str, tak aby niemożliwe było zapisanie do bufora wiecej bajtów niż posiada bufor UART.
...
Teraz wygląda, że jest ok. Narazie nie zauważyłem resetów. Wie ktoś, dlaczego tak się działo?
By można było odpowiedzieć na to pytanie musiałbyś pokazać więcej kodu, szczególnie tego dotyczącego obsługi buforów. Bardzo istotne jest np. to, co tak na prawdę zwraca funkcja
uart_getc(), bo nie jestem pewien, czy Twoja pętla odczytu bufora działa prawidłowo.