Bevor ich mich jetzt "zu Tode werkel" nur weil ich etwas nicht wahrhaben mag: Ich möchte den Flashspeicher des STM32F401RC aus einem laufenden Programm heraus beschreiben und auch wieder auslesen. Ich arbeite mit dem Libopencm3-Framework, habe aber auch die HAL von ST jetzt schon bemüht und auch Experimente auf Registerebene druchgeführt. Natürlich leß ich hierfür das Datenblatt des ST32F401RC (um denjenigen, die da sagen: Datenblatt lesen hilft, vorweg zu greifen). Grundsätzlich muß der Flashspeicher erst gelöscht werden um diesen neu beschreiben zu können. Hier fängt mein Problem jetzt an. Meine Frage hier an das Forum ist, ob ich das Datenblatt dahingehend richtig interpretiere, dass ich den Flashspeicher immer nur ab einer Sektorengrenze mit einer dann "beliebigen" Anzahl Speicheradressen löschen kann. Der 401RC hat "nur" 256 kByte Flashspeicher und Sektor 5 wäre hier dann ab Adresse 0x8020000. Jetzt kann ich ab hier zwar den Speicher löschen, aber ein Anwenderprogramm hätte dann nur noch die unteren 128 kByte ab Adresse 0x8000000 zur Verfügung. Im Datenblatt habe ich nichts gefunden, um bspw. den Speicher ab Adresse 0x8030000 zu löschen. Kann ich also den Speicher innerhalb einer Sektorgrenze tatsächlich nicht gezielt löschen, sondern wirklich nur ab der Sektorengrenze? Viele Grüße, Ralph
Du kannst immer nur einen ganzen Sektor löschen. Die ersten Sektoren sind aber kleiner..
Tassilo H. schrieb: > Du kannst immer nur einen ganzen Sektor löschen. Die ersten Sektoren > sind aber kleiner.. Hrmpf, so etwas hatte ich befürchtet. Das einzige was ich also tun kann, wäre wirklich Sektor0, Adresse 0x8000000 für die Vektoren verwenden, Sektor1 bis max. 16 kByte als Speicher für ein Beschreiben aus einem Programm heraus verwenden und je nachdem wie groß der reservierte Platz für das Anwenderprogramm ist, dieses ab Sektor2 dort ablegen. Hierfür dann das Linkerscript entsprechend abändern damit der Bereich für das Anwenderprogramm nicht von einem Schreiben auf den Flash überschrieben wird ? Schade, dass es da keine einfachere Lösung gibt. Aber danke für deine Aussage.
Ich habe typischerweise in Sektor 0 einen Bootloader und das Anwendungsprogramm beginnt in Sektor 1. Der Init-Code vom Anwendungsprogramm legt die Vektoren dann auf den Beginn des Anwendungsprogramms. Das würde genauso funktionieren, wenn man das Anwendungsprogramm in Sektor 2 beginnen läßt, Sektor 1 wäre dann frei verfügbar.
Tassilo H. schrieb: > Ich habe typischerweise in Sektor 0 einen Bootloader und das > Anwendungsprogramm beginnt in Sektor 1. Der Init-Code vom > Anwendungsprogramm legt die Vektoren dann auf den Beginn des > Anwendungsprogramms. > Das würde genauso funktionieren, wenn man das Anwendungsprogramm in > Sektor 2 beginnen läßt, Sektor 1 wäre dann frei verfügbar. So ähnlich habe ich mir das gedacht gehabt. Jetzt muß ich mal schauen, wie das Libopencm3-Framework mit dem Init-Code umgeht und das für diesen einen Fall dann abändern (und alles nur, weil ich mir ein externes EEProm sparen will)
Ralph S. schrieb: > So ähnlich habe ich mir das gedacht gehabt. Jetzt muß ich mal schauen, > wie das Libopencm3-Framework mit dem Init-Code umgeht und das für diesen > einen Fall dann abändern (und alles nur, weil ich mir ein externes > EEProm sparen will) Ich habe auch mal mit einen anderen STM versucht, den internen Flash zu beschreiben. Das hat alles nicht funktioniert, irgendwas blieb hängen und die geänderten Bereiche stimmten nicht. Nachdem ich einige Zeit darauf verschwendet habe, kommt jetzt einfach ein I2C Flash oder EEProm daran, und alles wird einfacher. Die Dinger sind doch so billig. Ein 32KByte EEProm STM M24256 gibt es für unter einem Euro. Das verwende ich, funktioniert prima.
Peter schrieb: > Ich habe auch mal mit einen anderen STM versucht, den internen Flash zu > beschreiben. Das hat alles nicht funktioniert, irgendwas blieb hängen > und die geänderten Bereiche stimmten nicht. Na ja, mit dem F030 und dem F103 habe ich das mit dem internen Flash schon hinbekommen und funktioniert auch gut. Bei diesen Typen (STM bezeichnet die als low-density devices) ist der Flashspeicher in 1 kByte Pages unterteilt (und somit hat ein 128 kByte Device eben 128 Pages). Da kann man relativ zielgenau einen Flashspeicher in 1 kByte Häppchen beschreiben. Leider geht das mit einem F4xx so dann nicht, da ist die Unterteilung in unterschiedlich großen Sektoren (anstelle von Pages) angegeben. Grundsätzlich hat das auch beim F4 funkioniert, nur leider muß ich da, wenn ich den Flash hinter dem Programm nutzen mag eben 128 kByte reservieren die dem Hauptprogramm dann fehlen. Deswegen "fummel" ich momentan am Linkerscript, damit ich beim F4 den Flashspeicher in Sektor 1 nutzen kann (wie oben bereits angemerkt). Peter schrieb: > Nachdem ich einige Zeit darauf verschwendet habe, kommt jetzt einfach > ein I2C Flash oder EEProm daran, und alles wird einfacher. Die Dinger > sind doch so billig. Das funktioniert ja immer, aber ich wollte mir ein EEProm sparen, nicht nur des Geldes wegen, sondern auch des Platzes auf einem PCB.
Ralph S. schrieb: > Das funktioniert ja immer, aber ich wollte mir ein EEProm sparen, nicht > nur des Geldes wegen, sondern auch des Platzes auf einem PCB. Heißt also: Du hast nicht mal platz für ein SOT23-5 oder ein 2mm*3mm UDFN8? Glaube ich nicht. fchk
> UDFN8? Glaube ich nicht.
Es gibt auch noch WLP8. Aber dann jammern wieder alle, "kann ich nicht
loeten". :-D
Nun ja, bei manchen Devices hat der Hersteller halt den Speicher
relativ grob strukturiert, dann muss man damit leben.
Vanye
Vanye R. schrieb: > Nun ja, bei manchen Devices hat der Hersteller halt den Speicher > relativ grob strukturiert, dann muss man damit leben. ... oder vorher Datenblätter lesen und sich Gedanken machen. fchk
Vanye R. schrieb: > Nun ja, bei manchen Devices hat der Hersteller halt den Speicher > relativ grob strukturiert, dann muss man damit leben. Ja klar, mit den Fakten muss man leben, daran führt kein Weg vorbei. Allerdings muss es erlaubt sein, über Sinn und Nutzen der vom Hersteller geschaffenen Fakten zu sinnieren. Und gerade im Bezug auf die Organisation des Flash bei den STM32 habe ich hier doch arge Zweifel, ob das auch Herstellerseite wirklich durchdacht wurde. Ganz sicher jedenfalls nicht bezüglich der Nutzersicht der Dinge... Wenn da so wäre, hätte man natürlich die kleiner gestückelten Flashbereiche nicht an den Anfang, sondern an das Ende gelegt... Ja, das hätte ein paar Gatter in der Hardware mehr gekostet. Vielleicht im Wert von 0,00001 Cent/pro Exemplar (grobe Schätzung, Fehlerrate mindestens eine Größenordnung). Es hatte aber die Nutzung massiv vereinfacht. Und zwar sowohl für Bootloader als auch für EEProm-Emulationen. Fazit: STM32 ist architektonisch sicher nicht das Gelbe vom Ei. Das hat sogar ST selber gemerkt und wohlweislich den Bootloader-Support der eigenen Wichsvorlagen-Fabrik (sprich: CubeMX) bei sehr vielen neueren Devices gecancelt. Das hat allerdings wohl auch noch andere Gründe. So stößt man nämlich erst dann, wenn man das selber baut, auf die Tatsache, dass da etwas sehr optimistisch spezifiziert wurde, was Zugriffszeiten betrifft. Sprich: Diese Scheiße erfüllt nicht die Specs des DB (die letztlich in CubeMX umgesetzt werden)! Bei den konkret im OT angesprochenen F401 stößt man z.B. sehr oft auf das Problem, dass beim Bootloading plötzlich (undebugbare) hard faults der Klasse "imprecise fault" auftreten. Versucht man dann, die Sache debugbar zu machen (in der normalerweise vorzuziehenden Annahme, dass der Hersteller seinen Job gemacht hat und eigene Fehler das Problem triggern), etwa nach: https://interrupt.memfault.com/blog/cortex-m-hardfault-debug#imprecise-error-code-example stößt man auf die Tatsache, dass das simple Abschalten des Prefetch bereits reicht, damit die Fehler überhaupt nicht mehr auftreten. Sprich: es gibt keine Software-Ursache. Probiert man dann noch eine wenig weiter rum, stellt sich raus: man kann den Prefetch aktiviert lassen, wenn man statt dessen entweder den Takt reduziert oder die Zahl der Flash-Waitstates erhöht. Mehr gibt es dazu wohl nicht zu sagen...
Ralph S. schrieb: > Grundsätzlich muß der Flashspeicher erst gelöscht werden um diesen neu > beschreiben zu können. Nicht ganz: Successive write operations are possible without the need of an erase operation when changing bits from ‘1’ to ‘0’. Writing ‘1’ requires a Flash memory erase operation. Weiterhin hat man drei 16k Seiten und 10000 Löschzyklen bei 55°C. Das reicht für rund 500MB Daten. Damit könnte man 20 Jahre jede Sekunde ein Byte schreiben. Dass der Speicher am Flash-Anfang stehen muss, ist doch egal: Auch wenn er am Ende stehen dürfte, dann müsste man ihn trotzdem im Linkerskript oder auf anderem Wege reservieren. (Anders wärs doch Pfusch.)
:
Bearbeitet durch User
Daniel V. schrieb: > Dass der Speicher am Flash-Anfang stehen muss, ist doch egal: Auch wenn > er am Ende stehen dürfte, dann müsste man ihn trotzdem im Linkerskript > oder auf anderem Wege reservieren. (Anders wärs doch Pfusch.) Ja klar, Es ist aber viel, viel einfacher, dem Linkersript nur sagen zu müssen, dass einfach weniger Speicher verfügbar ist.
Ob S. schrieb: > Ja klar, Es ist aber viel, viel einfacher, dem Linkersript nur sagen zu > müssen, dass einfach weniger Speicher verfügbar ist. Aber wenn die großen Seiten am Anfang des Flash wären, wäre ein Bootloader ein speicherfressendes Problem (prinzipbedingt in Seite 0). Oder man braucht Fuses wie beim AVR um die Bootadresse festzulegen.
Tassilo H. schrieb: > Aber wenn die großen Seiten am Anfang des Flash wären, wäre ein > Bootloader ein speicherfressendes Problem (prinzipbedingt in Seite 0). ... das wird wohl der Grund sein, warum die großen Sektoren hinten sind. Prinzipiell ist das aber egal, man muß damit "leben" was man hat, oder eben den Controller wechseln. Angesichts des Preises: https://www.lcsc.com/product-detail/Microcontroller-Units-MCUs-MPUs-SOCs_STMicroelectronics-STM32F401RCT6_C74524.html und was der kann, werde ich aber für bestimmte Dinge bei dem Chip bleiben, vor allem weil es auch sehr preiswerte BlackPill-Boards mit dem F401/F411 gibt.
Tassilo H. schrieb: > Ob S. schrieb: >> Ja klar, Es ist aber viel, viel einfacher, dem Linkersript nur sagen zu >> müssen, dass einfach weniger Speicher verfügbar ist. > > Aber wenn die großen Seiten am Anfang des Flash wären, wäre ein > Bootloader ein speicherfressendes Problem (prinzipbedingt in Seite 0). > Oder man braucht Fuses wie beim AVR um die Bootadresse festzulegen. Der Bootloader hat natürlich einen kleinen Teil ab Flash-Beginn mit sich selbst zu überschreiben. Im Minimum die ersten 8 Bytes. Es ist sehr leicht, bei dem hochgeladenen Programm eben diese acht Bytes zu ersetzen, bevor sie in den Flash geschrieben werden. Liegt auch daran, dass der übliche Startup-Code die ersten vier dieser acht Bytes sowieso schon wieder irrelevant macht. Im Prinzip ist also nur noch der Reset-Vektor zu verbiegen, also die Bytes 4..7 ab Flash-Start. Das macht nur das Linkersrcript des Bootloaders etwas komplizierter. Ist es aber sowieso, denn der sollte sowieso sinnvollerweise vollständig aus dem RAM agieren. Macht aber keinen Schlimmen, den Bootloader schreibt man aber nur einmal, Anwendungen, die darüber geladen werden sollen, schreibt (und ändert) man typisch wesentlich häufiger...
Tassilo H. schrieb: > Oder man braucht Fuses wie beim AVR um die Bootadresse festzulegen. Auch hier zeigt sich, dass du nicht wirklich irgendwas weißt. Bootvektor per Fuse ändern geht z.B. nicht den klassischen ATtinys (mit zwei winzigen Ausnahmen). Da wird dann genau deshalb genau dasselbe Prinzip verwendet, wie ich es bei den STM32 verwende...
Ob S. schrieb: > Auch hier zeigt sich, dass du nicht wirklich irgendwas weißt. Dein Tonfall lässt zu wünschen übrig; ob DU irgendwas weißt, können andere entscheiden. a) Ich habe nicht geschrieben "wie bei allen AVRs" - Es gibt genug AVRs bei denen es so ist wie ich geschrieben habe, das Beispiel war also zutreffend. b) Beim Firmwareupdate regelmäßig Seite 0 zu überschreiben ist ganz toll, wenn was schiefgeht zwischen Page Erase und Neuprogrammierung (Stromversorgung, was auch immer), geht der Bootloader auch nicht mehr.
Ob S. schrieb: > Daniel V. schrieb: > >> Dass der Speicher am Flash-Anfang stehen muss, ist doch egal: Auch wenn >> er am Ende stehen dürfte, dann müsste man ihn trotzdem im Linkerskript >> oder auf anderem Wege reservieren. (Anders wärs doch Pfusch.) > > Ja klar, Es ist aber viel, viel einfacher, dem Linkersript nur sagen zu > müssen, dass einfach weniger Speicher verfügbar ist. Ach, und das Programm soll dann den nicht verfügbaren Speicher benutzen? Ja, Pfusch sieht manchmal einfacher aus. Das "große Problem" ist doch, das Linkerscript überhaupt zu ändern (oder erstmal zu finden). Wenn du das schaffst, kannst du es genauso gut richtig machen und Programm und "EEPROM" auf beliebige Adressen legen. Bonus: der Bootloader muss sich nicht überschreiben. Der eigentliche Fehler ist auch nicht die Hardware, sondern die Dokumentation der IDE. Der Linker bietet einfach viel zu viele Möglichkeiten und welche davon von IDE und Compiler genutzt werden, scheint geheim zu sein.
Bauform B. schrieb: >> Ja klar, Es ist aber viel, viel einfacher, dem Linkersript nur sagen zu >> müssen, dass einfach weniger Speicher verfügbar ist. > > Ach, und das Programm soll dann den nicht verfügbaren Speicher benutzen? Nein, wozu sollte das (zu ladende) Programm das tun? Das genau ist ja der Witz meines Ansatzes. Das zu ladenden Programm braucht über den Bootloader exakt garnix zu wissen außer der Tatsache, dass es halt den Umfang des verfügbarten Flash-Speichers "nach hinten" etwas verringert. Und, genau genommen, braucht es nichtmal das zu wissen. Die entsprechende Änderung im Linker-Script dient letztlich ausschließlich dazu, dass das Problem Speichermangel schon beim Kompilieren der Anwendung erkannt und gemeldet werden kann. So lange die Programme weit weg von dieser Grenze sind, lassen sie sich halt auch mit dem Standard-Script übersetzen und trotzdem problemlos per Bootloader laden.
Ob S. schrieb: > Bauform B. schrieb: > >>> Ja klar, Es ist aber viel, viel einfacher, dem Linkersript nur sagen zu >>> müssen, dass einfach weniger Speicher verfügbar ist. >> >> Ach, und das Programm soll dann den nicht verfügbaren Speicher benutzen? > > Nein, wozu sollte das (zu ladende) Programm das tun? Um den Platz als EEPROM-Ersatz zu nutzen?
Flash als EEPROM-Ersatz zu nutzen, ist doch eher fragwürdig. Eine sehr ineffiziente Nutzung, die außerdem einen intensiven Verwaltungsaufwand verursacht und die Lebensdauer beeinträchtigt. Wenn ich einen nichtflüchtigen Speicher für Parameter und Einstellungen benötige, hänge ich extern ein FRAM an den STM32. Da brauche ich keine Page-Verwaltung und kein Wear-Leveling wie beim Flash und muß auch beim Schreiben nicht wie beim EEPROM auf ein Busy-Flag warten.
Tassilo H. schrieb: > b) Beim Firmwareupdate regelmäßig Seite 0 zu überschreiben ist ganz > toll, wenn was schiefgeht zwischen Page Erase und Neuprogrammierung > (Stromversorgung, was auch immer), geht der Bootloader auch nicht mehr. Das Problem hast du immer, so lange der Bootloader nicht in einem speziell geschützten Bereich liegt, also in Quasi-ROM. In praktisch jedem anderen Fall lassen sich Szenarios konstruieren (und auch gezielt praktisch herbeiführen), die den Bootloader lahmlegen. Mehr noch: selbst ein wirklich wirkungsvoll gegen Überschreiben gesicherter Bootloader läßt sich oft noch auf anderen Wegen lahmlegen. Bootloader sind immer ein Sicherheitsrisiko! Und das übrigens nicht nur bezogen auf die Ausfallsicherheit...
Ob S. schrieb: > Bootloader sind immer ein Sicherheitsrisiko! Und das übrigens nicht nur > bezogen auf die Ausfallsicherheit... Das dürfte für den gesamten Flash-Speicher gelten. Das Risiko lauert überall :)
Bauform B. schrieb: > Der eigentliche Fehler ist auch nicht die Hardware, sondern die > Dokumentation der IDE. Der Linker bietet einfach viel zu viele > Möglichkeiten und welche davon von IDE und Compiler genutzt werden, > scheint geheim zu sein. Das ist der "normale" GNU ld, und es gibt schon einen Grund, warum ich nicht irgendeine IDE für den Buildprozess verwende, sondern mir ein Makefile schreibe, das die IDE dann einfach anwendet. Geht sicher auch mit den meisten IDEs, aber da sind die Einstellungen für Präprozessor, Compiler, Linker so verstreut, dass es halt total undurchsichtig ist.
Andreas B. schrieb: > Das ist der "normale" GNU ld Nein. Das kommt natürlich drauf an, welche Toolchain man verwendet. Nur dann, wenn man die gnu-Toolchain verwendet, kann man auch gnu-ld erwarten... > und es gibt schon einen Grund, warum ich > nicht irgendeine IDE für den Buildprozess verwende, sondern mir ein > Makefile schreibe, das die IDE dann einfach anwendet Die üblichen IDEs für STM legen immer auch irgendwo das Linkerscript persistent ab. Man muss es halt nur finden, was aber für jeden Normalbegabten wohl kein Problem darstellen sollte. > mit den meisten IDEs, aber da sind die Einstellungen für Präprozessor, > Compiler, Linker so verstreut, dass es halt total undurchsichtig ist. Nö. Ist sicher deutlich durchsichtiger als die Klartextverschlüsselung in einem Makefile. Eher kritisch ist der Startup-Code. Nur wenn man den findet und versteht und versteht, wie der mit dem Linker interagiert, dann erschließt sich eigentlich wirklich, was da passiert. Und hier geht es dann an's Eingemachte. ARM hat die Sache zwar schon so konstruiert, dass es notfalls auch ohne Asm abgehen könnte, aber damit wirft man zwei Drittel der Hardware-Features weg. Deswegen benutzen praktisch alle relevanten Toolchains nach wie vor Asm-Startup-Code... Also: ASM rules. Und wirklich beherrschen kann man die Sache nur mit Asm-Kenntnissen. So einfach ist das.
Ob S. schrieb: > Eher kritisch ist der Startup-Code. Nur wenn man den findet und versteht > und versteht, wie der mit dem Linker interagiert, dann erschließt sich > eigentlich wirklich, was da passiert. > > Und hier geht es dann an's Eingemachte. ARM hat die Sache zwar schon so > konstruiert, dass es notfalls auch ohne Asm abgehen könnte, aber damit > wirft man zwei Drittel der Hardware-Features weg. Natürlich kann man mit Assembler mehr machen, alleine clz ist schon nett oder bkpt und für Multitasking will man wirklich nicht drauf verzichten. Aber der Startup Code funktioniert wirklich zu 100% in C. Welche Features wirft man da weg? OK, für C++ muss man sehr viel mehr von Linker- und Compiler-Internas wissen. Aber auch das dürfte komplett ohne Assembler funktionieren.
Bauform B. schrieb: > Aber der Startup Code funktioniert wirklich zu 100% in C. Macht dann ja auch so gut wie nix... OK, der standardmäßige Asm-Startup-Code macht ja auch so gut wie nix. Aber bietet halt die Option, die Features der Hardware wirklich umfassend zu nutzen. Das kann C-Startup-Code eben nicht leisten. Das Henne-Ei-Problem, du verstehst?
Ob S. schrieb: > Deswegen benutzen > praktisch alle relevanten Toolchains nach wie vor Asm-Startup-Code... NXP ist nicht relevant? Die haben schon seit Ewigkeiten den startup Code von Code Red in C. Gut leserlich ohne eine einzige Zeile asm. Ob S. schrieb: > Das kann C-Startup-Code eben nicht leisten. Das > Henne-Ei-Problem, du verstehst? Unfug. Siehe NXP.
Ob S. schrieb: > Aber bietet halt die Option, die Features der Hardware wirklich > umfassend zu nutzen. Hättest du bitte wenigstens ein Beispiel? > Das kann C-Startup-Code eben nicht leisten. Das > Henne-Ei-Problem, du verstehst? Ehrlich gesagt: Nein.
J. S. schrieb: > NXP ist nicht relevant? Nach Umsatzzahlen? Wohl nicht wirklich. > Die haben schon seit Ewigkeiten den startup Code > von Code Red in C. Gut leserlich ohne eine einzige Zeile asm. Der Witz ist: Startupcode ist eigentlich nur in Asm wirklich direkt lesbar. Implementierungen in C erfordern zum Verständnis wiederum tieferes Wissen um innere Details des verwendeten Compilers. Wo man dann auf was trifft? Natürlich wiederum auf Implementierungen in Asm... Begreif es endlich: C ist im Kern ein Macro-Assembler. Jeder, der irgendwas anderes behauptet, ist definitiv ein Lügner.
Ob S. schrieb: > Begreif es endlich: C ist im Kern ein Macro-Assembler. Jeder, der > irgendwas anderes behauptet, ist definitiv ein Lügner. Ja ist gut jetzt. Darum geht es hier nicht.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.