mega32 bootloader(linkt der linker hier korrekt?)

Gast #365220
Lesenswert?

Hi,

ich bin dabei einen Bootloader für den atmega32 zu schreiben. Nun habe
ich bereits herausgefunden, wie man den Linker dazu bewegt, das Program
auch an die richtige Adresse zu linken. Also habe ich bei LDFLAGS
noch hingeschrieben:

--section-start=.text=0x3800

(oder muss ich doch 2x 0x3800 rechnen wegen der word/byte adressen?)
Anyway, ich habe danach das map file begutachtet :

.text           0x00003800      0x886

Scheint also geklappt zu haben. Naja, dann habe ich das Hexfile kurz
mit Notepad geöffnet und bin stutzig geworden. Die erste Zeile beginnt
so:  :10000000
Die Adresse ist also 0x0000 ?! Sollte dort nun nicht 3800 stehen?
Ich bin verwirrt...naja, falls das so dennoch stimmen sollte habe ich
noch eine Frage. Wenn ich aus beliebiger Stelle in meinem Programm
(application section) in den bootloader springen möchte.
Dazu habe ich folgendes hier gefunden:

  asm volatile( "ldi r30, lo8(0x3800)");
  asm volatile( "ldi r31, hi8(0x3800)");
  asm volatile( "ijmp");

Ich habe zwar mit asm keine Erfahrung, dennoch meine ich mal gehört zu
haben das man für adressen höher als 8kb jmp benutzen muss, weshalb
hier also ijmp?

Nik
#365221
Lesenswert?

Ich habs so gemacht:

flashloader.S:
1
.section .flashloader,"ax",@progbits
2
//void flashloader_load()
3
.global flashloader_load
4
.func flashloader_load
5
flashloader_load:
6
 ....
7
 ret

flashloader.h:
1
void flashloader_load(void);

und im Makefile:
ASRC = update/flashloader.S
...
LDFLAGS =
-Wl,-Map=$(TARGET).map,--cref,--section-start=.flashloader=0x7F00
(also das ,--section dazu)

Musst du ggf anpassen.
Müsste auch in c gehen ;)

Bye, Simon
Gast #365222
Lesenswert?

danke :)

Ich kann asm zwar einigermassen lesen, allerdings meinem Bootloader
kaum in asm schreiben(wird mir zu kompliziert)

Ich nehme an, dass du mit

.section .flashloader,"ax",@progbits

irgendwie definierst, dass der darauf folgende Code dort hin gelinkt
werden soll, wo du es im makefile definiert hast.

Nun sollte es bei mir aber doch eigentlich automatisch klappen, denn
das C Programm ist doch schon die Section .text? Oder muss ich das noch
irgendwo schreiben "Hier fängt .text an, linke mich an adresse xy" ?

"Müsste auch in c gehen ;)" Welche zeile meinst du genau?
#365223
Lesenswert?

>"Müsste auch in c gehen ;)" Welche zeile meinst du genau?
Das mit dem sagen wo ers hinlinken soll ;)

Was steht denn bei dir im hex bei adresse0 ?
Poste doch mal so ein hex.
Evtl ist das nur irgendein initkram für die interrupts ?
Ka, so genau hab ich mir das beim gcc noch nicht angesehen.

Da ich meinen code + bootloader aufeinmal hochladen wollte
hab ich mir die zweite section (.flashloader) definiert.

Bye, Simon
Gast #365224
Lesenswert?

Ich hab das hex kurz angehängt. Das Problem ist, dass nicht nur einige
Zeilen an diesen Adressen stehen, es wird einfach ganz normal von 0 an
hochgezählt.. aber nirgends sehe ich meine 0x3800 :-(
Angehängte Dateien:
Gast #365226
Lesenswert?

ARGH+"*()( !! :)

Ich hab mich bei http://en.wikipedia.org/wiki/Intel_hex
verlesen und gemeint die Adresse fängt erst zwei byte später an, hab
mich schon gewundert warum da das lsb zuerst kommt...oh mann,
bleibt nur noch die Frage wie ich das nun aus meinem hauptrogramm dann
aufrufe, ich werds einfach mal mit folgendem Versuchen:

asm volatile( "ldi r30, lo8(0x3800)");
asm volatile( "ldi r31, hi8(0x3800)");
asm volatile( "ijmp");

Hab übrigens noch gemerkt das es 7000 sein muss und nicht 3800,
word>byte adressen...
Vielen Dank, mir wärs wohl so nicht aufgefallen.. Mein Tag ist gerettet
:P

ciao, Nik
Gast #365229
Lesenswert?

Ich habe gerade einen Boot Loader für einen ATmega32 geschrieben. Einige
Anmerkungen dazu:

1. Du solltest dir überlegen, wie gross dein Boot-Programm werden soll.
Bei 2KB ist die Linkadresse 0x7800 bei 4KB 0x7000. Also für den Linker:
 Wl,--section-start=.text=0x7800
oder
 Wl,--section-start=.text=0x7000
Entsprechend dazu musst du natürlich auch die Fuse-Bits für Bootsize
ändern.
2. Wenn du mit Interrupts im Boot Loader arbeiten willst, musst du noch
ein Bit im GICR setzen damit die Interruptvektoren im Boot Loader
angesprungen werden (siehe Doku zum ATmega32 und ASM-Zeilen unten):

#define IO_REG(n) _SFR_IO_ADDR(n)
#define temp1 r16

.section .text
.global init_vec_jmp

init_vec_jmp:
ldi  temp1, 0x01
out  IO_REG(GICR), temp1
ldi  temp1, 0x02
out  IO_REG(GICR), temp1
ret

Viel Glück
Werner
Gast #365230
Lesenswert?

Soo ich habs nun hinbekommen, vielen Dank an euch alle :-)

Der Upload eines 10kb programms übers netzwerk geht <1s. Ich bau dann
wohl noch einen Prüfsummecheck ein und die möglichkeit, am Ende des
Transfers in Software zu resetten, anstatt den Taster zu drücken.
watchdog braucht man da irgendwie damit alles klar geht hab ich
gelesen(?) Ich versuch mich dort auch mal einzuarbeiten, dann kann man
endgültig sein Programm von irgendwo updaten :-). Die Codegrösse liegt
im Moment so bei 3.2kb, es ist also 0x7000 ;) (hat aber noch einige LCD
Ausgaben drinn!) wenn ichs extrem quetsche, passts dann evt noch in die
2kb bootsection, aber dies würde ich als Wunder bezeichnen :-).

Nik
Gast #365232
Lesenswert?

ahso also du schaltest den watchdog ein und hängst das programm quasi
auf?

Also ich muss mal sehen ob ich das mit dem watchdog überhaupt richtig
verstehe: Der wdt ist eigentlich nichts als ein zähler, hat er sein
ende erreicht (möge das 0 oder was auch immer sein) dann resettet er
den uC.
Damit das nicht passiert, setzt man in gewissen Abständen den Wert
wieder auf den "Ursprung", somit wird automatisch ein Reset
ausgeführt, wenn sich das Prog irgendwo aufhängt > zähler nicht mehr
auf diesen ursprünglichen Wert gesetz wird.

Also wenns so ist dann habe ich - denke ich mal - kapiert wie es
klappen müsste, thx :P

Nik
Gast #365233
Lesenswert?

1
WDTCR |= 1<<WDE;
2
while(1);

Vielleicht gehts schöner, aber so hab ichs nun gemacht, klappt
wunderbar :-)
Ich bau noch einen Prüfsummencheck rein und was sonst noch kluges in
die 4kb reinpasst, auf 2kb runter bringe ich es leider nicht, also
wieso auch die restlichen 800bytes verschwenden. Wenns dann fertig ist,
ist es ja evt. wieder was für die Codesammlung... ;)
Moderator Persönliche Seite #365235
Lesenswert?

1
#include <avr/wdt.h>
2
#include <avr/interrupt.h>
3
...
4
wdt_enable(WDTO_15MS);
5
cli();
6
for (;;) ;

Bei neueren Watchdog-Implementierungen aber
aufgepasst: der Watchdog bleibt nach einem
Watchdog-Reset am Leben, den muss man danach
sofort abschalten, und bevor man ihn abschalten
kann, muss man erst einmal das WDRF-Bit gelöscht
haben.  Steht alles im Datenblatt und auch in
der avr-libc-Doku.
Gast #365236
Lesenswert?

Oh, das ist gut zu wissen danke. Ich nehme an, dass dies beim mega32
noch nicht der Fall ist, es klappt nämlich auch ohne super. Aber wenn
ich den Code dann hier reinstelle, könnte es Probleme geben..;)
Warscheinlich bezieht sich das auf die neueren mega48/88/2650 usw(?)
Dann werde ich das dann berücksichtigen :-)

Habs nun noch genau gemessen : 8.4kb/sek sind möglich, ist aber
wahrscheinlich deshalb so 'lahm' weil ich in ein UDP packet jeweils
nur eine Page reinpacke, lässt sich vielleicht noch optimieren.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren