Forum: Mikrocontroller und Digitale Elektronik Arduino Uno R3: Bootloader beenden, Programm starten


von Michael (k-mte)


Lesenswert?

Hallo,

ich habe an einem Linux-System einen Arduino Uno R3 an /dev/ttyUSB0 
hängen. Es freut mich sehr, dass ich ihn - auch dank Hilfe von hier - 
ohne die Arduino-IDE betreiben kann. Zum Aufspielen von Code verwende 
ich in einem shell script den Befehl "avrdude -F -V -c arduino -p m328p 
-P /dev/ttyUSB0 -U flash:w:$1.hex". Avrdude resettet den Uno, wodurch 
der Bootloader startet, der Code runtergeladen, gebrannt und gestartet 
wird.

Ich ein Programm geschrieben und auf den Uno gebrannt, das nach dem 
Empfang des Strings "xyz" die LED auf der Platine einschaltet. Ich sende 
den String mit folgendem Programm vom Linux-System an den Uno:
1
...
2
void fehler (char *s);
3
...
4
if ((fp = fopen ("/dev/ttyUSB0", "w")) == NULL)
5
  fehler ("Die Datei läßt sich nicht anlegen!");
6
fprintf (fp, "%s","xyz\n");
7
fclose (fp);
8
...

Beim Öffnen von ttyUSB0 wird ein Reset generiert, der den Bootloader 
startet. Ich sende meinen String also an den Bootloader, nicht an mein 
zuvor in den Uno gebranntes Programm.

Frage:

Gibt es eine Zeichensequenz, die ich via ttyUSB0 an den Bootloader 
senden kann, die den Bootloader beendet und das bereits zuvor in den Uno 
gebrannte Programm startet, so dass ich mein "xyz" an mein Programm 
senden kann?

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Michael schrieb:
> Gibt es eine Zeichensequenz, die ich via ttyUSB0 an den Bootloader
> senden kann, die den Bootloader beendet und das bereits zuvor in den Uno
> gebrannte Programm startet, so dass ich mein "xyz" an mein Programm
> senden kann?

Es bieten sich 2 Möglichkeiten an, den Reset zu unterbinden.
1. auf dem Uno sollte sich eine Lötbrücke befinden welche sich "Reset 
Enable" o.ä. nennt. Auftrennen.
2. einen 10µF Kondensator zwischen Reset und GND des Uno platzieren.


Unter Win kann man mit Mode den DTR Reset unterbinden. Ist abhängig vom 
Anwendungsprogramm und USB-UART Chip ob das klappt.

Auch Linux sollte das Gezappel an DTR unterbinden können, habe aber KA 
wie

: Bearbeitet durch User
von N. M. (mani)


Lesenswert?

Michael schrieb:
> Gibt es eine Zeichensequenz, die ich via ttyUSB0 an den Bootloader
> senden kann, die den Bootloader beendet und das bereits zuvor in den Uno
> gebrannte Programm startet

Ich kenne das meist so dass sich der Bootloader automatisch beendet:
Nach dem Powerup wird als erstes der Bootloader angesprungen.
Der Bootloader checkt das Applikationsprogramm ob das Konsistent (z.B. 
CRC) und valide (z.B. richtiges Programm) ist. Ist das nicht der Fall 
bleibt der Bootloader so lange aktiv bis über ihn ein gültiges 
Applikationsprogramm geladen wurde.
Ist das Applikationsprogramm gültig, so wartet der Bootloader eine Zeit 
x bis er ins Hauptprogramm springt. Wenn man sich die Zeit sparen möchte 
oder sehr kurz machen will gibt es da auch Abwandlungen dass Taste x 
oder auf ein Zeichen in einer Kommunikationsschnittstelle geprüft wird 
das dann den Sprung ins Applikationsprogramm verhindert.

In deinem Fall oben, würde dann automatisch nach dem Bootloader das 
Hauptprogramm angesprungen werden. Ohne weiteres zutun.

Michael schrieb:
> Beim Öffnen von ttyUSB0 wird ein Reset generiert

Wobei ich das als erstes versuchen würde abzustellen. Finde ich unschön. 
Nur weil die Kommunikation geöffnet wird springt die Kiste in den Reset?

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

N. M. schrieb:
> Nur weil die Kommunikation geöffnet wird springt die Kiste in den Reset?
Das Gezappel an "Data Terminal Ready" ist ganz offensichtlich das 
Standard Verhalten.
Unabhängig davon, was man selber darüber denken mag.
DTR löst am UNO den Reset aus.

Das Problem ist in der Arduino Welt gut bekannt.
Oben habe ich 2 praktikable und zuverlässige Verfahren genannt.

von Manfred P. (pruckelfred)


Lesenswert?

Michael schrieb:
> Beim Öffnen von ttyUSB0 wird ein Reset generiert, der den Bootloader
> startet. Ich sende meinen String also an den Bootloader, nicht an mein
> zuvor in den Uno gebranntes Programm.

Es ist keine Option, eine Pause zu machen oder erst zu senden, nachdem 
sich der Uno gemeldet hat?

Arduino F. schrieb:
> 1. auf dem Uno sollte sich eine Lötbrücke befinden welche sich "Reset
> Enable" o.ä. nennt. Auftrennen.

Könnte beim Original so sein, bei den Chinesen scheinbar nicht.

> 2. einen 10µF Kondensator zwischen Reset und GND des Uno platzieren.

Wenn man schon löten will:
3. Den 100n-Kondensator zwischen DTR des 16U2 / CH340 und Reset des 
AT328 auslöten.

> Unter Win kann man mit Mode den DTR Reset unterbinden. Ist abhängig vom
> Anwendungsprogramm und USB-UART Chip ob das klappt.

Hahaha .. dazu gibt/gab es gerade einen Thread, dessen Ersteller das 
nicht gelingt.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Manfred P. schrieb:
> Wenn man schon löten will:
Nein, nöö.
Beim Uno kann man den auch stecken.
Ganz ohne löten.


> Hahaha .. dazu gibt/gab es gerade einen Thread, dessen Ersteller das
> nicht gelingt.
Da sagt im aber nicht was ihm mit mode gemacht hat.
Riesig viel Getue um hub4com und com0com. Hat nur nix mit dem 
eigentlichen Problem zu tun. Nebelkerzen.

von Rainer W. (rawi)


Lesenswert?

Michael schrieb:
> Beim Öffnen von ttyUSB0 wird ein Reset generiert, der den Bootloader
> startet.

Warum schickst du einen Reset, wenn du das nicht möchtest. Der Reset 
beim Uno wird durch DTR ausgelöst und wenn diese Leitung beim Öffnen von 
ttyUSB durch dein fopen() gesetzt wird, bekommt der Uno eben genau den 
Reset. Avrdude nutzt genau diese Funktion, damit der Code geflasht 
werden kann. Wenn du die Reset-Leitungen hardwaremäßig unterbrichst, 
musst du zum Flashen den Reset manuell auslösen.

Arduino F. schrieb:
> Das Problem ist in der Arduino Welt gut bekannt.

Das ist nicht ein Problem der "Arduino Welt", sondern eine Frage des 
Schnittstellen-Handligs auf der PC-Seite. Bei Terminalprogrammen wie 
z.B. HTerm kann man doch auch einstellen, ob beim Öffnen der 
Schnittstelle das DTR-Signal gesetzt werden soll oder eben nicht.

: Bearbeitet durch User
von Michael (k-mte)


Lesenswert?

Hallo,

dass das Öffnen von ttyUSB0 einen Reset auslöst, stört mich nicht, im 
Gegenteil, ich bin ja darauf angewiesen, dass der uC in einem 
definierten Zustand ist, wenn ich mit ihm kommuniziere.

(Falls es mich stören würde, könnte ich es möglicherweise in einem 
Terminal-Fenster mit
1
 stty -F /dev/ttyUSB0 -hup
 oder in einem C-Programm mit
1
 system ("stty -F /dev/ttyUSB0 -hup");
 unterbinden, ich habe das allerdings nicht getestet.)

Ich könnte auch durch Setzen der Fuses, hier des Bootloader Jump Bits, 
das Ausführen des Bootloaders abschalten, was ich aber ebenfalls nicht 
möchte.

Mein Problem ist nicht der Reset, sondern der Bootloader. Ich bin noch 
nicht dazu gekommen, zu untersuchen, ob der nach einer gewissen Zeit das 
im uC geflashte Programm startet. Wenn das nicht eine Ewigkeit dauern 
sollte, wäre das durchaus eine Möglichkeit für mich. Am elegantesten 
wäre natürlich, wenn ich dem Bootloader eine bestimmte Zeichenfolge 
senden könnte, auf die hin er das bereits zuvor geflashte Programm 
startet...

: Bearbeitet durch User
von Bauform B. (bauformb)


Lesenswert?

Die Linux-Treiber kennen 2 verdächtige Flags: wenn CLOCAL gesetzt ist 
und HUPCL nicht, könnte es funktionieren; man termios sagt
1
  HUPCL  Lower modem control lines after last process closes
2
         the device (hang up).
3
4
  CLOCAL Ignore modem control lines.
Alle Flags werden mit einem ioctl() gesetzt, siehe ioctl_tty(2). Im 
Gegensatz zu vielen Beispielen im Netz mache ich kein TCGETS, sondern 
setze alle Flags wie ich sie brauche. Nebenbei wird so der "raw mode" 
benutzt. Damit werden alle Zeichen 1:1 gesendet und empfangen.
1
{
2
  struct termios  comm_params;
3
4
  comm_params.c_iflag = IGNBRK | IGNPAR | strip;
5
  comm_params.c_oflag = 0;
6
  comm_params.c_cflag = CREAD | CLOCAL | bits | parity | stopbits | baud;
7
  comm_params.c_lflag = 0;
8
  comm_params.c_line = 0;
9
  comm_params.c_cc[VMIN] = 1;
10
  comm_params.c_cc[VTIME] = 0;
11
  if (ioctl (port, TCSETS, &comm_params)) {
12
    error (0, errno, "sci_open: ioctl TCSETS '%s'", dev);
13
    return -1;
14
  }
15
  return port;
16
}
Ungetestet mangels griffbereiter Hardware; alle Angaben ohne Gewähr ;)

Edit: Entschuldigen Sie bitte die Störung, aber evt. hilft es in einem 
anderen Fall :(

: Bearbeitet durch User
von Wastl (hartundweichware)


Lesenswert?

Michael schrieb:
> Mein Problem ist nicht der Reset, sondern der Bootloader. Ich bin noch
> nicht dazu gekommen, zu untersuchen, ob der nach einer gewissen Zeit das
> im uC geflashte Programm startet. Wenn das nicht eine Ewigkeit dauern
> sollte, wäre das durchaus eine Möglichkeit für mich.

Da ich gerade mit dem Arduino Uno (nicht mit der Arduino IDE)
zu tun habe kann ich dir sagen dass einer der bei der IDE mit-
gelieferten Bootloader (optiboot_atmega328.hex) das von dir
erwartete Verhalten erfüllt. Ich flashe die Anwendung über die
USB-Schnittstelle und benutze dann die gleiche Schnittstelle
zum Steuern der Anwendung mittels Terminal-Software. Dabei
ergibt sich nach dem Starten des Terminals und Öffnen der
Schnittstelle eine kurze Verzögerung (das Bootloader-Delay)
bis die Kommunikation mit dem Terminal startet.

von Sn60pb38cu2 (sn60pb38cu2)


Lesenswert?

1. Schnittstelle öffnen.
2. 4 Sekunden warten.
3. "xyz" senden.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Michael schrieb:
> dass das Öffnen von ttyUSB0 einen Reset auslöst, stört mich nicht, im
> Gegenteil, ich bin ja darauf angewiesen, dass der uC in einem
> definierten Zustand ist, wenn ich mit ihm kommuniziere.

Wenn dein µC in undefinierte Zustände fällt, hast du ganz andere 
Probleme, als die mit dem Bootloader.


>  Ich bin noch
> nicht dazu gekommen, zu untersuchen, ob der nach einer gewissen Zeit das
> im uC geflashte Programm startet.
Natürlich tut er das!



>  Am elegantesten
> wäre natürlich, wenn ich dem Bootloader eine bestimmte Zeichenfolge
> senden könnte, auf die hin er das bereits zuvor geflashte Programm
> startet...
Wenn es sowas gibt findest du das im STK500 Protokoll.
Der UNO Bootloader verwendet eine reduzierte Variante davon.

Wastl schrieb:
>  kann ich dir sagen dass einer der bei der IDE mit-
> gelieferten Bootloader (optiboot_atmega328.hex) das von dir
> erwartete Verhalten erfüllt.
Genau der wird auf dem UNO verwendet, und hat von allen Arduino 
Bootloadern die kürzeste Wartezeit.

Siehe:
> uno.bootloader.file=optiboot/optiboot_atmega328.hex
Aus der aktuellen platform.txt

: Bearbeitet durch User
Beitrag #7921897 wurde vom Autor gelöscht.
von Rainer W. (rawi)


Lesenswert?

Michael schrieb:
> Ich bin noch nicht dazu gekommen, zu untersuchen, ob der nach einer
> gewissen Zeit das im uC geflashte Programm startet.

Tut er

> Am elegantesten wäre natürlich, wenn ich dem Bootloader eine bestimmte
> Zeichenfolge senden könnte, auf die hin er das bereits zuvor geflashte
> Programm startet...

Dann ändere ihn doch entsprechend.

von Flunder (flunder)


Lesenswert?


von Michael (k-mte)


Lesenswert?

Vielen Dank für die Hilfe, ganz besonders für den Link auf den Beitrag 
"Bytesequenz"! Ich muss jetzt erst mal alles durchlesen und 
ausprobieren.

von Achim H. (pluto25)


Lesenswert?

Q wie quit beendet ihn per Watchdog.
Richtiger 0x51 (Q) 0x20 (Satzendezeichen) dann antwortet er noch mit 
0x14,0x10 und übergibt sofort ans das Hauptprogramm.

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.