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
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
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?
>"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
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 :-(
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
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
wie wär es denn mit typedef void (*funct)(void); und dann zum springen an eine adresse ((funct)0x3800)();
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
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
>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
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
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... ;)
ja genau, hast du richtig verstanden ;) Bye, Simon
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.