Hallo Leute, ich benutze den NXP MK64FN1M0VDC12 (also den ohne EEROM) mit GCC. Ich möchte nach einem Reset mit meinen alten Variablenwerten weiterrechnen. Nur wird beim Reset die statischen Variablen genullt/gesetzt. Was muss ich machen, damit meine Variablen NICHT beim Systemstart gesetzt werden? Gibt es eventuell noch eine andere Möglichkeit? Beim STM32 hat das RTC-Modul noch ein paar BackupRegister, die ich auch schon erfolgreich nutzen konnte. Leider habe ich keinen anderen Chip mit freien Registern auf der Schaltung. Danke für Hinweise, Adib. --
Adib schrieb: > Nur wird beim Reset die statischen Variablen genullt/gesetzt. Dann schmeiß das Ausnullen doch ganz einfach aus dem Startup-Code raus. Allerdings solltest du dann in deinem Programm davon ausgehen, daß alle globalen Variablen eben so sind, wie sie halt sind. Und wenn der Reset durch nen Brownout oder Kaltstart gekommen ist, dann sind deine Variablen eben unbestimmt. W.S.
Leg die Variablen in die .noinit section
Du musst auch Reset und Power-Up unterscheiden können. Ansonsten arbeitest du mit völlig zufälligen Werten nach dem power-up. Jep, SRAM ist zufällig beim starten. Zwar nicht jedes mal komplett unterschiedlich, aber definitiv schwierig vorherzusagen.
.noinit war wohl das gute Stichwort. Danke. Ich hatte mir überlegt von Zeit zu Zeit eine Schattenkopie mit CRC anzulegen. Bei Programmstart will ich dann diese Schattenkopie testen und evtl kopieren. Danke und Grüße, Adib. --
> Leg die Variablen in die .noinit section
Wie macht man das in C?
Stefan U. schrieb: > Wie macht man das in C? GCC:
1 | int meineVariable __attribute__((section(".noinit"))); |
Die interessante Frage ist doch, wie oft tritt denn ein Reset ein, der kein Power-On-Reset ist? Wenn du im Betrieb öfter den Controller zurücksetzt (wo der SRAM erhalten bleiben könnte) würde ich mir Gedanken übers Design machen... Und beim Hochfahren ist eh alles weg. Da müsste man schon in den Flash für schreiben.
wenn das als EEPROM Ersatz dienen soll: hat der K64 evtl. ISP Routinen im ROM? Damit kann man Parameter die sich selten ändern auch zur Laufzeit im Flash ablegen. Nachtrag: hier ist eine AppNote die sowas für kinetis beschreibt: https://www.nxp.com/docs/en/application-note/AN4282.pdf
> Die interessante Frage ist doch, wie oft tritt denn ein Reset ein, > der kein Power-On-Reset ist? Ich könnte mir durchaus vorstellen, auf diese Art manchmal einen Taster und/oder Pin einzusparen. Wenn zum Beispiel ein Gerät mit fest eingelötetem Akku nur einen "Start" Taster hätte, bräuchte ich zusätzlich noch einen "Reset" oder "Power-Cycle" Taster (so wie bei viele Smartphones, Tablets und Navis irgendwo versteckt vorhanden). >> Wie macht man das in C? > So:... Danke Dr. Sommer
Stefan U. schrieb: >> Leg die Variablen in die .noinit section > > Wie macht man das in C? Gar nicht :-) In GNU-C/C++ geht's wie oben gezeigt mit section-Attribut, einer C-Erweiterung. Dies setzt allerdings voraus, dass es von der Toolchain unterstützt wird, also insbesondere durch Zusammenspiel von Linker-Skript und Startup-Code: Das ld-Skript legt .noinit in eine alloc noload section, die nicht vom Startup-Code genullt wird. Ohne Nennung im ld-Skript ist .noinit eine Orphan-Section und deren Lage geschieht nach spezellen[tm] Regeln. .noinit wird von den GNU avr-Tools unterstützt; bei ARM sind "standardisierte" ld-Skripte und Startup-Code wie von der avr-libc weit weniger verbreitet. Schließlich ist der Name der Section im Endeffekt Wurscht — es kommt auf deren Unterstützung in Startup-Code und dem Zusammenspiel zwischen Symbolen aus dem Start-Code und dem ld-Skript an. Beispiel:
1 | .data: |
2 | {
|
3 | PROVIDE (__data_start = .) ; |
4 | ... |
5 | PROVIDE (__data_end = .) ; |
6 | } > data AT> text |
7 | .bss ADDR(.data) + SIZEOF (.data) : AT (ADDR (.bss)) |
8 | {
|
9 | PROVIDE (__bss_start = .) ; |
10 | ... |
11 | PROVIDE (__bss_end = .) ; |
12 | } > data |
13 | __data_load_start = LOADADDR(.data); |
14 | __data_load_end = __data_load_start + SIZEOF(.data); |
15 | /* Global data not cleared after reset. */ |
16 | .noinit ADDR(.bss) + SIZEOF (.bss) : AT (ADDR (.noinit)) |
17 | {
|
18 | PROVIDE (__noinit_start = .) ; |
19 | *(.noinit*) |
20 | PROVIDE (__noinit_end = .) ; |
21 | ... |
22 | } > data |
Die zur Verfügung gestellten Symbole werden dann im Start-Code verwendet; je nach verwendetem Code heißen die anders und sind an diesen anzupassen.
Johann L. schrieb: > .bss ADDR(.data) + SIZEOF (.data) : AT (ADDR (.bss)) > { > PROVIDE (__bss_start = .) ; > ... > PROVIDE (__bss_end = .) ; > } > data Hm, was ist hier der Unterschied zum einfacheren:
1 | .bss (NOLOAD) : {
|
2 | PROVIDE (__bss_start = .) ; |
3 | ... |
4 | PROVIDE (__bss_end = .) ; |
5 | } > data |
und fehlt bei dir nicht ein NOLOAD (insb. bei .noinit) damit die Section nicht eben doch überschrieben wird, wenn man per GDB startet?
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.