Forum: Projekte & Code Konzept für einen ATtiny-Bootloader in C


von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Konzept für einen ATtiny-Bootloader in C

Die ATtiny-Mikroprozessoren unterstützen das Prinzip des Bootloaders der 
ATMega-Prozessorreihe eigentlich nicht. Dafür fehlen den ATtinys 
folgende Merkmale:

  - Fehlende Fuses für einen definierten und geschützten
    Bootloader-Bereich

  - Fehlender Resetvektor exklusiv für den Bootloader

  - Fehlende Interruptvektor-Tabelle für ISRs innerhalb des Bootloaders

Trotzdem sind Bootloader-Implementationen für ATtinys durchaus möglich - 
wie zum Beispiel diese Threads aus der Codesammlung belegen:

  - Beitrag "ATtiny45 Bootloader"
  - Beitrag ""Bootloader" für ATTiny2313"
  - Beitrag "UART Bootloader ATtiny13 - ATmega644"

Jedoch sind diese Bootloader allesamt in Assembler realisiert, denn nur 
hier hat der Programmierer alle Freiheiten, die er braucht, um die 
Speicherverwaltung im SRAM (und auch im Flash) selbst zu kontrollieren. 
C (hier im speziellen avr-gcc) ermöglicht es eigentlich nicht, ohne 
größere Klimmzüge einen Bootloader für ATtinys zu programmieren - aus 
oben genannten Gründen.

Hinzu kommt, dass ATtinys einen eher kleinen Flash-Speicher haben. Daher 
wäre es sinnvoll, wenn die Applikation Funktionen des Bootloaders selbst 
nutzen könnte, ohne sie neu zu implementieren und diese damit doppelt im 
Flash-Speicher abzulegen. Wenn der Bootloader zum Beispiel sowieso 
eigene Software-UART-Funktionen verwendet, ist es Unsinn, diese nochmals 
für die Applikation neu zu programmieren. Dabei ergibt sich aber wieder 
ein neues Problem: Der Bootloader wird dann eventuell globale Variablen 
benötigen, die in einem geschützten Bereich liegen müssen. Nur so ist 
ein "Parallelbetrieb" von Bootloader und Applikation möglich, damit die 
Applikation Funktionen des Bootloaders (wie z.B. den Software-UART) 
nutzen kann.

In folgenden Threads werden u.a. die oben angedeuteten Probleme 
angesprochen, ohne dafür Lösungen anzubieten:

  - Beitrag "ATTiny85 Interrupt Vector verschieben"
  - Beitrag "Re: Bootloader Grundkenntnisse"
  - Beitrag "ATtiny861 Interruptvektoren für Bootloader manipulieren"
  - Beitrag "bootloader + Software-Uart"

Der Artikel

  http://www.mikrocontroller.net/articles/Konzept_f%C3%BCr_einen_ATtiny-Bootloader_in_C

soll zeigen, dass ein ATtiny-Bootloader auch in C möglich ist - ja, dass 
sogar eigene Interrupt-Routinen innerhalb des Bootloaders realisiert 
werden können, obwohl ein ATtiny keinen Austausch der 
Interruptvektor-Tabelle über das IVSEL-Bit bietet, wie es bei den 
ATMegas der Fall ist. Auch wird das Thema, wie man Funktionen zwischen 
Bootloader und Applikation "sharen" kann, beschrieben.

Ich freue mich über Feedback und wünsche viel Spaß beim Lesen,

Frank

P.S.
Einige Kapitel (für die Fortgeschrittenen) sind noch nicht gefüllt, 
werden aber von mir in Kürze nachgetragen.

von Hagen R. (hagen)


Lesenswert?

Die entscheidende Fragestellung ist: was soll ein Bootloader machen ? 
Die Prioritäten wie man die Antworten daraufhin ordnet entscheidet dann 
welchen Weg man gehen muß. Die oberste Priorität bei einem Bootloader 
sollte Stabilität und Produktsicherheit sein. Aus Stabilitätsgründen 
sollte man also die Vermischung von Bootloader und Applikation immer 
vermeiden da mit dem Zugriff der Applikation auf den Bootloader ein für 
den Entwickler des Bootloaders unbestimmbares neues Element eingeführt 
wird. Und alles was nicht bestimmbar ist, zu einem Zeitpunkt, macht aus 
der deterministischen Strategie des Bootloader-Entwicklers ein Produkt 
dessen Eigenschaften defakto ebenfalls unbestimmbar sind. Ergo: ein 
solches Konzept wie deines widerspricht dem Konzept eines Bootloaders.

Es ist also nicht verwunderlich das die meistens erfahrenen Entwickler 
von Bootloadern von vornherein eine solche Mixtur meiden wie die Pest. 
Es zeugt von der Erfahrung dieser Leute.

Das nun die Realität grau ist und nicht schwarz weiß gemalt wird sollte 
allen klar sein. Dh. Ausnahmen bestätigen die Regel.

Gruß Hagen

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Die Prioritäten wie man die Antworten daraufhin ordnet entscheidet dann
> welchen Weg man gehen muß. Die oberste Priorität bei einem Bootloader
> sollte Stabilität und Produktsicherheit sein. Aus Stabilitätsgründen
> sollte man also die Vermischung von Bootloader und Applikation immer
> vermeiden da mit dem Zugriff der Applikation auf den Bootloader ein für
> den Entwickler des Bootloaders unbestimmbares neues Element eingeführt
> wird.

Die Vermischung (die ich im Artikel übrigens noch nicht dokumentiert 
habe) besteht lediglich im Sharen von Funktionen bzw. Interrupts. Beides 
ist optional. Was bisher im Artikel beschrieben ist, ist ein Bootloader, 
der nichts - aber auch gar nichts mit der Applikation zu tun hat. Die 
Applikation hat auch keinen(!) Zugriff auf Elemente des Bootloaders. 
Somit ist die Stabilität absolut gegeben, der Bootloader behält die 
Kontrolle.

Nun zum Sharen von Interrupts und Funktionen - was, wie gesagt, nur ein 
optionales Schmankerl sein soll:

Du musst Dir das so vorstellen: Der Bootloader ist das "Betriebssystem", 
die Applikation kann Betriebssystem-Funktionen kontrolliert benutzen - 
mehr nicht. Der Bootloader behält in jedem Fall die Kontrolle. Die 
Applikation kann in keinem Fall Funktionen des Bootloaders benutzen, 
welche das Flash beschreiben. Diese sind natürlich alle static definiert 
und können nicht von der Applikation genutzt werdne.

Der Bootloader wird für sich allein kompliliert - und auch geflasht. Der 
Bootloader lädt die Applikation nach und kann - auf Abruf - bestimmte 
Funktionalitäten an die Applikation exportieren - d.h. freigeben. Das 
können zum Beispiel die vom Bootloader verwendeten SW-UART-Funktionen 
sein. Sie können aber nur über eine kontrollierte Schnittstelle 
verwendet werden. Vermischt wird hier gar nichts!

Wenn ich diesen Mechanismus beschrieben habe, können wir uns darüber 
gern nochmal unterhalten ;-)

> Und alles was nicht bestimmbar ist, zu einem Zeitpunkt, macht aus
> der deterministischen Strategie des Bootloader-Entwicklers ein Produkt
> dessen Eigenschaften defakto ebenfalls unbestimmbar sind. Ergo: ein
> solches Konzept wie deines widerspricht dem Konzept eines Bootloaders.

Was ist an meinem Konzept nicht bestimmbar?

> Es ist also nicht verwunderlich das die meistens erfahrenen Entwickler
> von Bootloadern von vornherein eine solche Mixtur meiden wie die Pest.

Ich glaube, Du bist da einem Missverständnis auferlegen. Hast Du den 
Artikel überhaupt gelesen? Da ist überhaupt nicht von Mixtur die Rede. 
Ausserdem ist der Bootloader nicht(!) vom Good-Will der Applikation 
abhängig. Die Applikation kann noch so "böse" sein, sie kriegt den 
Bootloader nicht kaputt!

Anmerkung dazu:
Natürlich kann die Applikation auf einem ATtiny mutwillig das Flash 
löschen, weil so ein Schutz bei ATtinys nicht möglich ist, aber damit 
kriege ich auch jeden Deiner Bootloader kaputt ;-)

> Es zeugt von der Erfahrung dieser Leute.

Du kannst Dir gewiss sein, dass ich genügend Erfahrung besitze ;-)

> Das nun die Realität grau ist und nicht schwarz weiß gemalt wird sollte
> allen klar sein. Dh. Ausnahmen bestätigen die Regel.

Bitte lies den Artikel nochmal und zeige mir eine Schwachstelle, die die 
Stabilität gefährden könnte.

Danke für Dein Feedback,

Frank

von Hagen R. (hagen)


Lesenswert?

Nur mal dieser Absatz:

Frank M. schrieb:
> Die Vermischung (die ich im Artikel übrigens noch nicht dokumentiert
> habe) besteht lediglich im Sharen von Funktionen bzw. Interrupts. Beides
> ist optional. Was bisher im Artikel beschrieben ist, ist ein Bootloader,
> der nichts - aber auch gar nichts mit der Applikation zu tun hat. Die
> Applikation hat auch keinen(!) Zugriff auf Elemente des Bootloaders.
> Somit ist die Stabilität absolut gegeben, der Bootloader behält die
> Kontrolle.

Deine Aussage stimmt wenn du den Best Case betrachtest. Was passiert 
wenn die Applikation Code im Bootloader ausführen kann und dabei mit 
fehlerhaft mit falschen Einsprungspunkten arbeitet ? Dh. die Applikation 
möchte die UART Routinen im Bootloader aufrufen ruft aber auf Grund 
eines Fehlers die FLASH Programmierfunktionen ohne Sinn und Verstand auf 
?

Der Bootloader sollte vollständig getrennt, also nochnichtmal sichtbar 
für die ALU zu diesem Zeitpunkt, sein. Ein falscher Sprung in den 
Bootloader Bereich sollte durch die Hardware blockiert werden, zb. durch 
Exceptions wie im Protected Mode einer heutigen CPU.

Bootloader sind nicht nur Softwareseitig zu betrachten, sondern auch 
Hardwareseitig.

Gruß Hagen

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Deine Aussage stimmt wenn du den Best Case betrachtest. Was passiert
> wenn die Applikation Code im Bootloader ausführen kann und dabei mit
> fehlerhaft mit falschen Einsprungspunkten arbeitet ? Dh. die Applikation
> möchte die UART Routinen im Bootloader aufrufen ruft aber auf Grund
> eines Fehlers die FLASH Programmierfunktionen ohne Sinn und Verstand auf
> ?

Du hast es immer noch nicht verstanden:

Der Bootloader ist ein Stand-Alone-Programm und wird OHNE Applikation 
auf den Chip gebrannt. Die Applikation wird NICHT mit dem Bootloader 
gelinkt!

Der Bootloader kann später, wenn die Applikation geladen ist, bestimmte 
Einstiegspunkte exportieren, macht dies aber natürlich nicht für die 
FLASH-Programmierfunktionen. Da kommt die Applikation gar nicht dran - 
ausser, indem sie willkürlich irgendwohin durch Trial- und Error in den 
Bootloader-Bereich springt. Aber das kann man mit jedem Bootloader!

> Der Bootloader sollte vollständig getrennt, also nochnichtmal sichtbar
> für die ALU zu diesem Zeitpunkt, sein. Ein falscher Sprung in den
> Bootloader Bereich sollte durch die Hardware blockiert werden, zb. durch
> Exceptions wie im Protected Mode einer heutigen CPU.

Du weisst genau, dass dies auf einem ATtiny hardware-technisch nicht 
möglich ist. Auch Du als Assembler-Bootloader-Programmierer weisst, dass 
ein ATtiny dies nicht verhindern kann.

Was soll das also jetzt? Zuerst sagst Du, dass mein Konzept her nicht 
sicher ist, jetzt sagst Du, dass alle ATtiny-Bootloader schon aus 
hardware-technischen Gründen nicht sicher sein können.

Auf einem AVR-µC, auf dem auch ein Bootloader ist, kann eine 
wildgewordene Applikation immer auch "versehentlich" auf 
Bootloader-Funktionen zugreifen. Auf einem ATmega wird aber 
hardware-technisch verhindert, dass die Applikation dadurch das Flash 
modifizieren kann. Auf einem ATtiny kannst Du das nicht verhindern, denn 
hier fehlen diese Schutzmechanismen - außer Du löschst die 
SELFPRGEN-Fuse und führst damit einen Bootloader ad absurdum.

Also: Wie blockierst Du den Aufruf Deines Bootloader-Codes auf einem 
ATtiny durch eine amoklaufende Applikation?

> Bootloader sind nicht nur Softwareseitig zu betrachten, sondern auch
> Hardwareseitig.

Es geht um einen Bootloader für ATtinys, der komplett in C realisierbar 
ist. Ich will lediglich zeigen, dass dies eben auch in C möglich ist und 
dass man nicht notwendigerweise in Assembler programmieren muss.

Ich habe bisher keinen einzigen Bootloader für ATtinys gefunden, der in 
C programmiert ist. Alle sind in Assembler geschrieben - eben weil sich 
da noch keiner rangetraut hat. Auf den ATmegas hat man es leicht, denn 
da hat der Bootloader einen eigenen Reset-Vektor (in seiner eigenen 
Interrupt-Vektor-Tabelle). Und dieser fehlt auf den ATtinys - wie auch 
die anderen Interrupt-Vektoren. Ich wollte zeigen, dass man dieses Manko 
auch in C durch entsprechende Mechanismen ausgleichen kann.

Die Argumente, die Du hier jetzt bringst, sind vollkommen allgemeiner 
Natur. Sie gelten für alle ATtiny-Bootloader. Letztendlich lese ich 
nur ein Fazit aus Deinem Beitrag: ATtiny-Bootloader sind unmöglich, da 
nicht sicher. Die Hardware bringts einfach nicht. Aber was hat das jetzt 
im speziellen mit meinem Konzept zu tun? Hier geht es um: "Und es geht 
doch in C" und nicht darum, dass er sicherer ist als alle anderen 
Assembler-Bootloader für ATtinys.

Bitte weiche nicht in allgemeingültiges Geschwafel ab. Ich las in Deiner 
ersten Antwort, dass gerade im speziellen mein Konzept nicht sicher bzw. 
stabil ist. Du konntest aber bisher noch keinen einzigen Punkt nennen, 
wo er unsicherer ist als irgendein anderer ATtiny-Bootloader. Er ist 
genauso sicher und er ist genauso unsicher.

Für die Hardware (ATtiny) mit ihrer eingeschränkten Sicherheit bzgl. 
Flash-Programmieren kann ich persönlich gar nichts.

Gruß,

Frank

von Anon Y. (avion23)


Lesenswert?

Hi Frank,
ich finde die Idee gut. So hat man wenigstens eine Chance zu verstehen 
wie das alles funktioniert.

Was mir noch nicht klar ist:
- wie bekommst du die Daten in den attiny?
- bei welchem Speicherverbrauch bist du jetzt (mit -Os, aber ohne 
schwarze Magie)

Weiter so!

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Anon Ymous schrieb:
> ich finde die Idee gut. So hat man wenigstens eine Chance zu verstehen
> wie das alles funktioniert.

Genau darum ging es mir - nämlich den Vorgang Schritt für Schritt zu 
erklären, wie man einen Bootloader auf ATtinys bauen kann, obwohl den 
Tinys dafür wichtige Features fehlen. Man sollte das Konzept daher nicht 
auf ATmegas übertragen. Denn da ist alles ganz anders... und viel 
einfacher.

> Was mir noch nicht klar ist:
> - wie bekommst du die Daten in den attiny?

Genau das wollte ich eigentlich offen lassen, denn mir ging es um die 
Mechanismen und nicht um eine konkrete Schnittstelle. Die Übertragung 
der Daten kann über einen SW-UART erfolgen, kann aber auch über jede 
andere denkbare Kommunikationsschnittstelle erfolgen. Ich hatte da zum 
Beispiel schon einmal den SOUNDRX-Bootloader in einem Artikel 
vorgestellt, wo man einen ATmega über die Soundkarte des PCs flasht. 
Soundkarte hat jeder am PC, aber einen UART nicht unbedingt ;-)

Ich werde aber später im Artikel einen konkreten Bootloader vorstellen, 
der das beschriebene Konzept über einen SW-UART nutzt. Diesen habe ich 
für ein spezielles Projekt entwickelt, wo 60 ATtinys in einer einzigen 
Schaltung in Reihe über einen einzigen Anschluss miteinander in einer 
Kette verbunden sind. Hier werden alle 60 ATtinys "in einem Rutsch" über 
den Bootloader geflasht. Wofür man 60 ATtinys in einer langen Kette (mit 
insgesamt 480 MIPS Leistung) braucht, möchte ich aber erst verraten, 
wenn es soweit ist. Den konkreten Bootloader-Source werde ich jedoch 
schon vorab in den nächsten Tagen im Artikel vorstellen.

> - bei welchem Speicherverbrauch bist du jetzt (mit -Os, aber ohne
> schwarze Magie)

Es sind momentan ca. 1800 Bytes, also unter 2 KB. Das hört sich erstmal 
nach viel an gegenüber einem in Assembler-Bootloader programmierten 
Bootloader. Man muss aber bedenken, dass die SW-UART-Routinen und die 
Kommunikationroutinen über die "Kette" der seriell geschalteten ATtinys 
da schon miteingerechnet sind... und auch von der Applikation genutzt 
werden, also nur einmal im Flash vorhanden sind. Von daher relativiert 
sich die Größe.

> Weiter so!

Danke, natürlich mache ich weiter, schließlich will ich mein 
60-ATtiny-Projekt damit realisieren - und irgendwann hier auch 
vorstellen ;-)

Gruß,

Frank

von Hagen R. (hagen)


Lesenswert?

Frank, du kannst mir glauben das ich dich sehr gut verstehe und das ich 
sehr genau abschätzen kann was real möglich ist und was theoretisch am 
Besten wäre.

Nun, meine Kritik ist das Du mit deinem Artikel ein Problem lösen 
möchtest das sich theoretisch garnicht ergeben sollte. Ich sehe den 
konkreten Sinn nicht ausser in einer akademischen Anwendung, als eine 
Machbarkeitsstudie.

Bei meinem AVRootloader zB. habe ich ebenfalls mit Sprungtabellen das 
Gleiche gemacht. Das erfolgte auf mehrfachem Wunsch von Anwendern da ich 
selbst es nicht brauchte und auch nicht als sinnvoll erachtete. Und das 
Fazit: bis heute haben selbst diejenigen die mich darum baten diese 
Schnittstelle nicht benutzt, ergo nicht real benötigt.

Die Strategie die Abhängigkeiten zwischen Bootloader und Applikation so 
gering wie möglich zu halten ist sinnvoll und entspricht am meisten den 
realen Anforderungen.

Es geht hier also eher in eine philosophie Richtung weshalb ich schrieb: 
Ausnahmen bestätigen die Regeln.

Letzendlich zählt doch nur eines: die Vielfalt an verschiedenen 
Ansichten und Meinungen. Also kein Grund es zu persönlich zu nehmen.

Ich bin gespannt auf die Vervollständigung deines Artikels.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Frank M. schrieb:
> Es geht um einen Bootloader für ATtinys, der komplett in C realisierbar
> ist. Ich will lediglich zeigen, dass dies eben auch in C möglich ist und
> dass man nicht notwendigerweise in Assembler programmieren muss.
>
> Ich habe bisher keinen einzigen Bootloader für ATtinys gefunden, der in
> C programmiert ist. Alle sind in Assembler geschrieben - eben weil sich
> da noch keiner rangetraut hat.

Naja ich hätte auch meine Bootloader die ich in C programmiert habe hier 
posten können aber warum sollte ich dies wenn die in Assembler 
programmierten weit leistungsfähiger sind.

Schau: die Hauptaufgabe eines Programmieres ist das Abwägen bei der Wahl 
der Mittel um ein Ziel effektiv und effizient zu erreichen. Ein 
Programmier der zB. nur C als Sprache beherrscht und eines Tages vor dem 
Problem steht das er nicht das richtige Werkzeug als Mittel zum 
Erreichen eines Zieles beherrscht sollte sich eher frage warum er dieses 
Werkzeug nicht beherrscht. Er sollte es anstreben das Werkzeug zu 
beherrschen.

Desegen meine Ansicht das ein C Bootloader aus Sicht der maximal 
machbaren Effizienz das falsche Werkzeug gewählt hat und eher 
akademischer Natur ist. Dies zeigt auch deine Vorgehensweise in deinem 
Artikel.

Was möchtest du mit der Aussage "ich beweise das man Bootloader mit C 
programmieren kann" beweisen ? Das wissen wir doch schon längst, warum 
sollte es mit C nicht möglich sein ? Das du das Vorhandensein von 
ausschließlich in Assembler programmierten Bootloadern als Indiz dafür 
wertest das es keine Programmierer gäbe die das könnten ist schlichtweg 
ein Denkfehler der kausalen Zusammenhänge. Es ist so weil alle diese 
Entwickler sich für das best geeignete Werkzeug entschieden haben, und 
das ist ein Indiz das man in Assembler bessere Bootloader programmieren 
kann.

Die Nichtexistenz eines C Bootloaders für Tinys zeugt davon das alle 
ASM-Bootloader-Programmierer sich aus ihren Erfahrungen heraus Gedanken 
gemacht haben und ihre besten Leistungen präsentieren möchten.

Glaubst du wirklich das all diese ASM Programmierer nicht in C hätten 
programmieren können ? Nein, sie tun es in Assembler weil sie der 
Meinung sind das das für die Lösung eines Problemes am besten ist.

Mein C-Prototyp eines Bootlaoders für Tinys/Megas hat nichtmal 50% der 
Funktionalitäten meines ASM Bootloaders und verbracht dabei mehr als 
doppelt zuviel FLASH. Warum sollte ich diese Krücke veröffentlichen 
wollen ?

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Frank M. schrieb:
> Es sind momentan ca. 1800 Bytes, also unter 2 KB. Das hört sich erstmal
> nach viel an gegenüber einem in Assembler-Bootloader programmierten
> Bootloader.

Mal eine Zahl von mir: der AVRootloader von mir benötigt in minimalster 
Konfiguration ca. 360 Bytes mit SW-UART. In Maximalkonfiguration unter 
1kB dann ist aber schon eine starke Kryptographie mit inklusive, neben 
EEPROM, CRCs in der Kommunikation usw. usw. Physikalisch und 
Protokolltechnisch kann er alle UART Protokolle wie 1/2 Wire, 
invertiert/nicht invertiert, RS485, und auch 1-Wire Bussystem zur 
Anbindung meherer verschiedener AVR auf einem Board mit gleichem 
Bootloader an einer einzigen Leitung. Das alles schon ab 360 Bytes zu 
haben.

Das wirst du niemals in C erreichen können. Praktisch gesehen ist also 
dein Artikel ein akademsiches Projekt. Und das wiederum halte ich für 
positiv und auch erforderlich, denn wir wollen alle ja was lernen. Und 
da gebe ich dir vollkommen recht: ein ASM Bootloader bis aufs letzte 
Byte mit Expertentricks übersäht ist kein wirklich gutes Lehrbeispiel.

Gruß Hagen

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:

> Das wirst du niemals in C erreichen können.

Da gebe ich Dir absolut recht. Ich will da auch keine "Konkurrenz" zu 
den ASM-Bootloadern herstellen. Deshalb habe ich einige relevante Links 
zu bereits existierenden Bootloadern auch direkt am Anfang des Artikels 
eingestreut. Mit einem ASM-Bootloader ist man in den meisten Fällen 
besser bedient - auch wenn man ihn vielleicht gar nicht versteht ;-)

> Praktisch gesehen ist also dein Artikel ein akademsiches Projekt.

Ja, so kann man es durchaus sehen, der Artikel ist vorwiegend 
akademischer Natur. Ich werde dies im Artikel noch einmal ausdrücklich 
erwähnen. Trotzdem ist er in der Praxis durchaus anwendbar - auch wenn 
er gegenüber den ASM-Bootloadern bzgl. Speicherplatz der klare Verlierer 
ist.

> Und da gebe ich dir vollkommen recht: ein ASM Bootloader bis aufs letzte
> Byte mit Expertentricks übersäht ist kein wirklich gutes Lehrbeispiel.

Gut, dann sind wir uns ja einig :-)

Gruß,

Frank

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Was möchtest du mit der Aussage "ich beweise das man Bootloader mit C
> programmieren kann" beweisen ?

Natürlich kann man Bootloader in C programmieren. Für den ATmega ist das 
ein Klacks in C. Da gibt es auch genügend Bootloader im Netz. Ich selbst 
habe da auch schon ein halbes Dutzend Bootloader in C entwickelt, die 
alle nicht der Rede wert sind.

> Das wissen wir doch schon längst, warum sollte es mit C nicht möglich sein ?

Es ging mir um ein spezielles Problem beim ATtiny: Wie stelle ich in C 
einen Reset-Vektor (und die Interrupt-Vektor-Tabelle) an der Stelle 
0x000 her? Das war das Hauptproblem bei bei der ganzen Geschichte. Beim 
ATmega braucht man sich darum nicht zu kümmern. Hier hat der Bootloader 
seine eigene Vektortabelle.

Gruß,

Frank

von Peter D. (peda)


Lesenswert?

Läuft der Bootloader unter allen bekannten AVR-Compilern (IAR, 
Codevision, GCC)?
Und unter welchen Versionen läuft er?


Frank M. schrieb:
> Die
> Applikation kann in keinem Fall Funktionen des Bootloaders benutzen,
> welche das Flash beschreiben.

Braucht sie auch nicht. Bei den ATtiny und dem ATmeg48 kann die 
Applikation direkt das SPM ausführen.


Peter

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Läuft der Bootloader unter allen bekannten AVR-Compilern (IAR,
> Codevision, GCC)?

Er läuft unter avr-gcc, das ist im Artikel auch erwähnt. Andere Compiler 
habe ich nicht ausprobiert.

Der Artikel soll auch keinen konkreten Bootloader vorstellen, sondern 
lediglich das allgemeine Konzept dafür erläutern, wie es beim ATtiny 
überhaupt geht. Der konkrete Trick, einen Reset-Vektor an der Adresse 
0x000 zu erzeugen ohne Assembler, obwohl die .text-Section "hinten im 
Flash" liegt, ist avr-gcc-typisch und muss bei anderen Compilern anders 
umgesetzt werden - falls das überhaupt möglich ist.

> Und unter welchen Versionen läuft er?

Ich selbst habe ihn unter avr-gcc (WinAVR 20100110) 4.3.3 programmiert 
und getestet. Er sollte aber auch mit anderen avr-gcc-Versionen 
funktionieren, wenn diese nicht gerade steinalt ist.

> Braucht sie auch nicht. Bei den ATtiny und dem ATmeg48 kann die
> Applikation direkt das SPM ausführen.

Eben. Ein Bootloader für den ATtiny ist auch kein echter Bootloader im 
strengen Sinne.

Gruß,

Frank

von Hagen R. (hagen)


Lesenswert?

Frank du solltest bemerkt haben das in dieser Diskussion die praktischen 
Anwendungsmöglichkeiten deines Vorhabens immer mehr schrumpfen.

Peter zielte mit seinen Bemerkungen korrekterweise auf die richtige 
Fragestellung: Welchen realen Hauptvorteil bietet C gegenüber Assembler 
? Unter der Annahme das der Programmierer die freie Wahl der Mittel hat, 
er also sowohl in Asm als auch in C oder jeden anderen Sprache gleich 
gut programmieren kann, besteht der Hauptvorteil in einer Hochsprache zu 
programmieren letzendlich nur in der besseren Portierbarkeit und höheren 
Effizienz bei der Fertigstellung der Software. Und exakt das sind die 
einzigen realen Gründe die für Hochsprachen im Allgemeinen sprechen. Ein 
Auftraggeber wählt die Manpower die er benötigt.

Desweiteren macht die Benutzung der Linker-Optionen, um eigene Sections 
benutzen zu können, die oben angesprochene Portierbarkeit wieder zu 
nichte.

Gleichzeitig stellte Peter fest das im Falle der Tinys sowieso die 
Anwendung den FLASH umprogrammieren könnte und damit das Sharen dieser 
Bootloader Funktionalität im Grunde überflüssig macht. Denn wenn wir 
einen C Bootloader auf dem Tiny programmieren, dann verbraucht dieser 
viel mehr zusätzlichn FLASH im Vergleich zu ASM, so das bei einem ASM 
Bootloader soviel mehr an FLASH übrig bleibt, so das die Applikation mit 
eigenen SPM Funktionen immer noch mehr FLASH zur Verfügung hätte. Das 
trifft nach meinen Erfahrungen dann auf die komplette Bootloader 
Funktionalität zu. Da meine Erfahrungen besagen das ein guter ASM Code 
ca. 50% kompakter als WinAVR GCC ist und dabei noch mehr Funktionalität 
besitzt. Mit anderen Worten: in ASM bekäme man die Bootloader 
Funktionalität > 2 mal in den gleichen FALSH den ein vergleichbarer C 
Bootloader benötigte. Mit einem ASM Bootloader hat man also in der 
eigenen Applikation soviel zusätzlichen FALSH das man die Funktionalität 
des Bootloader dort nochmal, aber dieses mal nach Bedürfnissen der 
Anwendung, programmieren könnte.

Ich möchte wirklich nicht deine Arbeit und deine Motive schlecht machen, 
ganz im Gegenteil: weil ich sehe wieviel Aufwand du in dieses Projekt 
reinsteckst, weil ich sehe das du dein Wissen teilen möchtest, weil ich 
also meine das Du meine Zeit wert bist, nehme ich mir diese Zeit und 
diskutiere mit dir um dir ein bischen von meiner Sichtweise mit zu 
geben.

So komme ich also zu dem Schluß das ein akademisches Projekt das 
zusätzlich noch eine praktische Anwendungsmöglichkeit eröffnet immer 
besser ist als ein akademsiches Projekt das nur das und nichts mehr ist. 
Bei dieser Feststellung geht es mir um Dich, denn Du machst die gleichen 
Fehler die ich in meiner Jugend machen musste, weil mich kein Erfahrener 
darauf hinwies. Ich habe Zeit verschwendet mit akademischen Projekten 
ohne praktische Ziele damit zu verfolgen. Es wäre für mich besser 
gewesen wenn ich Zeit investiert hätte in Projekte die auch ein 
praktisches Ziel verfolgten und dabei noch akademische, lehrreiche 
Erfahrungen f´ür mich enthielten.

Ich bin also der Auffassung das es gut ist wenn junge Menschen ihre 
Kreativität ausleben können, sich selbst auf die Suche machen und dabei 
aber von erfahrenen Leuten manchmal in die richtige Richtung gestubst 
werden, so das diese Jugend aus den Fehlern der Alten lernen können.

Gruß hagen

von Hagen R. (hagen)


Lesenswert?

sorry für meine schlechte Grammatik/Rechtschreibung/krummen Finger aber 
ich bin noch nicht ganz wach :)

Wie gedenkst du die Einsprungtabelle/-Funktionalität zu lösen ?

Gruß hagen

von Hagen R. (hagen)


Lesenswert?

Hagen Re schrieb:
> besteht der Hauptvorteil in einer Hochsprache zu
> programmieren letzendlich nur in der besseren Portierbarkeit und höheren
> Effizienz bei der Fertigstellung der Software

Und das letzendlich verlängert die Zeitspanne des Profites sowohl nach 
vorne wie nach hinten. Nach vorne weil man schneller fertig ist, nach 
hinten weil durch die Portierbarkeit sich der Lebenszyklus der Software 
verlängern lässt und in die Breite weil mehr Plattformen in Zukunft 
unterstützbar sind. Und bei Profit meine ich nicht nur das Geld sondern 
das Wissen für Dich und Alle anderen, wenn man es denn teilen mag.

Es geht also nur um Zeit als wichtigsten Faktor.

Gruß Hagen

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Frank du solltest bemerkt haben das in dieser Diskussion die praktischen
> Anwendungsmöglichkeiten deines Vorhabens immer mehr schrumpfen.

Natürlich sind die praktischen Anwendungsmöglichkeiten begrenzt, das 
habe ich nie bestritten. Aber auch ein Assembler-Programmierer, der 
einen Bootloader für einen ATtiny schreiben möchte, kann die 
Mechanismen, die im Artikel beschrieben werden, in seine 
Lieblingssprache Assembler "übersetzen", das ist überhaupt kein Problem. 
Ich will nur zeigen, wie es geht - mehr nicht.

Ich habe hier C gewählt, weil ich seit ca. 25 Jahren über 
Assembler-Programmierung hinaus bin. Das Thema habe ich hinter mir. Ich 
kann ein halbes Dutzend Assembler-Dialekte, angefangen bei Z80, das ich 
heute noch als Hex-Code einfach so runterschreiben kann, über M68K bis 
zu moderneren Prozessor-Architekturen. Auch PIC- und AVR-Assembler 
beherrsche ich.

Der Artikel benutzt avr-gcc im konkreten, weil hier die Sprache C 
lediglich ein anschauliches Werkzeug ist, um das Konzept eines 
Tiny-Bootloaders umzusetzen. Ich hätte auch alles in Pseudo-Code 
schreiben können. Assembler jedoch wäre hier eine schlechte Wahl 
gewesen. Wie Du schon selbst geschrieben hast, ist Assemlber nicht immer 
sehr verständlich.

Ich benutze grundsätzlich C auf AVRs - das gilt auch für Bootloader. Ich 
kann zwar AVR-Assembler problemlos lesen und verstehen, jedoch weigere 
ich mich, Assembler selber anzuwenden. Das ist aber reine Religion und 
steht hier nicht zur Debatte. Wenn ich einen ATtiny85 zu demselben Preis 
oder noch günstiger als einen ATtiny45 bekomme, warum soll ich mir dann 
Assembler antun, nur um das Ganze noch in einen ATtiny45 oder -25 zu 
quetschen?

(Der Attiny45 reicht übrigens für mein 60fach-µC-Projekt auch noch aus, 
die eigentliche Applikation ist auch nicht größer als 2KB, so dass mir 
4KB durchaus reichen)

> Peter zielte mit seinen Bemerkungen korrekterweise auf die richtige
> Fragestellung: Welchen realen Hauptvorteil bietet C gegenüber Assembler
> ?

Die Antwort ist einfach:

C ist lesbarer als Assembler - jedenfalls dann, wenn man sich bemüht, 
lesbaren Code zu schreiben. Der Leser kann sofort nachvollziehen, was da 
passiert.

> Unter der Annahme das der Programmierer die freie Wahl der Mittel hat,
> er also sowohl in Asm als auch in C oder jeden anderen Sprache gleich
> gut programmieren kann, besteht der Hauptvorteil in einer Hochsprache zu
> programmieren letzendlich nur in der besseren Portierbarkeit und höheren
> Effizienz bei der Fertigstellung der Software.

Auch von Peter habe ich schon desöfteren in der jüngeren Vergangenheit 
gelesen, dass er prinzipiell C der Assembler-Programmierung vorzieht. 
Wenn man sich Peters ältere Projekte anschaut, waren darunter sehr viele 
in Assember programmierte Geschichten. Seine jüngeren Beiträge sind fast 
allesamt in C geschrieben. Offenbar hat Peter da auch eine Entwicklung 
durchgemacht.

> Desweiteren macht die Benutzung der Linker-Optionen, um eigene Sections
> benutzen zu können, die oben angesprochene Portierbarkeit wieder zu
> nichte.

Ich erhebe hier nicht Anspruch auf Portierbarkeit, sondern auf 
Lesbarkeit. Bei Programmen für Unix-/Linux achte ich jedoch sehr auf 
Portierbarkeit. Da lassen sich meine Programme auf so ziemlich allen 
Unix-Derivaten ohne jegliche Anpassungen des Quellcodes übersetzen.

Auch mein IRMP-Projekt läuft sowohl auf AVRs, auf PICs, unter Unix, 
unter Linux, unter Windows als auch auf diversen ARMs. Das ist überhaupt 
kein Problem.

Aber bei einer so hardwarenahen Geschichte wie einem Tiny-Bootloader 
tritt Portierbarkeit auf einen anderen C-Compiler in den Hintergrund. 
Hier muss der Leser des Artikels die Gedankengänge auf seinen Compiler 
bzw. seine Programmiersprache selbst adaptieren.

Assembler-Source kann noch so gut dokumentiert sein, nach 3 Jahren 
versteht man seinen eigenen Source nicht mehr und muss sich komplett neu 
einarbeiten ins eigene Programm und in die eigenen Gedankengänge, die 
man damals hatte. Man muss alles wieder mühsehlig rekonstuieren. Bei C 
erkenne ich auf einen Blick, was ich da vor 3 Jahren 
"zusammengeschustert" habe.

> Gleichzeitig stellte Peter fest das im Falle der Tinys sowieso die
> Anwendung den FLASH umprogrammieren könnte und damit das Sharen dieser
> Bootloader Funktionalität im Grunde überflüssig macht.

Das ist nichts neues. Das habe ich Dir bereits gestern hier mitgeteilt, 
dass die Applikation auf ATtinys tun und lassen kann, was sie will und 
daher ATtinys "nicht sicher" sind.

> Denn wenn wir
> einen C Bootloader auf dem Tiny programmieren, dann verbraucht dieser
> viel mehr zusätzlichn FLASH im Vergleich zu ASM,

Es geht mir nicht um den Flash-Verbrauch, sondern um die Vorstellung 
eines Konzepts. Und da ist C als Werkzeug das Mittel der Wahl.

Ich habe bereits heute morgen folgende Passage in den Artikel eingefügt, 
nur damit sich die Assembler-Programmierer nicht angepisst fühlen, weil 
ich "geheime Algorithmen" veröffentliche:

-------------------------- >8 schnipp) 8< ----------------------------
Da ein in Assembler geschriebener Bootloader in der Regel viel weniger 
Speicherplatz benötigt und daher effizienter auf einem kleinen µC ist 
als ein in C programmierter Bootloader, ist dieser Artikel eher 
akademischer Natur. Hier sollen lediglich die Mechanismen, die nötig 
sind, um für einen ATtiny einen Bootloader zu realisieren, ausführlichst 
vorgestellt werden. Ein Einsatz in der Praxis ist durchaus möglich, 
jedoch wird in den meisten Fällen ein in Assember geschriebener 
Bootloader (auch wenn man ihn evtl. gar nicht versteht) die bessere Wahl 
sein.
-------------------------- >8 schnapp) 8< ----------------------------

Ich hoffe, dass sich nun niemand mehr an den Karren gefahren fühlt, nur 
weil er meint, ich wolle die bereits hier im Forum (speziell in der 
Codesammlung) vorgestellten Bootloader komplett in Frage stellen.

> Ich möchte wirklich nicht deine Arbeit und deine Motive schlecht machen,
> ganz im Gegenteil: weil ich sehe wieviel Aufwand du in dieses Projekt
> reinsteckst, weil ich sehe das du dein Wissen teilen möchtest, weil ich
> also meine das Du meine Zeit wert bist, nehme ich mir diese Zeit und
> diskutiere mit dir um dir ein bischen von meiner Sichtweise mit zu
> geben.

Ich fand die mir selbst gestellte Aufgabe, einen Tiny-Bootloader in C zu 
realisieren, so ungeheuer spannend, dass ich mir dachte, dass der Weg, 
um dorthin zu kommen, auch für andere interessant sein könnte. Dieses 
mündete in den Artikel, der mit dem Wort "Konzept" beginnt. Ich hoffe, 
dass die Leser dieses kleine aber wichtige Wörtchen zu schätzen wissen.

> Ich bin also der Auffassung das es gut ist wenn junge Menschen ihre
> Kreativität ausleben können, sich selbst auf die Suche machen und dabei
> aber von erfahrenen Leuten manchmal in die richtige Richtung gestubst
> werden, so das diese Jugend aus den Fehlern der Alten lernen können.

Hagen, Du bist auf dem völlig falschen Dampfer. Ich habe bereits die 50 
Jahre überschritten und programmiere seit 30 Jahren kommerziell in allen 
möglichen Programmiersprachen. Ich habe sogar selbst schon 
Programmiersprachen entwickelt, die kommerziell eingesetzt werden. Wenn 
Du mal auf meine "Benutzerseite" geklickt hättest, würdest Du sehen, 
dass ich ein ganz alter Hase bin. Du kannst mich aber trotzdem schubsen 
- auch wenn Du mir nichts vormachen kannst ;-)

Gruß,

Frank

P.S.
Ab und zu stehen die Fragezeichen in Deinen Postings auf einer extra 
Zeile, ist Dir das schon mal aufgefallen? Das sieht höchst komisch aus. 
Plenken sollte man meiden ;-)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Wie gedenkst du die Einsprungtabelle/-Funktionalität zu lösen ?

Es ist eine Struct mit Pointern auf Funktionen. Diese wird über eine 
definierte Adresse im Flash ausgetauscht - ganz einfach.

Alles, was im Artikel unter "TODO" steht, läuft bei mir längst. Die 
Schreiberei des Artikels macht einfach Arbeit. Deshalb sind die Passagen 
dort noch leer.

Gruß,

Frank

von Hagen R. (hagen)


Lesenswert?

Frank M. schrieb:
> Hagen Re schrieb:
>> Frank du solltest bemerkt haben das in dieser Diskussion die praktischen
>> Anwendungsmöglichkeiten deines Vorhabens immer mehr schrumpfen.
>
> Natürlich sind die praktischen Anwendungsmöglichkeiten begrenzt, das
> habe ich nie bestritten. Aber auch ein Assembler-Programmierer, der
> einen Bootloader für einen ATtiny schreiben möchte, kann die
> Mechanismen, die im Artikel beschrieben werden, in seine
> Lieblingssprache Assembler "übersetzen", das ist überhaupt kein Problem.
> Ich will nur zeigen, wie es geht - mehr nicht.

Tja aber wie sinnvoll ist es dann solche Technologien in Assembler 
umzusetzen wenn dadurch kein Vorteil mehr erlengt wird ?

> Ich habe hier C gewählt, weil ich seit ca. 25 Jahren über
> Assembler-Programmierung hinaus bin.

Das war mein Risiko als ich abschätzen musste ob ich mit einem 
erfahrenen Entwickler oder mit einem Jungsporn diskutiere ;)

> Ich benutze grundsätzlich C auf AVRs - das gilt auch für Bootloader. Ich
> kann zwar AVR-Assembler problemlos lesen und verstehen, jedoch weigere
> ich mich, Assembler selber anzuwenden. Das ist aber reine Religion...

Möö es ist Dummheit, genauer gesagt Ignoranz. Wenn Du selber von Dir 
behuptest das du die freie Wahl der Mittel hast und nicht das Geeigneste 
auswählst nach objektiven Erfordernissen, sondern auf Glaube basierend, 
dann ist das Ignorranz.

> steht hier nicht zur Debatte. Wenn ich einen ATtiny85 zu demselben Preis
> oder noch günstiger als einen ATtiny45 bekomme, warum soll ich mir dann
> Assembler antun, nur um das Ganze noch in einen ATtiny45 oder -25 zu
> quetschen?

Ah, und warum dann mit C arbeiten wenn man eh die freie Wahl hat und 
dann in Assembler den 45'er nehmen kann was dann Kosten senken wird ?

> (Der Attiny45 reicht übrigens für mein 60fach-µC-Projekt auch noch aus,
> die eigentliche Applikation ist auch nicht größer als 2KB, so dass mir
> 4KB durchaus reichen)

Jo, die Fakten sich schön reden ;)

> C ist lesbarer als Assembler - jedenfalls dann, wenn man sich bemüht,
> lesbaren Code zu schreiben. Der Leser kann sofort nachvollziehen, was da
> passiert.

Denkfehler in den kausalen Zusammenhängen. Assembler ist genauso leicht 
lesbar wie C wenn man es kann.

> Auch von Peter habe ich schon desöfteren in der jüngeren Vergangenheit
> gelesen, dass er prinzipiell C der Assembler-Programmierung vorzieht.

Das tut ich auch, aber meine Prinzipien bei dieser Entscheidung heissen 
das prinzipiel nach dem geeigneten Mittel gesucht wird und das auch 
benutzt wird. Prinzipiell heist also aus objektiven Erwägungen heraus 
und nicht aus Glauben heraus, mein Prinzip heist nicht glauben zu 
wollen.

> Wenn man sich Peters ältere Projekte anschaut, waren darunter sehr viele
> in Assember programmierte Geschichten. Seine jüngeren Beiträge sind fast
> allesamt in C geschrieben. Offenbar hat Peter da auch eine Entwicklung
> durchgemacht.

Tja, und was heist das jetzt ? Weil Peter der Meinung ist das C immer 
besser wäre ? Oder nur das Peter seinen Lebenshorizont so wie ich 
übrschritten hat und das Gefühl die eigene Zeit wird knapper kennt ?

> Ich erhebe hier nicht Anspruch auf Portierbarkeit, sondern auf
> Lesbarkeit.

Dann wäre es geschickter Assembler als ein Mittel der Wahl den neulingen 
näher zu bringen da es für diese Aufgabe desöfteren die bessere Wahl 
ist.

>Bei Programmen für Unix-/Linux achte ich jedoch sehr auf
> Portierbarkeit. Da lassen sich meine Programme auf so ziemlich allen
> Unix-Derivaten ohne jegliche Anpassungen des Quellcodes übersetzen.

Du betrachtest geänderte Umweltbedingungen, hier geht es um Bootloader 
und nicht allgmein um andere Projekte. Hier geht es um AVRs und nicht 
UNIX PCs.

> Auch mein IRMP-Projekt läuft sowohl auf AVRs, auf PICs, unter Unix,
> unter Linux, unter Windows als auch auf diversen ARMs. Das ist überhaupt
> kein Problem.

Bestreitet ja keiner.

> Aber bei einer so hardwarenahen Geschichte wie einem Tiny-Bootloader
> tritt Portierbarkeit auf einen anderen C-Compiler in den Hintergrund.

Ah, meine Rede ;)

> Hier muss der Leser des Artikels die Gedankengänge auf seinen Compiler
> bzw. seine Programmiersprache selbst adaptieren.

Warum sollte er, es gibt genügend fertige Bootloader.

> Assembler-Source kann noch so gut dokumentiert sein, nach 3 Jahren
> versteht man seinen eigenen Source nicht mehr und muss sich komplett neu
> einarbeiten ins eigene Programm

Indiz für was ? Das der Entwickler an Alzheimer leidet ? das der 
Entwickler nicht gut dokumentieren kann ?

> und in die eigenen Gedankengänge, die
> man damals hatte. Man muss alles wieder mühsehlig rekonstuieren. Bei C
> erkenne ich auf einen Blick, was ich da vor 3 Jahren
> "zusammengeschustert" habe.

Und so könnte es auch in Assembler sein, die Freiheit für den Entwickler 
in Asm sind größer als in C warum sollte dann C grundsätzlich loeichter 
lesbar sein als Assembler ? Das liegt nicht in diesen Sprachen begründet 
sondern in unseren Fähigkeiten. Das hat jeder selbst in der Hand und ist 
unabhängig von der Programmiersprache.

Ändert aber nichts daran das Hochsprache eher auf das natürliche 
menschliche Denken abgestimmt sind als Assembler.

>> Gleichzeitig stellte Peter fest das im Falle der Tinys sowieso die
>> Anwendung den FLASH umprogrammieren könnte und damit das Sharen dieser
>> Bootloader Funktionalität im Grunde überflüssig macht.
>
> Das ist nichts neues. Das habe ich Dir bereits gestern hier mitgeteilt,
> dass die Applikation auf ATtinys tun und lassen kann, was sie will und
> daher ATtinys "nicht sicher" sind.

Gut das Dir das klar ist nur dann verstehe ich nicht warum du der 
Argumentation nicht folgen möchtest.

>> Denn wenn wir
>> einen C Bootloader auf dem Tiny programmieren, dann verbraucht dieser
>> viel mehr zusätzlichn FLASH im Vergleich zu ASM,
>
> Es geht mir nicht um den Flash-Verbrauch, sondern um die Vorstellung
> eines Konzepts. Und da ist C als Werkzeug das Mittel der Wahl.

Das habe ich begriffen, ich zweifle den Nutzen dieses Konzeptes an.

> -------------------------- >8 schnipp) 8< ----------------------------
> Da ein in Assembler geschriebener Bootloader in der Regel viel weniger
> Speicherplatz benötigt und daher effizienter auf einem kleinen µC ist
> als ein in C programmierter Bootloader, ist dieser Artikel eher
> akademischer Natur. Hier sollen lediglich die Mechanismen, die nötig
> sind, um für einen ATtiny einen Bootloader zu realisieren, ausführlichst
> vorgestellt werden. Ein Einsatz in der Praxis ist durchaus möglich,
> jedoch wird in den meisten Fällen ein in Assember geschriebener
> Bootloader (auch wenn man ihn evtl. gar nicht versteht) die bessere Wahl
> sein.
> -------------------------- >8 schnapp) 8< ----------------------------

Schade eigentlich aber wahr. Schade weil das Konzept deines Artikels 
schon innerhalb deines Artikels als fragwürdig dargelegt wird.

> Ich hoffe, dass sich nun niemand mehr an den Karren gefahren fühlt, nur
> weil er meint, ich wolle die bereits hier im Forum (speziell in der
> Codesammlung) vorgestellten Bootloader komplett in Frage stellen.

Hey, überlege mal logisch: warum sollte ich mich so fühlen als ob man 
mir an den Karren gepisst hätte. Ich bin hier der Pisser ;)

> Ich fand die mir selbst gestellte Aufgabe, einen Tiny-Bootloader in C zu
> realisieren, so ungeheuer spannend, dass ich mir dachte, dass der Weg,
> um dorthin zu kommen, auch für andere interessant sein könnte. Dieses
> mündete in den Artikel, der mit dem Wort "Konzept" beginnt. Ich hoffe,
> dass die Leser dieses kleine aber wichtige Wörtchen zu schätzen wissen.

Exakt das hättest du vor deinem obigen Absatz in den Artikel schreiben 
sollen. Es erklärt deine Motive und der geneigte Leser weiß sofort was 
er zu erwarten hat und welchen Nutzen er rausziehen möchte.

>> Ich bin also der Auffassung das es gut ist wenn junge Menschen ihre
>> Kreativität ausleben können, sich selbst auf die Suche machen und dabei
>> aber von erfahrenen Leuten manchmal in die richtige Richtung gestubst
>> werden, so das diese Jugend aus den Fehlern der Alten lernen können.
>
> Hagen, Du bist auf dem völlig falschen Dampfer. Ich habe bereits die 50
> Jahre überschritten und programmiere seit 30 Jahren kommerziell in allen
> möglichen Programmiersprachen. Ich habe sogar selbst schon

Jo das habe ich jetzt auch wahrgenommen, ich lache jetzt immer noch über 
mich da meine Progonse das du ein Jungspunt wärest mal wieder, wie so 
viele Prognosen im Leben, voll in die Hose gegangen ist;) Wie oben 
gesagt, diese Risiko der Fehleinschätzung musst ich eingehen da die 
Alternative eben schlechter ist. Es ist ein erfahrener Entwickler der 
sich auf den Weg macht dieses Konzeopt zu entwickeln;)

> Programmiersprachen entwickelt, die kommerziell eingesetzt werden. Wenn
> Du mal auf meine "Benutzerseite" geklickt hättest, würdest Du sehen,
> dass ich ein ganz alter Hase bin. Du kannst mich aber trotzdem schubsen
> - auch wenn Du mir nichts vormachen kannst ;-)

Das war ein Fehler meinerseits unbestritten, ich habe es schlicht 
übersehen da ich mich inhaltilich auf deinen Artikel fokusiert habe.

> Ab und zu stehen die Fragezeichen in Deinen Postings auf einer extra
> Zeile, ist Dir das schon mal aufgefallen? Das sieht höchst komisch aus.
> Plenken sollte man meiden ;-)

Jo ist mir, blöde Forensoftware die solche Details nicht autom. regeln 
kann. Und bitte, da gleich auf plenken zu schließen sieht schon nach 
persönlichem Ehrgeiz aus. Wie gesagt: das Leben ist zu kurz, die eigenen 
Fußspuren im  WEB viel zu schnell verblasst, da sollte man schnell 
lernen nichts persönlich zu nehmen ;)

>Es ist eine Struct mit Pointern auf Funktionen. Diese wird über eine
>definierte Adresse im Flash ausgetauscht - ganz einfach.

Hm, und warum nicht deine Sections, die du ja als Kern des Lehrbeispiels 
anführst, dafür benutzen ? Also eine Section in der diese Struct an 
fester Adresse liegt ? In meinen AVRootloader befindet sich diese 
Sprungtabelle direkt am Ende des FLASHs. Das Ende und die Anzahl der 
Einträge sind bekannt, ergo stellt sich die Frage welchen Vorteil hat 
deine dynamsiche Ermittlung dieser Adresse über eine eigene Funktion ?

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Frank M. schrieb:
> Hagen Re schrieb:
>> Wie gedenkst du die Einsprungtabelle/-Funktionalität zu lösen ?
>
> Es ist eine Struct mit Pointern auf Funktionen. Diese wird über eine
> definierte Adresse im Flash ausgetauscht - ganz einfach.

Shit, entschuldige bitte ich habe das falsch interpretiert. Du gehst ja 
damit schon den Weg den ich im vorherigen Posting ansprach.

Denoch nochmal zur Verfikation: Diese Struct ist deine Sprungtabelle und 
wird im FLASH an fester und bekannter Adresse gespeichert. Es gibt also 
keine weitere Funktion die nötig ist um diese Adresse zu ermitteln ?

Interessant ist dann nämlich die Frage an welche Adresse du diese 
Sprungtabelle reallokieren möchtest und wie du das am geschicktesten dem 
GCC beibringst, da ja Änderungen an dieser Sprungtabelle zu einer 
geänderten Reallokation im Linker führen muß, also die nötige 
Deklaration deisr Section dem Linker möglichst dynamisch beigebracht 
werden muß.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Frank, wo finde ich den diesen Link auf deine private Seite ? Ich bin zu 
blöd den im Artikel zu finden :(

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
>> steht hier nicht zur Debatte. Wenn ich einen ATtiny85 zu demselben Preis
>> oder noch günstiger als einen ATtiny45 bekomme, warum soll ich mir dann
>> Assembler antun, nur um das Ganze noch in einen ATtiny45 oder -25 zu
>> quetschen?
>
> Ah, und warum dann mit C arbeiten wenn man eh die freie Wahl hat und
> dann in Assembler den 45'er nehmen kann was dann Kosten senken wird ?

Ich bitte Dich, genau zu lesen, nicht meine Passagen zu überfliegen. Da 
oben steht, dass ich entweder den ATtiny85 günstiger oder zumindest zu 
demselben Preis wie einen ATtiny45 bekomme. Es senkt also keine Kosten, 
wenn ich den Tiny45 nehme - ganz im Gegenteil: das Projekt wird teurer.

Zum Beispiel bei Mouser:

   ATtiny85 1,07 + 19% MwSt
   ATtiny45 1,36 + 19% MwSt

Also komm mir bitte nicht mit Kosten, die man mit Assembler einsparen 
kann - ganz im Gegenteil: Deine Wahl ist teurer.

> Jo, die Fakten sich schön reden ;)

Die Fakten stehen da oben - in knallharten Euros.

> Denkfehler in den kausalen Zusammenhängen. Assembler ist genauso leicht
> lesbar wie C wenn man es kann.

Das ist Geschmackssache. Ich könnte hier jetzt auch mit Ignoranz 
Deinerseits zurückschießen, verkneife mir das aber. Diese Diskussion (C 
vs Assembler) wird hier jeden Tag in irgendwelchen anderen Threads 
geführt. Das Thema gehört hier einfach nicht hin. Ich habe die Freiheit, 
mir meine Programmiersprache selbst auszusuchen. Punkt.

> Das tut ich auch, aber meine Prinzipien bei dieser Entscheidung heissen
> das prinzipiel nach dem geeigneten Mittel gesucht wird und das auch
> benutzt wird. Prinzipiell heist also aus objektiven Erwägungen heraus
> und nicht aus Glauben heraus, mein Prinzip heist nicht glauben zu
> wollen.

Ich sage dazu nur noch eins: Bootloader in C sind genauso 
praxistauglich, wenn man vom Flash-Verbrauch absieht. Es gibt keine 
sonstigen Nachteile, höchstens Vorteile.

> Du betrachtest geänderte Umweltbedingungen, hier geht es um Bootloader
> und nicht allgmein um andere Projekte. Hier geht es um AVRs und nicht
> UNIX PCs.

Ich wollte nur erläutern, wann ich wo welche Schwerpunkte setze. Diese 
können von Projekt zu Projekt verschieden sein.

>> Aber bei einer so hardwarenahen Geschichte wie einem Tiny-Bootloader
>> tritt Portierbarkeit auf einen anderen C-Compiler in den Hintergrund.
>
> Ah, meine Rede ;)

Na also. Hier ist mein Schwerpunkt nicht Portierbarkeit, sondern 
Lesbarkeit.

> Warum sollte er, es gibt genügend fertige Bootloader.

Ja, besonders Deinen. Ich wusste genau, warum Du auf diesen Thread so 
schnell angesprungen bist. Tut mir leid, dass ich den Link auf Deinen 
Bootloader im Artikel vergessen habe. Habe ich nun nachgeholt.

Auf diesen Sch...-Satz habe ich die ganze Zeit gewartet. Gekränkte 
Eitelkeit oder was soll das? Mit diesem Argument kannst Du alles 
schlachten. "Warum baust Du Dir eine Uhr? Es gibt genügend fertige Uhren 
auf der Welt!". Booah, nicht zu fassen.

Für die fertigen Tiny-Bootloader gibt es aber keine begleitenden Artikel 
im Wiki. Oder hast Du vielleicht ausserhalb Deines Sources irgendwo 
Deinen Bootloader derart dokumentiert, dass jemand die Technik, wie er 
funktioniert, verstehen kann?

Ich verwende keine Software, die ich nicht verstehe. Ich möchte mir 
nicht den Aufwand antun, einen fremden in Assembler programmierten 
Bootloader zu verstehen, bis ich ihn verwende. Da ist mir die Zeit zu 
schade. In der gleichen Zeit habe ich ihn in C neu geschrieben und habe 
es selbst getan. Reicht dir das als Gegenargument?

> Das habe ich begriffen, ich zweifle den Nutzen dieses Konzeptes an.

Das bleibt Dir überlassen. Ich habe den Artikel nicht für Dich 
geschrieben.

> Jo das habe ich jetzt auch wahrgenommen, ich lache jetzt immer noch über
> mich da meine Progonse das du ein Jungspunt wärest mal wieder, wie so
> viele Prognosen im Leben, voll in die Hose gegangen ist;)

Man sollte sich die Leute vorher genau anschauen, bevor man sich auf sie 
einlässt. Ich kenne auch Deine Beiträge in diesem Forum ganz genau.

> Wie oben
> gesagt, diese Risiko der Fehleinschätzung musst ich eingehen da die
> Alternative eben schlechter ist. Es ist ein erfahrener Entwickler der
> sich auf den Weg macht dieses Konzeopt zu entwickeln;)

Dieses Risiko gab es gar nicht. Meine Benutzerseite existiert schon seit 
vielen Monaten.

> Jo ist mir, blöde Forensoftware die solche Details nicht autom. regeln
> kann. Und bitte, da gleich auf plenken zu schließen sieht schon nach
> persönlichem Ehrgeiz aus. Wie gesagt: das Leben ist zu kurz, die eigenen
> Fußspuren im  WEB viel zu schnell verblasst, da sollte man schnell
> lernen nichts persönlich zu nehmen ;)

Man sollte als erstes vielleicht lernen, dass es viel mehr Arbeit für 
tausende von Lesern ist, Deine falsche Punktuation beim Lesen im Kopf zu 
korrigieren, als es für den einzelnen Schreiber Arbeit ist, das 
Fragezeichen an die richtige Stelle zu schreiben. Du machst diese Arbeit 
nur einmal, die Leser müssen es tausendfach tun. Das ist Verschwendung 
von Ressourcen ohne Ende.

> Hm, und warum nicht deine Sections, die du ja als Kern des Lehrbeispiels
> anführst, dafür benutzen ? Also eine Section in der diese Struct an
> fester Adresse liegt ?

Das ginge auch, braucht aber mehr Flash. Ich speichere lediglich den 
Pointer auf die Struktur, Du willst aber den Inhalt der Struktur im 
Flash sehen. Hatte ich vorher auch mal so ausprobiert, hat mich aber 
nicht ganz zufriedengestellt. Ich werde das nochmal überdenken, denn es 
gibt dafür ein paar Für und Widers.

Viele Deiner Antworten zeigen mir, wer von uns beiden ignorant ist. 
Größtes Manko ist bei Dir, dass Du nicht genau liest. Bis auf den 
letzten Absatz in Deinem Posting halte ich den Rest lediglich gut genug 
für die Tonne. Den letzten Absatz halte ich für konstruktiv, da sie der 
Sache förderlich ist. Den Rest hier habe ich nur aus Gründen der 
Höflichkeit beantwortet.

Ich werde auf Deine Provokationen in Zukunft nicht mehr eingehen und sie 
einfach ignorieren. Wenn Du aber etwas konstruktives beizusteuern hast, 
werde ich mich selbstverständlich darüber freuen.

Gruß,

Frank

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Frank, wo finde ich den diesen Link auf deine private Seite ? Ich bin zu
> blöd den im Artikel zu finden :(

Der Link steht in jedem meiner Thread-Beiträge. Du klickst einfach auf 
das Blatt-Symbol rechts neben meinem Kürzel ukw:

       Autor: Frank M. (ukw) [ ]
                              ^
                              hier

Aber für Dich hier nochmal:

  http://www.mikrocontroller.net/articles/Benutzer:ukw

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Shit, entschuldige bitte ich habe das falsch interpretiert. Du gehst ja
> damit schon den Weg den ich im vorherigen Posting ansprach.

Ja, eigentlich schon. Es gibt nur die Frage zu klären, ob der komplette 
Inhalt der Struct oder nur der Pointer auf diese gespeichert werden 
soll.

Die erste Alternative braucht mehr Flash, Zugriffe über Pointer sind 
aber langsamer (und brauchen dann auch wieder mehr Flash, nämlich an 
Code)

Um das zu erläutern:

    boot.uart_getc ();

ist schneller und verbraucht weniger Flash als

    boot->uart_getc ();

Ich werde wohl den Mittelweg gehen: Pointer auf die Struct im vorletzten 
Wort des Flashs und ein Kopieren der Inhalte per memcpy_P(). Aber 
eigentlich ist jedem Anwender das selbst überlassen, denn es betrifft 
die Anwendung, nicht den Bootloader.

> Denoch nochmal zur Verfikation: Diese Struct ist deine Sprungtabelle und
> wird im FLASH an fester und bekannter Adresse gespeichert.

Ja.

> Es gibt also
> keine weitere Funktion die nötig ist um diese Adresse zu ermitteln ?

Ja.

> Interessant ist dann nämlich die Frage an welche Adresse du diese
> Sprungtabelle reallokieren möchtest und wie du das am geschicktesten dem
> GCC beibringst, da ja Änderungen an dieser Sprungtabelle zu einer
> geänderten Reallokation im Linker führen muß, also die nötige
> Deklaration deisr Section dem Linker möglichst dynamisch beigebracht
> werden muß.

Eben deshalb mache ich es ohne Sections. Ich knalle einfach den Wert des 
Pointers auf die existierende(!) Struct in das vorletzte Wort des 
Flashs. Die Anwendung kann sich das einfach abholen mit:
1
#include "tinyboot.h" 
2
struct BOOT_FUNCTIONS * boot;
3
...
4
  boot = (void *) pgm_read_word (BOOTLOADER_FUNCTIONS_ADDRESS);

Fertig. Und schon kann er zugreifen auf boot->uart_poll() bzw. 
boot->uart_getc().

Alternativ ohne Pointer:
1
struct BOOT_FUNCTIONS boot;
2
...
3
  memcpy_P (&boot, (void *) BOOTLOADER_FUNCTIONS_ADDRESS, sizeof BOOTLOADER_FUNCTIONS);

Dann geschieht der Aufruf über boot.uart_poll() bzw. boot.uart_getc(). 
Das ist etwas effizienter, hat aber den Nachteil, dass die Struct 2x im 
SRAM liegt - einmal im SRAM des Bootloaders und einmal im SRAM der 
Applikation.

von Hagen R. (hagen)


Lesenswert?

Danke Frank für die Infos mit dem kleinen Symbol neben den Namen ich 
dachte das wäre der PN Button zusätzlich zum blauen Namen.

Sicherlich wirst Du verstehen können das keiner sich soviel Zeit nehmen 
wird erstmal all diese Links soweit zu folgen bis der geneigte WEB 
Besucher sich ausmalen kann wen er vor sich hat. Ich mache das niemals 
da ich nicht die Zeit habe mich neben dem rein inhaltlichen noch mit 
personellem zu befassen. Davon abgesehen stellt sich die Frage welchen 
Nutzen ich dann von personalisiertem, gefärbtem Wissen haben sollte, bei 
dem man nie die dahinter liegenden wahren Absichten der Personen 
erkennen kann. Ausnahmen bestätigen diese Regel, aber dann lohnt sich 
für mich der Zeitaufwand auch.

Ansonsten bitte ich dich um Nachsicht das meine Argumente dich so 
persönlich verletzt haben, das war sicherlich nicht meine Absicht. Ich 
bin deiner Einladung zu einer Diskussion gefolgt, einer Diskussion über 
das Konzept und den Alternativen, also inhaltlich. Eben weil ich der 
Meinung war das meine praktischen Erfahrungen von Interese sein könnten.

Die Kritik an meiner Schreibweise kann ich gut verstehen, was wäre wenn 
du von mir wüsstest das ich Legastheniker bin, das ich im Praktikum im 
Sägewerk 6 Finger verloren habe, würde das deine Meinung verändern?

Mein Schreibstil ist eine Frage meiner Persönlichkeit meiner eventuell 
eingeschänkten Fertigkeiten und meiner Gechichte, aber der Inhalt ist 
eine Frage des Geistes, Wissens, Ideen. Es macht keinerlei Sinn in 
irgendeiner Form Aussagen im WEB persönlich zu nehmen oder persönliche 
Aussagen als objektiv wahrzunhmen, Die inhaltliche Diskussion, Argumente 
und Kritik sind es die zählen. Hast du meine Kommentare wirklich so 
persönlich genommen? für mich unverständlich.

Egal: ich halte mich demnächst zurück und verfolge den Fortschritt 
deines Artikels, Ehrenwort ;)

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Frank M. schrieb:
> Hagen Re schrieb:
>> Shit, entschuldige bitte ich habe das falsch interpretiert. Du gehst ja
>> damit schon den Weg den ich im vorherigen Posting ansprach.
>
> Ja, eigentlich schon. Es gibt nur die Frage zu klären, ob der komplette
> Inhalt der Struct oder nur der Pointer auf diese gespeichert werden
> soll.
>
> Die erste Alternative braucht mehr Flash, Zugriffe über Pointer sind
> aber langsamer (und brauchen dann auch wieder mehr Flash, nämlich an
> Code)
>
> Um das zu erläutern:
>
>     boot.uart_getc ();
>
> ist schneller und verbraucht weniger Flash als
>
>     boot->uart_getc ();
>
> Ich werde wohl den Mittelweg gehen: Pointer auf die Struct im vorletzten
> Wort des Flashs und ein Kopieren der Inhalte per memcpy_P(). Aber
> eigentlich ist jedem Anwender das selbst überlassen, denn es betrifft
> die Anwendung, nicht den Bootloader.

Aus eben diesen Erwägungen heraus kommt meine Frage. Die Größe dieser 
Struct ist im Grunde nur abhängig von der Anzahl an Funktionen die aus 
dem Bootloader exportiert werden sollen, also mit größter 
Wahrscheinlichkeit fix. Du hast schon am Ende einen Sprung zur Main der 
Applikation hinterlegt, warum davor/dahinter nicht auch alle andernen 
Exporte ?
Der Vorteil akkumuliert sich dann beim Aufruf dieser Funktionen aus der 
Anwendung heraus, schneller und weniger FALSH. Dieser Vorteil wächst mit 
der Nützlichkeit undd amit höhren Häufigkeit deren Benutzung durch die 
Applikation.

Auch entfällt der zusätzliche Speicherverbrauch an knappen SRAM und 
FLASH um diese Sprungtabelle mit zusätzlichen MCU-Takten umzukopieren.

Davon abgesehen sehe ich diese "Umkopiererei" im Artikel ebenfalls als 
zusätzliche unnötige Operationen die nur die Wahrscheinlichkeiten von 
Fehlern inkrementieren. zB. ist das Tor geöffnet für Inkonsistenzen wenn 
man die gleiche Tabelle gleich zweimal im SRAM kopiert hat.

Das Interessante für den Leser des Konzeptes ist nun wie man dem GCC 
Linker möglichst transparent diese Reallokation beibringt.

Bitte! diese Worte sind inhaltlicher Natur, selbst wenn der Autor Gott 
hiese wäre der mir egal, es geht um inhaltliche Alternativen.

Gruß Hagen

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Sicherlich wirst Du verstehen können das keiner sich soviel Zeit nehmen
> wird erstmal all diese Links soweit zu folgen bis der geneigte WEB
> Besucher sich ausmalen kann wen er vor sich hat.

Ich halte es schon für wichtig. Wenn ich jemandem antworte, will ich 
auch wissen, wen ich vor mir habe - das gilt hier auch wie im realen 
Leben. Also werde ich mich schlaumachen... und kann dann mit dem 
Gegenüber auf Augenhöhe diskutieren.

> Ansonsten bitte ich dich um Nachsicht das meine Argumente dich so
> persönlich verletzt haben, das war sicherlich nicht meine Absicht.

Ich reagiere nur auf eines allergisch... nämlich, wenn es "von oben 
herab" erscheint. Und es tut mir leid, Dir sagen zu müssen, dass ich 
diesen Eindruck des öfteren hatte beim Lesen Deiner Antworten.

> Die Kritik an meiner Schreibweise kann ich gut verstehen, was wäre wenn
> du von mir wüsstest das ich Legastheniker bin, das ich im Praktikum im
> Sägewerk 6 Finger verloren habe, würde das deine Meinung verändern?

Selbstverständlich würde das meine Meinung ändern. Ich weiß aber, dass 
Du weder Legastheniker bist noch jemals in einem Sägewerk gearbeitet 
hast ;-)

> [...] Es macht keinerlei Sinn in
> irgendeiner Form Aussagen im WEB persönlich zu nehmen [...]

Korrekt. Es macht aber auch keinerlei Sinn, sich im Web anders zu 
benehmen als im realen Leben. Es ist ein Privileg, hier schreiben zu 
dürfen. Dieses Privileg sollte man nicht missbrauchen, schon gar nicht, 
um hier die Sau rauszulassen. Ganz im Gegenteil: man sollte dem Leser 
den geeigneten Respekt erweisen. Das fängt schon mit der Sorgfältigkeit 
des Schreibens (hinsichtlich Rechschreibung) an.

> Hast du meine Kommentare wirklich so
> persönlich genommen? für mich unverständlich.

Die etwas größere Distanz über das Internet lässt einigen Leuten schon 
mal schnell das eine oder andere Wort aus der Feder (... ähem Tastatur) 
gleiten, was sie im realen Leben niemals dem jeweiligen Gegenüber ins 
Gesicht gesagt hätten.

Mich störte - wie oben schon erwähnt - Deine Behandlung "von oben 
herab". Sonst ist alles okay, mach Dir keine Gedanken ;-)

> Egal: ich halte mich demnächst zurück und verfolge den Fortschritt
> deines Artikels, Ehrenwort ;)

Na prima. Wie gesagt: Kommentare zur Sache sind immer gern gesehen.

Gruß,

Frank

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Aus eben diesen Erwägungen heraus kommt meine Frage. Die Größe dieser
> Struct ist im Grunde nur abhängig von der Anzahl an Funktionen die aus
> dem Bootloader exportiert werden sollen,

Korrekt.

> also mit größter Wahrscheinlichkeit fix.

Auch richtig.

> Du hast schon am Ende einen Sprung zur Main der Applikation hinterlegt,
> warum davor/dahinter nicht auch alle andernen Exporte ?

Genau so mache ich es doch, hier ein Auszug aus meinem Source:

tinyboot.h:
1
#define BOOTLOADER_APPL_ADDRESS (BOOTLOADER_ENDADDRESS - 2)
2
#define BOOTLOADER_FUNC_ADDRESS (BOOTLOADER_ENDADDRESS - 4)
3
4
typedef struct
5
{
6
    uint8_t                     (*uart_getc) (void);
7
    void                        (*uart_putc) (unsigned char);
8
    void                        (*set_timer1_compa_isr) (void (*) (void));
9
    void                        (*set_pcint0_isr) (void (*) (void));
10
} BOOTLOADER_FUNCTIONS;

tinyboot.c:
1
static BOOTLOADER_FUNCTIONS bootloader_functions;
2
int
3
main ()
4
{
5
    ...
6
7
    bootloader_functions.uart_getc                  = uart_getc;
8
    bootloader_functions.uart_putc                  = uart_putc;
9
    bootloader_functions.set_timer1_compa_isr       = set_timer1_compa_isr;
10
    bootloader_functions.set_pcint0_isr             = set_pcint0_isr;
11
    ...
12
    pgm_write_word (BOOTLOADER_FUNC_ADDRESS, (uint16_t) (&bootloader_functions));
13
    ...
14
}

Ich sehe schon, ich sollte das mal endlich in den Artikel reinschreiben, 
bevor hier noch wilde Spekulationen auftreten ;-)

Okay, ich erläutere hier schon mal die oben genannten Funktionen, bevor 
gleich wieder gefragt wird:

uart_getc() & uart_putc() sind klar. Mittels set_timer1_compa_isr() kann 
die Applikation selbst eine Funktion anmelden, die im Falle des 
Timer1-COMPA-Interrupts ausgeführt wird. Analoges gilt für 
set_pcint0_isr(). Beide ISRs sind im Bootloader definiert. Die eine für 
den Software-Uart, die andere zum Durchreichen an den nächsten ATtiny in 
der Kette. Letztere ist projektspezifisch und wird daher im Artikel 
nicht erwähnt werden.

Möchte die Applikation also eigene ISRs verwenden, muss sie in dem Fall, 
wo diese schon im Bootloader genutzt werden (aber nur dann!) diese 
Funktion anmelden. Der Bootloader tauscht nämlich nicht nur den 
Reset-Vektor vorn im Flash gegen den eigenen aus, sondern natürlich auch 
die Interrupt-Vektoren, die er selber braucht. Das habe ich bisher im 
Artikel nicht erwähnt, weil es erst im Kapitel "Sharen von Interrupts" 
von Relevanz ist.

> Das Interessante für den Leser des Konzeptes ist nun wie man dem GCC
> Linker möglichst transparent diese Reallokation beibringt.

Da der Pointer auf die Struct at-Runtime gebildet wird, gibt es dieses 
Problem momentan nicht.

> Bitte! diese Worte sind inhaltlicher Natur, selbst wenn der Autor Gott
> hiese wäre der mir egal, es geht um inhaltliche Alternativen.

So habe ich es diesmal durchaus verstanden :-)

Gruß,

Frank

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Ich habe nun das Kapitel "Sharen von Funktionen" im Artikel 
vervollständigt.

Gruß,

Frank

von Hagen R. (hagen)


Lesenswert?

Frank M. schrieb:
>> Du hast schon am Ende einen Sprung zur Main der Applikation hinterlegt,
>> warum davor/dahinter nicht auch alle andernen Exporte ?
>
> Genau so mache ich es doch, hier ein Auszug aus meinem Source:

Sorry das ich widersprechen muß, Du machst es nicht so.

Du legst im FALSH nur eine Adresse auf eine einzige Funktion die als 
Handler eine im SRAM-Stack liegende Struktur als eine Sprungtabelle 
intialisiert.

Ich meine es so: lege vor der Adresse im FALSH an der du den Entrypoint 
zur MAIN als 2 Bytes Opcode ablegst auch alle anderen vom Bootloader 
exportieren Funktionsadressen ab.

Du sparrst:

- deine Funktion bootloader_functions; in der du erst zur Laufzeit eine 
im SRAM liegende Struktur initialisierst, mein Vorschlag lässt das schon 
zur Compile-/Linkertime erledigen

- die nötigen Taltzyklen in deiner bootoader_functions Funtion da diese 
ja garnicht mehr benötigt wird

- die sich ergebende unnötige Redundanz der Einsprungpunkte fest im 
FLASH gespeichert satt wie bei dir in SRAM Strukturen. Der Nutzer deiner 
Funktionen kann diese SRAM Struktur mehrfach erzeugen, was garnicht 
nötigt ist, es gibt nur einen FLASH mit festen Einsprungspunkten an 
feste Funktionsadressen im Bootloader.
Das alles wird schon zur Compile/Linkertime erledigt und nicht erst 
später zur Laufzeit des Bootlaoders.

- den Erklärungsaufwand an den Nutzer dieses APIs.

Ehrlich gesagt: ich finde den Weg sinnlos kompliziert.

Was spräche dagegen an einer festen FLASH Adresse im Code diese 
Sprungtabelle komplett abzulegen ? So wie es bei den ISR Vektoren auch 
der Fall ist ?

Es ändert sich später nichts mehr an den Adressen dieser Sprungtabelle, 
dh. schon zur Compile/Linkerzeit sind diese fest reallokiert.
Der FLASH kann vor überschreiben geschützt werden (ja ich weiß Argument 
Tiny, wir betrachten es mal akademisch) und damit kann diese 
Sprungtabelle zur Laufzeit nicht mehr unbeabsichtigt manipuliert werden. 
Das geht mit deiner dynamisch zur Laufzeit gefüllten SRAM Struktur aber. 
Damit inkrementierst du die Fehleranfälligkeit, sowohl technologisch wie 
auch auf Nutzerseite. Und das alles für welchen Nutzen ?

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Hm vielleicht nochmal in anderen Worten:

Du hast einen Zeiger im FLASH "bootloader_functions" der auf eine 
Struktur im SRAM zeigt in der dann dynamisch zur Laufzeit die 
Einsprungpunkte zu den Funktionen im FLASH zum Bootloader liegen.

Ich meine: du hast eine Sprungtabelle im FLASH bestehend aus dem Inhalt 
der bei dir im SRAM liegt und dieser Inhalt wird schon zur Linkerzeit 
erzeugt. Ohne Umwege über SRAM Strukturen, ohne Notwendigkeit diese zur 
Laufzeit dynamisch erzeugen zu müssen.

Also exakt so wie es der WinAVR GCC sowieso bei den ISR Vektoren auch 
macht.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Frank M. schrieb:
>> Du hast schon am Ende einen Sprung zur Main der Applikation hinterlegt,
>> warum davor/dahinter nicht auch alle andernen Exporte ?
>
> Genau so mache ich es doch, hier ein Auszug aus meinem Source:

in diesem Sinne stimmt deine Aussage eben nicht, ich schrieb alle 
Exporte.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Du legst im FALSH nur eine Adresse auf eine einzige Funktion die als
> Handler eine im SRAM-Stack liegende Struktur als eine Sprungtabelle
> intialisiert.

Nein, ich speichere den Pointer auf die Struktur BOOTLOADER_FUNCTIONS im 
Flash an vorletzter Stelle ab. In dieser Struktur stecken dann die 
Pointer auf die zu exportierenden Funktionen. Diese Struktur liegt im 
SRAM.

> Ich meine es so: lege vor der Adresse im FALSH an der du den Entrypoint
> zur MAIN als 2 Bytes Opcode ablegst auch alle anderen vom Bootloader
> exportieren Funktionsadressen ab.

Wir meinen fast dasselbe. Du willst alle Pointer auf die zu 
exportierenden Funktionen am Flash-Ende speichern, ich speichere dort 
lediglich einen Pointer auf die Funktions-Liste (in Form einer 
Datenstruktur). Ich komme daher mit 2 Bytes im Flash aus.

> Du sparrst:
>
> - deine Funktion bootloader_functions;

Es gibt keine Funktion bootloader_functions. Es gibt nur eine 
Datenstruktur. Diese wird in main() des Bootloaders ganz am Anfang 
initialisiert.

> in der du erst zur Laufzeit eine
> im SRAM liegende Struktur initialisierst, mein Vorschlag lässt das schon
> zur Compile-/Linkertime erledigen

Achso! Jetzt habe ich es verstanden. Der Compiler soll bereits at 
CompileTime die Datenstruktur füllen. Sag das doch gleich ;-)

Alt:
1
    static BOOTLOADER_FUNCTIONS bootloader_functions;
2
3
    bootloader_functions.uart_getc = uart_getc;
4
    bootloader_functions.uart_putc = uart_putc;

Neu:
1
    static BOOTLOADER_FUNCTIONS bootloader_functions =
2
    {
3
        uart_getc,
4
        uart_putc
5
    };

Ja, das geht... und spart auch ein paar Bytes an. Werde ich so ändern.

> Was spräche dagegen an einer festen FLASH Adresse im Code diese
> Sprungtabelle komplett abzulegen ? So wie es bei den ISR Vektoren auch
> der Fall ist ?

Es spart Flash. Ich komme mit 2 Bytes aus, egal wieviele Funktionen in 
der Struktur abgelegt werden - aber zu Lasten des SRAM. Die von Dir 
vorgeschlagene Alternative braucht für jede Funktion 2 Bytes im Flash, 
aber keinen SRAM. Wie gesagt, ich habe bereits beides vor Tagen 
ausprobiert. Es gibt da Für und Wider - ich schrieb das schon heute 
mittag. Hattest Du offenbar überlesen.

> Der FLASH kann vor überschreiben geschützt werden (ja ich weiß Argument
> Tiny, wir betrachten es mal akademisch) und damit kann diese
> Sprungtabelle zur Laufzeit nicht mehr unbeabsichtigt manipuliert werden.

Okay, das ist ein Argument, das ich sofort akzeptiere. Du hast mich 
überzeugt: Ich lege die Struktur komplett ins Flash - statt nur den 
Pointer darauf.

Ich werde das gleich mal testen und anschließend den Artikel anpassen.

Gruß,

Frank

von Hagen R. (hagen)


Lesenswert?

Ja das bemerke ich immer wieder, die Kommunikation zwischen Menschen ist 
primär von den eigenen Vorstellungen geprägt und unser Gehirn 
"übersetzt" die Argumente der Anderen immer wieder, oft unbewusst für 
uns, auf unsere eigenen Vorstellungen. Wir filtern das raus, bzw. 
verbiegen was nicht in unseren Kram passt. Erst duch häufigeren Kontakt 
können wir diese, zu Vorurteilen führenden, Denkfehler beseitigen, bzw. 
erkennen.

Zurück zum Thema:

Bei deiner Methode muß der Compiler pro Initialisierung eines Zeigers in 
der Tabelle folgenden Pseudocode minimal ausführen:
1
; in X Zeiger auf SRAM Struct
2
3
  ldi  rX, Low(FLASH_ADDRESS)
4
  ldi  rY, High(FLASH_ADDRESS)
5
  sts  X+0, rX
6
  sts  X+1, rY

Das sind also 4*2 Bytes an FLASH um einen Zeiger zu intialiseren, ohne 
Berücksichtigung der Initialisierung der Basiszeiger X,Y,Z auf die SRAM 
Struktur usw.

Das Ratio an FLASH Verbrauch der verschiedenen Lösungen muß also 
mindestens 1 zu 4 sein.

Aber das ist nicht das was mich stören würde (schei. auf FLASH).
Schwerer wiegen für mich die Fakten das
1. der Compiler/Linker uns un-intelligente Arbeit abnehmen kann, wenn 
wir schon ein solch intelligentes Monster nutzen dann richtig ;) ASM 
Programmierer müssen das von Hand machen.
2. die HW-Fähigkeiten uns unterstützen bei der Ausführungssicherheit, 
sprich FLASH ist wesentlich weniger auf Überschreiben anfälliger als 
SRAM, also nutzen wir diesen Vorteil ohne Einbußen
3. es für den Nutzer viel transparenter ist, was dem Entwickler 
Supportstreß spart und Freude schafft

und 4. finde ich es intuitiver. Das ist zwar höchst subjektiv würde man 
meinen aber ich habe die Erfahrung gemacht das Dinge die man intuitiv 
macht viel natürlicher, flutschiger sind. Sowohl wenn man sich später 
daran nochmal versucht und auch wenn man es anderen erklären möchte.

Gruß Hagen

PS: das mit dem SRAM-Stack und eigener Funktion war eine 
Fehlinterpretation die aber keine echte Relevanz für meine inhaltlichen 
Argumente hatte. Ob du das in Main() und globaler SRAM Struct oder 
Funktional mit SRAM Struct als Rückgabe im Stack machst ist vom Aufwand 
her ähnlich. Das mit der Funktion und SRAM Struct auf dem Stack ist aber 
denoch besser als die Lösung über eine dauerhafte globale SRAM Struct. 
Da dort die Zeitspanne in der durch Fehler (Stackoverflow zB) diese 
zerstört wird maximal ist, nämlich die komplette Laufzeit der Software. 
Bei einer Lösung als Funktion und Rückgabe über den Stack wäre diese 
Zeitspanne so kurz wie die aufrufende Funktion diese Infos benötigte. 
Was natürlich zustzlich auch mehr SRAM für andere Aufgaben frei macht im 
Gegensatz zu einer globalen SRAM Struct.
Es gibt also noch mehr Argumente die Dich überzeugen sollten ;)

von Hagen R. (hagen)


Lesenswert?

Übrigens würde ich Dir empfehlen, im Gegensatz zu vielen ASM Bootloadern 
die sowas machen, deine Sprungtabelle an den Anfang deiner Bootloader 
Section zu legen. Wohl bemerkt alle diese Sprünge inklusive des Sprungs 
zur Main(). Diese würde ich ganz am Anfang legen damit bei einem Fehler 
in der Anwendung, der dazu führt das der PC in den Bootloader läuft, auf 
diesen Jump nach Main() trifft, quasi ein Failsave Software Reset macht. 
Nach diesem Sprung sollten die exportieren Bootloader Einsprungspunkte 
kommen und danach Dein ISR Vector Clone.

Warum ? Weil du so besser dies dem GCC Linker beibiegen kannst. Dieser 
reallokiert nämlich dann autom. und nahtlos deinen Bootloader Code 
danach. Durch die Verlagerung an das Ende dieser Section hast du ein 
Problem mit dem Linker.

1. musst du ihm die Adresse dieser Sprungtabelle separat beibringen
2. du musst diese Startadresse dieser Srungtabelle aufwendig berechnen
3. könnte dein Bootloader Code in diese Tabelle reinlaufen und der 
Linker bekommt Probleme.

Exakt Punkt 3. bedeutet zukünftigen Supportstreß da viele Entwickler die 
Erweiterungen einbauen, die den compilierten Bootloadercode größer 
machen als die allokierte Section ist, mit der Anpassung des 
Linkerscriptes Probleme haben.

Gruß Hagen

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hi,

ich habe nun den Artikel angepasst - selbstverständlich das Ganze vorher 
getestet. Die Liste der exportierten Funktionen wird nun komplett im 
Flash gespeichert. Dabei ist der Pointer auf die Applikation selbst mit 
in die Struct gewandert. Dies spart Flash-Speicherzugriffe, weil ich 
dann die Pointer auf die zu exportierenden Funktionen mitsamt dem 
Start-Pointer auf die Applikation "in einem Rutsch" schreiben kann. Die 
Funktion pgm_write_word() musste ich dafür durch die Funktion 
pgm_write_block() ersetzen.

Diese Änderung betraf dann auch das Kapitel "Ansprung der Applikation", 
also nicht nur das zuletzt gefüllte Kapitel "Sharen von Funktionen".

Nichtsdestotrotz muss die Applikation die Pointer ins RAM laden. Anders 
lassen sich aus der Applikation die exportierten Funktionen nicht 
aufrufen. Vor jedem uart_getc() extra ein pgm_read_word() zu machen, um 
ad hoc den Pointer auszulesen, halte ich für übertriebenen Unsinn. 
Sollte sich die Applikation ihr eigenes SRAM zerschießen, ist es auch 
egal ob der Pointer dabei kaputtgeht oder nicht.

Gruß,

Frank

P.S.
Code habe ich durch die Maßnahme nicht gespart. Sowohl Bootloader und 
Applikation sind in etwa gleich groß geblieben.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Übrigens würde ich Dir empfehlen, im Gegensatz zu vielen ASM Bootloadern
> die sowas machen, deine Sprungtabelle an den Anfang deiner Bootloader
> Section zu legen.

Am Anfang der Bootloader-Section liegt die vom Linker angelegte 
Interrupt-Vektor-Tabelle. Also ganz am Anfang der Reset-Vektor, im 
konkreten Beispiel ab 0x1800.

> Wohl bemerkt alle diese Sprünge inklusive des Sprungs
> zur Main(). Diese würde ich ganz am Anfang legen damit bei einem Fehler
> in der Anwendung, der dazu führt das der PC in den Bootloader läuft, auf
> diesen Jump nach Main() trifft, quasi ein Failsave Software Reset macht.
> Nach diesem Sprung sollten die exportieren Bootloader Einsprungspunkte
> kommen und danach Dein ISR Vector Clone.

Das ist bereits so gegeben. Am Anfang der Bootloader-Section liegt der 
Reset-Vektor auf den Bootloader. Damit wird in Deinem Fehlerszenario der 
Bootloader aufgerufen... was besseres kann einem nicht passieren. 
Empfängt der Bootloader keine Daten, führt er die Applikation aus. Daher 
geht alles seinen geordneten Weg.

> Warum ? Weil du so besser dies dem GCC Linker beibiegen kannst. Dieser
> reallokiert nämlich dann autom. und nahtlos deinen Bootloader Code
> danach. Durch die Verlagerung an das Ende dieser Section hast du ein
> Problem mit dem Linker.

Schau bitte in den Artikel, insbesondere in die oben erwähnten 
neuformulierten Kapitel. Es gibt keine Linker-Probleme.

Gruß,

Frank

von Hagen R. (hagen)


Lesenswert?

Frank M. schrieb:
> Nichtsdestotrotz muss die Applikation die Pointer ins RAM laden. Anders
> lassen sich aus der Applikation die exportierten Funktionen nicht
> aufrufen.

Doch das geht ;) Ich suche mal in meinen Source nach der exakten C 
Syntax. Wird aber erst morgen was werden und schaue mal ob ich die Zeit 
finde ein Beispiel zu bauen.

Letzendlich deklarierst du die Prototypen dieser Funktionen in normaler 
C Syntax und gibts deren FLASH Adresse an, statt einer Implementierung.

Es müsst sogar so gehen das man diese Sprungtabelle als Struct in den 
FLASH deklariert.

SRAM benötigst du keinen dafür, ein FLASH lesen/schreiben zur Laufzeit 
sollte komplett entfallen, und am Ende wird man mindestens 75% an FLASH 
einsparen können.

Und das Beste daran: es erscheint dem Nutzer so als ob er eine reguläre 
Funktion wie seine eigene aufrufen kann. Nur mit dem Unterschied das wir 
dem Linker das manuell beibiegen müssen.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Frank M. schrieb:
> Schau bitte in den Artikel, insbesondere in die oben erwähnten
> neuformulierten Kapitel. Es gibt keine Linker-Probleme.

Jo als ich meinen Beitrag schrieb hast du am Artikel geschrieben, wie 
soll ich das wissen können ?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:

> 1. musst du ihm die Adresse dieser Sprungtabelle separat beibringen

Nein, das ist eine Preprocessor-Konstante in tinyboot.h. Diese muss vom 
Anwender angepasst werden, wenn die Größe des Flashs abweicht.

2. du musst diese Startadresse dieser Srungtabelle aufwendig berechnen

Nein, das macht der Preprocessor für mich. Heraus kommt eine konkrete 
Zahl. Da muss nichts berechnet werden.

3. könnte dein Bootloader Code in diese Tabelle reinlaufen und der
Linker bekommt Probleme.

Der Bootloader könnte größer werden als die "sizeof (section_bootloader) 
- sizeof (BOOTLOADER_FUNCTIONS)", ja. Das kann man aber leicht abbiegen. 
Man definiert eine eigene Section die auf FLASHSIZE - sizeof 
(BOOTLOADER_FUNCTIONS) beginnt. Dann bemerkt dieses der Linker, weil 
sich zwei Sections überschneiden und wirft einen Fehler.

Ich sehe daher keinen Grund, vom skizzierten Layout (siehe Artikel) 
abzuweichen.

Gruß,

Frank

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Doch das geht ;) Ich suche mal in meinen Source nach der exakten C
> Syntax.

Ohne Performance-Verschlechterung? Da bin ich mal gespannt ;-)

> SRAM benötigst du keinen dafür, ein FLASH lesen/schreiben zur Laufzeit
> sollte komplett entfallen, und am Ende wird man mindestens 75% an FLASH
> einsparen können.

75% von was? Ich kopiere Pointer ins RAM, das sind im Beispiel des 
Artikels 3 x 2 = 6 Bytes. Genau diese 6 Bytes "verschwende" ich im 
Flash.

> Und das Beste daran: es erscheint dem Nutzer so als ob er eine reguläre
> Funktion wie seine eigene aufrufen kann. Nur mit dem Unterschied das wir
> dem Linker das manuell beibiegen müssen.

Das hört sich so an, als ob Du die Funktionen als "irgendwo extern" 
deklarieren willst und dem Applikations-Linker das MAP-File des 
Bootloaders unterjubeln willst. Böse böse ;-)

EDIT:

Das hatte ich übrigens mal ganz am Anfang gemacht: Den Bootloader in der 
separaten Section zur Applikation gelinkt und anschließend hat das 
PC-Programm, welches die erzeugte Hex-Datei der Applikation einliest und 
an den Bootloader schickt, die HEX-Daten ab 0x1800 einfach gekappt und 
nicht mit übertragen. Dann musst Du aber penibel darauf achten, dass Du 
die Applikation immer neu linkst, wenn Du den Bootloader veränderst. Das 
wollte ich nicht und deshalb hab ich das ganze wieder separiert und die 
Pointer-auf-Funktionen-Lösung eingebaut.

von Hagen R. (hagen)


Lesenswert?

Frank M. schrieb:
> Hagen Re schrieb:
>> Doch das geht ;) Ich suche mal in meinen Source nach der exakten C
>> Syntax.
>
> Ohne Performance-Verschlechterung? Da bin ich mal gespannt ;-)

Es verbessert die Performance weil: kein indirekter Sprung über eine 
SRAM Tabelle mehr erfolgt sondern direkt durch den Linker diese Funktion 
wie jede andere Funktion aufgerufen werden kann.

Übrigens ich bleibe dabei: die Sprungtabelle an das Ende der Bootloader 
Section zu legen ist ungeschickt.

Gruß Hagen

von Hagen R. (hagen)


Lesenswert?

Frank M. schrieb:
> Das hört sich so an, als ob Du die Funktionen als "irgendwo extern"
> deklarieren willst und dem Applikations-Linker das MAP-File des
> Bootloaders unterjubeln willst. Böse böse ;-)

Nö warum sollte man sowas machen ?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Es verbessert die Performance weil: kein indirekter Sprung über eine
> SRAM Tabelle mehr erfolgt sondern direkt durch den Linker diese Funktion
> wie jede andere Funktion aufgerufen werden kann.

Dann ist die Applikation aber abhängig vom Versionsstand des 
Bootloaders. Wenn sich uart_getc() im Flash durch eine Änderung im 
Bootloader verschiebt, hast Du andere Adressen. Du kannst also nicht ein 
und dieselbe Applikation auf 2 µCs schieben, auf denen eine 
unterschiedliche Version des Bootloaders installiert ist. Daher halte 
ich Deinen Lösungsvorschlag für suboptimal.

Komm mir bitte jetzt nicht damit, jede zu exportierende Funktion in eine 
extra Section zu legen, damit sie immer an festen Adressen steht, das 
ist wenig bis gar nicht praktikabel ;-)

> Übrigens ich bleibe dabei: die Sprungtabelle an das Ende der Bootloader
> Section zu legen ist ungeschickt.

Das können wir gerne nochmal diskutieren, wenn der Artikel vollständig 
ist. Zum jetzigen Zeitpunkt ist die Diskussion darüber kontraproduktiv.

Gruß,

Frank

von Hagen R. (hagen)


Lesenswert?

Frank M. schrieb:
> Dann ist die Applikation aber abhängig vom Versionsstand des
> Bootloaders. Wenn sich uart_getc() im Flash durch eine Änderung im
> Bootloader verschiebt, hast Du andere Adressen.

Wenn sich die Addresse der uart_getc() verschieben sollte dann 
verschiebt sich noch lange nicht die Adresse des Einsprungpunktes in der 
Sprungtabelle zur uart_getc() Funktion. Das ist ja der Sinn solcher 
Sprungtabellen, exakt so wie bei den ISR Vektoren.

Gruß Hagen

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Wenn sich die Addresse der uart_getc() verschieben sollte dann
> verschiebt sich noch lange nicht die Adresse des Einsprungpunktes in der
> Sprungtabelle zur uart_getc() Funktion. Das ist ja der Sinn solcher
> Sprungtabellen, exakt so wie bei den ISR Vektoren.

Die ISR-Vektoren sind verkappte RJMPs. C-Funktionen werden aber nicht 
über RJMP aufgerufen. Daher hinkt hier Dein Vergleich.

Ich benutze zur Zeit Pointer auf Funktionen, die kannst Du eher mit 
einem indirekten Call vergleichen. Ich wüsste momentan nicht, wie Du das 
über RJMP oder ähnliches anders realisieren könntest. Naja, ich bin auf 
Deinen Lösungsvorschlag morgen gespannt ;-)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hier ein Beispiel aus meiner Anwendung:

        cmd = boot.uart_getc ();
 320:  e0 91 7e 00   lds  r30, 0x007E
 324:  f0 91 7f 00   lds  r31, 0x007F
 328:  09 95         icall

Wie willst du das effizienter mit einer wie auch immer gearteten 
Sprungtabelle im flash hinbekommen?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Wenn sich die Addresse der uart_getc() verschieben sollte dann
> verschiebt sich noch lange nicht die Adresse des Einsprungpunktes in der
> Sprungtabelle zur uart_getc() Funktion. Das ist ja der Sinn solcher
> Sprungtabellen, exakt so wie bei den ISR Vektoren.

Hm, habe da jetzt eine Linkeroption gefunden:

    --defsym externeFunktion=0xNNNN

Damit könnte es gehen. Es wird dann in der Applikation ein

    rcall NNNN

ausgeführt. Bei NNNN könnte dann der RJMP stehen. Damit würde dann ein 
Funktionsaufruf übersetzt werden als:

    rcall NNNN   ; in Applikation
    rjmp OFFSET  ; in Sprungtabelle des Bootloaders

Das sind dann nur 4 Byte Opcode und ist kürzer als das:

        cmd = boot.uart_getc ();

was 10 Bytes an Opcode braucht. Eine Struct im SRAM wird dadurch unnötig 
- zumindest in der Applikation.

Ich werde das mal testen.

Gruß,

Frank

von Vlad T. (vlad_tepesch)


Lesenswert?

leute, leute, was ist denn hier los :)


Ich finde Franks Ansatz interessant.
Er hat ja auch einen Link zu einem meiner Threads gepostet, der 
prinzipiell immer noch aktuell ist.

Das Nuzen der Uart-Funktionalität des Bootloaders aus der Applikation 
ist immer noch ein Wunsch. For allem die Tinys bringen ja teilweise 
Features mit, die es bei den Megas (zunmindest bei denen in DIP) nicht 
gibt, haben aber allerhöchstens 8k.
Wenn da 1k eingespart werden könnte, indem man die 
Kommunikatiosnroutinen des Bootloaders mitnutzt, wäre das doch keine 
schlechte Sache.

Nach meinen Vorstellungen Ideal wäre ein AVRootLoader mit C-Interface 
für die Soft-Uart mit automatischer Baudraten-Anpassung.

Bisher ist es nicht selten bei mir so, dass auf dem AVR der AVRootloader 
landet und dann separat eine C-SW-Uart-Lib. Die C-lib hat leider nicht 
dieses tolle Feature der Baudratenerkennung (hab noch keine gefunden, 
die das kann)

Das diese Kombination immer noch platzsparender ist, als Franks 
Bootloader, spricht natürlich gegen das Konzept den BL unbedingt in C 
implementieren zu wollen, aber aus rein akademischer Sicht - um die 
Mechanismen, die nötig sind vorzuführen - ist sicher nichts dagegen 
einzuwenden.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Vlad Tepesch schrieb:
> leute, leute, was ist denn hier los :)

Och, ab und zu muss man sich mal kloppen, um das Revier abzustecken ;-)
Jetzt haben wir aber wieder Frieden.

> Wenn da 1k eingespart werden könnte, indem man die
> Kommunikatiosnroutinen des Bootloaders mitnutzt, wäre das doch keine
> schlechte Sache.

Genau. Ich habe eben mal alles projektspezifische rausgeworfen, der 
Tiny-Bootloader hat jetzt inkl. SW-UART 1546 Bytes. Dabei geht das 
meiste auf den SW-UART, der ziemlich fett ist, da er "nach Lehrbuch" 
programmiert ist. Ein anderer SW-UART ist da bestimmt genügsamer, so 
dass sich der Bootloader wohl noch auf 1KB oder schlimmstenfalls 1,2KB 
drücken lässt.

> Nach meinen Vorstellungen Ideal wäre ein AVRootLoader mit C-Interface
> für die Soft-Uart mit automatischer Baudraten-Anpassung.

Ja, das wäre ideal. Ich bin da immer noch auf der Suche nach einem 
genügsamen SW-Uart in C, der auch eine Autobaud-Erkennung kann. Notfalls 
in Assembler, den würde ich dann nach C umschreiben.

> Das diese Kombination immer noch platzsparender ist, als Franks
> Bootloader, spricht natürlich gegen das Konzept den BL unbedingt in C
> implementieren zu wollen, aber aus rein akademischer Sicht - um die
> Mechanismen, die nötig sind vorzuführen - ist sicher nichts dagegen
> einzuwenden.

Warten wir mal ab, wenn der Tiny-Bootloader an die 1K von der Größe 
kommt und der SW-UART auch von der Applikation genutzt werden kann, kann 
das Ganze durchaus auch für die Praxis interessant werden...

Ich bin dran,

Frank

von Hagen R. (hagen)


Lesenswert?

Frank, so wie ich mir das mit der Sprungtabelle gedacht habe geht es in 
purem C mit dem GCC leider nicht. Mit Borland C auf PCs garkein Problem 
aber nicht mit dem GCC möglich.

Man müsste schon die integrierten Assemblerfähigkeiten des GCCs benutzen 
aber ich denke das würde deinem Konzept widersprechen. Wobei, wenn man 
es strikt betrachtet das jetzt schon der Fall ist.

Beispiele:
1
#define RJMP                        (0xC000U - 1)                 // opcode of RJMP minus offset 1

in deinem Source, das ist schon sehr assembler/Hardwarenah.

Dann die Verwendung der Funktionen wie pgm_write_word(). Die sehen im 
Aufruf nach purem C aus sind aber in deren Sourcen in Assembler 
geschrieben.

Man könnte also einen Kompromiß eingehen und quasi eine 
Bootloader_Helper Source schreiben, sie als RTL deklarieren, und da über 
zB. die inline ASM Fähigkeiten der C Sprache das machen was mir 
vorschwebte.

Das änderte aber nichts am Problem mit der Konzeptionierung des 
Artikels, alles in C damit es erklärbar wird.

Letzendlich gehts nur um par Takte und um par Bytes an FLASH. Wären es 
zb. 10 exportierte Funktionen so ergäbe sich in ASM 20 Bytes FLASH und 
in C 80 Bytes an FLASH. Die Mühe lohnt nicht.

Gruß Hagen

Sorry, kam erst heute wieder zu meiner Runde hier.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Letzendlich gehts nur um par Takte und um par Bytes an FLASH. Wären es
> zb. 10 exportierte Funktionen so ergäbe sich in ASM 20 Bytes FLASH und
> in C 80 Bytes an FLASH. Die Mühe lohnt nicht.

Im Moment bin ich auch dieser Meinung. Ich hatte zwar in der Applikation 
rumgespielt mit dem --defsym und hatte auch einen Teilerfolg, nämlich 
dass ich dann wirklich

    ch = uart_getc()

statt

    ch = boot.uart_getc()

schreiben konnte. Das sparte auch ca. 100 Byte in der Applikation ein. 
Anschließend habe ich im Bootloader probiert, RJMPs in die Sprungtabelle 
zu patchen. Leider ist mir da der Linker mit einem Overflow-Error 
ausgestiegen.

Ich habe also dieses Teilproblem, ein paar Bytes durch ein paar fiese 
Tricks herauszuholen, erstmal zurückgestellt. Das ist auch nicht so 
wichtig, denn es geht ums Prinzip. Und das funktioniert auch :-)

Ich habe mittlerweile den Bootloader auf 1500 Bytes zusammenstauchen 
können. Ich mache mich jetzt erstmal an die Vervollständigung des 
Artikels...

First make it work, then make it fine ;-)

Gruß,

Frank

von Hagen R. (hagen)


Lesenswert?

Frank M. schrieb:
> Im Moment bin ich auch dieser Meinung. Ich hatte zwar in der Applikation
> rumgespielt mit dem --defsym

Naja, am Linker rumzufummeln macht es auch nicht verständlicher für 
deinen Artikel.

Interessant wird ja der nächste Schritt: ISRs sharen.

Gruß Hagen

von Vlad T. (vlad_tepesch)


Lesenswert?

Hagen Re schrieb:
> Interessant wird ja der nächste Schritt: ISRs sharen.

wie machen dies denn die ganzen bootloader?
arbeiten die Tatsächlich alle ohne Interupts?

vom Prinzip her sollte Sharing ja nich so schwer sein.

Der bootloader lässt seine Sprungtabelle an der Origalstelle stehen und 
schreibt die der Applikation an eine definierte Stelle in seinen 
Bootloaderspeicher.
in der bootloader-ISR wird dann je nach Modus (Bootloader/App) der 
Booloadercode ausgeführt oder weiter zu App gesprungen.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Vlad Tepesch schrieb:
> wie machen dies denn die ganzen bootloader?

Auf dem ATmega ist das einfach: Da hat der Bootloader eine eigene 
Interruptvektor-Tabelle. Die kann er mittels IVSEL-Bit umschalten. Hier 
mal ein Beispiel-Code aus dem SOUNDRX-Bootloader, wo ich das nutze:
1
int
2
main (void)
3
{
4
    ...
5
    temp = MCUCR;                      // set interrupt vectors to bootloader section
6
    MCUCR = temp | (1<<IVCE);
7
    MCUCR = temp | (1<<IVSEL);
8
    sei ();                            // enable interrupts
9
    ...                                // start bootloader, continue here if timeout
10
    cli ();
11
    temp = MCUCR;                      // reset interrupt vectors (set to application section)
12
    MCUCR = temp | (1<<IVCE);
13
    MCUCR = temp & ~(1<<IVSEL);
14
   asm volatile("jmp 0x0000");         // jump to application
15
}

Genau diese Spielerei mit dem IVSEL-Bit gibt es nur auf den ATmegas, 
aber nicht auf den ATtinys.

> arbeiten die Tatsächlich alle ohne Interupts?

Nein, aber es gibt Meinungen, dass man in einem Bootloader auch pollen 
kann, wenn man sowieso nichts parallel machen muss. Ich finde, man 
sollte Interrupts ruhig auch im Bootloader nutzen, wenn es den Code 
einfacher macht.

> vom Prinzip her sollte Sharing ja nich so schwer sein.

Nein, ist ganz simpel. Geht auch wieder über Pointer auf Funktionen. Ich 
schreibs gleich rein, dann gibts keine weitere Spekulationen ;-)

> in der bootloader-ISR wird dann je nach Modus (Bootloader/App) der
> Booloadercode ausgeführt oder weiter zu App gesprungen.

So isses.

Gruß,

Frank

von Peter D. (peda)


Lesenswert?

Vlad Tepesch schrieb:
> wie machen dies denn die ganzen bootloader?
> arbeiten die Tatsächlich alle ohne Interupts?

Ja.

Ein Bootloader hat eine klare einfache Aufgabe:
- Empfangen von Daten
- Schreiben in den Flash
Was soll da ein Interrupt?

Ein Empfang von Daten während des Programmieren ist eh nicht möglich, da 
die ATmega <8kB und die ATtiny die CPU beim Flashen anhalten (~4ms).


Peter

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Ein Bootloader hat eine klare einfache Aufgabe:
> - Empfangen von Daten
> - Schreiben in den Flash
> Was soll da ein Interrupt?

Prinzipiell hast Du recht, man kann das (fast) immer mit Pollen 
erledigen.

Wenn die Daten aber ohne Pause kontinuierlich an den µC gesendet werden 
(z.B. bei SOUNDRX über die PC-Soundkarte), wird es sehr kompliziert, das 
Timing exakt einzuhalten. Das geht mit einem Interrupt (Timer und/oder 
PCINT) wesentlich komfortabler.

> Ein Empfang von Daten während des Programmieren ist eh nicht möglich, da
> die ATmega <8kB und die ATtiny die CPU beim Flashen anhalten (~4ms).

Jepp. In dem Fall muss der Sender darauf Rücksicht nehmen und eine Pause 
zwischen den einzelnen Pages einlegen, z.B. durch Warten auf eine 
Antwort vom µC nach jedem Schreiben einer Page.

Gruß,

Frank

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Ich habe nun das Kapitel "Sharen von Interrupts" vervollständigt. Es 
kann sein, dass ich dies im Laufe des Tages noch etwas "verschönere". 
Die nötigen Mechanismen stehen aber schon mal drin.

Link auf das Kapitel:

  http://www.mikrocontroller.net/articles/Konzept_f%C3%BCr_einen_ATtiny-Bootloader_in_C#Sharen_von_Interrupts

Gruß,

Frank

von Hagen R. (hagen)


Lesenswert?

Frank M. schrieb:
>> Ein Empfang von Daten während des Programmieren ist eh nicht möglich, da
>> die ATmega <8kB und die ATtiny die CPU beim Flashen anhalten (~4ms).
>
> Jepp. In dem Fall muss der Sender darauf Rücksicht nehmen und eine Pause
> zwischen den einzelnen Pages einlegen, z.B. durch Warten auf eine
> Antwort vom µC nach jedem Schreiben einer Page.

das muss er auch bei Interrupts im Bootloader. Denn die 
Programmierzeiten sind absolut. ISRs hätten nur dann einen Sinn wenn die 
Datenübertragung viel langsammer wäre als das Programmieren des 
FLASHs/EEPROMs. Denn nur dann lonht die Hintergrunddatenübertragung 
innerhalb von ISRs. Wenn da nicht das Problem wäre das bei der FLASH 
Programmierung nur unter bestimmten Bedingungen parallel Code im FLASH 
ausgeführt werden kann und gleichzeitig Pages im FLASH programmiert 
werden können.

Es verschärft sogar noch die Problematik des Programflusses. Denn mit 
ISRs ist es ja das Ziel die Daten für die nächsten FLASH/EEPROM Pages 
schon zu übertragen wenn man noch die aktuell empfangenen Daten in den 
FLASH/EEPROM programmieen möchte. Sollte dabei ein Fehler auftreten dann 
hat man einen Versatz im Programablauf. Dh. alles zurück auf vorherige 
Datenbuffer, Fehler an PC Software gesendet, und die muß die schon 
nächsten gesendeten Daten in ihrem Programablauf verwerfen. 
Verkompliziert alles nur unnötig.

Kein Bootloader den ich kenne für MCUs arbeitet so. Alle empfangen einen 
Datenblock, programmieren FLASH/EEPROM, senden ein ACK und so gehts mit 
dem nächsten Datenblock weiter. Das ist aus Sicht des Programflusses wie 
auch aus Sicht der Anforderungen der Nutzer am sinnvollsten. Denn 
Sicherheit geht vor und man möchte sicher sein das auch alles korrekt 
programmiert wurde. Ergo: no need for ISRs da ein Bootloader dann zu 
diesem Zeitpunkt nur diese eine Aufgabe hat.

Gruß Hagen

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hagen Re schrieb:
> Frank M. schrieb:
>>> Ein Empfang von Daten während des Programmieren ist eh nicht möglich, da
>>> die ATmega <8kB und die ATtiny die CPU beim Flashen anhalten (~4ms).
>>
>> Jepp. In dem Fall muss der Sender darauf Rücksicht nehmen und eine Pause
>> zwischen den einzelnen Pages einlegen, z.B. durch Warten auf eine
>> Antwort vom µC nach jedem Schreiben einer Page.
>
> das muss er auch bei Interrupts im Bootloader.

Nein, bei ATmegas mit >=8KB nicht. Da wird die CPU nicht angehalten, der 
Bootloader läuft weiter, während im Hintergrund die Daten ins Flash 
gebrannt werden. Genau darum ging es in Peters Aussage. Bei ATtinys muss 
man immer warten - egal ob Interrupts oder nicht. Wo hast Du was anderes 
gelesen???

Hagen, bitte genauer lesen, sonst entstehen Missverständnisse ;-)

> Denn die
> Programmierzeiten sind absolut. ISRs hätten nur dann einen Sinn wenn die
> Datenübertragung viel langsammer wäre als das Programmieren des
> FLASHs/EEPROMs.

ISRs haben Sinn, wenn ich den SW-UART im Bootloader und in der 
Applikation haben will. In der Applikation machen sie meistens Sinn, im 
Bootloader muss ich sie dann zwangsläufig nehmen, wenn ich den 
SW-UART-Code share. Lies bitte dazu das Interrupt-Kapitel in meinem 
Artikel. Da steht diese Begründung ausdrücklich drin.

> Kein Bootloader den ich kenne für MCUs arbeitet so. Alle empfangen einen
> Datenblock, programmieren FLASH/EEPROM, senden ein ACK und so gehts mit
> dem nächsten Datenblock weiter.

Dann kennst Du noch nicht meinen SOUNDRX-Bootloader. Der hämmert mit 
25KBit/sec die Daten ins Flash und hat keine Möglichkeit zu antworten. 
Die Daten werden vom PC kontinuierlich ohne Pausen durchgesendet. 
Natürlich funktioniert der nur auf ATmegas mit >= 8KB Flash.

> Ergo: no need for ISRs da ein Bootloader dann zu
> diesem Zeitpunkt nur diese eine Aufgabe hat.

Siehe Begründung oben: Bei Sharen von Funktionen kann es plötzlich 
notwendig sein, wenn man auf die Interrupts in der Applikation nicht 
verzichten kann.

Gruß,

Frank

von Vlad T. (vlad_tepesch)


Lesenswert?

man könnte die SW-Uart/den Bootloader eventuell so schreiben, dass die 
SW uart nicht selbst den Timer intialisiert und die ISR implementiert.
Das hätte für die App den Vorteil, sie kann selbst entscheiden, auf 
welchen Timer das laufen soll.
DAs ist auch etwas, was ich schon öfters gemacht habe: die ISRs aus 
irgendwelchen libs rausgezerrt und das ganze in einen normalen 
Funktionsaufruf zu packen. Klar die Lib muss die Anforderung an die 
Aufruffrequenz genau spezifizieren. imho ist es aber schlechtes design, 
wenn man diese Hardwareabhängigkeit in die lib packt und damit auch 
gleich die entsprechende Peripherie blockiert. Andererseits verstehe ich 
auch, dass für Anfänger sehr viel einfacher ist, wenn nicht erst der 
Initialisierungscode selbst geschrieben werden muss.


und für den Bootloader hätte es den vorteil, er könnte diese 
Poll-Funktion direkt aufrufen mit passenden Delays dazwischen und 
braucht dafür eventuell gar keine Ints mehr.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Vlad Tepesch schrieb:
> man könnte die SW-Uart/den Bootloader eventuell so schreiben, dass die
> SW uart nicht selbst den Timer intialisiert und die ISR implementiert.
> Das hätte für die App den Vorteil, sie kann selbst entscheiden, auf
> welchen Timer das laufen soll.
> [...]
> und für den Bootloader hätte es den vorteil, er könnte diese
> Poll-Funktion direkt aufrufen mit passenden Delays dazwischen und
> braucht dafür eventuell gar keine Ints mehr.

Okay, ohne Ints im Bootloader könnte es so gehen. Der Bootloader müsste 
die im Artikel erwähnte Funktion uart_interrupt() einfach selbst mit 
entsprechenden Delays aufrufen. Die Applikation muss dann einfach dafür 
sorgen, dass uart_interrupt() im Bootloader regelmäßig aufgerufen wird. 
Wie sie das macht (ob über eigenen Timer-Interrupt oder anders) ist ihr 
dann überlassen.

Die Geschichte vergrößert aber den Code im Bootloader - wegen den 
einzustreuenden Delays. Aber vielleicht wäre dies eine Alternative, die 
man im Artikel zumindest erwähnen oder als alternatives Teilkonzept 
vorstellen könnte.

Ich werde das am Wochenende mal im konkreten Projekt testen.

von Vlad T. (vlad_tepesch)


Lesenswert?

Frank M. schrieb:
> Die Geschichte vergrößert aber den Code im Bootloader

tut es dies wirklich, wenn dafür die gesamte Intterupt-Replacement-Logic 
wegfällt?
Das passt jetzt natürlich nicht zu deinem BL-Konzept, da hier ja 
explizit gezeigt werden sollte, dass und wie es mit Ints ebend doch 
geht.

von Julien Thomas (Gast)


Lesenswert?

Hallo Leute!
Interessanter Thread. Die bereits angesprochenen Grundsätze (weitgehende 
Trennung zwischen Applikation und Bootloader, flexible Nutzung der 
Ports, geeignetes Protokoll, Flash-Schutz, effektive Speichernutzung) 
sind auf der Attiny-Plattform natürlich eine gewisse Herausforderung...
Die Assemblerlösungen haben zwei entscheidende Vorteile: Sie 
funktionieren in der Realität und sind auch noch *unschlagbar 
kompakt*. Das trifft sogar auf mein eigenes Projekt zu, auf das ich hier 
einfach mal "off-topic" hinweise:
http://jtxp.org/tech/tinysafeboot.htm
Der Bootloader orientiert sich best-practice-mäßig an FastBoot vom Peter 
Dannegger, hat aber einige sensationelle Extras und ist vor allem 
flexibler und auch für Assembler-Hasser geeignet, da man für andere 
ATtiny-Typen nichts neu assemblieren muss. Vielleicht ist das ja für den 
einen oder anderen hier eine Alternative zum Rad-neu-Erfinden?
Hey, mir geht es darum, TinySafeBoot weiter zu verbessern, und für 
Anregungen aus der C-Gemeinde habe ich aber immer ein offenes Ohr!

Viele Grüße,

Julien

von avion23 (Gast)


Lesenswert?

Hallo Frank,

ich denke gerade laut ueber einen bootloader fuer die nrf24l01 
Funkmodule nach. Im wiki stehen noch fette Todos. Kannst du dein 
Beispielprojekt vielleicht noch posten? Es muss nicht den Standard des 
restlichen Artikels erreichen, wuerde mir die Arbeit aber wesentlich 
erleichtern.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Hallo,

avion23 schrieb:
> ich denke gerade laut ueber einen bootloader fuer die nrf24l01
> Funkmodule nach. Im wiki stehen noch fette Todos. Kannst du dein
> Beispielprojekt vielleicht noch posten? Es muss nicht den Standard des
> restlichen Artikels erreichen, wuerde mir die Arbeit aber wesentlich
> erleichtern.

Ja, kann ich gern machen. Ich versuche diese Woche noch, die TODOs durch 
Text zu ersetzen.

Viele Grüße,

Frank

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.