Forum: Compiler & IDEs mega32 bootloader(linkt der linker hier korrekt?)


von Nik Bamert (Gast)


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

von Ssss S. (sssssss)


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

von Nik Bamert (Gast)


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?

von Ssss S. (sssssss)


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

von Nik Bamert (Gast)


Angehängte Dateien:

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 :-(

von Ssss S. (sssssss)


Lesenswert?

häh ?! Das fängt doch bei 0x3800 an ??
:103800000C942A1C0C94451C0C94451C0C94451CCF
:103810000C94451C0C94451C0C94451C0C94451CA4
:103820000C94451C0C94451C0C94451C0C94451C94
...

mal hervorgehoben:
:10_3800_000C942A1C0C94451C0C94451C0C94451CCF

http://www.keil.com/support/docs/1584.htm

Bye, Simon

von Nik Bamert (Gast)


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

von Ssss S. (sssssss)


Lesenswert?

:)

von Lokko (Gast)


Lesenswert?

wie wär es denn mit

typedef void (*funct)(void);

und dann zum springen an eine adresse

((funct)0x3800)();

von Werner XYZ (Gast)


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

von Nik Bamert (Gast)


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

von Ssss S. (sssssss)


Lesenswert?

>watchdog braucht man da irgendwie damit alles klar geht hab ich
gelesen(?)

jo geht ganz einfach:
1
watchdog_enable();
2
3
while(1){
4
}
wobei ich grad nicht ausm kopf weiss wie beim avrgcc die wdt
einschaltfunktion is ;)

Bye, Simon

von Nik Bamert (Gast)


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

von Nik Bamert (Gast)


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... ;)

von Ssss S. (sssssss)


Lesenswert?

ja genau, hast du richtig verstanden ;)

Bye, Simon

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Nik Bamert (Gast)


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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ja, alles ab ATmega48 hat den neuen Watchdog.

Äußerlich gut erkennbares Merkmal: der Watchdog kann auch einen
Interrupt auslösen.

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
Noch kein Account? Hier anmelden.