Also ich habe ein kleines Protokoll zur Datenübertragung mit dem PC implementiert, welches beim Empfang eines gültigen (nach CRC Prüfung usw) Steuercodes die globale Variable "usart_cmd_recv" auf das empfangene Kommando setzt, der Empfang ist Interrupt-gesteuert. Ich hatte bisher gar keine Probleme. Im Hauptprogramm wird in einer while(1) Schleife unter anderem überprüft ob ein Kommando angekommen ist (usart_cmd_recv != 0) und dann wird eine switch-case Abfrage gemacht und je nach dem welches Kommando empfangen wurde die ein oder andere Funktionen ausgeführt. Eine Funktion dient dazu Daten vom PC ins EEPROM zu schreiben. Diese Funktion wird auch aufgerufen und ein ACK wird zurückgesendet danach kommt folgende while schleife: while(usart_cmd_recv != EEPROM_DATA_START) { // Implement TIME OUT } Diese Schleife soll einfach nur darauf warten, dass der PC das Kommando EEPROM_DATA_START sendet, aber wenn das passiert wird die Schleife einfach nicht beendet, woran kann das liegen. Ich kann mit sicherheit sagen, dass das programm zugriff auf die Variable hat, weil wenn ich die Schleife folgendermaßen konstruiere: while(usart_cmd_recv != WRITE_EEPROM_DATA) { // Implement TIME OUT } wird die Schleife nicht ausgeführt, da WRITE_EEPROM_DATA das Kommando ist um die Funktion aufzurufen ...
Hello, also so richtig verstehen tue ich den genauen Ablauf deines Programms nicht, hab' aber auch nur flüchtig gelesen. Aber vielleicht ziehst du mal folgenden Ansatz in Betracht: Wenn das EEPROM mit Schreibvorgängen beschäftigt ist, kann/wird eventuell selbst ein per Interrupt empfangenes Zeichen verloren gehen. Der Controller verhindert nämlich währenddessen ein korrumpiertes Schreiben ins EEPROM durch Ignorieren anderer Events. Ich hatte das Problem bei mehreren Geräten, die seit Jahren zuverlässig über RS232 kommunizierten. Nach Einsatz von USB-Konvertern ging dann am Ende der Übertragung immer ein Byte verloren. Die Untersuchung des Problems hatte dann ergeben, dass durch leichte Änderung des Timings durch den Einsatz des USB-Seriell-Konverters, das verlorene Byte immer beim Zugriff auf's EEPROM des Controllers (Atmel M128) ankam. Da kann man sich eventuell den Wolf suchen, bis man das findet! Schau doch mal, ob du einen ähnlichen Konstrukt bei dir vorliegen hast und spiel mal mit verzögerten Transfers. Gruss Gunb
Also zu dem Zeitpunkt wird noch gar nichts geschrieben. Die Variable ist in der Datei usart.c als unsigned char usart_cmd_recv = 0; am Dateianfang außerhalb jeder Funktion deklariert. In der Datei eeprom.c wird sie am Anfang mit extern unsigned char usart_cmd_recv; eingebunden, genauso wie in der Datei welche die main Funktion enthält und dort läuft alles ohne Probleme.
Die aufgerufene Funktion erwartet auch erst später die zu schreibenden Daten weil mit der Funktion der ganze EEPROM beschrieben werden kann. Erst kommt das bereits gennante START Kommando was der Funktion eigentlich nur sagt das nächste Kommando enthält Daten uns soll ins EEPROM geschrieben werden und dann könnten nochmal Daten kommen solange bis das Kommando EEPROM_WRITE_END gesendet wird. Die Daten werden in 32Byte Blöcken gesendet.
Severino hat den wesentlichen Hinweis gegeben: volatile
so, habe mir die Zeit genommen, noch mal genau zu lesen (sorry, hatte vorher ne Baustelle vor der Tür). Schliesse mich den beiden Vorgängern an. Wäre aber interessant zu wissen, ob du Erfolg mit 'volatile' hattest?! Gruss Gunb
Immer den ganzen wesentlichen Quelltext posten, nicht nur Fetzen. Sonst kann keiner was dazu sagen, nur raten.
Naja, der Fetzen hat schon gereicht... Leere Whileschleife soll auf Variable warten. Kann daher nur aus nem Interrupt geändert werden. => volatile vergessen.
Jo, also mit volatile funktioniert das, besten Dank. Jedoch versteh ich den Grund ehrlich gesgat nicht so genau. Hab nochmal mein C Buch rausgekramt, (The C Programming Language von Brain W. Kernighan und Dennis M. Ritchie) selbst da steht nur sehr wenig zu volatile ...
>volatile
weist den Compiler an, diese Variable bzw. einen Zugriff darauf nicht
wegzuoptimieren, wenn er der "Meinung" ist, dass er sie wegoptimieren
könnte.
Aus seiner Sicht wird sie nicht geändert und ist deswegen "über"...
Dass sie in einer ISR geändert wird (Regelfall für die Verwendung von
"volatile"), kann er bei der Übersetzung eines anderen Programmteils
nicht "sehen".
In der Tat ist es so, dass der Compiler zur Compilierzeit den Inhalt der Variable noch nicht kennt. Der Zugriff kann also nicht komplett wegoptimiert werden. Letztendlich schaut der erzeugte Assemblercode so aus, dass das Programm die Variable einmal (wegen Optimierung) in ein Register lädt. Anschließend (in der while-Schleife) wartet das Programm nur noch auf eine Änderung des Registerinhalts, der natürlich nie eintritt, anstatt immer wieder den tatsächlichen Variablenwert zu lesen. Das schafft dann aber der Zusatz volatile.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.