Datum:
Hallo, ich habe ein Problem mit der Funktion ltoa. In folgendem Progammcode wir die Zahl "-234567" auf dem LCD rückwärts ausgegeben. Die LCD-Ausgabe mit lcd_puts funktioniert. Offensichtlich wird der String von der Funktion ltoa in der falschen Reihenfolge erstellt.
char text [12]; // String lcd_init(LCD_DISP_ON); // initialize display, cursor off lcd_clrscr(); // clear display and home cursor lcd_puts("V 0.1b"); // put string to display (line 1) lcd_gotoxy(0,1); // move cursor to position 1 on line 2 ltoa (-234567, text, 10); lcd_puts(text); // put string to display |
Die Ausgabe auf den Display: V 0.1b 765432- Was mache ich falsch?
Datum:
Vielleicht ein Bug in der verwendeten ltoa-Funktion? Welche Library/Toolchain benutzt du in welcher Version für welchen µC?
Datum:
Ziemlich sicher ein Bug. In der originalen Version von ltoa wird der string tatsächlich umgekehrt in ein array geschrieben. Am Schluss der Funktion wird der String dann umgedreht: ... conv_finished: st Z, _zero_reg_ ; terminate string pop a_val_hlo ; restore &string as return value pop a_val_hhi pop r28 ; restore r28 XJMP _U(strrev) ; reverse string .endfunc ...
Datum:
Joachim schrieb: > Ich habe mir inzwischen damit geholfen, den String rückwärts auszugeben. Das ist eine unbefriedigende Lösung, denn sie bedeutet, dass das eigentliche Problem nicht behoben ist. Bei derartigen Basisfunktionen kannst du davon ausgehen, dass sie fehlerfrei in der Library sind. Wenn da etwas aussergewöhnliches passiert, dann deutet das auf einen Fehler irgendwo in deinem Programm hin, der unentdeckt geblieben ist.
Datum:
Das ist richtig, das Problem habe ich weder gefunden noch behoben. Der betroffene Quelltext ist recht einfach:
ltoa (-234567, text, 10); lcd_puts(text); // put string to display |
Die Zahl wurde vom Compiler vermutlich richtig als HEX-Wert in das Listing übernommen (alle Ziffern tauchen anschließend wieder im Ergebnis auf). Die Funktion lcd_puts() stammt aus einer viel benutzten LCD-Bibliothek. Ich habe die Funktion überprüft, indem ich die Zeichen des Strings in einer Schleife Byte für Byte übertragen und jede Stelle separat adressiert habe. Der erzeugte Assemblercode enthält offensichtlich eine Routine zum reversieren. Beim Übersetzen für andere Controller (ATmega8 und ATmega32) hat sich die Länge des Codes geändert. Das ist aber auf andere Interruptvektoren und komfortablere Assemblerbefehle zurückzuführen. Die Funktion habe ich nicht identisch wiedergefunden. Evtl. hat ja wirklich noch niemand diese Funktion beim ATtiny26 probiert? U. U. habe ich auch irgendwelche Flags falsch gesetzt? Echte Compilerfehler sind selten, meistens sitzt das Problem vor dem Computer. Ich bin zumindest nicht auf ein Problem gelaufen, dass außer mir bereits alle kennen.
Datum:
Joachim schrieb: > Das ist richtig, das Problem habe ich weder gefunden noch behoben. > Der betroffene Quelltext ist recht einfach: Das Problem könnte genausogut auch irgendwo ganz anders stecken. Du siehst nur die Symptome. Das bedeutet aber nicht, dass die Ursache ebenfalls hier zu finden ist.
Datum:
Angehängte Dateien:Das ltoa-Problem besteht in der fehlenden Stringumkehrung beim ATtiny26. Im Web ist dazu nichts zu finden. Wenn nun die Funktion ltoa nicht funktioniert, dann bestehen gute Aussichten, dass auch die Funktion itoa nicht richtig arbeitet. Mit einem kurzen Test konnte das gezeigt werden. Da die Funktion itoa häufiger gebraucht wird, sind auch schon mehrere Anwender darüber gestolpert. (Ich bin nun nicht mehr allein mit dem Problem). Hier nennt man das "strange behavior": http://www.avrfreaks.net/index.php?name=PNphpBB2&f... Das Problem beim ATtiny26 wurde einfach durch Einsatz eines ATmega128 behoben. Auch hier ist das Problem mit itoa aufgetreten. 1234 wird als 4321 ausgegeben: http://www.elektroda.pl/rtvforum/topic1511704.html Hier schiebt es der Programmierer auf seine mangelnden Kenntnisse: Beitrag "lcd_putint falsche Ausgabe" und 2003 hat man das Problem auch schon beobachtet: Beitrag "bei verwendung von itoa alles verkehrtherum" Der Compiler erzeugt für einen ATmega16 den gleichen Code, wie für einen ATtiny26. Der Code funktioniert auf dem ATmega16, nicht jedoch auf dem ATtiny26. Daraus könnte man ableiten, dass der Code in Ordnung ist und der Prozessor nicht richtig arbeitet. Dazu wurde der Code der Stringumkehrung extrahiert und als separates Assemblerprogramm eingebunden. Die Kommentare zeigen was passiert. (siehe Anlage) Hier der problematische Teil des Codes:
cp r26, r30 ; Stelle fest, ob Z > X, cpc r27, r31 brcs schleife2 ; Wenn Z > X, Bytes austauschen ret |
Z und X sind Registerpaare, mit denen indirekt RAM adressiert wird. Da der ATtiny nur 128 Byte RAM hat, kann kein Seitenüberlauf auftreten. Es reicht deshalb aus, r26 und r30 zu vergleichen. Der Befehl cpc ist unnütz. Insoweit könnte man von einem Compilerfehler sprechen. Nach der Auskommentierung des cpc-Befehls arbeitet die Stringumkehrung auf dem ATtiny26 einwandfrei. Der cpc-Befehl scheint aber nach meinen ersten Versuchen nicht ordentlich zu arbeiten und das Carry-Bit nicht in den Vergleich zu übernehmen, aber das ist eine andere Baustelle. Gruß Joachim
Datum:
Die Frage ist eher, wieso sind r27, r31 nicht richtig initialisiert. Also was übergibt der Aufrufer an strrev(). Und gibt es vielleicht eine Unterscheidung/Optimierung innerhalb AVR-GCC die bei kleinen AVRs von 16-Bit Pointern auf 8-Bit-Pointer runterschaltet. Das Problem kann ja ohne weiteres bei weiteren Funktionen zu schlagen.
Datum:
Das könnte von der SRAM Größe (<= 256 Bytes) auch betreffen: Attinys ATtiny28L ATtiny10 ATtiny4 ATtiny5 ATtiny9 ATtiny13A ATtiny13 ATtiny2313 ATtiny25 ATtiny26 ATtiny24 ATtiny261 ATtiny261A ATtiny2313A ATtiny24A ATtiny20 ATtiny40 ATtiny44A ATtiny43U ATtiny4313 ATtiny45 ATtiny461A ATtiny461 ATtiny48 ATtiny44 Atmegas ATmega48 ATmega48A ATmega48P ATmega48PA
Datum:
Joachim schrieb: > Das ltoa-Problem besteht in der fehlenden Stringumkehrung beim ATtiny26. > [...] > Der Compiler erzeugt für einen ATmega16 den gleichen Code, wie für einen > ATtiny26. Der Code funktioniert auf dem ATmega16, nicht jedoch auf dem > ATtiny26. Daraus könnte man ableiten, dass der Code in Ordnung ist und > der Prozessor nicht richtig arbeitet. In der neuesten Version der avr-libc ist strrev in asm implementiert: http://cvs.savannah.gnu.org/viewvc/avr-libc/libc/s... > Dazu wurde der Code der Stringumkehrung extrahiert und als separates > Assemblerprogramm eingebunden. Die Kommentare zeigen was passiert. > (siehe Anlage) > > Hier der problematische Teil des Codes: >
> cp r26, r30 ; Stelle fest, ob Z > X, > cpc r27, r31 > brcs schleife2 ; Wenn Z > X, Bytes austauschen > ret > |
> Z und X sind Registerpaare, mit denen indirekt RAM adressiert wird. Da > der ATtiny nur 128 Byte RAM hat, kann kein Seitenüberlauf auftreten. Es > reicht deshalb aus, r26 und r30 zu vergleichen. Der Befehl cpc ist > unnütz. Insoweit könnte man von einem Compilerfehler sprechen. Nein, offenbar nicht. Bestenfalls eine "missed Optimization in der avr-libc". > Nach der Auskommentierung des cpc-Befehls arbeitet die Stringumkehrung > auf dem ATtiny26 einwandfrei. > > Der cpc-Befehl scheint aber nach meinen ersten Versuchen nicht > ordentlich zu arbeiten und das Carry-Bit nicht in den Vergleich zu > übernehmen, aber das ist eine andere Baustelle. NACK. Wenn es Versionen des ATtiny26 gibt, die einen Hardware-Bug haben, dann darf CPC nicht so verwendet werden. Die Register werden als 16-Bit-Register initialisiert, so wie die ABI es für Zeiger vorsieht: diese sind 16 Bit groß, einen Sonderfall für 8-Bit-Pointer kennt avr-gcc nicht.
Datum:
Mit meiner jetzigen Konfiguration kann ich den Fehler nicht nachvollziehen: WinAVR-20081205 (der Version aus der Arduino IDE 0022) _AVR_LIBC_VERSION_STRING_ "1.6.4"
Datum:
Angehängte Dateien:Auch in der folgenden Konfiguration gibt es keine Auffälligkeiten: WinAVR-20100110 (die Letzte von Sourceforge) _AVR_LIBC_VERSION_STRING_ "1.6.7" Projektoptionen: Default (-Os) von AVR Studio 4.16 (build 628) @ Joachim Kannst du eine komplette Minimalsource geben, die den Fehler noch zeigt?
Datum:
Hallo, Stefan B. schrieb: > Die Frage ist eher, wieso sind r27, r31 nicht richtig initialisiert. In meinem Text habe ich nur drei Zeilen des Anhangs wiedergegeben. Gleich zu Anfang der Routine werden r26:r27 und r30:r31 eindeutig mit dem übergebenen Parameter geladen. Stefan B. schrieb: > Also was übergibt der Aufrufer an strrev(). An strrev wird die Adresse des Strings übergegeben, der umgekehrt werden soll. Johann L. schrieb: > In der neuesten Version der avr-libc ist strrev in asm implementiert: Der Code entspricht m. E. dem, der aktuell für den ATtiny26 erzeugt wird. Ich habe das Assemblerprogramm aus dem .lss -Listing herauskopiert. Die Wurzel des Übels scheint mir im cpc-Befehl zu liegen. Dieser "reicht das Carry-Bit nicht durch". Nachdem ich cpc r27, r31 auskommentiert hatte, habe ich den cp r26, r30 in cpc r26, r30 umgestellt und einmal ein CLC und dann ein SEC vorangestellt. Beides funktionierte. Der Befehl cpc müsste auf dem ATtiny26 noch einmal intensiver untersucht werden. Stefan B. schrieb: > Mit meiner jetzigen Konfiguration kann ich den Fehler nicht > nachvollziehen: > > WinAVR-20081205 (der Version aus der Arduino IDE 0022) > AVR_LIBC_VERSION_STRING "1.6.4" Wichtig ist der Prozessor. Der Fehler wurde bisher nur auf dem ATtiny26 beobachtet. Die WinAVR Version ist unerheblich. Ich habe den Fehler bei WinAVR-20080110 und WinAVR-20100110 beobachtet. 2003 war der Fehler offensicht bereits vorhanden. Ich halte es deshalb für sehr wahrscheinlich, dass alle WinAVR-Versionen von 2003 bis heute betroffen sind. Falls Du wirklich einen ATtiny26 hast, der den Fehler nicht zeigt, wäre der Date-Code des ICs interessant. Gruß Joachim
Datum:
@ Stefan B. Ich vermute, dass Du eine Simulation benutzt hast. Die wird keinen Fehler zeigen. Wenn ich das fehlerhafte Programm erst für einen ATtiny26 und dann für einen ATmega16 übersetze und anschließend beide .lss-Dateien mit Microsoft Word vergleiche, dann stelle ich fest, dass der entsprechende Programmteil identisch ist! Ich will das noch mal auf einem ATmega16 praktisch testen, um nachzuweisen, dass sich die Controller bei identischem Code verschieden verhalten. Eine Minimalversion stelle ich noch zusammen. Gruß Joachim
Datum:
Ja, ich habe nur die Simulation. Wenn die Toolchain den Pointer richtig 16-Bit an die itoa() und die den richtig 16-Bit an strrev() übergibt und nur bei paar Attiny26 auf der Welt (bisher) ein Fehler bei CPC auftritt... liegt es vielleicht an dem einen Attiny26. Es ist also richtig und wichtig, dass du nach anderen Berichten und nach dem Datecode des Attiny26 forschst. Vielleicht ist es ein Produktionsfehler. Steht etwas in dem Errata-Abschnitt des Datenblatts? Welcher Datecode hat dein Attiny26? Vielleicht können die Leute aus Beitrag "Bleiakku-Lader 12/24V" noch etwas beitragen. Dort wurde ein Attiny26 benutzt.
Datum:
Stefan B. schrieb: > ... und nur bei paar Attiny26 auf der > Welt (bisher) ein Fehler bei CPC auftritt... Ich würde sagen: "... beobachtet wurde". Ich besitze zwei ATtiny26 mit der Aufschrift: ATTINY26-16PU 0743 Im Datenblatt ist ein Codefehler festgehalten. Und zwar in REV1477D-05/03 Punkt 14 und REV1477D-10/03 Punkt 9. Beides hat aber nichts mit dem hier betrachteten Fall zu tun.
Datum:
Hast du denn inzwischen ein Minimalbeispiel? Etwa strrev() direkt aufrufen und anhand des Ergebnisses ne LED an/aus, so daß Fehler anderswo (LCD, out of RAM, ...) ausgeschlossen werden können. Zumindest für einige Versionen des ATtiny26 funktioniert kein LPM Rd, Z+, ditto für LPM Rd, Z; siehe zB in den Errata oder auch EW15952 in http://supp.iar.com/FilesPublic/UPDINFO/004793/ew/... Damit wird womöglich im Startup-Code die .data-Section nicht richtig initialisiert. AFAIK gibt es für dieses Erratum keinen Workaround in den GNU-Tools bzw. der avr-libc
Datum:
Hallo Joachim, ich habe noch nie mit der Funktion Itoa() gearbeitet und diesen Bitrag nur überflogen, aber wenn ich das richtig verstehe macht sie aus einem Integer einen String. Jetzt setzt du einen zahlenwert -234567 ein. Ein Uint hat einen Maximalwert von 65536, ein signed int geht von -32767 bis 32768. Also ist deine Zahl zu groß, Itoa() kann nur was falsches rausgeben. Schon mal mit "-23456" versucht, um Itoa() zu prüfen? MFG Markus
Datum:
Nee, ltoa (long integer to ascii) packt die -234567 schon. itoa (integer to ascii) hätte die Probleme.
Datum:
Joachim schrieb: > Der Prozessor ist ein ATtiny26. > Ich habe mir inzwischen damit geholfen, den String rückwärts auszugeben. Ich würd dann doch eher zu nem ATtiny261 raten, so teuer sind die ja nicht. Ein "falsches" Programm zu schreiben, ist keine gute Lösung. Vielleicht bist Du auch schon knapp mit Speicher und könntest eh nen Attiny461 oder 861 gut gebrauchen. Peter
Datum:
@Joachim und Peter Meine Hochachtung und vielen Dank für diesen Einsatz. Derlei HW-Bugs sind unheimlich schwer zu finden und zu beweisen. Mit solchen Threads steigt der Wert dieses Forums für uns Entwickler ganz enorm an.
Datum:
Angehängte Dateien:Erst einmal vielen Dank Peter! Ich hatte vor, den Code auf einem ATmega16 zu überprüfen. Dazu hätte ich das ganze auf einer anderen Hardware laufen lassen müssen. Dein Ansatz ist um einiges eleganter. Mit dem Verwenden zweier pinkompatibler Controller ist der fehlerhafte Controller leichter zu bestimmen und das Risiko einer abweichenden Hardware sicher auszuschalten. Da meine bevorzugten Elektronikversender nur den Attiny26 im Programm haben, hatte ich keinen neueren 261, 461 etc. zur Hand. Meine Vermutung, dass der cpc-Befehl fehlerhaft ist, hat sich als falsch erwiesen. Der cpc-Befehl arbeitet so wie es sein soll. Der Befehl ld r23, Z+ weist einen gravierenden Fehler auf. Z wird um 1 erhöht und das HOB von Z wird überraschend auf 0 gesetzt! Ein Testprogramm dazu im Anhang. Um den Fehler sehen zu können muss das Programm auf einem ATtiny26 laufen. Eine Simulation reicht sicher nicht aus. Damit ist der ursächliche Fehler gefunden. Das Auskommentieren des cpc-Befehls in der strrev-Funktion der Bibliothek ist sicher eine brauchbare Umgehung für den ATtiny26. Evtl. finden die Compilerbauer ja auch eine andere Lösung. Gruß Joachim
Datum:
Joachim schrieb: > Z wird um 1 erhöht und das HOB von Z wird überraschend auf 0 gesetzt! Möglicherweise hat ein übereifriger Designcompiler hier festgestellt, dass das höhere Adressbyte von Z ja nie benutzt werden kann, sodass es egal ist, auf welchen Wert man dieses Register setzt. > Das Auskommentieren des cpc-Befehls in der strrev-Funktion der > Bibliothek ist sicher eine brauchbare Umgehung für den ATtiny26. Leider wird die avr-libc nicht pro einzelnem Controller compiliert, sondern die Controller werden zu relativ groben Familien zusammen- gefasst. Daher ist es nicht ohne weiteres möglich, nur beim ATtiny26 (oder etwa nur bei Controllern mit <= 128 Byte SRAM) diesen Befehl wegzulassen.
Datum:
Jörg Wunsch schrieb: > Leider wird die avr-libc nicht pro einzelnem Controller compiliert, > sondern die Controller werden zu relativ groben Familien zusammen- > gefasst. Daher ist es nicht ohne weiteres möglich, nur beim ATtiny26 > (oder etwa nur bei Controllern mit <= 128 Byte SRAM) diesen Befehl > wegzulassen. Damit ist der Attiny26 aber immer noch kaputt, d.h. falls irgendwo Arithmetik/Vergleiche > 1 Byte gemacht wird, geht's sehr wahrscheinlich in die Hose -- und das sind ja nicht nur Zeiger. Je nach Ausgeberoutine werden damit auch falsche Werte angezeigt; zudem ist nicht mal klar, ob alle Versionen des ATtiny26 betroffen sind. Vorstellbar als Hack in iotn26.h ist ein
asm (".macro cpc a b"); asm (".warning ..."); asm (".endm"); |
Aber am wichtigsten ist, daß der Fehler nachgewiesen ist. Wenn in der Zufunft wieder jemand Huddel mit einem ATtiny26 hat, klingeln bestimmt bei irgendjemand hier zumindest die Glocken und es muss nicht erst ewig gesucht werden.
Datum:
Johann L. schrieb: > Aber am wichtigsten ist, daß der Fehler nachgewiesen ist. Wenn in der > Zufunft wieder jemand Huddel mit einem ATtiny26 hat, klingeln bestimmt > bei irgendjemand hier zumindest die Glocken und es muss nicht erst ewig > gesucht werden. Man (also: jemand, der davon betroffen ist) sollte zumindest mal einen Bugreport bei Atmel öffnen.
Datum:
Langsam, langsam ... Mit so einem Fehler ist das nicht so einfach. Anfangs habe ich festgestellt, dass die Begrenzung der Pointerberechnung auf 8 Bit den Fehler behebt. (durch das auskommentieren von cpc ...) Das ist aber nicht unbedingt ein Compilerfehler. Im nächsten Schritt habe ich festgestellt, dass der Pointer zur indirekten Adressierung Z, bei dem Postincrement-Befehl Z+ überraschend im HOB auf 0 gesetzt wird. Das ist überraschend und nicht dokumentiert. Es ist aber nicht zwingend ein Controller-Fehler. Der ATtiny 26 verfügt über einen SRAM-Bereich, der von 0x00 bis 0x5f adressiert wird. Register zur indirekten Adressierung sollten deshalb sinnvollerweise auch nur auf diesen erlaubten Bereich zugreifen. Wenn das alle tun, fällt niemandem auf, wenn das HOB des Pointers <> 0 ist. Es sollte deshalb niemand ein Problem mit dem Verhalten des Z+ Befehls haben. Die Frage ist nun, weshalb der Maschinencode den String nicht mit 0x005f adressiert. Das HOB der Stringadresse wird im Controller dynamisch ermittelt. Und das geht so: Zuerst wird der Stackpointer auf die letzte Speicherstelle gesetzt. Beim Attiny26 wird der 8Bit-Stackpointer korrekt auf 0x5f gesetzt. Das "HOB-Register des Stackpointers" ist nicht definiert, weil es nicht benötigt wird und 8 Bit gut ausreichen. Das Hauptprogramm liest dann den 16-Bit-Stackpointer!, zieht die Länge des benötigten Speichers ab und setzt den Stackpointer unter den benötigten Speicher. Die Adresse des definierten Strings liegt nun über dem Stackpointer und seine Adresse setzt sich aus dem berechneten LOB und dem HOB aus dem nicht definierten Inhalt des HOB-Stackpointer-Registers zusammen. Der Befehl Z+ funktioniert immer dann einwandfrei, wenn die Speicherseite 0 angesprochen wird. Da das HOB-Stackpointer-Register beim ATtiny26 beim Lesen nicht definierte Werte liefert, wird eine Speicherseite <> 0 angesprochen (d.h. HOB <>0), was offensichtlich sogar gelegentlich funktioniert. Beim Lesen eines nichtdefinierten Registers besteht aber kein Anspruch auf die Ausgabe eines bestimmten Wertes. Zusammenfassend: 1. CPC ist in Ordnung. Das Auskommentieren ist nur eine Umgehung. 2. Z+ verhält sich ungewohnt und undokumentiert, ist aber logisch konsequent. 3. Der vom Compiler generierte Code liest einen 16 Bit Stackpointer aus einem 8 Bit Stackpointerregister und einem nicht definierten Register (das auf größeren Controllern als HOB des Stackpointers definiert ist) So wird der Stackpointer gesetzt (korrekt): ldi r28, 0xDF ; 223 out 0x3d, r28 ; 61 So wird er am Anfang von main ausgelesen: in r28, 0x3d ; 61 ; ok in r29, 0x3e ; 62 ; reserviertes ATtiny26 Register Nach dieser Erkenntnis würde ich nun doch für einen Compilerfehler plädieren. Karl heinz Buchegger schrieb: > Das Problem könnte genausogut auch irgendwo ganz anders stecken. > Du siehst nur die Symptome. Das bedeutet aber nicht, dass die Ursache > ebenfalls hier zu finden ist. Karl Heinz hat in weiser Voraussicht recht gehabt. Gruß Joachim
Datum:
Joachim schrieb: > So wird er am Anfang von main ausgelesen: > in r28, 0x3d ; 61 ; ok > in r29, 0x3e ; 62 ; reserviertes ATtiny26 Register > > Nach dieser Erkenntnis würde ich nun doch für einen Compilerfehler > plädieren. "Das haben wir aber schon immer so gemacht." ;-) Auf jedem anderen AVR funktioniert das auch (auch auf den kleinen mit 128 oder weniger Byte SRAM). Eigentlich sollte das egal sein, was im oberen Byte des Zeigers drin steht, denn da dieses Byte für die Adressierung des SRAMs nicht benötigt wird, sollte es einfach ignoriert werden. Damit ist es wiederum auch wurscht, ob das Auslesen des nicht vorhandenen SPH nun 0, 0xff oder 42 ergibt. Wenn der ATtiny26 das nicht ignoriert und "auf nichts" zugreift, wenn das obere Byte != 0 ist, dann würde ich das zumindest unter "surprisingly unexpected behaviour" einsortieren.
Datum:
Das paßt dann sehr gut mit dem Datenblatt zusammen: Datasheet Revision History: 9. Removed LPM Rd, Z+ from “Instruction Set Summary” on page 171. This instruction is not supported in ATtiny26. Also auch beim LPM-Befehl wird Z+ fehlerhaft berechnet und daher hat man diesen Befehl einfach wieder "gestrichen". Statt: Z = Z + 1; wird also ausgeführt: Z = (Z + 1) & 0x00FF; Atmel hätte besser den Fehler korrigieren sollen, anstatt Befehle zu entfernen. Peter
Datum:
Peter Dannegger schrieb: > Atmel hätte besser den Fehler korrigieren sollen, anstatt Befehle zu > entfernen. Eine neue Chiprevision kostet halt deutlich mehr als eine neue Datenblattrevision. ;-) Da es außerdem den ATtiny261 als de-facto- Nachfolger gibt, wird keiner mehr die Summen für einen neuen Maskensatz für den alten IC in die Hand nehmen.
Datum:
Joachim schrieb: > Zusammenfassend: > 1. CPC ist in Ordnung. Das Auskommentieren ist nur eine Umgehung. Nein. CPC ist nicht in Ordnung, zumindest nach obigen Ergebnissen. Wer sagt dir, daß das Byte, das per CPC verglichen wird, zu einer Adresse gehört? Es kann ebenso zur 16-Bit Arithmetik eines Skalars gehören (Fixed-Point, Integer mit 16, 24, 32, ... Bits). Ein richtiger Workaround für diesen Silicon-Bug hätte im Assembler avr-as zu geschehen, z.B.
mov R0, Ra sbc R0, Rb |
anstatt
cpc Ra, Rb |
und einem Fatal Error falls Rb = R0. Ein WA im Compiler ist aufwändiger und fängt weniger Stellen, z.B. keine in (Inline-)Assembler, und damit auch keine wie im strrev der avr-libc. Da strrev per ltoa -- also nicht unwahrscheinlich -- benutzt wird, würde ich vorschlagen, diesen WA für mcu=avr2 direkt in die avr-libc einzubauen, oder was auch immer grep cpc zu Tage fördert. Ich weiß ja nicht, wie langsam die Mühlen bei den avr-binutils mahlen... aber wenn sie so fix sind wie die von avr-gcc, dann gibt es nie einen WA für diesen Bug im Prozessorkern -- um so übler, da er nicht bei den Errata auftaucht. Die Initialisierung von SP geschieht im Startup-Code, und dort könnte SPH explizit mit Null geladen werden (section .init2 in crttn26.[oS]).
Datum:
@ Johann L. Der Fehler ist hier eine Verkettung mehrerer Umstände. Wenn ich den 16-bit-Vergleich am Ende der strrev-Routine zu einem 8-bit-Vergleich mache, dann verdecke ich das Problem und das Programm funktioniert. Da der angesprochene Vergleich korrekt ist und auf allen anderen AVR's funktioniert, ist entweder, wie von mir Anfangs fälschlicherweise festgestellt der CPC-Befehl fehlerhaft oder die Eingangsdaten stimmen nicht. Hier stimmen die Eingangsdaten nicht, weil der Z+ Befehl das HOB des Vektors überraschend auf 0 gesetzt hat. Da ein Zeiger auf das RAM im ATtiny immer 0 im HOB stehen haben muss, ist es kein wirklicher Fehler, wenn bei Z+ das HOB auf 0 gesetzt wird. Der Fehler liegt an dieser Stelle darin, dass das HOB des Vektors nicht bereits vorher auf 0 stand. Und das ist darauf zurückzuführen, dass die RAM-Adresse gebildet wurde, in dem man darauf vertraute dass ein nicht definiertes Register beim Lesen 0 ausgibt. Auch wenn die anderen AVR's offensichtlich 0 ausgeben, ist es ein Risiko darauf zu vertrauen und das generell vorauszusetzen. Die Beseitigung des Mangels sollte man an der Quelle durchführen. Dort, wo zu Beginn der main-Routine die höchste Speicheradresse festgestellt wird, ist das HOB auf 0 zu setzen und nicht aus dem Stackpointer zu lesen. Beim Setzen des Stackpointers wurde das ATtiny26-individuell korrekt gemacht. Zu Beginn der main-Routine sollte das auch ATtiny26-individuell machbar sein. Gruß Joachim
Datum:
Jörg Wunsch schrieb: > Wenn der ATtiny26 das nicht ignoriert und "auf nichts" zugreift, > wenn das obere Byte != 0 ist, dann würde ich das .... Es ist schon so, dass der ATtiny26 das HOB beim Zugriff auf das SRAM ignoriert. Das SRAM wird entsprechend oft gespiegelt. Das geht solange gut, bis vor einem Vergleich zweier Zeiger der eine Zeiger nach einem Z+ Befehl mit & 0x00FF maskiert wurde. Der Vergleich muss schiefgehen und das Programm liefert eine Fehlfunktion.
Datum:
Johann L. schrieb: > Die Initialisierung von SP geschieht im Startup-Code, und dort könnte > SPH explizit mit Null geladen werden (section .init2 in crttn26.[oS]). Das Laden eines reservierten Registers kann gut gehen, ist aber ebenfalls keine dokumentierte Funktion. Der ATtiny26 hat nur einen 8-Bit-Stackpointer! An der Stelle, wo ich einen 16-Bit-Zeiger aus einem 8-Bit-Stackpointer lade, muss die Korrektur ansetzen.
Datum:
Joachim schrieb: > @ Johann L. > wie von mir Anfangs fälschlicherweise > festgestellt der CPC-Befehl fehlerhaft Ok, hatte ich oben wohl überlesen. Was bedeutet eigentlich HOB? Bei der Suche finde ich da bestenfalls "House of Boys" :-)
Datum:
Das wird "high order byte" sein, also der höherwertige teil der Adresse. Peter Frauenhaus ist mir ein Begriff, aber das es sowas auch für Männer gibt war mir neu.
Datum:
Ich verwende seit Jahren HOB für high order Byte und LOB für low order Byte. Offensichtlich hat sich das aber nicht allgemein durchgesetzt. Hat jemand andere geeignetere Begriffe dafür? Zurück zum Thema Hier noch einmal der fehlerhafte Code:
char text [12]; // String ltoa (-234567, text, 10); lcd_puts(text); // put string to display |
und hier eine im ATtiny26 funktionierende Lösung:
char text [12]; // String ltoa (-234567, (char*)((int)text & 0xff), 10); lcd_puts(text); // put string to display |
Gruß Joachim
