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.
> 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.
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
registerunsignedintCurrentAdress@0x0006;//CurrentAdress in Register 6 speichern
2
3
voidDO_SPM(void)
4
{
5
#asm
6
WAIT_SPM:
7
inr16,0x37;//SPMCR in Register r16 einlesen 37= Address von SPMCR, passt für ATmega32
8
sbrcr16,0x01;//Skip if Bit in Register is Cleared
9
rjmpWAIT_SPM;
10
out0x37,r17;//schreibe in SPMCR-Register und führe aus
11
spm;
12
#endasm
13
}
14
15
voidPAGE_ERASE(unsignedintadress)
16
{
17
18
CurrentAdress=adress;
19
//Löscht Page die in PAGE-Adresse des Z-Pointer(Z6...Z12) steht
20
#asm
21
movwr30,r6;//move CurrentAddress to Z pointer
22
ldir17,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.
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
voidREENABLE_RWW(void);
2
voidDO_SPM(void);
3
voidPAGE_ERASE(unsignedint);
4
voidREAD_COM_2_PUFFER(void);
5
voidRAM_2_TEMP_PAGE(void);
6
voidPAGE_WRITE(void);
7
8
#pragma regalloc- /* Deaktivierung der automatischen Vergabe von Adressen an Variablen*/
9
registerunsignedintdaten@0x0002;
10
registerunsignedintCurrentAdress@0x0006;//CurrentAdress in Register 6 speichern
11
unsignedintj@0x0068;
12
unsignedcharPAGE_BUFFER[128]@0x008A;
13
#pragma regalloc+ /* Aktivierung der automatischen Vergabe von Adressen an Variablen*/
14
15
16
17
voidDO_SPM(void)
18
{
19
#asm
20
WAIT_SPM:
21
inr16,0x37;//SPMCR in Register r16 einlesen 37= Address von SPMCR, passt für ATmega32
22
sbrcr16,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
rjmpWAIT_SPM;
27
out0x37,r17;//schreibe in SPMCR-Register und führe aus
28
spm;
29
#endasm
30
}
31
32
voidPAGE_ERASE(unsignedintadress)
33
{
34
35
CurrentAdress=adress;
36
//Löscht Page die in PAGE-Adresse des Z-Pointer(Z6...Z12) steht
37
#asm
38
movwr30,r6;//move CurrentAddress to Z pointer
39
ldir17,0x03;//Bit 0 – SPMEN: Store Program Memory Enable, Bit 1 – PGERS: Page Erase
40
#endasm
41
DO_SPM();
42
}
43
44
45
voidREENABLE_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
voidREAD_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
voidRAM_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
voidPAGE_WRITE(void)
88
{
89
#asm
90
movwr30,r6;//move CurrentAddress to Z pointer
91
ldir17,0x05;//Bit 0 – SPMEN: Store Program Memory Enable, Bit 2 – PGWRT: Page Write
92
#endasm
93
DO_SPM();
94
}
95
96
97
98
voidmain(void)
99
{
100
do
101
{
102
if(rx_counter>=1)
103
{
104
c=getchar();
105
106
switch((unsignedchar)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
Ich denke ich habe einen kleinen Fehler gefunden:
j immer um 2 erhöhen, da ja pro Durchlauf ein Wort übergeben wird
1
voidRAM_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. )-: