Forum: Mikrocontroller und Digitale Elektronik SRAM initialisieren nach Watchdog-Reset


von Dennis Peters (Gast)


Lesenswert?

Hallo Forum,

ich mache gerade meine ersten Erfahrungen mit nem STK600 und den AVR 
XMega Mikrocontrollern. Nach dem Tutorial klappten die ersten kleineren 
Programme schon ganz ordentlich. Leider bin ich jetzt an einem Punkt wo 
ich nicht weiterkomme und weder hier im Forum oder im Datenblatt etwas 
gefunden habe was mir weiterhilft.

Zu meinem Problem, ich möchte nach einem ausgeführten Watchdog-Reset nur 
einen Teil der globalen Variablen wieder zurücksetzen. Sicherlich ist 
eskein Problem diese einzeln mit 0 zu initialisieren. Schöner fände ich 
aber eine Routine, die das SRAM bis auf ein paar Adressen wieder 
zurücksetzt.

Jetzt meine Frage, wie kann ich auf das SRAM zugreifen? Das ist mir 
irgendwie unklar. Und ist es möglich einer Variablen eine bestimmte 
Adresse zuzuweisen, oder einen Adressbereich für bestimmte Variablen zu 
definieren.

Über Hilfe würde ich mich echt freuen.......


Viele Grüße

von Marius W. (mw1987)


Lesenswert?

Pack doch die Variablen, die du behalten wollst in die "noinit"-Section. 
Dann bist du allerdings für die korrekte Initialisierung verantwortlich.

Siehe: http://www.nongnu.org/avr-libc/user-manual/mem_sections.html

Gruß
Marius

von Dennis Peters (Gast)


Lesenswert?

Ok,

das hört sich gut an. Wo bzw. Wie muss ich dem Linker mitteilen, ab 
welcher Adresse der .noinit Bereich beginnt?

von (prx) A. K. (prx)


Lesenswert?

Normalerweise irgends. Wenns sein muss: siehe Link.
Wir reden aber schon von C Programmierung?

: Bearbeitet durch User
von Dennis Peters (Gast)


Lesenswert?

Ja, C Programmierung.

Also ich hätte schon gerne einen fest definierten Bereich. Jetzt kann 
ich ja im AVRStudio6 unter Toolchain - AVR/GNU Linker einmal unter 
Memory Settings das SRAM Segment definieren (weiß leider nicht wie)oder 
unter Miscellaneous ein Linker Flag setzen.

Der Befehl -Wl,--section-start=.noinit=0x2000 als Linker Flag scheint 
schon mal zu funktinieren.

Nur wie greife ich jetzt auf das Adresse 0x2010 bis 0xffff zu?

von (prx) A. K. (prx)


Lesenswert?

Dennis Peters schrieb:
> Also ich hätte schon gerne einen fest definierten Bereich.

Weshalb? Normalerweise attributierst du die nicht beim Start zu 
initialisierenden Variablen entsprechend dem Link und überlässt die 
Speicherwaltung dem Linker. Der legt diese Variablen automatisch in die 
benannte Sektion und sorgt für die richtigen Adressen.

Wenn du eine komplett eigene Speicherverwaltung des Linkers im Auge 
hast, dann wirds halt etwas komplizierter. Weil du dann erst einmal 
gründlich verstehen solltest, wie die normale Speicherverwaltung 
funktioniert.

: Bearbeitet durch User
von Dennis Peters (Gast)


Lesenswert?

Weil ich dann wie oben beschrieben genau den SRAM Bereich löschen kann, 
der keine .nonit Variablen enthält.

von (prx) A. K. (prx)


Lesenswert?

Wozu? Das macht der Startup-Code doch sowieso schon von selbst. Alle 
external/static Vars, die nicht explizit in die .noinit Sektion gelegt 
werden, werden beim Start automatisch initialisiert.

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

>Weil ich dann wie oben beschrieben genau den SRAM Bereich löschen kann,
>der keine .nonit Variablen enthält.

Und den Stack gleich mit plattmachen?

MfG Spess

von (prx) A. K. (prx)


Lesenswert?

spess53 schrieb:
> Und den Stack gleich mit plattmachen?

Nebst der grad eben frisch ins RAM kopierten Strings.

von Thomas (kosmos)


Lesenswert?

hier mal ein .asm Beispiel von mir für einen ATMega16 also für 1kByte 
SRAM muss du halt entsprechend anpassen. Ich hatte das ganze direkt vor 
dem Programm gemacht deswegen war mir das mit Zeitaufwand egal, den im 
Programm weiter unten gibt dann keine solchen Verzögerungen.
1
reset:
2
ldi temp, low(RAMEND)    ;Stackpointer initialisieren
3
out SPL, temp
4
ldi temp, high(RAMEND)
5
out SPH, temp
6
7
clear_sram:       ;Setze alle 1024 SRAM-Zellen auf 0
8
clr temp          ;320,75 µSek bei 16 MHz
9
ldi temp2, 0      ;256
10
ldi temp3, 4      ;4      4x256=1024
11
clr R27           ;Startadresse SRAM $0060
12
ldi R26, $60
13
14
Schleife1:
15
st X+, temp
16
dec temp2
17
brne Schleife1
18
dec temp3
19
brne Schleife1

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Thomas O. schrieb:
> hier mal ein .asm Beispiel

Drum fragte ich nach Assembler vs. C. Ein Assembler-Beispiel ist in 
dieser Frage bei C Programmierung zu 100% nutzlos.

von Dennis Peters (Gast)


Lesenswert?

>Wozu? Das macht der Startup-Code doch sowieso schon von selbst. Alle
>external/static Vars, die nicht explizit in die .noinit Sektion gelegt
>werden, werden beim Start automatisch initialisiert.

Aber nicht nach einem Watchdog_Reset. Das ist mein Problem, denn sonst 
könnte ich die Variable auch im EEPROM speichern.

>Und den Stack gleich mit plattmachen?
Ich frag jetzt mal ganz dumm, wäre das kritisch wenn ich den Bereich 
einhalte?

von Thomas (kosmos)


Lesenswert?

du wirst es doch in C hinbekommen eine Schleife z.B. 1024mal 
abzuarbeiten und eine Adresse bei jedem Schreiben um 1 zu erhöhen? Da 
ich mit C nichts am Hut habe mache ich mir den Aufwand nicht aber ein 
.asm Beispiel ist doch besser als garkeins. Vielleicht kann jemand 
anderes das Beispiel oben nach C umwürfeln.

von (prx) A. K. (prx)


Lesenswert?

Dennis Peters schrieb:
> Aber nicht nach einem Watchdog_Reset.

Doch, meines Wissens ist es dem Startup-Code völlig schnurz, wodurch ein 
Reset ausgelöst wurde. Anders wärs beim Watchdog-Interrupt.

von (prx) A. K. (prx)


Lesenswert?

Thomas O. schrieb:
> du wirst es doch in C hinbekommen eine Schleife z.B. 1024mal
> abzuarbeiten und eine Adresse bei jedem Schreiben um 1 zu erhöhen?

Sein Problem ist nicht das Löschen selbst, sondern die Frage der 
Speicherorganisation. Also welche Variable an welcher Stelle landet und 
welcher Bereich wann gelöscht werden muss/kann/darf.

von spess53 (Gast)


Lesenswert?

Hi

>Ich frag jetzt mal ganz dumm, wäre das kritisch wenn ich den Bereich
>einhalte?

Welchen Bereich? Der Stack ist dynamisch. Wie weit er in den RAM 
hineinreicht, ist einfach ausgedrückt, von der Stelle im Programm 
abhängig, die gerade abgearbeitet wird.

>ich mache gerade meine ersten Erfahrungen mit nem STK600 und den AVR
>XMega Mikrocontrollern.

Dann ist der Watchdog das allerletzte was du brauchst. Ergo hast du kein 
Problem mit den Variablen.

MfG Spess

von Thomas M. (thomaswm)


Lesenswert?

Ich habe etwas ähliches gemacht:

Es handelt sich hier zwar um einen V850-Automotive Controller, aber bei 
den AVRs sollte das gleich sein.
Zu meinem Projekt habe ich das .ld-File angepasst. Darin steht der 
Aufbau des SRAMs. Bei meinem Controller beginnt der SRAM an der Adresse 
0xFFFF0000 und genau dort hin habe ich die .noinit-Section gelegt.
Die Größe wird automatisch angepasst, was für meine Zwecke ok ist. Man 
kann aber auch feste Werte eintragen.
1
/************************************************************************/
2
/*                          DF3441.ld                                   */
3
/*                                                                      */
4
/*  NEC V850 microcontroller device uPD70F3441                          */
5
/*                                                                      */
6
/*  Template of linker directive file for the                           */
7
/*  Green Hills Multi 2000 environment                                  */
8
/*  Usage:  ccv850e file1.o file2.o ... fileN.o -o a.out DF3441.ld      */
9
/*                                                                      */
10
/*  Copyright (C) NEC Corporation 2006                                  */
11
/*  This file was created from device file DF3441.800       [E1.00d]    */
12
/*  by DeFiX V1.24                                                      */
13
/*                                                                      */
14
/*  This file is only intended as a sample supplement to NEC tools.     */
15
/*  Feel free to adapt it to your own needs.                            */
16
/*  This File is provided 'as is' without warranty of any kind.         */
17
/*  Neither NEC nor their sales representatives can be held liable      */
18
/*  of any inconvenience or problem caused by its contents.             */
19
/************************************************************************/
20
21
MEMORY
22
 {
23
  iROM    : ORIGIN = 0x00000000,  LENGTH = 992k
24
  iRAM    : ORIGIN = 0xFFFF0000,  LENGTH = 60k
25
 }
26
27
SECTIONS
28
 {
29
30
/* Start of internal ROM area (iROM) */
31
32
  .intvect                         :>iROM   /* start of interrupt vector */
33
  .intvect_end  0x07CF             :>.      /* end   of interrupt vector */
34
  .rozdata                         :>.      /* constant datas in ZDA area */
35
  .robase   align(4)               :>.      /* initialize textpointer TP for SDA addressing */
36
  .rosdata  align(4)               :>.      /* constant datas in SDA area */
37
  .rodata   align(4)               :>.      /* constant datas in normal area */
38
39
  .text     align(4)               :>.      /* program code area */
40
41
  .fixaddr  align(4)               :>.      /* ghs internal (compiler) */
42
  .fixtype  align(4)               :>.      /* ghs internal (compiler) */
43
  .secinfo  align(4)               :>.      /* ghs internal (runtime library) */
44
  .syscall  align(4)               :>.      /* ghs internal (linker) */
45
46
  .romdata  ROM(.data)             :>.      /* constant data to initialize variables (copied to RAM at startup)*/
47
  .romzdata ROM(.zdata)            :>.      /* constant data to initialize variables in ZDA area (copied to RAM at startup)*/
48
  .romsdata ROM(.sdata)            :>.      /* constant data to initialize variables in SDA area (copied to RAM at startup)*/
49
  .romtdata ROM(.tdata)            :>.      /* constant data to initialize variables in TDA area (copied to RAM at startup)*/
50
51
/* Start of internal RAM area (iRAM) */
52
53
  .noinit   align(4)               :>iRAM   /* not initialized data */
54
  .data                            :>.      /* initialized data */
55
  .bss      align(4)               :>.      /* zero initialized data*/
56
57
  .sdabase  align(4)               :>.      /* initialize globalpointer GP for SDA addressing */
58
  .sdata    align(4)               :>.      /* initialized data in SDA area*/
59
  .sbss      align(4)               :>.      /* zero initialized data in SDA area*/
60
61
  .zdata    align(4)               :>.      /* initialized data in ZDA area*/
62
  .zbss     align(4)               :>.      /* zero initialized data in ZDA area*/
63
64
  .tdata    align(4) MAX_SIZE(256) :>.      /* initialized and zero-initialized data in TDA area */
65
66
  .stack    align(4) pad(0x200)    :>.      /* definition of stack size */
67
68
//  .heap     align(4) pad(0x800)    :>.      /* definition of heap size (enable if needed) */
69
70
 }
71
72
/************************************************************************/
73
/*      End of File                                                     */
74
/************************************************************************/

hier noch etwas Theorie:

http://www.math.utah.edu/docs/info/ld_3.html

von Thomas (kosmos)


Lesenswert?

nach einem Reset würde ich mich auf nichts mehr (Variablen/SRAM) 
verlassen. Wenn ich sichergehen will das nichts verloren geht, würde ich 
den µC ausreichend Puffern, mit einem Analogeingang die Spannung vor dem 
Spannungsregler messen und wenn diese Abfällt sofort alles wichtige ins 
EEPROM schreiben. Damit ich nach dem folgendem Reset damit 
weiterarbeiten kann.

von (prx) A. K. (prx)


Lesenswert?

Thomas O. schrieb:
> nach einem Reset würde ich mich auf nichts mehr (Variablen/SRAM)
> verlassen.

Die Quelle des Reset geht aus einem Statusregister hervor. Das kann man 
also schon differenzieren. Bei Watchdog/Pin ist die Situation anders als 
bei Powerup/Brownout.

: Bearbeitet durch User
von Thomas (kosmos)


Lesenswert?

sorry habe das mit dem Brown Out verwechselt.

von Marian (phiarc) Benutzerseite


Lesenswert?

Ich habe das mal ein bissl getestet und der Mega8 verhält sich da wie 
erwartet (BOD an, Watchdog an), wenn der BOD resettet, zählt das als 
quasi-POR, nur eben mit dem BOD-Reset-Bit gesetzt. Ein eventuell vorher 
gesetztes WD-Reset-Bit wird also auch zurückgesetzt => kein Problem.


Ich weiß nicht so ganz, wo OPs Problem noch liegt.
-Seine Variablen, die er behalten will, packt er ins .noinit (attribute)
-In main() oder auch below-main, wie er mag, prüft er aufs WD-Reset-Bit 
und wenn es nicht gesetzt ist, initialisiert er die .noinit-Variablen
-Fertig.

: Bearbeitet durch User
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.