Ich versuche, eine Nachschlagetabelle zu definieren, die auf einem STM32F103 keine Konstante ist. Grundsätzlich möchte ich eine Flash-Seite haben, die sich im normalen Betrieb wie eine konstante Nachschlagetabelle verhält, aber hin und wieder (denken Sie an Tage auseinander) möchte ich in der Lage sein, diese Tabelle zu löschen und eine neue auf die Flash-Seite zu schreiben . Ich glaube, ich verstehe, wie man die HAL verwendet, um Funktionen auszuführen, die ich in meinem Programm benötige, aber es scheint, als müsste ich diesen Speicherblock in der Linker-Datei deklarieren, und ich habe große Probleme, ein Beispiel dafür zu finden deckt das ab. Die Standard-mem.ld von CubeMX sieht folgendermaßen aus:
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
}
Es scheint, als ob ich danach einen Block mit Ausgabeabschnitten benötige, in dem ich ein Schlüsselwort für> FLASH festschreibe, aber ich weiß nicht, welches Schlüsselwort das wäre oder wie ich die Tabelle im Code deklarieren würde, um ihr die richtige Adresse zu geben.
Ich habe den emulierten EEPROM-Anwendungshinweis gesehen, aber es scheint viel zusätzlicher Aufwand für den Speicher zu sein, der nicht genügend Lösch- / Schreibzyklen aufweist, um über die Lebensdauer des Speichers besorgt zu sein. Hilfe!
Antworten:
Hinweis: Das Verknüpfen ist nicht Teil der C-Sprachstandards, daher implementiert jeder Compiler Linker-Dateien anders. Sie scheinen GCC zu verwenden, daher werde ich einen Code freigeben, der damit funktioniert.
linker.ld:
In C:
Was dies tut:
(1) Erstellen Sie einen Bereich mit dem Namen FIXED_DATA mit der angegebenen Position und Größe. Beachten Sie, dass mein Code von einem anderen Gerät stammt. Überprüfen Sie in Ihrem Datenblatt, wie groß Ihre Blöcke sind (sie sind in einem Gerät möglicherweise nicht gleich groß!). Stellen Sie sicher, dass Sie FLASH entsprechend verkleinern, da sonst eine Fehlermeldung angezeigt wird, dass sie nicht in den Speicher passen.
(2) Erstellen Sie einen Abschnitt mit dem Namen FIXED_DATA. Es muss eigentlich nicht FIXED_DATA heißen, aber es hilft, den Überblick zu behalten. Das Attribut NOLOAD weist den Linker an, den Bereich nicht zu füllen (siehe unten).
(3) Fügen Sie alle mit STATIC DATA gekennzeichneten Variablen in diesen Speicherbereich ein
(4) Fügen Sie alles in diesem Abschnitt in den Bereich FIXED_DATA ein, den wir oben erstellt haben
In der C-Datei müssen Sie nur die Variablen markieren, die Sie in den Bereich einfügen möchten. Ich empfehle, sie const zu nennen, da Sie im Allgemeinen nicht direkt in Flash schreiben möchten. Volatile hilft bei Compiler-Optimierungen, bei denen davon ausgegangen wird, dass sich konstante Daten nie ändern.
Warum all diese Schwierigkeiten durchmachen, anstatt die viel einfacheren Lösungen in anderen Antworten zu verwenden? Weil es aufrüstbar ist . Wenn Sie in Zukunft ein FW-Update durchführen möchten, möchten Sie möglicherweise die gespeicherten Daten im Speicher behalten. Die NOLOAD-Anweisung in der Linker-Datei bewirkt genau das: Der Linker füllt die Daten nicht mit 0, wie dies normalerweise der Fall wäre, wenn dort eine globale Variable lebt.
Sie können mehr über die arkanen Wege des Linkers erfahren, wenn Sie nach "ld syntax" suchen.
quelle
Das ist nicht so kompliziert zu machen.
Grundsätzlich benötigen Sie eine konstante globale Variable, die in Flash platziert wird und die Position mithilfe eines Pragmas definiert.
In C ++ könnte der Header ungefähr so aussehen:
Und so sieht die Implementierung aus:
Um diese Seite in Flash zu schreiben, benötigen Sie einen Puffer (entweder im RAM oder in Flash) mit der gleichen Größe wie eine Flash-Seite, da Sie die Seite löschen müssen, bevor Sie sie erneut schreiben, sodass eine Änderung eines einzelnen Werts an Ort und Stelle erfolgt nicht möglich.
Je nachdem, wie genau Sie es verwenden, müssen Sie die Struktur möglicherweise als deklarieren
volatile
. Dies geschieht insbesondere, wenn Sie direkt auf die Tabelle zugreifen (nicht mit einem Zeiger wie in diesem Fall).Einige Compiler optimieren den Code so, dass sie die Konstante aus der Tabelle direkt in den Code übernehmen. Das Ergebnis ist, dass wenn Sie den Wert in Ihrer Tabelle ändern, der Wert im Code nicht berücksichtigt wird.
Der IAR-Compiler hatte einige Probleme (es ist in der aktuellen Version behoben) bei der Handhabung von a,
static volatile const
also wechselte ich zur Verwendung eines Zeigers.Wenn Sie die Werte ändern möchten, benötigen Sie eine Art Flash-Algorithmus.
Das Schreiben von Flash besteht immer aus:
Hinweis für Fortgeschrittene: In einigen Fällen können Sie ausnutzen, dass Sie Nullen an Positionen schreiben können, an denen sich eine Eins befand, sodass Sie 0x7F in 0x3F ändern können, aber nicht umgekehrt. In diesem Fall müssen Sie keine Seite löschen. Einige Controller unterstützen dies möglicherweise nicht.
quelle
Ja, es wäre am saubersten, einen Abschnitt für Ihre Tabelle zu deklarieren.
Am einfachsten ist es jedoch, den FLASH-Bereich um die Seitengröße zu reduzieren und dann:
Hier ist "0x20000" die Größe des Flash-Speichers. In / my / code verwende ich eine Definition von MY_FLASH_SIZE, definiert als: #define MY_FLASH_SIZE ((* (kurz *) 0x1ffff7cc) << 10), die für die F0-Serie funktioniert, vielleicht auch für Ihre. Ich bin von 128.000 Geräten in der Entwicklung (nur ein paar Nickel teurer als die 64.000) zu 64.000 Geräten in der Produktion gewechselt, ohne zu bemerken, dass dies die Position des Flash-Bereichs verändert hat ... :-)
quelle
Wenn Sie Flash übrig haben, können Sie eine globale const-Variable deklarieren, die doppelt so groß wie eine Flash-Seite ist, und ihre Startadresse auf ein Vielfaches der Flash-Seitengröße runden. Ein bisschen verschwenderisch, aber keine Notwendigkeit, Linkerscript-Magie zu betreiben.
quelle