Variable an definierte Adress im RAM schreiben

Gast #5799625
Lesenswert?

Hallo,
weiß einer wo es bescrieben steht, wie ich eine Variable auf einer 
definierten Adresse erstellen kann? Hintergrund ist, dass ein TEil vom 
RAM bei einem Reset nicht gelöscht wird. Dort muss ich ein FLAG setzen, 
welches nach einem Reset abgefragt werden muss. Allerdings habe ich 
keine Ahnung, wie ich sagen kann, dass die Variable xy an Adresse xyz 
erstellt werden soll.
(Firma: privat) #5799656
Lesenswert?

Du kannst das mit volatilen pointern machen. Volatil, damit der Compiler 
Dir nicht Deine Leseoperationen wegoptimiert, also z.B.:
1
  *(volatile uint8_t*)0x12345678u = 1; // write
2
  int var = *(volatile uint8_t*)0x12345678u; // read

Wenn Dir das zu hässlich ist, dann baust DU halt ein Define drumherum:
1
#define MY_VAR (*(volatile uint8_t*)0x12345678u)
2

3
  MY_REGISTER = 1;  // write
4
  int var = MY_REGISTER;  // read

Oder wenn Du mehrere Variablen hast und C++ verwendest, dann machst Du 
halt ne Klasse draus (wobei DU hier auch noch volatile setzen musst, so 
wie Dein compiler das zulässt):
1
class MyMem 
2
{
3
public:
4
  uint32_t somePort;
5
  uint32_t someOtherPort;
6
};
7

8
class MyMem *mem = (MyMem*)(uintptr_t)0x12345678;
9

10
mem->somePort = 100;
11
uint32_t data = mem->someOtherPort;

Du kannst auch weit auseinander liegende Speicherstellen so belegen, da 
ja Dein Klasse nie alloziert wird, also:
1
class MyMem 
2
{
3
public:
4
  uint32_t PORT_A;
5
  uint32_t offset_zu_b[1023]; // A, B und C sind 4096 bytes auseinander
6
  uint32_t PORT_B;
7
  uint32_t offset_zu_c[1023];
8
  uint32_t PORT_C;
9
};
10

11
class MyMem *mem = (MyMem*)(uintptr_t)0x12345678;

verbraucht 0 bytes Speicher.
#5799716
Lesenswert?

Matthias M. schrieb:

> class MyMem *mem = (MyMem*)(uintptr_t)0x12345678;

So legst du zwar die Speicheradresse fest, aber du allokierst sie nicht. 
Der Compiler/Linker könnte den Speicherbereich daher bereits anderweitig 
verwendet haben (wenn es sich um RAM und nicht um Hardware-Register 
handelt). Das gibt ganz tolle Fehler, viel Spass beim Suchen.

Sven P. schrieb:
> Der eigentlich (fast) einzig sinnvolle Weg mit zeitgemäßen Compilern
> ist, das Symbol im Linkerskript festzunageln.

Genau, zusammen mit dem attribut
1
section ("section-name")
siehe https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html

 Michael
Gast #5799924
Lesenswert?

Michael D.

Ich habe die Variable absichtlich nicht alloziert, da solche Tricks ja 
eigentlich nur nötig sind, um auf Hardwareregister zuzugreifen, und dann 
wäre eine Allokation falsch.

Auch in allen anderen Fällen, die wohl eher nicht in den Mikrocontroller 
Bereich gehören, so wie Shared Memeory, MMU und DMA Aufgaben wäre der 
Speicher ja bereits anderweitig alloziert worden.

Aber wenn es da noch einen anderen Fall gibt, dann würde mich das sehr 
interessieren.
#5799977
Lesenswert?

Sven P. schrieb:
> Der eigentlich (fast) einzig sinnvolle Weg mit zeitgemäßen Compilern
> ist, das Symbol im Linkerskript festzunageln.

Oder die beiden unterschiedlichen RAM-Bereiche in separate Sektionen zu 
stecken und beim Anlegen der Variablen die gewünschte Sektion anzugeben.

MatthiasM schrieb:
> Ich habe die Variable absichtlich nicht alloziert, da solche Tricks ja
> eigentlich nur nötig sind, um auf Hardwareregister zuzugreifen, und dann
> wäre eine Allokation falsch.

Die Variable soll nicht allokiert werden, sondern es muss sichergestellt 
sein, dass sie nicht im Pool, den der Compiler zur freien Verwendung 
hat, enthalten ist.

> Aber wenn es da noch einen anderen Fall gibt, dann würde mich das sehr
> interessieren.

Der steht doch im Ursprungsposting:

Johannes schrieb:
> Hintergrund ist, dass ein TEil vom RAM bei einem Reset nicht gelöscht
> wird. Dort muss ich ein FLAG setzen, welches nach einem Reset abgefragt
> werden muss.
#5800299
Lesenswert?

Julian Mettler schrieb:
> Wie Fanboy schon sagt. Du musst einfach eine Variable
> in der .noinit section anlegen.

Dann bekommt er eine nicht initialisierte Variable irgendwo im Speicher, 
aber ganz sicher nicht an der Stelle, an der er das Flag für den 
Bootloader setzen muss.

Dieser Vorschlag geht am Problem vorbei.

Ein Beispiel, um direkt in den Arduino "Caterina" Bootloader (AVR) zu 
springen:
1
#include <stdint.h>
2
#include <avr/wdt.h>
3

4
void __attribute__((noreturn)) bootloader(void) {
5
  *(uint16_t*)0x0800 = 0x7777;
6
  wdt_enable(WDTO_15MS);
7
  while(1);
8
}
#5800324
Lesenswert?

Arduino Fanboy D. schrieb:
> S. R. schrieb:
>> Dann bekommt er eine nicht initialisierte Variable irgendwo im
>> Speicher, aber ganz sicher nicht an der Stelle, an der er das Flag für
>> den Bootloader setzen muss.
>
> Das ist ja eine lustige Anforderung....
> Wie kommst du darauf?

Schauen wir uns die Frage des TO doch mal an:

Johannes schrieb:
> weiß einer wo es bescrieben steht, wie ich eine Variable auf einer
> definierten Adresse erstellen kann?

Da steht zwar nichts von einem Bootloader, aber dass die Variable an 
einer ganz bestimmten Adresse stehen soll.
Gast #5800344
Lesenswert?

Rolf M. schrieb:
> Mach noch einen, und
> dann bist du auch so weit, wie der Rest hier.

Häää...

Bisher ist mir nur klar, dass eine Variable(besser: ihr Inhalt), einen 
Reset überleben soll.
Alles andere ist Kaffeesatzleserei.

Macht das, wenn es Spaß macht.....
Ich warte lieber auf etwas konkretere Informationen.
#5800357
Lesenswert?

Arduino Fanboy D. schrieb:
> Rolf M. schrieb:
>> Mach noch einen, und
>> dann bist du auch so weit, wie der Rest hier.
>
> Häää...
>
> Bisher ist mir nur klar, dass eine Variable(besser: ihr Inhalt), einen
> Reset überleben soll.

Ich zitiere nochmal die initiale Frage des TO:

Johannes schrieb:
> weiß einer wo es bescrieben steht, wie ich eine Variable auf einer
> definierten Adresse erstellen kann?

Wenn ich dann davon ausgehe, dass er wissen will, wie er eine Variable 
auf einer definierten Adresse erstellen kann, würde ich das nicht als 
Kaffeesatzleserei bezeichnen.
Gast #5800370
Lesenswert?

Rolf M. schrieb:
> Ich zitiere nochmal die initiale Frage des TO:
Und ich zitiere den initialen Irrtum des TE.

Johannes schrieb:
> Hintergrund ist, dass ein TEil vom
> RAM bei einem Reset nicht gelöscht wird. Dort muss ich ein FLAG setzen,
> welches nach einem Reset abgefragt werden muss.

Zumindest in der AVR gcc Welt kann man davon ausgehen, dass Speicher bei 
einem Reset nicht gelöscht wird.

Allerdings werden (nicht lokale) Variablen üblicherweise initialisiert.
Nur eben nicht in der .noinit Section, woher sie ja auch ihren Namen 
hat.

Johannes schrieb:
> Allerdings habe ich
> keine Ahnung, wie ich sagen kann, dass die Variable xy an Adresse xyz
> erstellt werden soll.
Wenn man in C oder C++ eine Variable erstellt, bekommt sie auch einen 
Speicherplatz zugewiesen. Spätestens vom Linker.
Die Frage, warum dieser Variablen händisch eine Adresse vorgegeben 
werden muss, ist hier für mich noch nicht geklärt.
Könnte eine überflüssige Bedingung sein, basierend auf einer weiteren 
irrtümlichen Annahme, da ja der Compiler/Linker das durchaus selber 
erledigen kann.

Und muss es wirklich händisch sein, dann geht der Weg eben über Pointer
Gast #5800527
Lesenswert?

S. R. schrieb:
> Also ist es deiner Meinung nach besser, garnichts zu sagen und den TO
> allein stehen zu lassen, als eine möglicherweise passende Lösung zu
> posten.
Nunja...
Offensichtlich habe ich das Gegenteil deiner Behauptung schon längst 
getan:

Arduino Fanboy D. schrieb:
> Vielleicht möchtest du die Variable in der .noinit Section erstellen?

Mir reicht das erstmal an Kaffesatzleserei...
Solange der TE nicht etwas mehr Information liefert.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren