mikrocontroller.net

Forum: Compiler & IDEs Bootloader Codevision


Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
seit einigen Tagen versuche ich einen Bootloader in Codevision zu 
programmieren.
Folgende Routine habe ich geschrieben
#include <mega16.h>
// Standard Input/Output functions
#define RXC         = 7;
#define SPMEM       = 0;
#define PGERS       = 1:
#define RWWSRE      = 4;
flash unsigned char PAGESIZE    = 64;         //Pagegröße in word -> 128Byte
flash unsigned char SITESIZE    = 128;        //Anzahl der Seiten -> 128Seiten * 128 Byte    
flash unsigned char DeviceID    = 16;
flash unsigned char PAGE_OK     = 1;
flash unsigned char PAGE_FALSE  = 0;
flash unsigned int  PageAdress  = 0x0200;
 

#pragma regalloc-        /* Deaktivierung der automatischen Vergabe von Adressen an Variablen*/
register unsigned int    daten               @0x0002;
register unsigned int    SiteAdress          @0x0004;
register unsigned int    CurrentAdress       @0x0006;
unsigned char            recbyte             @0x0062;
unsigned int             SendSite            @0x0064; 
unsigned int             i                   @0x0066;
unsigned int             j                   @0x0068;
unsigned char            PAGE_BUFFER[128]    @0x008A;
#pragma regalloc+        /* Aktivierung der automatischen Vergabe von Adressen an Variablen*/


//+++++++++++++++++++++++++++++++++++++++++++++++++++++
void BOOTLOAD(void);
void READ_COM_2_PUFFER(void);
void RAM_2_TEMP_PAGE(void);
void PAGE_ERASE(void);
void REENABLE_RWW(void);
void PAGE_WRITE(void);
void DO_SPM(void);
void RESTORE_ZPOINTER(void);
                    
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
// Get a character from the USART1 Receiver
char getchar(void)
{
     unsigned char data;
     while ( (UCSRA & 0x80)==0x00 );//0->keine Daten zum Lesen vorhanden 1->Daten bereit zum Lesen
     data=UDR;
     return data;
}

// Write a character to the USART1 Transmitter
void putchar(char c)
{
     while ( (UCSRA & 0x20)==0x00 );//0->Daten vorhanden zum senden 1->Frei zum Senden
     UDR=c;
}

//M A I N ++++++++++++++++++++++++++++++++++++++++++++++
void main(void)
{
//INIT USART
     UCSRB=0x18;
     UCSRC=0x86;
     UBRRL=0x17;
//##########
     i=0;
//Sende Startzeichen
     putchar(0x01);
//Warte um Daten zu empfangen - i>65000->Timeout führe Programm aus
     while ( ((UCSRA & 0x80)==0) & (i<65000) )i++;
     if (i<65000) 
     {
          recbyte=getchar();
          if(recbyte==0x02)BOOTLOAD();
     }
     #asm("jmp 0x00");   //Springe zur an Adresse0x00
}

void BOOTLOAD(void)
{
     putchar(DeviceID);
     i = 0;
//Warte um Daten zu empfangen - i->Timeout führe Programm aus
     while ( ((UCSRA&0x80)==0) & (i<65000) ) i++;
     if (i<65000)
     {    
         SendSite=getchar();
         for(SiteAdress=0; SiteAdress<=SendSite; SiteAdress++)
         {
         //Z-Pointer auf Adresse abstimmen
                    CurrentAdress = SiteAdress * (1<<6) + PageAdress;
         //Page löschen           
                    PAGE_ERASE();
         //Reaktivierung des RWW-Bereichs
                    REENABLE_RWW();
         //Daten aus serielle Schnittstelle lesen und in Array speichern
                    READ_COM_2_PUFFER();
         //Von Array in temporären Pagespeicher speichern       
                    RAM_2_TEMP_PAGE();
         //Page schreiben
                    PAGE_WRITE();
         //Reaktivierung des RWW-Bereichs
                    REENABLE_RWW();
                    //von temp Page nach Flash seitenweise kopieren
                    //Rückmelung an HOST, dass PAGE erfolgreich kopiert wurde und soll wenn i<SEND
/*                    if(SiteAdress<SendSite)
                    {    
                         putchar(0xFE);
                         while(!(UCSRA&0x80));
                         recbyte=getchar();
                         if(recbyte==1)SendSite++;
                    }
 */        }
     }
     putchar(0xFF);
}
void READ_COM_2_PUFFER(void)
{
     //Bereit zum Empfangen
     putchar(0x03);
     for(j=0;j<(PAGESIZE*2);j++)PAGE_BUFFER[j]=getchar();
}


void PAGE_ERASE(void)
{
     //Löscht Page die in PAGE-Adresse des Z-Pointer(Z6...Z12) steht 
     #asm   
          movw r30,r6;
          ldi  r17,0x03;
     #endasm     
     DO_SPM();
}

void REENABLE_RWW(void)
{
     #asm("ldi r17,0x11");
     DO_SPM();

}


void RAM_2_TEMP_PAGE(void)
{
     unsigned char n;
     for(n=0;n<128;n+=2)
     {    
          daten=PAGE_BUFFER[j]+256*PAGE_BUFFER[j+1];   //schreibt wort in registerpar r3+r2
          #asm("movw r0,r2");                             //kopiert wert r3+r2 in r1+r0
          DO_SPM();
          #asm("adiw r31:r30,2");                             //kopiert wert r3+r2 in r1+r0
     }
     
     
}

void PAGE_WRITE(void)
{
     #asm
          movw r30,r6;
          ldi r17,0x05;
     #endasm
     DO_SPM();
}


void DO_SPM(void)
{
     #asm
     WAIT_SPM:
          in   r16,0x37;           //SPMCR in Register r16 einlesen
          sbrc r16,0x01;           //Skip if Bit in Register is Cleared
          rjmp WAIT_SPM;
          out  0x37,r17;           //schreibe in SPMCR-Register und führe aus
          spm;
     #endasm
}

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.

Autor: kosmonaut_pirx (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: kosmonaut_pirx (Gast)
Datum:

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

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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ß

Autor: kosmonaut_pirx (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja, schon gesehen.

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

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke, für den Hinweis.
Da war noch ein Fehlrer mit der Laufvariablen drin
void RAM_2_TEMP_PAGE(void)
{
     for(j=0;j<128;j++)
     {    
          daten=PAGE_BUFFER[j]+256*PAGE_BUFFER[j+1];   //schreibt wort in registerpar r3+r2
          #asm("movw r0,r2");                             //kopiert wert r3+r2 in r1+r0
          #asm("ldi r17,0x01");
          DO_SPM();
          #asm("adiw r31:r30,2");                             //Addiert +2 in Z-Register-> Pageadresse
     }  
}

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schaue ich mir nun den kompilierten ASM-Text an sehe ich bei gleicher 
Funktion "void RAM_2_TEMP_PUFFER(void)" folgenden ASM-CODE
_RAM_2_TEMP_PAGE:
;        175      for(j=0;j<128;j++)
  LDI  R30,0
  STS  _j,R30
  STS  _j+1,R30
_0x1A:
  LDS  R26,_j
  LDS  R27,_j+1
  CPI  R26,LOW(0x80)
  LDI  R30,HIGH(0x80)
  CPC  R27,R30
  BRSH _0x1B
;        176      {
;        177           daten=PAGE_BUFFER[j]+256*PAGE_BUFFER[j+1];   //schreibt wort in registerpar r3+r2
  CALL SUBOPT_0x3
  SUBI R30,LOW(-_PAGE_BUFFER)
  SBCI R31,HIGH(-_PAGE_BUFFER)
  LD   R30,Z
  MOV  R26,R30
  CALL SUBOPT_0x3
  __ADDW1MN _PAGE_BUFFER,1
  LD   R30,Z
  MOV  R31,R30
  LDI  R30,0
  LDI  R27,0
  ADD  R30,R26
  ADC  R31,R27
  MOVW R2,R30
;        178           #asm("movw r0,r2");                             //kopiert wert r3+r2 in r1+r0
  movw r0,r2
;        179           #asm("ldi r17,0x01");
  ldi r17,0x01
;        180           DO_SPM();
  CALL _DO_SPM
;        181           #asm("adiw r31:r30,2");                             //kopiert wert r3+r2 in r1+r0
  adiw r31:r30,2
;        182      }
  CALL SUBOPT_0x4
  JMP  _0x1A
_0x1B:
;        183 
;        184 
;        185 }
  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.

Autor: kosmonaut_pirx (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
zugegeben, ich weiß nicht, warum du das
;        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.

Autor: Daniel (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
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
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
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
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
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
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
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
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

Autor: kosmonaut pirx (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.