Forum: Mikrocontroller und Digitale Elektronik avr-libc, Bootloader, CodeVision


von Mark (Gast)


Lesenswert?

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

von Kali (Gast)


Lesenswert?

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.

von Mark (Gast)


Lesenswert?

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

von Kali (Gast)


Lesenswert?

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

von Mark (Gast)


Lesenswert?

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

von Kali (Gast)


Lesenswert?

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

von Ignatz-Finn (Gast)


Lesenswert?

@Mark,

hast Du schon mal auf der hpinfotech Seite geschaut? Da sind ja auch 
bootloader portierungen (download).

IF

von Mario G. (mario)


Lesenswert?

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

von Mark (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Mark (Gast)


Lesenswert?

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?

von Mark (Gast)


Lesenswert?

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.

???

von Mark (Gast)


Lesenswert?

ach ne, hier stimmt was nicht.
Irgentwie verwirren mich die ganzen word Byte hex und dec und bin 
Formate gerade etwas.

von Mark (Gast)


Angehängte Dateien:

Lesenswert?

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
}

von Mark (Gast)


Lesenswert?

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