Hallo, ich bin gerade bei mich durch den Artikel: http://www.mikrocontroller.net/articles/AVR_Bootloader_in_C_-_eine_einfache_Anleitung zu arbeiten Die 2 ersten Punkte: Der "Hallo Welt" - Bootloader Die Test-Anwendung habe ich bereits geschaft. Nun hänge ich aber etwas planlos an dem Punkt: "Um in den Flash zu schreiben, werden wir Makros aus der boot.h der avr-libc verwenden. Hier findet man alle Werkzeuge, die wir brauchen" Ich programmiere mit CodeVisionAVR, und müsste jetzt irgendwo wahrscheinlich die beschriebene avr-libc herunterladen und einbinden. Aber wo bekomme ich diese her, und wie bindet man sie richtig ein. Lässt sich die avr-libc den überhaupt so einfach in CodeVision verwenden? Danke für alle hilfreichen Tipps. mfg Mark
Das wird ein Problem. Die avr-libs ist für die Verwendung mit gcc gedacht, nicht für Codevision. In dem Artikel wird ja auch ausdrücklich auf die nötige Software verwiesen: Zitat: Für den Artikel werden folgende Software-Pakete benötigt: aktuelles AVR Studio (hier verwendet: AVR Studio v4.18) aktuelles WinAVR (hier verwendet: WinAVR20100110) PuTTY als serielle Konsole (Version v0.6) Nix von Codevision zu sehen.
Danke für die Information, dies war mir bewusst. Nichts desto trotz würde ich gerne mich mit dem Thema Bootloader und Codevision beschäftigen. Und irgendwo muss man ja anfangen. Ich dachte mir vielleicht wenn ich die entsprechenden Dateien finde. (boot.h und boot.c) könnte man diese ja an die Codevision Besonderheiten anpassen? mfg Mark
> Und irgendwo muss man ja anfangen.
Besser nicht "irgendwo" anfangen, besonders nicht mit einem Text der
sich auf gcc und avr-libc bezieht und dann Codevision verwenden.
Theoretisch ist es sicherlich möglich, die avr-libc auf Codevision zu
portieren. Es wäre günstig zu wissen, wieviele und welche Erfahrungen Du
in C, in der Portierung von Code zwischen Compilern und in der
Programmierung allgemein hast. Unter ein paar Jahren kannst Du das,
denke ich, nicht leisten.
Die Alternative wäre mal mit Google und den Stichworten "Codevision
Bootloader" zu suchen.
schade, )-: dann ist hier wohl eher Schluss für mich. Aber wenigstens hat das mit den hin und her springen zwischen den 2 Programmen geklappt. (-:
> dann ist hier wohl eher Schluss für mich.
Nicht unbedingt. Nur solltest Du spezifischer fragen. Ein "Kochrezept"
gibt es hier eben nur in Bezug auf gcc und avrlibc.
Problem ist, das Deine Vorkenntnisse nicht einzuschätzen sind und Deine
anderen Fragen hier darauf hindeuten, das Du Kochrezepte brauchst und
wenig Vorkenntnisse hast. Dann würde man eigentlich erwarten, das Du
Google benutzt und mit spezifischen Fragen kommst, aber das geschah auch
nicht.
Es bleibt also eine Rundumfrage à la "Wie kriege ich die Beispiele für
avr-libc | gcc unter Codevision zum laufen und das erfordert doch schon
einiges an Vorwissen und Erfahrungen insbesondere mit den Erweiterungen
von gcc und Codevision das man Dir hier nicht in zwei Sätzen vermitteln
kann.
Du wirst Dich intensiv in gcc, codevision, avr-libc und Bootloader
einarbeiten müssen. Dabei helfen wir Dir gerne, aber wiegesagt,
vorzugsweise bei spezifischen Fragen.
@Mark, hast Du schon mal auf der hpinfotech Seite geschaut? Da sind ja auch bootloader portierungen (download). IF
Hallo Mark, nun werfe nicht gleich die Flinte ins Korn (Ich habe den Artikel geschrieben). Die die avr-libc opensource ist, kannst du dir die Makros auch anschauen. In der Doku der Lib ist genau beschrieben was die Markos machen, schau mal hier: http://www.nongnu.org/avr-libc/user-manual/group__avr__boot.html Es sollte kein Problem sein, dieses Markos/Funktionen und CodeVision nachzubauen. Evtl. kann auch ein Studium des Datenblatts des Controllers helfen :) Poste mal eine Lösung wenn du hast :)
Hallo, versuche gerade als erster die Funktion: "#define boot_page_erase ( address ) __boot_page_erase_normal(address) Erase the flash page that contains address." umzusetzen. Nach einigen Rescherschen im Datenblatt und hier im Forum hab ich folgendes geschafft.
1 | register unsigned int CurrentAdress @0x0006; //CurrentAdress in Register 6 speichern |
2 | |
3 | void DO_SPM(void) |
4 | {
|
5 | #asm
|
6 | WAIT_SPM:
|
7 | in r16,0x37; //SPMCR in Register r16 einlesen 37= Address von SPMCR, passt für ATmega32 |
8 | sbrc r16,0x01; //Skip if Bit in Register is Cleared |
9 | rjmp WAIT_SPM; |
10 | out 0x37,r17; //schreibe in SPMCR-Register und führe aus |
11 | spm; |
12 | #endasm
|
13 | }
|
14 | |
15 | void PAGE_ERASE(unsigned int adress) |
16 | {
|
17 | |
18 | CurrentAdress = adress; |
19 | //Löscht Page die in PAGE-Adresse des Z-Pointer(Z6...Z12) steht
|
20 | #asm
|
21 | movw r30,r6; //move CurrentAddress to Z pointer |
22 | ldi r17,0x03; //Bit 0 – SPMEN: Store Program Memory Enable, Bit 1 – PGERS: Page Erase |
23 | #endasm
|
24 | DO_SPM(); |
25 | }
|
26 | |
27 | |
28 | |
29 | |
30 | //Aufruf im Hauptprogramm
|
31 | PAGE_ERASE(0x00); |
Wie "Bild1" im Anhang zeigt löscht er mir auch die ersten 128 Bytes also die erste Page. Jetzt möchte ich als nächsten Test aber versuchen die 2te Page zu löschen. Welche Adresse muss ich den hierfür vorgeben? Irgendwie löscht er mir bis jetzt immer nur die erste Page.
ok einfach 0x80 vorgeben. also 128. Das dürfte doch nun die gleiche Funktion sein wie die Funktion: "boot_page_erase" aus der avr-libc oder?
Hallo die Herren, hätte mal zwischendurch eine Verständnisfrage: Auszug aus einer HEX.Datei: :040000000C946800F4 :100004000C9400000C9400000C9400000C9400006C :100014000C9400000C9400000C9400000C9400005C :100024000C9400000C9400000C9400000C9400004C :100034000C9486000C9400000C94B8000C940000FE :100044000C9400000C9400000C9400000C9400002C = :04an 0000adr 00ty 0C 94 68 00 F4Pr :10an 0004adr 00ty 0C 94 00 00 0C 94 00 00 0C 94 00 00 0C 94 00 00 6CPr :10an 0014adr 00ty 0C 94 00 00 0C 94 00 00 0C 94 00 00 0C 94 00 00 5CPr :10an 0024adr 00ty 0C 94 00 00 0C 94 00 00 0C 94 00 00 0C 94 00 00 4CPr :10an 0034adr 00ty 0C 94 86 00 0C 94 00 00 0C 94 B8 00 0C 94 00 00 FEPr :10an 0044adr 00ty 0C 94 00 00 0C 94 00 00 0C 94 00 00 0C 94 00 00 2CPr :10an 0054adr 00ty 10 27 E8 03 64 00 0A 00 01 00 00 10 00 01 10 00 EAPr :10an 0064adr 00ty 01 00 0A 0D 48 69 65 72 20 69 73 74 20 64 61 73 24Pr ist dann folgende befüllung eines PAGE_BUFFERs korrekt?
1 | unsigned char PAGESIZE = 64; |
2 | unsigned char PAGE_BUFFER[PAGESIZE*2] @0x008A; |
3 | |
4 | PAGE_BUFFER[0]=0x0C; |
5 | PAGE_BUFFER[1]=0x94; |
6 | PAGE_BUFFER[2]=0x68; |
7 | PAGE_BUFFER[3]=0x0C; |
8 | PAGE_BUFFER[4]=0x94; |
9 | PAGE_BUFFER[5]=0x00; |
10 | PAGE_BUFFER[6]=0x00; |
11 | //usw.
|
???
ach ne, hier stimmt was nicht. Irgentwie verwirren mich die ganzen word Byte hex und dec und bin Formate gerade etwas.
So nochmals eine Zusammenfassung des derzeitigen Standes: Ausgangszustand des Flash: siehe Bild0 Beim Empfang des Zeichens "l" soll die erste Page gelöscht werden: i.0. siehe Bild1 Beim Empfang des Zeichens "w" soll die erste Page wieder mit dem PAGE_BUFFER beschreiben werden. (Den PAGE_BUFFER steht erstweils noch fix im Code): n.i.O siehe Bild2 Könnte vielleicht wer von euch mal über den Code schauen und mir Tipps geben woran außer meiner Unfähigkeit es scheitert. Danke
1 | void REENABLE_RWW(void); |
2 | void DO_SPM(void); |
3 | void PAGE_ERASE(unsigned int); |
4 | void READ_COM_2_PUFFER(void); |
5 | void RAM_2_TEMP_PAGE(void); |
6 | void PAGE_WRITE(void); |
7 | |
8 | #pragma regalloc- /* Deaktivierung der automatischen Vergabe von Adressen an Variablen*/ |
9 | register unsigned int daten @0x0002; |
10 | register unsigned int CurrentAdress @0x0006; //CurrentAdress in Register 6 speichern |
11 | unsigned int j @0x0068; |
12 | unsigned char PAGE_BUFFER[128] @0x008A; |
13 | #pragma regalloc+ /* Aktivierung der automatischen Vergabe von Adressen an Variablen*/ |
14 | |
15 | |
16 | |
17 | void DO_SPM(void) |
18 | {
|
19 | #asm
|
20 | WAIT_SPM:
|
21 | in r16,0x37; //SPMCR in Register r16 einlesen 37= Address von SPMCR, passt für ATmega32 |
22 | sbrc r16,0x01; //Skip if Bit in Register is Cleared |
23 | //The SPMEN bit will auto-clear upon completion of an SPM instruction,
|
24 | //or if no SPM instruction is executed within four clock cycles. During page erase and page write,
|
25 | //the SPMEN bit remains high until the operation is completed.
|
26 | rjmp WAIT_SPM; |
27 | out 0x37,r17; //schreibe in SPMCR-Register und führe aus |
28 | spm; |
29 | #endasm
|
30 | }
|
31 | |
32 | void PAGE_ERASE(unsigned int adress) |
33 | {
|
34 | |
35 | CurrentAdress = adress; |
36 | //Löscht Page die in PAGE-Adresse des Z-Pointer(Z6...Z12) steht
|
37 | #asm
|
38 | movw r30,r6; //move CurrentAddress to Z pointer |
39 | ldi r17,0x03; //Bit 0 – SPMEN: Store Program Memory Enable, Bit 1 – PGERS: Page Erase |
40 | #endasm
|
41 | DO_SPM(); |
42 | }
|
43 | |
44 | |
45 | void REENABLE_RWW(void) |
46 | {
|
47 | #asm("ldi r17,0x11"); //Bit 0 – SPMEN: Store Program Memory Enable, Bit 4 – RWWSRE: Read-While-Write Section Read Enable
|
48 | DO_SPM(); |
49 | }
|
50 | |
51 | |
52 | |
53 | void READ_COM_2_PUFFER(void) |
54 | {
|
55 | //Bereit zum Empfangen
|
56 | printf("\n\rDaten werden empfangen"); |
57 | //for(j=0;j<(PAGESIZE*2);j++)
|
58 | //{
|
59 | // PAGE_BUFFER[j]=getchar();
|
60 | //}
|
61 | |
62 | PAGE_BUFFER[0]=0x0C; |
63 | PAGE_BUFFER[1]=0x94; |
64 | PAGE_BUFFER[2]=0x68; |
65 | PAGE_BUFFER[3]=0x00; //zeile1 |
66 | PAGE_BUFFER[4]=0x0C; |
67 | ...
|
68 | PAGE_BUFFER[127]=0x6F; |
69 | |
70 | }
|
71 | |
72 | |
73 | |
74 | void RAM_2_TEMP_PAGE(void) |
75 | {
|
76 | for(j=0;j<128;j++) |
77 | {
|
78 | daten=PAGE_BUFFER[j]+256*PAGE_BUFFER[j+1]; //schreibt wort in registerpar r3+r2 |
79 | #asm("movw r0,r2"); //kopiert wert r3+r2 in r1+r0
|
80 | #asm("ldi r17,0x01"); //If only SPMEN is written, the following SPM instruction will store the value in R1:R0 in the temporary page buffer addressed by the Z-pointer.
|
81 | DO_SPM(); |
82 | #asm("adiw r31:r30,2"); //Addiert +2 in Z-Register-> Pageadresse
|
83 | }
|
84 | }
|
85 | |
86 | |
87 | void PAGE_WRITE(void) |
88 | {
|
89 | #asm
|
90 | movw r30,r6; //move CurrentAddress to Z pointer |
91 | ldi r17,0x05; //Bit 0 – SPMEN: Store Program Memory Enable, Bit 2 – PGWRT: Page Write |
92 | #endasm
|
93 | DO_SPM(); |
94 | }
|
95 | |
96 | |
97 | |
98 | void main(void) |
99 | {
|
100 | do
|
101 | {
|
102 | if(rx_counter>=1) |
103 | {
|
104 | c = getchar(); |
105 | |
106 | switch((unsigned char)c) |
107 | {
|
108 | case 'q': |
109 | flag=0; |
110 | printf("\n\rVerlasse den Bootloader!"); |
111 | break; |
112 | |
113 | case 'l': |
114 | printf("\n\rLösche Page 0x0004"); |
115 | //Page löschen
|
116 | PAGE_ERASE(0x0); |
117 | //Reaktivierung des RWW-Bereichs
|
118 | REENABLE_RWW(); |
119 | break; |
120 | |
121 | case 'w': |
122 | //Daten aus serielle Schnittstelle lesen und in Array speichern
|
123 | READ_COM_2_PUFFER(); |
124 | //Von Array in temporären Pagespeicher speichern
|
125 | RAM_2_TEMP_PAGE(); |
126 | //Page schreiben
|
127 | PAGE_WRITE(); |
128 | //Reaktivierung des RWW-Bereichs
|
129 | REENABLE_RWW(); |
130 | break; |
131 | |
132 | |
133 | |
134 | default:
|
135 | printf("\n\rDu hast folgendes Zeichen gesendet: "); |
136 | printf("%c",c); |
137 | break; |
138 | }
|
139 | }
|
140 | }
|
Ich denke ich habe einen kleinen Fehler gefunden: j immer um 2 erhöhen, da ja pro Durchlauf ein Wort übergeben wird
1 | void RAM_2_TEMP_PAGE(void) |
2 | {
|
3 | for(j=0;j<128;j+=2) |
4 | {
|
5 | daten=PAGE_BUFFER[j]+256*PAGE_BUFFER[j+1]; //schreibt wort in registerpar r3+r2 |
6 | #asm("movw r0,r2"); //kopiert wert r3+r2 in r1+r0
|
7 | #asm("ldi r17,0x01"); //If only SPMEN is written, the following SPM instruction will store the value in R1:R0 in the temporary page buffer addressed by the Z-pointer.
|
8 | DO_SPM(); //The LSB of the Z-pointer is ignored. |
9 | #asm("adiw r31:r30,2"); //Addiert +2 in Z-Register-> Pageadresse
|
10 | }
|
11 | }
|
leider funktioniert das Schreiben einer Seite trotzdem nicht. )-:
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.