Forum: Mikrocontroller und Digitale Elektronik Self programming fuer eine Funktion


von Jan K. (j_kkk)


Lesenswert?

Hi,

ich habe absichtlich nicht Bootloader in den Titel geschrieben, denn ich 
moechte nur "fast" einen Bootloader bauen. Der Hintergrund ist der 
folgende:

Ich habe ein gut funktionierendes Funkprotokoll (CRC, ACK, encr) laufen. 
Das Funknetzwerk hat einzelne Nodes. Jede Node hat einen grossen Teil 
Code, der identisch ist (naemlich das Protokoll, usw.).
Es gibt auch einen Server, der mit dem PC verbunden ist.
Der Teil, der ab und zu ein Update braucht ist nur, wie auf Kommandos 
reagiert werden soll. Das heisst im Wesentlichen eine einzelne Funktion 
(und ausschliesslich von ihr benutzte daten) zB:

react(uint8_t *, uint8_t len);

Dabei benutzt der Funkcode externe ISRs und Timer. Die Reaktion auf ein 
Datenpacket braucht normalerweise keine ISRs oder aehnliches. Der 
"Bootloader" soll auch nicht beim Neustart sondern immer laufen, ein 
Kommando triggert dann nur das beschreiben des Flash.
Das recyclen der Funktionen aus dem Bootloader und dann springen in den 
App Code ueber jump tables. o.Ae. scheint ein bisschen zu viel.

Naiv wuerde ich erwarten, dass ich einfach nur eine Funktion zum Flash 
ab einer bestimmten Stelle schreiben einbauen muss und dann dem 
"Bootloader" (der eigentlich das Hauptprogramm ist) mitteilen muss, dass 
er in der Hauptschleife einmal die Funktion aufrufen an der Stelle 
aufrufen und der zwei Variablen uebergeben muss: react.
Und der Flashteil, wo die sitzt ist halt ueberschreibbar.

Vielleicht ist die Idee naiv - ich habe mich mit Bootloadern noch nicht 
tuefgehend beschaeftigt. Ich wuerde mich ueber Kommentare freuen.

Gruss

von Peter R. (pnu)


Lesenswert?

Ich hab den Eindruck, Du hältst ein software-update für gleichwertig zur 
Aufnahme irgendwelcher Daten zur Verarbeitung in einem Programm.

Das updaten ist m.E. aber wesentlich heikler und auch zeitraubender als 
eine normale Datenübergabe in ein RAM.

Die übliche Programmausführung wird beim bootloaden behindert oder gar 
gesperrt.

Als Reaktion auf ankommende Daten häufig ein update zu machen dürfte ein 
ziemlich riskanter Weg sein, was die Zeitabläufe angeht.

Auch wenn die EEPROMs schon eine hohe Zubverlässigkeit haben, stellt 
meiner Meinung nach häufige Umprogrammierung auch noch immer einen 
Verkürzungsfaktor für die Datenhaltigkeit dar.

von Georg I. (dschi-ai)


Lesenswert?

Ist es nicht einfacher, jedem Node den absolut identischen Code zu 
verpassen und mit einem Switch-Case anhand eines Flags im EEPROM oä. zu 
entscheiden, was gemacht werden soll? Oder ist es notwendig, dieses 
Stückchen Code ständig und überall ändern zu können?

von Jan K. (j_kkk)


Lesenswert?

Peter R. schrieb:
> Ich hab den Eindruck, Du hältst ein software-update für gleichwertig zur
> Aufnahme irgendwelcher Daten zur Verarbeitung in einem Programm.
>
Nein.


---
@ Georg:

Das hatte ich auch schon ueberlegt. Es ist aber ein bisschen komplexer 
als es nur mit ein paar Flags zu machen waere. Man muesste dann schon 
fast einen Parser basteln, und das sprengt wohl auch wieder den Umfang. 
Jedenfalls sprengt es den EEprom der Controller, die ich momentan 
einsetze.

Daher meine Idee, diese eine Funktion im Flash auf eine bestimmte Stelle 
zu schreiben und ein Update (ein ueberschreiben) der Funktionalitaet 
(wie auf uebergebene Daten aus dem RAM reagiert wird) zuzulassen. 
Natuerlich nur, wenn ein Firmware update durchgefuehrt wird und nicht 
bei jedem Eintreffen neuer Daten.

von Wolfgang S. (ws01)


Lesenswert?

Jan K. schrieb:

> ich habe absichtlich nicht Bootloader in den Titel geschrieben, denn ich
> moechte nur "fast" einen Bootloader bauen. Der Hintergrund ist der
> folgende:

Usw.

Vorab, der Begriff Bootloader wird im Zusammenhang mit Microcontrollern 
m.E. oft ungenau oder falsch gebraucht. Im allgemeinen bezeichnet 
bootstrap loader ein beim Start eines Computers bereits vorhandenes und 
initial ausgeführtes Programm, das einfach als Loader fungiert, also 
weitere Programmstücke in den volatilen Speicher (aka RAM) laden und 
dann ausführen kann, ggfs. auch mehrstufig.  Die Möglichkeit, diese 
nachgeladene Programm in einen weiteren nichtvolatilen Speicher zu 
übertragen und ggfs. bei nachfolgenden Einschaltvorgängen ohne bootstrap 
direkt auszuführen, oder sogar in einem weiteren Schritt den initialen 
Bootloader auszutauschen, ist damit nicht zwingend verbunden oder 
gleichzusetzen. Es scheint aber so, daß genau dieses (quasi ein 
Bootloader, der sich wie ein Brennprogramm verhält, das ihm übergebene 
Programm also nicht abschließend ausführt, sondern in nichtvolatilem 
Programmspeicher aka Flash ablegt) in diesem Umfeld der typische 
Sprachgebrauch geworden ist.

So einen Bootloader brauchst Du in der Tat nicht.  Allerdings 
unterscheidet sich das, was Du tun möchtest, m.E. nur bezüglich des 
Codeumfangs davon, insofern liegst Du mit "fast" schon ganz richtig. 
Der hauptsächliche Unterschied ist, daß Dein "Bootloader" groß und der 
nachzuladende Teil klein ist.  Etwas mehr als der "Bootloader" mußt Du 
allerdings insofern tun, als der mit dem Ablegen des Programms im Flash 
seine Arbeit erledigt hat, während Du Dir ggfs. auch noch einen 
Mechanismus für das Binden (das, was man früher einen Linker nannte - 
http://de.wikipedia.org/wiki/Linker_%28Computerprogramm%29) - ausdenken 
musst.


> Naiv wuerde ich erwarten, dass ich einfach nur eine Funktion zum Flash
> ab einer bestimmten Stelle schreiben einbauen muss und dann dem
> "Bootloader" (der eigentlich das Hauptprogramm ist) mitteilen muss, dass
> er in der Hauptschleife einmal die Funktion aufrufen an der Stelle
> aufrufen und der zwei Variablen uebergeben muss: react.

Genau.  Bzw. umgekehrt, Du reservierst ein Stück Programmspeicher für 
die nachzuladende Funktion (wenn es nur eine ist, entfällt das Linken, 
dann fängt die einzige Funktion einfach am Anfang an) und die dort 
abgelegte Funktion wird schlicht dort aufgerufen.  Natürlich mußt Du Dir 
Gedanken über Anfangsbedingungen machen (was steht da anfänglich drin, 
eine Dummyfunktion, oder eine Defaultfunktion?) und darüber, daß sich 
die allgemeine Programmausführung und das zeitraubende Überschreiben der 
nachzuladenden Funktion nicht in die Quere kommen.   Es kann auch nicht 
schaden, das Verfahren so robust wie möglich auszulegen, also den 
übertragenen Codeblock mit einer Prüfsumme abzusichern etc.

HTH

von Bernd M. (bernd_m)


Lesenswert?

Und danach kommen die speziellen Eigenschaften deines Controllers ins 
Spiel.

* Unter welchen Umständen kann das Flash programmiert werden?
- Im allgemeinen können im betroffenen Flashbereich keine Lesezugriffe 
vorgenommen werden, während das Flash gelöscht oder geschrieben wird. 
Also keine Programmausführung, keine ISRs, keine konstanten Daten lesen 
in diesem Bereich zu dieser Zeit.

* Wie ist die Architektur des uC?
- Havard: keine Programmausführung im RAM Bereich. Denkbar ist das 
Einblenden von RAM in den Codebereich. Beim ATmega kann der Bootblock 
das restliche Flash löschen/schreiben.
- von Neumann: Programm kann im RAM ausgeführt werden. Dazu wird der 
Flash Code ins RAM kopiert und dort ausgeführt. Er muss natürlich 
entsprechend lokatiert sein.

* Wie ist die Segmentierung des Flashs?
- Was ist die kleinste Segementgröße die gelöscht werden kann?
- Wie groß ist der Code der geschrieben werden soll?
- Ist genug RAM vorhanden um den neuen Code zu puffern und in einem 
Rutsch zu schreiben? Oder muss das in Häppchen unterteilt werden?

Wenn wir jetzt wüssten, um welche(n) Controller es sich handelt, hagelt 
es bestimmt lauter gut gemeinte Ratschläge. Aber so ist das alles noch 
zu akademisch.

Gruß,
Bernd

von Jan K. (j_kkk)


Lesenswert?

Danke fuer eure Antworten, Bernd, Wolfgang.

Ja, ich habe voellig vergessen, welche Controller ich verwende - das 
steht aber sogar schon fest, weil die Hardware schon existiert:

Ich verwende AVRs, genaugenommen Attiny841. Da bin ich auch (selbst wenn 
die Hardware nicht existierte) festgelegt, weil ich die beiden 16bit 
Timer, HardwareSPI usw. brauche.
Der hat keine separate Boot-Section im Flash, nicht genug RAM um den 
gesamten zu schreibenden Code zu puffern. Allerdings existieren kleine 
Bootloader dafuer bereits, und self-programming kann der laut Datenblatt 
auch.
Man muss immer 4 pages auf einmal loeschen, das macht 4*8 words. Das 
kann ich gut im RAM puffern. Waehrend der erase/write Zeiten muss ich 
halt aufpassen, dass das Timing stimmt. Wenn dort ISRs oder das 
restliche Programm aussetzen bedeutet das nur, dass der Sender des Codes 
eben warten muss und keine Antwort bekommt. Das macht das Funkprotokoll 
sowieso. Nur der timeout muss ggf. angepasst werden. Auch Pruefsumme 
etc. ist schon im Protokoll implementiert, sollten es mehrere Packete 
werden gibts eben eine eben noch eine obendrauf.

Gruesse

von Wolfgang S. (ws01)


Lesenswert?

Jan K. schrieb:
> Ich verwende AVRs, genaugenommen Attiny841. [...]
> Man muss immer 4 pages auf einmal loeschen, das macht 4*8 words.

Da nehmen sich die Controller von Atmel und Microchips offenbar nichts. 
Der 12F1840 z.B. erlaubt ebenfalls erase/write in Blöcken/rows/pages von 
32 words.

Bedenke, daß der Program-Flash nur eine Endurance von 10.000 solcher 
Zyklen hat, statt der 100.000 des EEPROM. Je nach Updatefrequenz sind 
die ziemlich schnell aufgebraucht.

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.