No to podsumujmy:
- uart_getc() zwraca znak z bufora, dekrementuje licznik znaków i przesuwa wskaźnik w buforze nawet wtedy, gdy bufor jest pusty.
- W przypadku przepełnienia bufora nowe znaki będą przyjmowane, a licznik będzie inkrementowany. Przy buforze na 4 bajty po nadaniu ciągu "123456" odbiorca odbierze "345634".
- Od czasu do czasu nastąpi zgubienie znaku poprzez jego niezliczenie, rx_count będzie miał wartość 0, a znak będzie w buforze i przy wywołaniiu uart_getc() ten znak zostanie zwrócony, bo uart_getc zawsze coś zwraca, nawet kiedy bufor jest pusty. Gdyby konsument przed wywołaniem uart_getc sprawdzał licznik znaków - nie dowie się, że w buforze jest znak. Kiedy odbierzemy następny znak, kolejne wywołanie uart_getc zwróci poprzedni znak, nowy będzie w buforze, a licznik znaków będzie wyzerowany. Co jakiś czas liczba znaków w buforze, które pozostaną niezauważone, będzie rosła.
- Gdyby kod uzupełnić o sensowną reakcję na przepełnienie, to i tak czasem znaki będą gubione poprzez zamazanie najstarszego znaku w buforze wskutek błędnej kolejności akcji w uart_getc().
Kod, który pokazałeś, nie jest więc ani dobry, ani sprawdzony. Losowo gubi znaki, zamazuje znaki, zwraca nieprawidłowe znaki, a zmienna rx_counter nie daje żadnej wiarygodnej informacji o tym, czy w buforze są jakieś znaki i ile ich jest.
Kiedyś popłeniłem kod obsługi UART, który miał tylko jeden z tych błędów, które opisuję powyżej. Błąd pojawiał się raz na kilkadziesiąt minut działania urządzenia przy średnim strumieniu danych rzędu 300 bajtów na minutę.
Być może rzeczywiście jedynym problemem jest mój paskudny charakter, bo przecież będą takie sytuacje, kiedy ten kod będzie działał. W końcu urządzenie nie musi działać cały czas dobrze.- Weźmy np. takie hamulce w samochodzie. Jak zadziałają 9 razy na 10, to można powiedzieć, że działają i nie ma się co czepiać - dla początkującego kierowcy powinny wystarczyć...
