Forum: Mikrocontroller und Digitale Elektronik NXP K64, GCC, Variablenspeicher nach Reset nicht überschreiben. Wie?


von Adib (Gast)


Lesenswert?

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.
--

von W.S. (Gast)


Lesenswert?

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.

von Stefan (Gast)


Lesenswert?

Leg die Variablen in die .noinit section

von meckerziege (Gast)


Lesenswert?

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.

von Adib (Gast)


Lesenswert?

.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.
--

von Stefan F. (Gast)


Lesenswert?

> Leg die Variablen in die .noinit section

Wie macht man das in C?

von Dr. Sommer (Gast)


Lesenswert?

Stefan U. schrieb:
> Wie macht man das in C?
GCC:
1
int meineVariable __attribute__((section(".noinit")));

von Dr. Sommer (Gast)


Lesenswert?

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.

von Johannes S. (Gast)


Lesenswert?

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

von Stefan F. (Gast)


Lesenswert?

> 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

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

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.

von Dr. Sommer (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.