www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATmega168 Bootloader


Important announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Jürgen (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hallo,

ich versuche gerade, diesen Bootloader

http://www.mikrocontroller.net/articles/AVR_Bootlo...

auf meinem ATmega168 zum Laufen zu bringen.
Ich hänge allerdings schon am "Hallo Welt" - Bootloader fest. Dieser 
funktioniert zwar einigermaßen, wenn ich ihn an Adresse 0x0000 schreibe, 
aber wenn ich ihn an die Bootloader-Adresse 0x3800(mithilfe der 
Linker-Option     -Ttext=0x3800) schreibe, passiert nichts.
Hier nochmal der Code:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/boot.h>
#include <util/delay.h>
#include "uart.h"
 #ifndef F_CPU
#define F_CPU 20000000UL
#endif
#define BOOT_UART_BAUD_RATE     9600     /* Baudrate */
#define XON                     17       /* XON Zeichen */
#define XOFF                    19       /* XOFF Zeichen */
 
int main()
{
    unsigned int   c=0;               /* Empfangenes Zeichen + Statuscode */
    unsigned char  temp,              /* Variable */
                        flag=1,            /* Flag zum steuern der Endlosschleife */
      p_mode=0;     /* Flag zum steuern des Programmiermodus */
    void (*start)( void ) = 0x0000;        /* Funktionspointer auf 0x0000 */
 
    /* Interrupt Vektoren verbiegen */
 
    char sregtemp = SREG;
    cli();
    temp = MCUCR;
    MCUCR = temp | (1<<IVCE);
    MCUCR = temp | (1<<IVSEL);
    SREG = sregtemp;
 
    /* Einstellen der Baudrate und aktivieren der Interrupts */
    uart_init( UART_BAUD_SELECT(BOOT_UART_BAUD_RATE,F_CPU) ); 
    sei();
 
    uart_puts("Hallo hier ist der Bootloader\n\r");
    _delay_ms(1000);
 
    do
    {
        c = uart_getc();
        if( !(c & UART_NO_DATA) )
        {
            switch((unsigned char)c)
            {
                 case 'q': 
         flag=0;
                     uart_puts("Verlasse den Bootloader!\n\r");
                     break;
                  default:
                     uart_puts("Du hast folgendes Zeichen gesendet: ");
                     uart_putc((unsigned char)c);
                     uart_puts("\n\r");
                     break;
            }
        }
    }
    while(flag);
 
    uart_puts("Springe zur Adresse 0x0000!\n\r");
    _delay_ms(1000);
 
    /* vor Rücksprung eventuell benutzte Hardware deaktivieren
       und Interrupts global deaktivieren, da kein "echter" Reset erfolgt */
 
    /* Interrupt Vektoren wieder gerade biegen */
    cli();
    temp = MCUCR;
    MCUCR = temp | (1<<IVCE);
    MCUCR = temp & ~(1<<IVSEL);
 
    /* Rücksprung zur Adresse 0x0000 */
    start(); 
    return 0;
}
Hat jemand ne Idee was ich falsch machen könnte?

Gruß Jürgen

Autor: Tom M. (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Wie hast du denn die Fuses gesetzt?

Autor: Jürgen (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Da hab ich folgendes:

low 0xEF
high 0xDF
extended 0xF8

Autor: Stefan Ernst (sternst)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Mit welcher Optimierungs-Einstellung kompiliert?

Autor: Thomas Eckmann (Firma: Thomas Eckmann Informationst.) (thomase)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Jürgen schrieb:
> wenn ich ihn an die Bootloader-Adresse 0x3800(mithilfe der
>
> Linker-Option     -Ttext=0x3800)
Wo trägst du die denn ein?
Im Makefile wäre das so richtig.
In die AVR-Studio-Options kommt die Wordadresse:
0x3800 / 2 = 0x1c00

mfg.

Autor: Jürgen (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Ich benutze die Optimierungseinstellung -Os und ich setze in den 
AVR-Studio options die Linker option -Ttext=0x3800, sodass dann im 
Makefile folgendes  erscheint:
## Linker flags
LDFLAGS = $(COMMON)
LDFLAGS +=  -Ttext=0x3800  -Wl,-Map=BootloaderTest.map

Autor: Jürgen (Gast)
Datum:
Angehängte Dateien:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Ich hab hier nochmal den Assemblercode dazu!

Autor: Tom M. (tomm) Benutzerseite
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Schau mal ins Hexfile, sind dort die Adressen 0x38xx sichtbar? Die 
zweite Zeile sollte etwa mit :1003800 beginnen.

Setzt du F_CPU richtig? Sonst ist die Baudrate total verwurstelt...

Autor: Jürgen (Gast)
Datum:
Angehängte Dateien:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Im Hex file beginnt die 2. Zeile mit :103810000C945...
Die F_CPU sollte richtig sein, da ich von der seriellen Schnittstelle 
einwandfreie Zeichenketten bekomme wenn ich das Programm nicht im 
Boot-Bereich starte.
Ich habe jetzt mithilfe der StatusLED herausgefunden, dass der 
Mikrocontroller in uart.c hängen bleibt. Ich verwende die 
Implementierung der seriellen Schnittstelle von Peter Fluery(siehe 
Anhang). An der durch den Pfeil markierten Stelle läuft das Programm nun 
nicht weiter:
void uart_putc(unsigned char data)
{
    unsigned char tmphead;

    
    tmphead  = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
    
    while ( tmphead == UART_TxTail ){
        ;/* wait for free space in buffer */
    }
    
    UART_TxBuf[tmphead] = data;
    UART_TxHead = tmphead;

    /* enable UDRE interrupt */
----->   UART0_CONTROL    |= _BV(UART0_UDRIE);
  

}/* uart_putc */

Autor: Tom M. (tomm) Benutzerseite
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Hmm sieht für mich alles ok aus. Vielleicht fällt ja jmd anders was auf?

Der Passus aus der uart.c passt (ich wundere mich, dass der Compiler 
hier das Z-Register verwendet, wo ein lds/ori/sts genügt):
+00001D6E:   ECE1        LDI       R30,0xC1       Load immediate
+00001D6F:   E0F0        LDI       R31,0x00       Load immediate
+00001D70:   8180        LDD       R24,Z+0        Load indirect with displacement
+00001D71:   6280        ORI       R24,0x20       Logical OR with immediate
+00001D72:   8380        STD       Z+0,R24        Store indirect with displacement
+00001D73:   9508        RET                      Subroutine return


In deiner "boot.txt" sieht die Vektoren-Tabelle okay aus; zumindest sind 
Rx complete und DRE umgesetzt:
+00001C24:   940C1CC9    JMP       0x00001CC9     Jump // USART Rx complete
+00001C26:   940C1CF9    JMP       0x00001CF9     Jump // USART Data Register Empty
+00001C28:   940C1C51    JMP       0x00001C51     Jump // USART Tx Complete

Das Verschieben der Tabelle erfüllt auch die Bedingung, dass das Setzen 
von IVCE und IVSEL innerhalb von 4 Zyklen (gem. Wiki-Aritkel) geschehen 
muss. Stack wird auch für den 168er passend gesetzt (0x4FF), deswegen 
knallt's auch nicht. Auch hier fällt mir wieder die Verwendung des Z 
Registers auf, mein Compiler macht das anders (avr-gcc 4.3.3).

Hab mal den C Code reingemischt:

    char sregtemp = SREG;

+00001C6B:   B72F        IN        R18,0x3F       In from I/O location

    cli();

+00001C6C:   94F8        CLI                      Global Interrupt Disable

    temp = MCUCR;

+00001C6D:   E5E5        LDI       R30,0x55       Load immediate
+00001C6E:   E0F0        LDI       R31,0x00       Load immediate
+00001C6F:   8180        LDD       R24,Z+0        Load indirect with displacement
+00001C70:   2F98        MOV       R25,R24        Copy register

    MCUCR = temp | (1<<IVCE);

+00001C71:   6091        ORI       R25,0x01       Logical OR with immediate
+00001C72:   8390        STD       Z+0,R25        Store indirect with displacement

    MCUCR = temp | (1<<IVSEL);

+00001C73:   6082        ORI       R24,0x02       Logical OR with immediate
+00001C74:   8380        STD       Z+0,R24        Store indirect with displacement

    SREG = sregtemp;

+00001C75:   BF2F        OUT       0x3F,R18       Out to I/O location

Autor: Stefan Ernst (sternst)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Tom M. schrieb:
> Hmm sieht für mich alles ok aus. Vielleicht fällt ja jmd anders was auf?

Ich bezweifle, dass das Disassembly tatsächlich von obigen Source-Code 
stammt, denn dieser Teil
    uart_init( UART_BAUD_SELECT(BOOT_UART_BAUD_RATE,F_CPU) ); 
    sei();
 
    uart_puts("Hallo hier ist der Bootloader\n\r");
    _delay_ms(1000);
ist dort doppelt drin, und zwar vor und nach dem Verschieben der 
Vektoren. Und das vor dem Verschieben ist natürlich tötlich.

Tom M. schrieb:
> Der Passus aus der uart.c passt (ich wundere mich, dass der Compiler
> hier das Z-Register verwendet, wo ein lds/ori/sts genügt):

Was mich ebenfalls an dem -Os zweifeln lässt.

Autor: Jürgen (Gast)
Datum:
Angehängte Dateien:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
So ich habe festgestellt, dass das Disassembly tatsächlich nicht das 
richtige war, denn der Teil
uart_init( UART_BAUD_SELECT(BOOT_UART_BAUD_RATE,F_CPU) ); 
sei();

uart_puts("Hallo hier ist der Bootloader\n\r");
_delay_ms(1000);

erscheint wie bereits erwähnt 2 mal. Diesen hatte ich zu Debugzwecken an 
der Anfang geschoben. Ich habe hier nun nochmal das richtige file, 
kompiliert mit -Os, das genausowenig funktioniert.

Autor: Jürgen (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht lesenswert
Also ich habe mittlerweile eine andere Implementierung für sie serielle 
Kommunikation genommen und jetzt klappt auch fast alles, nur das ich 
scheinbar nicht in den Flash speicher schreiben kann. Ich benutze die 
Funktion
 void boot_program_page (uint32_t page, uint8_t *buf)
aus dem Bootloader Tutorial(s.o). Ich habe testweise einfach mal 
versucht, irgendetwas an den Anfang des Speichers zu schreiben:
for (int i = 0; i < SPM_PAGESIZE; i++)
  {
    flash_data[i] = 0x01;
  }
  boot_page_erase (64);
  program_page((uint16_t)0, flash_data);
Jedoch ohne Erfolg. Hat vielleicht jemand eine Idee?

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




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 erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net