hallo,
besitzt jemand erfahrung im kopieren von bereichen des flash in einen
anderen bereich? plattform ist der avr (can128)
zum problem: ich lagere programmcode in einen zwischenpuffer im flash
aus. ist der gesamte code übertragen, erfolgt das kopieren an die
richtige adresse, damit der code zur ausführung kommt. bisher ist dies
noch adresse 0.
im prinzip also wie ein bootloader.
schreibe ich immer die gleiche anwendung, läuft alles bestens. nun habe
ich aber den effekt, dass es bei änderungen des puffers (sprich:
komplett neues programm) zu kleinen unstimmigkeiten kommt. im
zwischenpuffer liegt das richtige programm, das habe ich überprüft. an
die ziel-adresse verschoben liegt aber code, bei dem an festgelegten
positionen bits gekippt sind. das betrifft einzelne halb-bytes
mittendrin.
sowohl für das schreiben in den zwischenpuffer als auch das verschieben
benutze ich die gleiche routine. einziger unterschied ist die quelle der
daten. beim puffern ist dies ein bereich aus dem sram (kommt übers
netz), beim finalen verschieben an das ziel eben das flash. für
letzteres kommt der zugriff per pgm_read_far_byte zur anwendung.
der code der routine:
// every second read fill temporary buffer for the page
67
if(i&0x01){
68
// we're already one adress ahead
69
boot_page_fill_safe(aligned_dest_ptr.pgm-1,
70
*((uint16_t*)tmp_data));
71
boot_spm_busy_wait();
72
}
73
// increment target address
74
aligned_dest_ptr.pgm++;
75
}
76
// perform erase-write-cycle
77
boot_page_erase_safe(aligned_dest_ptr.pgm-1);
78
// store buffer in flash page
79
boot_page_write_safe(aligned_dest_ptr.pgm-1);
80
// reenable RWW-section again. necessary, if src is in RWW-section
81
boot_rww_enable_safe();
82
}
83
// restore SREG
84
SREG=sreg;
85
returndest;
86
}
beispiel für ein falsche bytes:
:2010200099F1AE014F5F5F4F6DE972E0FC01838194810E94D70F882339F566E172E0C80
19A
--- ^ ^ ^
:2010200099F1AE014F5F5F4F61E872E0FC01838194810E94D70F882339F56AEF71E0C80
196
^ ^ ^
entnommen aus einem hex-diff.
meine einzige vermuting ist bisher, dass vielleicht der zugriff auf das
flash (die quelle) beim kopieren nicht ganz sauber läuft. aus dem sram
zu schreiben funktioniert tadellos. aber so richtig kann ich's mir nicht
erklären. auf ein anderes board gewechselt habe ich auch schon
testweise.
möglicherweise hat jemand schon mal erfahrungen mit dem thema gemacht
und/oder hat eine idee. für jeden hinweis bin ich extremst zu dank
verpflichtet.
bye kosmo
Ist dein µC schon alt? Hast du ihn schon oft neu beschrieben?
Dann sieh mal nach, wieviele Schreibzyklen der Typ verträgt - das Flash
hält nur eine begrenzte Anzahl Schreibzyklen aus.
hallo,
ja, beide boards und uC's sind schon etwas älter. können die fehler
ständig an den gleichen stellen auf ein versagen des flash hindeuten?
falls ja, muss ich wohl doch nochmal die reserve aus der ecke
rauskramen.
bye kosmo
Hast Du zufällig Interrupts während dem Flashen aktiviert) (funktioniert
ja auch im Bootloader, wenn die Boot-Vektoren benutzt werden).
Dann kann es sein, dass die Sequenzen zum Flash-Beschreiben (selten) von
IRs unterbrochen werden. Da zum Schreiben des Flash 2 Befehle direkt
hintereinander (4 Zyklen) gegeben werden können, kann es passieren, dass
ein IR genau zwischen den beiden Befehlen auftritt - damit wird der
Schreibbefehl als ungültig erkannt und nicht ausgeführt.
Bei mir half, während den Schreib-Funktionen die IRs zu sperren:
1
cli();
2
boot_page_erase(..);
3
sei();
bzw.
1
cli();
2
boot_page_write(..);
3
sei();
Die Funktionen brauchen nur ein paar Takte, das Sperren der IR ist also
unkritisch. Das warten auf Flash-ready machst Du natürlich mit IRs
eingeschaltet.
Das hat meine Probleme mit sporadischen Flash-Fehlern komplett behoben.
Gruß, Stefan
hallo,
dass die flash bzw. die kontroller defekt sind, kann ich so gut wie
ausschliessen. habe nun alle drei boards ausprobiert, und jedes mal den
gleichen fehler.
wie im code oben zu sehen, sind die interrupts aus während des
kopierens. für die übertragung übers netz verwende ich interrupts, ja,
aber wie gesagt, die routine macht sie für die dauer aus.
was ich festgestellt habe: der fehler tritt nur auf, wenn ich eine
kleinere anwendung aufspiele, als vorher drauf war.
anwendung 1: 11k
anwendung 2: 9k
reihenfolge: erst 2 drauf, dann 1 drauf klappt.
reihenfolge: erst 1 drauf, dann 2 drauf klappt nicht.
hierzu muss gesagt werden, dass ich "alten" code nicht lösche, nur die
pages, die ich eben brauche. (also kein chip-erase, wie's bei avrdude
heißt). entsprechend hängt bei fall 2 an der anwendung (und auch im
zwischenpuffer) noch was dran. was aber nicht bestandteil des programms
ist und dementsprechend nicht verwendet wird.
bye kosmo
hm, das problem scheint tatsächlich in der 64k-grenze zu liegen.
bisher hatte ich meinen zwischenpuffer genau in der mitte der
RWW-section gelegt. bei adresse 0xF000 beginnend. bei 11k oder 9k
programmcode wurde da leicht die adresse 0xFFFF überschritten. beim
lesen des puffers für das kopieren kommt es nun dazu, dass mal lpm, mal
elpm beutzt werden muss. das scheint nicht zu klappen wie gewünscht.
habe den zwischenpuffer bei 0x4000 beginnend gelegt, so dass er immer in
die ersten 64k fällt. mit den beschriebenen programmgrößen wird die
64k-grenze nicht erreicht. alles funktioniert bestens.
habe den zwischenpuffer bei 0x10000 gelegt, so dass er immer in die
zweiten 64k fällt. alles funktioniert erneut bestens.
alles wieder kehrt marsch, kommando zurück und auf 0xF000 gelegt. das
beschriebene verhalten kehrt zurück: der zwischenpuffer wird nicht
richtig gelesen.
staun