Forum: Mikrocontroller und Digitale Elektronik Probleme mit Bootlader


von Andre I. (scuido)


Angehängte Dateien:

Lesenswert?

Hallo,
ich habe scheinbar falsch angefangen zu fragen und da ich den von mir 
erstellten thread nicht löschen kann hier nochmal ein neuanfang mit dem 
gleichen Problem nur nen andren (einfacheren Code), um vielleicht mal 
eine Lösung zu finden.

Das Projekt habe ich als .rar vor AVR-Studio 5 angehängt um es selbst 
simulieren zu können.
(Code ist von 
http://www.mikrocontroller.net/articles/AVR_Bootloader_in_C_-_eine_einfache_Anleitung#Schritt_1_-_Erstellen_des_Projektes)

genutzt wird der Mega644A @ 16Mhz


Folgendes Problem:

Wenn ich den Code einfach so kompiliere und brenne gibt der µC über UART 
Text aus und nimmt auch Befehle an.

Wenn ich nun aber versuche die Interrupts umzuleiten "-Ttext=7000" für 
maximale Größe Bootgröße und BOOTRST aktiviert, funktioniert nix mehr.

Dies passiert auch, wenn ich nur die Optimierung auf "-O1" stelle, ohne 
das umleiten mit -Ttext.

Woran mag das liegen?

1
/*
2
 * Bootlader_644.c
3
 *
4
 * Created: 02.08.2011 11:36:54
5
 *  Author: iwi
6
 */ 
7
8
#define F_CPU  16000000UL
9
10
11
#include <avr/io.h>
12
#include <avr/interrupt.h>
13
#include <util/delay.h>
14
#include "uart.h"
15
#include <avr/boot.h>
16
17
#define BOOT_UART_BAUD_RATE     9600     /* Baudrate */
18
#define XON                     17       /* XON Zeichen */
19
#define XOFF                    19       /* XOFF Zeichen */
20
 
21
 
22
 
23
int main()
24
{
25
    unsigned int   c=0;        /* Empfangenes Zeichen + Statuscode */
26
    unsigned char  temp,        /* Variable */
27
                    flag=1,        /* Flag zum steuern der Endlosschleife */
28
          p_mode=0;      /* Flag zum steuern des Programmiermodus */
29
          
30
    void (*start)( void ) = 0x0000;     /* Funktionspointer auf 0x0000 */
31
 
32
    /* Interrupt Vektoren verbiegen */
33
    char sregtemp = SREG;
34
    cli();
35
    temp = MCUCR;
36
    MCUCR = temp | (1<<IVCE);
37
    MCUCR = temp | (1<<IVSEL);
38
    SREG = sregtemp;
39
 
40
    /* Einstellen der Baudrate und aktivieren der Interrupts */
41
    uart_init( UART_BAUD_SELECT(BOOT_UART_BAUD_RATE,F_CPU) ); 
42
    sei();
43
 
44
    uart_puts("Bootloader");
45
    _delay_ms(1000);
46
 
47
    do
48
    {
49
        c = uart_getc();
50
        if( !(c & UART_NO_DATA) )
51
        {
52
            switch((unsigned char)c)
53
            {
54
                 case 'q': 
55
         flag=0;
56
                     uart_puts("Verlasse den Bootloader!\n\r");
57
                     break;
58
                  default:
59
                     uart_puts("Du hast folgendes Zeichen gesendet: ");
60
                     uart_putc((unsigned char)c);
61
                     uart_puts("\n\r");
62
                     break;
63
            }
64
        }
65
    }
66
    while(flag);
67
 
68
    uart_puts("Springe zur Adresse 0x0000!\n\r");
69
    _delay_ms(1000);
70
 
71
    /* vor Rücksprung eventuell benutzte Hardware deaktivieren
72
       und Interrupts global deaktivieren, da kein "echter" Reset erfolgt */
73
 
74
    /* Interrupt Vektoren wieder gerade biegen */
75
    cli();
76
    temp = MCUCR;
77
    MCUCR = temp | (1<<IVCE);
78
    MCUCR = temp & ~(1<<IVSEL);
79
 
80
    /* Rücksprung zur Adresse 0x0000 */
81
    start(); 
82
    return 0;
83
}

von Thomas E. (thomase)


Lesenswert?

Andre Iwers schrieb:
> Wenn ich nun aber versuche die Interrupts umzuleiten "-Ttext=7000"

Falsche Adresse!

Das ist die Word-Adresse. In den Linker-Options muß die entsprechende 
Byte-Adresse eingegeben werden:

0x7000 * 2 = 0xE000

mfg.

von Andre I. (scuido)


Lesenswert?

Vielen Dank für den Hinweis. Ich versuche gerade das ganze zu verstehen.

Im Datenblatt ist eine Tabelle:
Table 25-13. Boot Size Configuration(1)
1 1 512 words 4 0x0000 - 0x7DFF 0x7E00 - 0x7FFF 0x7DFF 0x7E00
1 0 1024 words 8 0x0000 - 0x7BFF 0x7C00 - 0x7FFF 0x7BFF 0x7C00
0 1 2048 words 16 0x0000 - 0x77FF 0x7800 - 0x7FFF 0x77FF 0x7800
0 0 4096 words 32 0x0000 - 0x6FFF 0x7000 - 0x7FFF 0x6FFF 0x7000

wenn ich nun "00" setze habe ich ja den größten speicher für den 
Bootbereich. Das müssten denn doch 8kb sein oder?

Ich habe gerade das nächste Beispiel ausprobiert, wo der gesamte 
Bootlader als Beispiel gegeben ist. Wenn ich den BL auf den Chip lade 
läuft er auch soweit. Man kann Zeichen schicken und er reagiert auch 
richtig.

Wenn ich nun aber ein von mir funktionierendes, für den Chip 
kompiliertes , Programm laden möchte (oder hier, das Beispiel für meinen 
kompiliert), zeigt er ca 20 Punkte in Putty dann kommen nur noch #'s . 
Nach kurzer Zeit stopt er dann und wenn man etwas eingibt kommt nur noch 
# als Echo

hier nochmal der Link:
http://www.mikrocontroller.net/articles/AVR_Bootloader_in_C_-_eine_einfache_Anleitung#Schritt_3_-_Programmieren_des_Bootloaders_2

von Thomas E. (thomase)


Lesenswert?

Andre Iwers schrieb:
> wenn ich nun "00" setze habe ich ja den größten speicher für den
> Bootbereich. Das müssten denn doch 8kb sein oder?

Das ist richtig.

Wenn ich mir aber das *.lss File aus deinem Debug Folder ansehe, sieht 
man zwar, daß der Code schön bei 0x7000 anfängt aber auch erst bei 
0x8436 endet. D.h. der Code ist über 10KB lang und passt nicht in den 
Bootsektor.

Mein Bootloader, der ähnlich gestrickt ist, wie der im Tutorial, ist 
gerade mal 1K lang. Und zwar Bytes nicht Word.

Also erstmal beste Optimierung rein und dann abspecken.

mfg.

von Andre I. (scuido)


Lesenswert?

Vielen Dank für die super Hilfe, nun weiß ich weningstens schonmal 
worauf ich achten muss. Könntest du mir eventuell mal dein c-file geben? 
Denn kann ich mir mal ein funktionierendes Beispiel anschauen.

von Andre I. (scuido)


Lesenswert?

Ich habe den Bootlader aus dem Beispiel nun soweit zum laufen bekommen, 
Wenn ich die Hex übertrage macht er am Ende zwar ein Reset nur springt 
er sofort wieder in den Bootlader. Was muss ich da noch beachten?

von Andre I. (scuido)


Lesenswert?

hat denn keiner ne Idee woran das liegen könnte?

von Tueftler (Gast)


Lesenswert?

Normalerweise muss du ja die Bootloader Fuse setzen, das heisst, nach 
einem Reset springt der controller in jedem Fall in den Bootloader.
du musst nun eine funktion in den Bootloader integrieren, die prüft, ob 
der bootloader überhaupt ausgeführt werden soll oder ob das normale 
programm ausgeführt werden soll.
Beispielsweise ob ein Pin low oder high ist.
Sofern das nicht der fall ist, muss du halt noch die Interrupttabelle 
geradebiegen und dann an die Addresse 0 springen.
Dann wird dein normales Programm ausgeführt.

mit grüßen,
Tueftler

von Andre I. (scuido)


Lesenswert?

Hey,


das wird nach erfolgreicher Übertragung ausgeführt:
1
 
2
    /* Interrupt Vektoren wieder gerade biegen */
3
    temp = MCUCR;
4
    MCUCR = temp | (1<<IVCE);
5
    MCUCR = temp & ~(1<<IVSEL);
6
 
7
    /* Reset */
8
    start();


mit
1
    void            (*start)( void ) = 0x0000;

von Andre I. (scuido)


Lesenswert?

Fehler gefunden!
Es Lag an der Baudrate. Irgendetwas lief bei der Übertragung schief.....

Mit 4800 läuft es.

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.