Hallo zusammen,
nachdem ich schon reichlich recherchiert habe und inzwischen eher noch
verwirrter, möchte ich hier nach Ideen und Wegweisern in die richtige
Richtung fragen.
Ich habe den STM32F105 RBT6 mit einiger Bechaltung auf einer Platine
vorliegen.
Der Mikrocontroller soll per USB oder USB/UART mit dem PC kommunizieren.
Von einem PC-Programm sollen über diese Verbindung Parameter des
Mikrocontrollerprogramms veränderbar sein, unzwar dauerhaft, also auch
nach einem Reset die upgedateten Werte gültig bleiben. .
Wenn ich nun im Interrupthandler nach Eintreffen der USB-Nachricht
einfach eine Variable verändere, wäre das ja nach dem Reset wieder
hinfällig.
Ich vermute, am ehesten ist ein EEPROM für die Ablage von updatebaren
Konstanten üblich. Leider hat meine Platine keins, müsste ich
nachträglich irgendwie anschliessen.
Gibt es andere sinnvolle Möglichkeiten?
Kann ich zur Programmlaufzeit irgendwie schreibend auf den Flash
zugreifen? Ist das schwierig zu implementieren?
Hat da jemand mit Erfahrung? Ist das mit dem EEPROm eher komplizierter
oder das Schreiben auf den Flash?
Ein paar erste Hinweise wie es gehen könnte und wo ich mehr
Informationen finden kann wäre super. Am besten ein verständlich
erklärtes Tutorial (gern auch englisch) oder ein Codebeispiel für STM32.
Zum Hintergrund des Projekts: Der Mikrocontroller soll eine Funkbake
ansteuern, über einen Transistor und ein Relais werden die
entsprechenden Kontakte geschaltet. Also letztlich wird nur ein
GPIO-Pin in einem bestimmten zeitlichen raster auf High und Low gesetzt.
Und dieses zeitliche Raster (und damit das Erkennungszeichen der Bake)
soll von einer einfachen graphischen benutzeroberfläche am PC aus
einstellbar sein, die Werte per USB oder UART übertragen werden und dann
ab dem Moment das Programm mi den neuen Werten ablaufen.
Besten Dank
Andreas
> Gibt es andere sinnvolle Möglichkeiten?
Hat der Controller ein Backup RAM? Den Backup RAM kann man mit einer
kleinen Batterie versorgen und so übersteht der Inhalt die Resets.
> Kann ich zur Programmlaufzeit irgendwie schreibend auf den Flash> zugreifen?
ja.
> Ist das schwierig zu implementieren?
nein. Lese dir mal die "Reference Manual" durch. Da steht das alles
drin.
> Hat da jemand mit Erfahrung? Ist das mit dem EEPROm eher komplizierter> oder das Schreiben auf den Flash?
Das ist beides gleich kompliziert. Ganz grob kann man sagen: Flash hat
viel Speicherplatz und weniger Schreibzyklen, EEPROM hat weniger
Speicherplatz bei mehr Schreibzyklen.
Ein I2C EEPROM an eine bestehende Schaltung hinzufrickeln ist
nun wirklich kein Problem. Der Käfer braucht 2 Pullups, einen
Abblock-Kondensator und 4 Leitungen: Vcc, GND, SDA und SCL.
Die Adressleitungen einfach auf Masse legen.
Kosten tut's auch nix. Wer will da noch jammern?
... hmmm ja ... man müsste was (ein klein wenig) arbeiten ...
Moin,
Auf so einen Pipifax muss man einen STM32 loslassen und dann hat der
kein Eeprom? Das ist wirklich lächerlich.
Nimm einen ATTiny mit ner Uart, die haben alle Eeprom drin.
Gruß,
Norbert
Neben I2C-EEPROMs gibt's auch noch SPI-EEPROMs. Preislich und von der
Größe her kaum ein Unterschied zu I2C. 8 Beinchen ...
Sowohl I2C- als auch SPI-Interfaces sind im F105 drin (sogar mehrfach),
wobei das auch problemlos softwaremäßig geht. Was man da nimmt, ist eher
Geschmackssache. Außer dass SPI m. E. vielleicht noch etwas simpler und
daher einfacher zu debuggen ist.
> Kann ich zur Programmlaufzeit irgendwie schreibend auf den Flash> zugreifen? Ist das schwierig zu implementieren?
Je nach Speichergrösse/layout ist es bei vielen STM32 recht störend,
dass beim Schreiben auf das interne Flash der jeweilige Speicherbus
blockiert ist und man zeitgleich keine Instruktionen daraus ausführen
kann.
Es lassen sich z.B. während Schreib- und Löschoperationen keine
Interrupts bedienen, wenn man nicht explizit den Code der Handler dafür
ins RAM verlegt hat (und auch die Vektortabelle).
Das kann schon sehr nervig sein, ein richtiges EEPROM macht vieles
einfacher, zumindest wenn man mit I2C/SPI dahin umgehen kann.
Ungeschlagen wäre ein echtes internes.. aber selbst das angebliche
EEPROM bei einigen STM32 ist nur "simuliert" und Zugriffe darauf
blockieren ebenfalls den Bus.
Aber wenn man mit den Blockaden leben kann, ist der interne
Flash-Speicher (IMHO) einfacher zu nutzen.
K.
Vielen Dank,
da habe ich ja jetzt mehrere Hinweise was alles gehen sollte.
- ein reales EEPROm dazubasteln, wahlweise über I2C oder SPI
anschliessen
- das emulierte EEPROM nach AN2594
- Backup-RAM , noch nie gehört , werde dazu mal recherchieren. Wie
soll da
eine Batterie dran? Ist dafür ein Pin des Controllers zuständig?
- auf den Flash schreiben zur Laufzeit. Was kann denn die genannte
kurzzeitige Blockade für Folgen haben? Mir fehlt da Hintergrundwissen.
Einfach eine kurzzeitige Verzögerung im Programmablauf? Das stört nicht.
Oder könnte ein weiterer Interrupt vom USB oder UART währenddessen
verlorengehen? Das wäre in der Tat ein Problem.
Andreas E. schrieb:> Ist dafür ein Pin des Controllers zuständig?
Ja, der heißt VBat. u.U. gehen auch Supercaps o.ä. Das Backup-RAM ist am
einfachsten zu nutzen - das muss man einmal initialisieren, danach
verhält es sich ganz normal wie ein RAM, man kann einfach direkt
schreiben & lesen (mit etwas Linker-Script-Magie kann man seine
Variablen da hinein legen, dadurch entsprechen die Schreib&Lese-Zugriffe
ganz normalen Variablen-Zugriffen), aber die Daten bleiben eben
persistent. Das nutzt sich auch nicht ab und hat keine Verzögerung.
Nachteil ist eben der Hardware-Aufwand.
Andreas E. schrieb:> Einfach eine kurzzeitige Verzögerung im Programmablauf? Das stört nicht.
Genau genommen werden Flash-Lesezugriffe blockiert. Läuft das Programm
aus dem Flash, bleibt es einfach eine Weile stehen (ein paar ms bis
Sekunden je nach Operation).
Andreas E. schrieb:> Oder könnte ein weiterer Interrupt vom USB oder UART währenddessen> verlorengehen?
Die UART/USB-Peripherie merkt sich ja dass ein Ereignis eingetreten ist.
Der Interrupt wird dann erst danach ausgeführt. Wenn jetzt z.B. der UART
mehrere Bytes empfangen hat, werden wohl alle bis auf das letzte
verloren gehen, weil die ISR verzögert wird und die Bytes nicht abholen
kann.
Die Lösung wäre hier, das Programm in den RAM zu verlagern und dort
auszuführen. Das läuft dann normal weiter. Allerdings ist die Ausführung
aus dem RAM etwas langsamer und der RAM ist natürlich auch kleiner. Man
könnte sich überlegen während des Speicherns nur ein "Not-Programm"
auszuführen.
Einige große STM32 haben zwei Speicherbänke, da kann man das Programm
aus der einen Bank ausführen während man in die andere schreibt. Es
lohnt sich aber kaum nur dafür auf den größeren Controller
umzusteigen...
Andreas E. schrieb:> nachdem ich schon reichlich recherchiert habe und inzwischen eher noch> verwirrter
Das wiederum finde ich reichlich seltsam. Hättest du reichlich
recherchiert, dann müßtest du nicht hier fragen.
Also:
Entweder bleibst du bei dem STM32 und plazierst einen externen seriellen
EEProm auf der LP - oder du benutzt z.B. einen LPC11Exx, denn der hat
einen EEPROM bereits intus.
Wo also ist das Problem?
Von solchen Ratschlägen wie dem Mißbrauch des internen Flash für
EEPROM-Zwecke kann ich nur abraten, denn der Flash ist NICHT dafür
gedacht, häufig umprogrammiert zu werden.
Das macht ihn nur kaputt.
Ich hatte sowas mal aus Kostengründen gemacht, hab aber die geänderten
Werte nicht gleich, sondern erst nach einigen Sekunden in den Flash
zurückgeschrieben - in der Annahme, daß bei Bedienvorgängen zumeist
mehrere Änderungen binnen einiger Sekunden stattfinden, so daß ich erst
dann zurückschreiben lasse, wenn nach der letzten Änderung ein paar
Sekunden Wartezeit vorbei sind. Einfach nur, um die Anzahl der
Schreibvorgänge möglichst klein zu halten.
W.S.
W.S. schrieb:> Von solchen Ratschlägen wie dem Mißbrauch des internen Flash für> EEPROM-Zwecke kann ich nur abraten, denn der Flash ist NICHT dafür> gedacht, häufig umprogrammiert zu werden.>> Das macht ihn nur kaputt.
Halb so schlimm. Der Flash bei den STM32 ist zwar weniger ausdauernd,
dafür aber größer (billiger) als EEPROM - das kann man ausnutzen. Wenn
man ein Wear-Leveling implementiert und z.B. 10 Speicherstellen
sequentiell beschreibt, statt die gleiche Speicherstelle 10x zu
beschreiben, hat man die Lebensdauer verzehnfacht. Da ST bei der
Herstellung des Chips sich den zusätzlichen Fertigungs- und
Integrations-Prozess für einen EEPROM-Die gespart hat, und stattdessen
den Flash größer gemacht hat, hat man weniger Overhead und weniger
Preis, aber ähnlich viel wiederbeschreibbaren Speicher. Ist halt nur
komplizierter zu nutzen, aber nicht prinzipiell verkehrt. Außer
zusätzlichem Programmieraufwand gibt es keinen wirklichen Grund, das
nicht so zu machen.
Dr. Sommer schrieb:> Wenn> man ein Wear-Leveling implementiert
Also jetzt übertreibst du es aber gewaltig.
Das mit weitem Abstand sinnvollste wäre, sein Projekt sauberer zu planen
und dann den geeigneten Chip dafür zu benutzen. Alles andere ist nur
Murks oder neudeutsch "Workaround".
W.S.
W.S. schrieb:> Also jetzt übertreibst du es aber gewaltig.>> Das mit weitem Abstand sinnvollste wäre, sein Projekt sauberer zu planen> und dann den geeigneten Chip dafür zu benutzen. Alles andere ist nur> Murks oder neudeutsch "Workaround".
Naja, murks würd ich jetzt nicht sagen. Wird in der Industrie zu
10^drölf mal gemacht und verkauft. Schau mal in dein Auto rein, da
wirste in keinem aktuellen Auto nen EEPROM finden.
Nachtrag:
Wer bitte sehr glaubt ernsthaft daran, daß die Leute hier, die Peter
Danneggers Tastenentprellung schon mehrtausendfach benötigt haben, weil
sie das Entprellen ihrer Taste aus eigener Kraft nicht zuwege bringen,
in der Lage sind, sich mal eben ein kleines und tatsächlich
funktionables wear-leveling auszudenken und zu implementieren?
ich nicht.
W.S.
W.S. schrieb:> Also jetzt übertreibst du es aber gewaltig.
Nur weil du kein Wear Leveling implementieren kannst... Je nach
Anforderung muss das ja nicht besonders kompliziert sein.
W.S. schrieb:> Das mit weitem Abstand sinnvollste wäre, sein Projekt sauberer zu planen> und dann den geeigneten Chip dafür zu benutzen.
Top Idee, die Hardware und Chip-Auswahl sind anscheinend schon fertig:
Andreas E. schrieb:> Ich habe den STM32F105 RBT6 mit einiger Bechaltung auf einer Platine> vorliegen.
Es kann jede Menge Gründe geben, warum genau dieser uC ausgewählt wurde.
Die perfekte Wahl gibt es eh nie, irgendwo muss man immer einen
Kompromiss machen. Und der genannte Kompromiss ist nicht so schlimm. Da
die meisten STM32 keinen EEPROM haben, diese Chip-Familie aber durchaus
weit verbreitet ist, scheint die Nutzung des Flash zum Daten Speichern
nicht allzu problematisch zu sein.
W.S. schrieb:> Nachtrag:>> Wer bitte sehr glaubt ernsthaft daran, daß die Leute hier, die Peter> Danneggers Tastenentprellung schon mehrtausendfach benötigt haben, weil> sie das Entprellen ihrer Taste aus eigener Kraft nicht zuwege bringen,> in der Lage sind, sich mal eben ein kleines und tatsächlich> funktionables wear-leveling auszudenken und zu implementieren?>> ich nicht.
Schließ doch nicht immer von dir auf andere. Man muss nicht immer das
Rad bzw. die Tastenentprellung neu erfinden. Oder hast du auch alle
deine Elektronik-Geräte komplett selber entwickelt? Nutzt du vielleicht
gar von anderen Herstellern produzierte Hardware?
Ein einfaches Wear-Leveling wäre:
Man reserviert z.B. den 10-fachen Speicher wie benötigt -
sinnvollerweise so dass man möglichst wenig Flash-Banks nutzt, und auch
so dass diese keine weiteren Daten/Code enthalten. Den Bereich
initialisiert man komplett mit '1'. Beim Programmstart sucht man den
letzten Block darin, der nicht komplett '1' ist, und liest ihn als
aktuellen Zustand. Findet man keinen, nutzt man Default-Werte. Zum
Speichern schreibt man in den jeweils nächsten Block (der erste, der
komplett '1' ist); sinnvollerweise sorgt man dafür dass mindestens ein
Bit '0' ist. Falls sich zum letzten Block nichts geändert hat, braucht
man natürlich gar nichts zu schreiben. Falls kein Block mehr frei ist,
führt man einen Erase Vorgang auf allen betroffenen Banks aus und
schreibt in den 1. Block. Stellt man beim Schreiben fest, dass die
geschriebenen Daten nicht korrekt im Flash ankommen, zeigt man an "Flash
Kaputt, Gerät bitte austauschen". So hat man die Anzahl der
Erase-Vorgänge durch 10 geteilt und die Lebensdauer verzehnfacht.
So, dann melde ich mich hier mal zurück.
Unter all den Varianten habe ich mir zuerst das emulierte EEPROm
angesehen, aber dann doch entschieden direkt auf den Flash zuzugreifen,
schien mir einfacher. Zumindest einfache Fälle von Variablenspeicherung
funktionieren schon. Aber da hänge ich dann auch schon.
Hier der relevante Codeausschnitt zum "Spielen" mit dem Flash.
Was der Code bisher kann: 5 uint32_t Variablenwerte hintereinander
abspeichern und alle 5 wieder zurückliefern, auch nach einem Reset des
Controllers.
Woran es noch hapert: mit char oder uint8_t gehts nicht genauso, und mit
Arrays bestehen wohl auch Probleme.
IDE ist Coocox CoIDE.
Das läuft so.
Sobald ich jetzt einen der 5 Werte zu einem char oder uint_t verändern
will, passt es nicht mehr. Speicheradreese auf ein Byte Breite angepasst
,
statt FLASH_ProgramWord() FLASH_ProgramOptionByte() versucht, hilft
alles nix.
Andreas.E. schrieb:> Sobald ich jetzt einen der 5 Werte zu einem char oder uint_t verändern> will, passt es nicht mehr.
Warum zeigst du dann ausgerechnet den Code der funktioniert, und nicht
den interessanten, nicht funktionierenden?! FLASH_ProgramWord
funktioniert nur mit Adressen die Vielfache von 4 sind.
Ausgabe ist:
Erster Eintrag: 3
Zweiter Eintrag: 15
Dritter Eintrag: 23
Vierter Eintrag: 27
F�nfter Eintrag: � Ja, genau diese Fragezeichenrauten in Coocox, also
irgendwas unbekanntes.
Könnte mir natürlich meine chars die ich speichern will vorher in
uint32_t werte umrechnen, und später wieder zurück, aber das ist
bestimmt nicht im Sinne des Erfinders, also von ST.
Andreas E. schrieb:> FLASH_ProgramOptionByteData(0x08019200 + 4 * sizeof(uint32_t),> (uint8_t)d);
Das Option Byte ist was völlig anderes als der Flash; damit kann man den
Watchdog und Reset konfigurieren.
Benutze stattdessen FLASH_ProgramHalfWord; da wird dann ein Byte
verschwendet. Das kannst du auffüllen mit einem anderen einzelnen Byte
falls du noch eines hast.
Andreas E. schrieb:> printf("Fünfter Eintrag: %c\r\n", *(pdata+4 ));
Hier dereferenzierst du einen Pointer auf uint32_t, und übergibst somit
noch irgendwelche anderen Daten an printf. Je nach Implementation macht
das dann ggf. Unsinn...
Dr. Sommer schrieb:> Hier dereferenzierst du einen Pointer auf uint32_t, und übergibst somit> noch irgendwelche anderen Daten an printf. Je nach Implementation macht> das dann ggf. Unsinn..
Jetzt habe ich es so:
int main(void)
{
uint32_t *pdata = 0x08019200;
uint8_t *smallPointer = 0x08019210;
printf("Erster Eintrag: %d\r\n", *pdata);
printf("Zweiter Eintrag: %d\r\n", *(pdata+1));
printf("Dritter Eintrag: %d\r\n", *(pdata + 2));
printf("Vierter Eintrag: %d\r\n", *(pdata+3));
printf("Fünfter Eintrag: %c\r\n", *smallPointer);
Und in der Flashfunktion steht jetzt als letzter Schreibzugriff:
FLASH_ProgramHalfWord(0x08019210, (uint8_t)d);
kann es weiterhin mit printf nicht auslesen.
Doch jetzt gehts. !!! Ich bekomm ein H ausgegeben.
Lag wohl an dem Flash_ProgramOptionByteData, wo ich dachte das wär die
Schreibfunktion für 8 bit Werte. Und dass der Pointer jetzt ein 8
bit-Wert Pointer ist beim Fünften printf.
Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
Groß- und Kleinschreibung verwenden
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang