Hallo zusammen,
ich habe möchte gerne im Bootloader (
http://www.mikrocontroller.net/articles/Konzept_f%C3%BCr_einen_ATtiny-Bootloader_in_C)
in das eeprom schreiben und lesen. Leider klappt das aber nicht.
Schreibe ich den Code ohne den linkerzusatz
"-Wl,--section-start=.text=0xBC0" klappt es.
Muss ich das eeprom anders addressieren oder was mache ich falsch?
Prozessor : Attiny45
Vielen Dank vorab.
Gruß
Frank
Hallo !
Ich hab' zwar nicht so viel Ahnung, aber gehört der Bootloader nicht
in's Flash und der ATiny hat keine FUSES für einen Bootbereich, also
geht das überhaupt ?
Frank Z. schrieb:> ich habe möchte gerne im Bootloader (> http://www.mikrocontroller.net/articles/Konzept_f%C3%BCr_einen_ATtiny-Bootloader_in_C)
> in das eeprom schreiben und lesen. Leider klappt das aber nicht.> Schreibe ich den Code ohne den linkerzusatz> "-Wl,--section-start=.text=0xBC0" klappt es.
Ich hab in diesem Projekt nicht gesehen, daß das R/W des EEPROM
überhaupt implementiert ist. Was dann plötzlich funktionieren soll, ist
mir daher auch rätselhaft.
Frank Z. schrieb:> Muss ich das eeprom anders addressieren oder was mache ich falsch?
Du mußt die EEPROM-Funktionen implementieren. EEPROM und Flash sind zwei
verschiedene Paar Schuhe.
knollo schrieb:> Ich hab' zwar nicht so viel Ahnung, aber gehört der Bootloader nicht> in's Flash und der ATiny hat keine FUSES für einen Bootbereich, also> geht das überhaupt ?
Ja, mit ein bißchen Trickserei und Reset-/Interrupt-Vektoren verbiegen
geht das.
Frank Z. schrieb:> ich habe möchte gerne im Bootloader (> http://www.mikrocontroller.net/articles/Konzept_f%C3%BCr_einen_ATtiny-Bootloader_in_C)
> in das eeprom schreiben und lesen. Leider klappt das aber nicht.
Eine sehr ausführliche Beschreibung deines Problems hast du da
abgeliefert. Ich liefere dir gerne eine ebenso ausführliche
Ursachenanalyse: "du machst etwas falsch".
> Schreibe ich den Code ohne den linkerzusatz> "-Wl,--section-start=.text=0xBC0" klappt es.>> Muss ich das eeprom anders addressieren oder was mache ich falsch?
Das Verschieben deines Codes an eine andere Adresse im Flash wird nicht
die Funktion des Codes verändern. Das passiert auch in normalen
Programmen laufend. Je nach Größe einzelner Programmteile werden
Funktionen mal an die eine, mal an eine andere Adresse gelinkt. Trotzdem
funktionieren diese Funktionen immer gleich. Du machst also ganz
offensichtlich etwas falsch. Was genau, kann dir natürlich mangels
Informationen keiner sagen.
Hallo zusammen,
vielen Dank für Eure Antworten. Ich sehe ein, dass es tatsächlich nicht
ganz so ausführlich ist. Dies möchte ich gerne hier noch einmal
nachholen.
Wie oben gesagt, habe ich den bootloader aus dem Artikel implementiert.
Es funktioniert auch alles einbandfrei. Da ich aber eine Variable
innerhalb des Bootloader ins eeprom schreiben möchte, habe ich die
folgenden Funktionen benutzt:
1
...
2
intmain(void){
3
....
4
uint8_teeFooByte=0x00;
5
unsignedcharmyByte=0x33;
6
eeprom_write_byte(&eeFooByte,myByte);
7
....
8
}
ebenfalls habe ich folgendes wie im Datasheet beschrieben ausprobiert:
1
voidEEPUT(intlocation,unsignedcharbyte){
2
while(EECR&(1<<EEPE));/* Check if EEPROM is ready*/
3
EEAR=location;/* Write EEPROM address register*/
4
EEDR=byte;/* Write EEPROM data register*/
5
EECR|=(1<<EEMPE);/* Set master write enable signal*/
6
EECR|=(1<<EEPE);/* Set write strobe*/
7
}
8
...
9
intmain(void){
10
....
11
EEPUT(0x00,0x33);
12
....
13
}
Beide Implementierungen funktionieren, wenn ich den Code nicht in einen
höheren Bereich verschiebe. Dies machen ich per Linkeranweisung mit:
-Wl,--section-start=.text=0xBC0 -Wl,--section-start=.bootreset=0x00
-Wl,--section-start=.data=0x800080
Wenn ich nur das nachfolgenen Elementes aus der Anweisung entferne,
funktioniert der Code : -Wl,--section-start=.text=0xBC0 ( neue
Linkeranweisung: -Wl,--section-start=.bootreset=0x00
-Wl,--section-start=.data=0x800080)
Warum schreiben die o.a. Funktionen nach der Verschiebung des Codes
nicht mehr ins eeprom.
Ich debuge das ganzen mit Atmel Studio und dem Dragon im OneWireDebug
Modus.
Vielen dank noch mal vorab.
Gruß
Frank
Frank Z. schrieb:> uint8_t eeFooByte = 0x00;> unsigned char myByte = 0x33;> eeprom_write_byte(&eeFooByte, myByte);
eeFooByte ist eine Variable im RAM. Die hat zwar auch eine Adresse, die
auf das EEPROM passen könnte, der Adressbereich fängt aber nicht bei 0
an, sondern bei deinem Tiny bei 0x60. Mit einer RAM-Adresse sind die
ersten 96 Byte des EEPROM gar nicht adressierbar und Zugriffe auf die
letzten 96 Byte erfolgen im Nirwana.
Du musst die Variable also im EEPROM anlegen:
1
uint8_teeFooByteEEMEM=0;
Oder du sparst dir das und verwaltest die Adressen selbst:
1
eeprom_write_byte((unsignedchar*)E2END,myByte);
Damit schreibst du bspw. auf die letzte Speicherstelle im EEPROM. Aber
du schiesst dir ins Knie, wenn du statt char ein int dahin schreibst.
Also überlasse es lieber dem Compiler.
Frank Z. schrieb:> Warum schreiben die o.a. Funktionen nach der Verschiebung des Codes> nicht mehr ins eeprom.
Keine Ahnung. Ist auch nicht wichtig, da du es grundsätzlich falsch
machst.
Das ist natürlich falsch, wie dein (unser?) Vorbild schon sagte. Der
erste Parameter für eeprom_write_byte() ist ein Pointer (vulgo: eine
Adresse) im EEPROM. Dazu kannst du die entsprechende Variable entweder
in die entsprechende section legen (z.B. mit dem EEMEM Makro) oder du
verwaltest die paar Adressen im EEPROM manuell und übergibst hier eine
Zahl. Die erste Variante hat den Vorteil, daß der Compiler ein HEX File
erzeugen kann mit dem du die initialen Werte im EEPROM setzen kannst.
> ebenfalls habe ich folgendes wie im Datasheet beschrieben ausprobiert:
1
>voidEEPUT(intlocation,unsignedcharbyte){
2
>while(EECR&(1<<EEPE));/* Check if EEPROM is ready*/
3
>EEAR=location;/* Write EEPROM address register*/
4
>EEDR=byte;/* Write EEPROM data register*/
5
>EECR|=(1<<EEMPE);/* Set master write enable signal*/
6
>EECR|=(1<<EEPE);/* Set write strobe*/
7
>}
8
>...
9
>intmain(void){
10
>....
11
>EEPUT(0x00,0x33);
12
>....
13
>}
Das hingegen könnte funktionieren; es schreibt deine 0x33 an die erste
Adresse (0x00) des EEPROMs. Hier ist das Problem, daß du möglicherweise
die Zeitanforderung von maximal 4 Takten zwischen dem Setzen von EEMPE
und EEPE nicht einhältst. Deswegen ist dieser Teil besser in
Inline-Assembler zu erledigen.
> Ich debuge das ganzen mit Atmel Studio und dem Dragon im OneWireDebug> Modus.
Unter Debugger-Kontrolle ist es noch wahrscheinlicher, daß du die
Zeitanforderung nicht einhältst.
Wenn du diesen Teil gefixt hast und es trotzdem nicht funktioniert, wäre
es hilfreich, wenn du dein "geht nicht" noch etwas präzisierst. Was
passiert genau? Steht nach dem Schreiben noch der alte Wert im EEPROM?
Oder gar ein ganz anderer Wert? Mein Vorschlag wäre, das EEPROM einmal
mit 0x00 und einmal mit 0xFF zu initialisieren (z.B. über ISP) und dann
mit deinem Bootloader auf 0x33 zu schreiben. Danach haben wir einen
etwas besseren Überblick was da passiert.
Einen ganz grossen Dank für Eure Anmerkungen. Hat mir echt geholfen.
Der Fehler lag aber nicht an den eeprom Funktionen. Es lag daran, dass
ich den Code zu weit nach hinten geschoben hatte. Grösse neue berechnet
- und schon klappt es mit dem eeprom.
Wie gesagt - vielen Dank. Hat mir echt geholfen.
Gruß
Frank
Axel S. schrieb:> Hier ist das Problem, daß du möglicherweise> die Zeitanforderung von maximal 4 Takten zwischen dem Setzen von EEMPE> und EEPE nicht einhältst. Deswegen ist dieser Teil besser in> Inline-Assembler zu erledigen.
das könnte von moby oder chater sein ;-)
ne, das schafft der Compiler mit links in 4 Takten
Frank Z. schrieb:> Der Fehler lag ... nicht an den eeprom Funktionen. Es lag daran, dass> ich den Code zu weit nach hinten geschoben hatte. Grösse neue berechnet> - und schon klappt es mit dem eeprom.
Autsch. Dann hast du da noch einen Fehler in deiner Build-Umgebung. Wenn
der Linker ein Executable erzeugt, das zu groß für den Ziel-µC ist, dann
muß da eine Fehlermeldung aufpoppen.
Walter S. schrieb:> Axel S. schrieb:>> Hier ist das Problem, daß du möglicherweise>> die Zeitanforderung von maximal 4 Takten zwischen dem Setzen von EEMPE>> und EEPE nicht einhältst. Deswegen ist dieser Teil besser in>> Inline-Assembler zu erledigen.>> das könnte von moby oder chater sein ;-)
Also, das war ja wohl weit unter der Gürtellinie, Freundchen!
Ich erwarte eine schriftliche Entschuldigung bis morgen 9:00 Uhr!
> ne, das schafft der Compiler mit links in 4 Takten
Du kannst dich aber nicht darauf verlassen, daß das immer und mit allen
Compilerschaltern so ist. So wie er dasteht, verläßt sich der Code auf
ein Verhalten des Compilers, das nirgendwo zugesichert wird. Und weil C
gar keine Ausdrucksmittel hat, um ein bestimmtes Zeitverhalten zu
erzwingen, kann man das in reinem C gar nicht sauber implementieren.
Deswegen mein Vorschlag für Inline-Assembler. Streng genommen gehört das
auch in einen nicht-unterbrechbaren Block.
Und jetzt darfst du genau einmal raten, wie das in avr-libc
implementiert ist. In C oder in Assembler?
Axel S. schrieb:> Und jetzt darfst du genau einmal raten, wie das in avr-libc> implementiert ist. In C oder in Assembler?
du darfst auch einmal raten wie es z.B. im Datenblatt des mega8
vorgeschlagen wird
Theoretisch hast du ja recht, aber es gibt halt keinen üblichen
C-Compiler der derart schlechten Code erzeugt
Axel S. schrieb:> Streng genommen gehört das> auch in einen nicht-unterbrechbaren Block.
das dagegen ist unbedingt notwendig
Walter S. schrieb:> Axel S. schrieb:>> Und jetzt darfst du genau einmal raten, wie das in avr-libc>> implementiert ist. In C oder in Assembler?>> du darfst auch einmal raten wie es z.B. im Datenblatt des mega8> vorgeschlagen wird
Das muß ich nicht raten, das weiß ich. Aber der Beispielcode im
Datenblatt ist auch eher als Illustration zum nebenstehenden Prosatext
zu sehen denn als Anleitung, wie man das produktionsreif implementiert.
>> Streng genommen gehört das>> auch in einen nicht-unterbrechbaren Block.>> das dagegen ist unbedingt notwendig
Und was sagt dir das jetzt, daß das im Datenblatt-Beispielcode auch
nicht so gemacht wird? "Der da macht es aber auch falsch" ist keine
akzeptable Entschuldigung.
Axel S. schrieb:> Und was sagt dir das jetzt, daß das im Datenblatt-Beispielcode auch> nicht so gemacht wird?
muss man ja auch nicht machen wenn man weiß dass keine Unterbrechungen
vorkommen.
Aber ich bin dann hier raus, du darfst das letzte Wort haben.