Forum: Compiler & IDEs Bootloader Codevision


von Daniel (Gast)


Lesenswert?

Hallo,
seit einigen Tagen versuche ich einen Bootloader in Codevision zu 
programmieren.
Folgende Routine habe ich geschrieben
1
#include <mega16.h>
2
// Standard Input/Output functions
3
#define RXC         = 7;
4
#define SPMEM       = 0;
5
#define PGERS       = 1:
6
#define RWWSRE      = 4;
7
flash unsigned char PAGESIZE    = 64;         //Pagegröße in word -> 128Byte
8
flash unsigned char SITESIZE    = 128;        //Anzahl der Seiten -> 128Seiten * 128 Byte    
9
flash unsigned char DeviceID    = 16;
10
flash unsigned char PAGE_OK     = 1;
11
flash unsigned char PAGE_FALSE  = 0;
12
flash unsigned int  PageAdress  = 0x0200;
13
 
14
15
#pragma regalloc-        /* Deaktivierung der automatischen Vergabe von Adressen an Variablen*/
16
register unsigned int    daten               @0x0002;
17
register unsigned int    SiteAdress          @0x0004;
18
register unsigned int    CurrentAdress       @0x0006;
19
unsigned char            recbyte             @0x0062;
20
unsigned int             SendSite            @0x0064; 
21
unsigned int             i                   @0x0066;
22
unsigned int             j                   @0x0068;
23
unsigned char            PAGE_BUFFER[128]    @0x008A;
24
#pragma regalloc+        /* Aktivierung der automatischen Vergabe von Adressen an Variablen*/
25
26
27
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
28
void BOOTLOAD(void);
29
void READ_COM_2_PUFFER(void);
30
void RAM_2_TEMP_PAGE(void);
31
void PAGE_ERASE(void);
32
void REENABLE_RWW(void);
33
void PAGE_WRITE(void);
34
void DO_SPM(void);
35
void RESTORE_ZPOINTER(void);
36
                    
37
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
38
// Get a character from the USART1 Receiver
39
char getchar(void)
40
{
41
     unsigned char data;
42
     while ( (UCSRA & 0x80)==0x00 );//0->keine Daten zum Lesen vorhanden 1->Daten bereit zum Lesen
43
     data=UDR;
44
     return data;
45
}
46
47
// Write a character to the USART1 Transmitter
48
void putchar(char c)
49
{
50
     while ( (UCSRA & 0x20)==0x00 );//0->Daten vorhanden zum senden 1->Frei zum Senden
51
     UDR=c;
52
}
53
54
//M A I N ++++++++++++++++++++++++++++++++++++++++++++++
55
void main(void)
56
{
57
//INIT USART
58
     UCSRB=0x18;
59
     UCSRC=0x86;
60
     UBRRL=0x17;
61
//##########
62
     i=0;
63
//Sende Startzeichen
64
     putchar(0x01);
65
//Warte um Daten zu empfangen - i>65000->Timeout führe Programm aus
66
     while ( ((UCSRA & 0x80)==0) & (i<65000) )i++;
67
     if (i<65000) 
68
     {
69
          recbyte=getchar();
70
          if(recbyte==0x02)BOOTLOAD();
71
     }
72
     #asm("jmp 0x00");   //Springe zur an Adresse0x00
73
}
74
75
void BOOTLOAD(void)
76
{
77
     putchar(DeviceID);
78
     i = 0;
79
//Warte um Daten zu empfangen - i->Timeout führe Programm aus
80
     while ( ((UCSRA&0x80)==0) & (i<65000) ) i++;
81
     if (i<65000)
82
     {    
83
         SendSite=getchar();
84
         for(SiteAdress=0; SiteAdress<=SendSite; SiteAdress++)
85
         {
86
         //Z-Pointer auf Adresse abstimmen
87
                    CurrentAdress = SiteAdress * (1<<6) + PageAdress;
88
         //Page löschen           
89
                    PAGE_ERASE();
90
         //Reaktivierung des RWW-Bereichs
91
                    REENABLE_RWW();
92
         //Daten aus serielle Schnittstelle lesen und in Array speichern
93
                    READ_COM_2_PUFFER();
94
         //Von Array in temporären Pagespeicher speichern       
95
                    RAM_2_TEMP_PAGE();
96
         //Page schreiben
97
                    PAGE_WRITE();
98
         //Reaktivierung des RWW-Bereichs
99
                    REENABLE_RWW();
100
                    //von temp Page nach Flash seitenweise kopieren
101
                    //Rückmelung an HOST, dass PAGE erfolgreich kopiert wurde und soll wenn i<SEND
102
/*                    if(SiteAdress<SendSite)
103
                    {    
104
                         putchar(0xFE);
105
                         while(!(UCSRA&0x80));
106
                         recbyte=getchar();
107
                         if(recbyte==1)SendSite++;
108
                    }
109
 */        }
110
     }
111
     putchar(0xFF);
112
}
113
void READ_COM_2_PUFFER(void)
114
{
115
     //Bereit zum Empfangen
116
     putchar(0x03);
117
     for(j=0;j<(PAGESIZE*2);j++)PAGE_BUFFER[j]=getchar();
118
}
119
120
121
void PAGE_ERASE(void)
122
{
123
     //Löscht Page die in PAGE-Adresse des Z-Pointer(Z6...Z12) steht 
124
     #asm   
125
          movw r30,r6;
126
          ldi  r17,0x03;
127
     #endasm     
128
     DO_SPM();
129
}
130
131
void REENABLE_RWW(void)
132
{
133
     #asm("ldi r17,0x11");
134
     DO_SPM();
135
136
}
137
138
139
void RAM_2_TEMP_PAGE(void)
140
{
141
     unsigned char n;
142
     for(n=0;n<128;n+=2)
143
     {    
144
          daten=PAGE_BUFFER[j]+256*PAGE_BUFFER[j+1];   //schreibt wort in registerpar r3+r2
145
          #asm("movw r0,r2");                             //kopiert wert r3+r2 in r1+r0
146
          DO_SPM();
147
          #asm("adiw r31:r30,2");                             //kopiert wert r3+r2 in r1+r0
148
     }
149
     
150
     
151
}
152
153
void PAGE_WRITE(void)
154
{
155
     #asm
156
          movw r30,r6;
157
          ldi r17,0x05;
158
     #endasm
159
     DO_SPM();
160
}
161
162
163
void DO_SPM(void)
164
{
165
     #asm
166
     WAIT_SPM:
167
          in   r16,0x37;           //SPMCR in Register r16 einlesen
168
          sbrc r16,0x01;           //Skip if Bit in Register is Cleared
169
          rjmp WAIT_SPM;
170
          out  0x37,r17;           //schreibe in SPMCR-Register und führe aus
171
          spm;
172
     #endasm
173
}

Programmblauf:
1. Atmega16 sendet "0x01" als Startzeichen
2. Terminalprogramm antwortet mit "0x02"
3. ATmega16 sendet "0x16" als DeviceID
4. Terminalprogramm sendet Anzahl der Seiten die übertragen werden 
sollen
5. Atmega16 löscht aktuelle Page gibt RWW bereich wieder frei und sendet 
"0x03" um Daten zu empfangen.
6. Terminalprogramm sendet 128 Bytes
7. Atmega16 empfängt die 128 Bytes und legt diese in SRAM 
(PAGE_PUFFER[128]) ab
8. Atmega16 schreibt Daten aus SRAM(PAGE_PUFFER[128]) in einen internen 
temporäre PAGE-Puffer
9. Page wird geschrieben
10.RWW bereich wird wieder frei gegeben
11. Programmende

Das Programm läuft auch so ab. Doch wenn ich mir den Flash auslese, sehe 
ich, ausser dem Bootloaderprogramm ab Adress 0x1C00, das nichts in den 
FLASH geschrieben wurde.´

Kann jemand mit Bootloadererfahrung mal über meinen Code schauen? 
Vielleicht mache ich etwas Grundsätzliches falsch.

von kosmonaut_pirx (Gast)


Lesenswert?

hallo,
na muss man nicht den temporären puffer des atmega's füllen? da war bzw. 
ist doch etwas mehr am SPMCR zu drehen, als nur ein Standard-muster zu 
schreiben.
iirc gibt es unterschiedliche belegungen des SPMCR für pageload, page 
erase und page write. du mal einfach in der doku nachschauen.
bye kosmo

von kosmonaut_pirx (Gast)


Lesenswert?

außer beim pageload machst du das auch. nur dort vermisse ich das 
setting, oder ich hab's übersehen.

von Daniel (Gast)


Lesenswert?

ich setzte in den Funktionen mit ldi r17,0x__ den SPMCR und mit der 
Unterfunktion DO_SPM wird r17 nach SPMCR übertragen und mit Befehl spm 
ausgeführt. Aber vorher wird geprüft ob er bereit ist eine neue 
spm-funktion auszuführen
Gruß

von kosmonaut_pirx (Gast)


Lesenswert?

ja, schon gesehen.

hier aber nicht:
1
void RAM_2_TEMP_PAGE(void)
2
{
3
     unsigned char n;
4
     for(n=0;n<128;n+=2)
5
     {    
6
          daten=PAGE_BUFFER[j]+256*PAGE_BUFFER[j+1];   //schreibt wort in registerpar r3+r2
7
          #asm("movw r0,r2");                             //kopiert wert r3+r2 in r1+r0
8
          DO_SPM();
9
          #asm("adiw r31:r30,2");                             //kopiert wert r3+r2 in r1+r0
10
     }
11
}

von Daniel (Gast)


Lesenswert?

danke, für den Hinweis.
Da war noch ein Fehlrer mit der Laufvariablen drin
1
void RAM_2_TEMP_PAGE(void)
2
{
3
     for(j=0;j<128;j++)
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");
8
          DO_SPM();
9
          #asm("adiw r31:r30,2");                             //Addiert +2 in Z-Register-> Pageadresse
10
     }  
11
}

von Daniel (Gast)


Lesenswert?

Schaue ich mir nun den kompilierten ASM-Text an sehe ich bei gleicher 
Funktion "void RAM_2_TEMP_PUFFER(void)" folgenden ASM-CODE
1
_RAM_2_TEMP_PAGE:
2
;     175      for(j=0;j<128;j++)
3
  LDI  R30,0
4
  STS  _j,R30
5
  STS  _j+1,R30
6
_0x1A:
7
  LDS  R26,_j
8
  LDS  R27,_j+1
9
  CPI  R26,LOW(0x80)
10
  LDI  R30,HIGH(0x80)
11
  CPC  R27,R30
12
  BRSH _0x1B
13
;     176      {
14
;     177           daten=PAGE_BUFFER[j]+256*PAGE_BUFFER[j+1];   //schreibt wort in registerpar r3+r2
15
  CALL SUBOPT_0x3
16
  SUBI R30,LOW(-_PAGE_BUFFER)
17
  SBCI R31,HIGH(-_PAGE_BUFFER)
18
  LD   R30,Z
19
  MOV  R26,R30
20
  CALL SUBOPT_0x3
21
  __ADDW1MN _PAGE_BUFFER,1
22
  LD   R30,Z
23
  MOV  R31,R30
24
  LDI  R30,0
25
  LDI  R27,0
26
  ADD  R30,R26
27
  ADC  R31,R27
28
  MOVW R2,R30
29
;     178           #asm("movw r0,r2");                             //kopiert wert r3+r2 in r1+r0
30
  movw r0,r2
31
;     179           #asm("ldi r17,0x01");
32
  ldi r17,0x01
33
;     180           DO_SPM();
34
  CALL _DO_SPM
35
;     181           #asm("adiw r31:r30,2");                             //kopiert wert r3+r2 in r1+r0
36
  adiw r31:r30,2
37
;     182      }
38
  CALL SUBOPT_0x4
39
  JMP  _0x1A
40
_0x1B:
41
;     183 
42
;     184 
43
;     185 }
44
  RET

Liegt es vieleicht daran das hier z.b. in der ersten ASM-Zeile das 
Register r30 mit "0" beschrieben wird?
r30 und r31 sind doch meine Page- sowie Siteadesse.

von kosmonaut_pirx (Gast)


Lesenswert?

zugegeben, ich weiß nicht, warum du das
1
;        181           #asm("adiw r31:r30,2");                             //kopiert wert r3+r2 in r1+r0

aus dem hut zauberst. für das page load brauchst du nur einen index in 
den temporären puffer, also quasi dein 'j' << 1

deine page-adresse (CurrentAddress) brauchst du dann beim schreiben.
cmiiw.

von Daniel (Gast)


Lesenswert?

Hallo kosmonaut_pirx,
danke erstmal für deine Hilfe.
Es funktioniert, ich kann eine Seite übertragen und in den Flash 
schreiben.
Nur habe ich bei der Übertragung einen Fehler.
Ich übergebe
1
01 02 03 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
3
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0F EF 04 BB 01 E1 05 BB FF CF
4
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

und erhalte
1
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
3
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0F EF 04 BB 01 E1 05 BB FF CF 00 00
4
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF

von kosmonaut pirx (Gast)


Lesenswert?

hallo,
scheint ja vorwärts zu gehen.
du bist irgendwie eine adresse zu früh dran im temp-buffer. schreib 
nochmal deinen derzeitigen "c"-code, wenn's nicht zuviel aufwand ist. 
fällt schwer, den aktuellen stand im auge zu behalten.
bye kosmo

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.