Hallo miteinander, ich versuche seit gestern interruptgetriebene Routinen für den USART0 des ATmega2560 zum Laufen zu bringen. Beim Empfang eines Zeichens wird URXC0 ausgelöst und in der zugehörigen Interrupt-Routine wird das Zeichen aus UDR0 ausgelesen und in einen Empfangspuffer geschrieben. Zu sendende Zeichen werden in einen Sendepuffer übertragen und von dort per UDRE0-Interruptroutine ins UDR0 übertragen. Ich habe unter http://avrbeginners.net/architecture/uart/uart.html ein schönes Code-Beispiel gefunden und dieses entsprechend für den 2560 angepasst (Registernamen!). Als "Gegenstation" benutze ich TeraTerm auf einem PC. Leider funktionierte zunächst weder Senden noch Empfangen. Durch Betreiben der USART0 im Pollingbetrieb wollte ich dann zunächst verifizieren, dass meine Parametrierung (Baudrate, Länge, Parity, Stopbist) der USART0 überhaupt korrekt funktioniert. Eine Simulation der Init-Routine im AVR-Studio (Vers. 4.18 Build 716) brachte den ersten Stolperstein zutage: beim Beschreiben von UCSR0C wird auch das Register UBRR0H wieder überschrieben. Ein Bug der CPU, wie ich nach einigem Googeln herausfinden konnte, aber einer der tödlich sein kann, wenn man ihn nicht kennt. Dieser lässt sich jedoch leicht dadurch beheben, dass man zunächst UCSR0C beschreibt und erst anschließend UBRR0H. Ein Glück war, dass der Simulator im AVR-Studio diesen Bug auch simuliert, sonst wäre ich da nie drauf gekommen! Im Pollingbetrieb konnte ich nun problemlos Daten zwischen ATmega2560 und TeraTerm austauschen. Interruptgetrieben funktionierte aber nach wie vor überhaupt nichts. Durch "Debug-Ausgaben" (LED einschalten ;-) stellte ich fest, dass weder die URXC0- noch die UDRE0-Interruptroutine überhaupt aufgerufen werden. Und jetzt kommt der Hammer: Um dem Problem zu Leibe zu rücken, warf ich wieder den Simulator des AVR-Studios und stellte nach längerem Debugggen fest, dass beim Auslösen eines UDRE0-Interrupts (Adresse des Vektors = 0x34) versucht wird, den Interrupt-Vektor an der Stelle des UDRE2-Vektors (Adresse des Vektors = 0x68) aufzurufen, wobei ich dort natürlich ein 'reti' stehen hatte, da ich diesen ja nicht verwendete. Kaum trug ich dort einen 'jmp' auf meine Interrupt-Routine für die Behandlung des Sendepuffers ein, schon funktionierte das interruptgetriebene Senden einwandfrei. Ich wusste zwar noch nicht, warum sich das so verhielt, aber ich abstrahierte und trug einfach den Sprung auf meine Routine zur Behandlung des Empfangspuffers ebenfalls statt unter URXC0 (Adresse des Vektors = 0x32) nun unter URXC2 (Adresse des Vektors = 0x66) ein und siehe da, das interruptgetrieben Empfangen funktionierte IMMER NOCH NICHT! Ein nochmaliges Betrachen der Vektortabelle ergab, dass ich bei der Senderoutine den Vektor statt an der Adresse 0x34 an der Adresse 0x68 eintragen musste, was genau der doppelte Wert ist. Folglich testete ich nun den Eintrag des Vektors für den Interrupt URXC0 statt an der Adresse 0x32 an der Adresse 0x64 und SO FUNKTIONIERT ES! Und nun meine staunende Frage: Was habe ich nicht verstanden oder wo muss ich nochmals nachlesen, um diesen Sachverhalt zu kapieren? Die include-Datei zum ATmega2560 (m2560def.inc) im AVR-Studio sagt eindeutig: .equ URXC0addr = 0x0032 .equ UDRE0addr = 0x0034 und so steht das auch im Atmel datasheet zum ATmega 2560 (ist zwar preliminary, hab' aber nichts Neueres gefunden). MfG UWF
UWF schrieb: > Ein Bug der CPU, wie ich nach einigem > Googeln herausfinden konnte, Quelle? > Dieser lässt sich jedoch leicht dadurch beheben, dass > man zunächst UCSR0C beschreibt und erst anschließend UBRR0H. Wenn du nur das übliche "8N1" haben willst, geht das noch einfacher: UCSR0C gar nicht erst anfassen. 8N1 ist die Voreinstellung, und die garantiert dir das Datenblatt. > Ein nochmaliges Betrachen der Vektortabelle ergab, dass ich bei der > Senderoutine den Vektor statt an der Adresse 0x34 an der Adresse 0x68 > eintragen musste, was genau der doppelte Wert ist. Willkommen in der wundervollen Verwechslungswelt zwischen Byte- und Wortadressen. AVR-Datenblätter zeigen 16-bit-basierte Wortadressen für alle Angelegenheiten, die sich um Codezugriffe kümmern. Wenn du den Flash jedoch mit LPM ansprichst, dann arbeitet er sehr wohl byteweise.
>0x32 an der Adresse 0x64 fällt dir was ins Auge? :-) Das tritt bei allen AVR auf, bei denen rjmp nicht ausreicht, den gesamten Programmspeicher zu erreichen. Statt rjmp muss man dann jmp verwenden. Und dieser Befehl passt nicht in 2 Byte.
Danke für Eure schnellen Hinweise. Ich muss zugeben, dass ich in Sachen AVRs ganz neu unterwegs bin. Hatte vor einigen Jahrzehnten mal mit dem KIM1 angefangen (CPU: 6502) und mich seither außer einigen Kleinversuchen mit 80535 (und Derivaten) nur mit PC-Programmierung beschäftigt. Im Moment geht es ein wenig "Back to the roots" (weil's einfach Spaß macht). Zu meiner Entlastung muss ich sagen, dass das mit den Wortadressen zwar logisch ist (jetz, im Nachinein!), aber man bei den vielen Neuigkeiten, die am Anfang auf einen zukommen (CPU, Assembler, Entwicklungssystem, AVR-Studio, Programmer, ...) einfach nicht an alles denkt, weil man höchstens EINblicke hat, aber noch keinen ÜBERblick ;-) Auch ist bei der entsprechenden Tabelle im datasheet mit keiner Silbe erwähnt, dass es sich dabei um Wortadressen handelt. Aufgrund der include-Datei (m2560def.inc) im AVR-Studio hätte man VIELLEICHT drauf kommen können, da entdeckte ich jetzt nämlich unterhalb der Definition der Vektor-Adressen: .equ INT_VECTORS_SIZE = 114 ; size in words (AHA!) Also, danke nochmals und speziell an dl8dtl: 73 de Uwe, DL8UF
Das Ganze ist letzten Endes aber auch eine Frage der SChreibweise. Wie hast du das Ganze denn ursprünglich geschrieben? Ich geh sowieso davon aus, dass du Assembler programmierst, aber auch dort ist das mit der richtigen Schreibweise kein Thema, um das man sich Gedanken machen muss. Mit .org URXC0addr jmp ReceiveHandler .org UDRE0addr jmp EmptyHandler macht der Assembler automatisch das richtige, ohne dass man sich um Zahlenwerte Gedanken machen muss. Wichtig: Vor jedem jmp oder rjmp immer mit .org und dem Namen aus dem Inc-File neu positionieren, selbst wenn die Vektoren laut Datenblatt unmittelbar aufeinander folgen.
@ Karl Heinz: Danke, dein Vorschlag ist nicht nur richtig, sondern auch konsequent. Den hab' ich inzwischen so umgesetzt. @ Jörg / alle: Hier noch die Quelle mit der Angabe zum Bug des ATmega2560: http://support.atmel.no/knowledgebase/avrstudiohelp/mergedProjects/Simulator/Known_Issues/Notes_for_ATmega2560_2561.htm <Zitat> Notes for ATmega2560/2561 * When writing to UCSRnC, the value will be copied to UBRRnH unless UMSELn1 is set. This behaviour should not happen on devices that have separate locations for these registers. A workaround is to write UBRRnH after UCSRnC. * The JTD bit in the MCUCR register must be set to the desired value twice within four cycles to change its value. In the simulator the JTD bit can be written directly. * The ADC noise reduction function is not supported. Setting the ADIF flag will not wake the CPU from sleep mode. * Timer/Counter2 * Output compare pins and FOC does not work. * Prescaler reset does not work correctly. * OCR2A/B registers are not buffered correctly in PWM mode. <Zitat Ende> Viele Grüße, UWF
UWF schrieb: > Hier noch die Quelle mit der Angabe zum Bug des ATmega2560: Das ist die Beschreibung eines Simulator-Fehlers. Und wo steht jetzt, dass auch der Chip diesen Fehler haben soll?
Du könntest Recht haben... Auch hier kann man's sich erst wieder zusammenreimen, wenn man auf die (recht lange) URL schaut, aus dem Text ansich geht nicht hervor, dass es nicht um die CPU, sondern um den Simulator geht (s.o.). Muss man sich bei Atmel wohl erst dran gewöhnen ;-) Obwohl, es gibt noch größere Unternehmen mit wesentlich schlechterer Doku, ansich scheint mir Atmel da ganz gut. Gruß UWF
UWF schrieb: > Auch hier kann man's sich erst wieder zusammenreimen, wenn man auf die > (recht lange) URL schaut, aus dem Text ansich geht nicht hervor, dass es > nicht um die CPU, sondern um den Simulator geht (s.o.). Naja, das sollte da gestanden haben, wo der Link auf diese Seite steht. > Obwohl, es gibt noch größere Unternehmen mit wesentlich schlechterer > Doku, ansich scheint mir Atmel da ganz gut. Wenigstens haben die CPUs nicht so viele Bugs. ;-) Neuere Controller (der ATmega2560 ist von der Entwicklung her schon ziemlich alt) sind auch im Simulator besser. Das Ganze nennt sich irgendwie "Simulator V2" oder so, und dort wird der Code der Simulation direkt aus der Hardwarebeschreibung des ICs abgeleitet, da können derartige Fehler nicht mehr auftreten. Ansonsten: traue keiner Simulation, die du nicht selbst gebaut hast. ;-) Kriterium ist immer das reale Leben, nicht die Simulation.
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.