Hallo,
in meinem Programm empfange ich Daten von der Seriellen Schnittstelle
per Interrupt und speichere sie in einem FIFO zwischen, bis sie vom
Hauptprogramm ausgelesen werden. Das funktioniert auch meistens. Aber
alle 1:100 bis 1:1000 Zeichen geht plötzlich mal irgendwie eins
verloren. Jetzt habe ich bereits den ganzen Vormittag den Fehler gesucht
und werde aber einfach nicht fündig.
Die Abfrage im Hauptprogramm sieht wie folgt aus:
1 | void analyse_income_cmd(void) { //Dekodiert die per RS232 erhaltenen Befehle
|
2 | u08 uart_emp_local[4];
|
3 | u08 i;
|
4 | u08 in_number = 0;
|
5 | //Look if there are at least 4 bytes in the RX FIFO
|
6 | cli();
|
7 | if ((UART_RX_BUF_SIZE-uart_rx_free()) < 4) {
|
8 | sei();
|
9 | return;
|
10 | }
|
11 | for (i = 0; i < 4; i++) {
|
12 | if ((UART_RX_BUF_SIZE-uart_rx_free()) == 0) { //may not happen
|
13 | sei();
|
14 | print_p(DEV_UART, fifoe2); //but happens in 1:1000 cases
|
15 | return;
|
16 | }
|
17 | uart_emp_local[i] = uart_rx_get();
|
18 | processed_rx_bytes++; //for debugging
|
19 | if ((uart_emp_local[i] == 13) && (i < 3)) {
|
20 | sei();
|
21 | cmd_error(uart_emp_local, i+1);
|
22 | return;
|
23 | }
|
24 | if (uart_emp_local[i] == 255) { //may not happen
|
25 | sei();
|
26 | print_p(DEV_UART, fifoe1);
|
27 | return;
|
28 | }
|
29 | }
|
30 | sei();
|
Die Konstanten sind:
#define UART_RX_BUF_SIZE 32
#define UART_TX_BUF_SIZE 64
Mit den ganzen cli() und sei() in dem Abfragecode funktioniert es
fehlerfrei. Nehme ich die aber raus, ist der FIFO manchmal unerwartet
leer.
Ich hatte den FIFO so gebaut, dass er eigentlich ohne Interruptsperren
funktionieren müsste. Ein Schreib und ein Lesezeiger laufen auf einem
Array immer "im Kreis". Eine leere Speicherzelle wird dadurch markiert,
dass 0xff drin steht, so dass die beiden Zeigen nicht miteinander
verglichen werden müssen um Unter und Überläufe auszuschließen. Der Code
für die RS232 Verbindung ist im Anhang.
Hat jemand eine Idee was falsch läuft?