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
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
Ok, das hört sich gut an. Wo bzw. Wie muss ich dem Linker mitteilen, ab welcher Adresse der .noinit Bereich beginnt?
Normalerweise irgends. Wenns sein muss: siehe Link. Wir reden aber schon von C Programmierung?
:
Bearbeitet durch User
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?
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
Weil ich dann wie oben beschrieben genau den SRAM Bereich löschen kann, der keine .nonit Variablen enthält.
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
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
spess53 schrieb: > Und den Stack gleich mit plattmachen? Nebst der grad eben frisch ins RAM kopierten Strings.
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
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.
>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?
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.
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.
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.
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
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
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.