Ist es möglich, etwas wie EEMEM und PROGMEM für externe RAM?

OP #5957219
Lesenswert?

Guten Abend,
ich habe folgende Frage:
Ich möchte gerne externe SPI-RAM etwa so wie EEPROM und FLASH benutzen: 
Variablen und Arrays definieren, Tabellen anlegen usw.
Gibt es in GCC dafür Mittel, um mit Hilfe von z.B. Attributen über 
Funkionen, die Zugang zu externem Speicher definieren, den Speicher 
"durchsichtig" zu verwenden?

Oder möchte ich zu viel?

Danke für Antworte im voraus.
Gast #5957222
Lesenswert?

> Gibt es in GCC dafür Mittel, um mit Hilfe von z.B. Attributen über
> Funkionen, die Zugang zu externem Speicher definieren, den Speicher
> "durchsichtig" zu verwenden?

Wenn die unbekannte Zielplattform adäquate Hardwareunterstützung dafür 
hat dann ja.
OP #5957359
Lesenswert?

A. K. schrieb:
> Mit C++ kannst du dem recht nahe kommen.

Es wäre schön für mich, zuerst C gut zu erlernen...

23LCV1024 habe ich auf der Platine, zusammen mit dem Speicherkondensator 
1,5F, der auch DS3234 bedient (wo auch 256 bytes RAM vorhanden. Gegen 
23LCV1024 eine Kleinigkeit, aber...). Nun überlege ich, wie ich das am 
sinnvollsten benutze. Erste Idee war, einen Puffer für SD-Card... Ich 
möchte noch FRAM ausprobieren, mit einem externen Modul. Schade, daß es 
nicht geht, diese Speicher so tief wie eigene RAM von ATMega zu 
integrieren.
#5957390
Lesenswert?

Wenn der interne Speicher zu klein ist, um alle kleinteiligen Daten zu 
speichern, dann wird es kompliziert. Wenn der externe Speicher aber nur 
für gepufferte Datenhaltung oder für grössere Datenmengen verwendet 
wird, dann ist ein solcher transparenter Layer ziemlich überflüssig.

Passen zumindest die kleinteiligen Daten ins interne RAM, dann ist es 
letztlich einfacher, diese Daten ein einer internen Struct zu halten und 
diese en bloc ins externe RAM zu spiegeln. Und grössere Mengen per 
Funktion zu adressieren, statt direkt als Arrayzugriff, ist oft 
akzeptabel. Wenn nicht, hat man vielleicht einen zu kleinen µC gewählt.
#5957929
Lesenswert?

Karl M. schrieb:
> Wilhelm M. schrieb:
>>> Das ist klar. Hier habe ich keine Frage.
>>> Meine Interesse ist aber teilweise theoretischer Natur: eine Variable
>>> deklarieren wie in intern-RAM.
>>
>> In C nein.
>> In C++ ja.
>
> Wie sieht das korrekt aus?

Das kann ich Dir für ein konkretes externes RAM nicht sagen, denn 
erstens habe ich das noch nie benötigt, und zweitens habe ich kein 
SPI-Ram herumliegen.

Ich kann Dir nur sagen, wie die Schnittstelle aussehen könnte:
1
template<typename T, template Dev>
2
struct ExternalData {
3
     ExternalData(const T&);
4
     ExternalData(const ExternalData&) = delete;
5

6
     void operator=(const T&);
7

8
     // der Rest ad libitum
9
};

Dann könnte man es folgendermaßen verwenden:
1
using spiRam = SPI<...>;
2

3
ExternalData<uint16_t, spiRam> d{42};
4

5
d = 0815;
#5957940
Lesenswert?

1
EEPROM Example:
2

3
int EEMEM n = 37;
4
int n_in_RAM;
5

6
while(1) {
7
    n_in_RAM == eeprom_read_word(&n);
8
    n_in_RAM++;
9
    eeprom_write_word(&n, n_in_RAM);
10
    // and to see it:
11
    LCD_print_var(n_in_RAM);
12
}
13

14
#include <stddef.h>
15
#define RRMEM(x)  offsetof(struct ram_ext_s,x)
16

17
struct ram_ext_s {
18
  word id;
19
  unsigned int test;
20
  unsigned char foo;
21
  void* bar;
22
  long long foobar;
23
  int value;
24
};
25

26
if(ram_read_word(RRMEM(id))!=(word)UUID) { // init external RAM
27
        ram_write_dword(RRMEM(foobar),123456789UL);
28
        ram_write_word(RRMEM(bar),NULL);
29
        ram_write_word(RRMEM(test),0);
30
        ram_write_word(RRMEM(value),37);
31
        ram_write_word(RRMEM(id),UUID);
32
}
33

34
while(1) {
35
    n_in_RAM == (int)ram_read_word(RRMEM(value));
36
    n_in_RAM++;
37
    ram_write_word(RRMEM(value), n_in_RAM);
38
    // and to see it:
39
    LCD_print_var(n_in_RAM);
40
}
#5958587
Lesenswert?

Maxim B. schrieb:
> Ich möchte gerne externe SPI-RAM etwa so wie EEPROM und FLASH benutzen:
> Variablen und Arrays definieren, Tabellen anlegen usw.

Auf welcher Plattform? Bei AVR: Vergiss es!

Bei ARM Cortex-M3 und höher gibt es etliche die QSPI Flash via Memory 
Controller in den Addressraum einblenden können - der wird dann wie 
"normaler" Flash angesteuert. Mann muss dann "nur" dem Compiler (und 
Linker) beibringen die Sachen auf die richtige Adresse zu packen.

Maxim B. schrieb:
> Keil ist mir zu teuer, da ich kein Profi bin. Ich muß dann ohne dieser
> Option leben.

Keil C51 ist umsonst, wenn man sich Silabs Simplicity Studio saugt. 
BTW:Produziert noch jemand vernünftige 8051ger in 2019?

Beim 8051 hätte man externen XRAM, der aber jede Menge Port Pins frisst.
OP #5958637
Lesenswert?

Jim M. schrieb:
> Keil C51 ist umsonst

Ach 51... Für C51 brauch man kein C, nicht einmal Assembler ist 
unbedingt notwendig. Ich habe Anfang 90-er C51 in Maschinencode ohne 
Computer gemacht: so bequem für Menschen ist Befehlssatz. Byte für 
Operation, Byte oder zwei für Daten oder Adressen. Mit AVR kann das 
schon kaum mehr gehen: Bits von Befehl und Daten sind eigenartig 
durcheinander. Ohne Flasche Schnaps versteht man hier mit Code kaum 
etwas.

Jim M. schrieb:
> Beim 8051 hätte man externen XRAM
Das gibt es auch bei manchen AVR. Wie bei ATMega8515 (wenn man nur 512 
bytes RAM hat, dann ist externe RAM schon eine Notwendigkeit!), so auch 
bei ATmega128A und ATMega2560.
#5958668
Lesenswert?

Maxim B. schrieb:
> Für C51 brauch man kein C, nicht einmal Assembler ist
> unbedingt notwendig.

Du hast einen C-Compiler (C51) benutzt, ohne C oder Assembler?

Achtung: C51 ist ein C-Compiler, 8051 ist die CPU-Architektur.

Zur Ursprungsfrage:

Du kannst die Zugriffe in Makros verpacken, dann sieht dein SPIMEM im 
Code ungefähr so aus wie EEMEM oder PROGMEM. Praktisch wird das aber 
sehr unhandlich, weil die Makros dann mehrfachen Code erzeugen und so 
weiter.

Vermutlich wäre es sinnvoller, wenn du eine gemeinsame Schnittstelle für 
PROGMEM, EEMEM und SPIMEM definierst, also dir Funktionen schreibst. Die 
kannst du dann überall benutzen.

Oder du lebst damit, dass AVR-interne Dinge anders funktionieren als 
Chips, die du ranklebst.
OP #5965483
Lesenswert?

S. R. schrieb:
> Vermutlich wäre es sinnvoller, wenn du eine gemeinsame Schnittstelle für
> PROGMEM, EEMEM und SPIMEM definierst, also dir Funktionen schreibst. Die
> kannst du dann überall benutzen.

Das hilft leider wenig. So kann ich in jedem Fall machen, dafür brauche 
ich keine Frage zu stellen...
Ich möchte lediglich:
1
__Spiram int a = 0;
2
for(char i=0;i<10;i++){
3
   PORTA = (char)a++;
4
}

Sebastian S. schrieb:
> da der Zugriff nur noch
> im Schneckentempo erfolgt.

Immer noch schneller, besonders blockweise, als mit einem graphischen 
128x64 über MCP23S17 ganze Bildschirm Punkt zu Punkt zu invertieren...
Ich überlege nun: eine von vernünftigen Anwendungen wäre vielleicht eine 
Kopie von Bildschirm...
#5965806
Lesenswert?

Maxim B. schrieb:
>> Vermutlich wäre es sinnvoller, wenn du eine gemeinsame
>> Schnittstelle für PROGMEM, EEMEM und SPIMEM definierst,
>> also dir Funktionen schreibst. Die kannst du dann
>> überall benutzen.
>
> Das hilft leider wenig. So kann ich in jedem Fall
> machen, dafür brauche ich keine Frage zu stellen...

Du darfst die Funktionsaufrufe auch in Makros verpacken, wenn dir das 
lieber ist. Mein Vorschlag bezog sich nur auf etwas, was im Rahmen 
deiner Möglichkeiten liegt.

Denn sowas:

> Ich möchte lediglich:__Spiram int a = 0;
> for(char i=0;i<10;i++){
>    PORTA = (char)a++;
> }

ist nicht möglich. Du kannst mit C++ recht nah da rankommen, aber ohne 
eine gemeinsame Abstraktion (die genannten Funktionen) unterscheidet 
sich dein SPIRAM trotzdem von allen anderen Speicherformen. Und es wären 
trotzdem keine normalen Variablen.

Soweit ich dich einschätze, sollten die Funktionen und Abstraktionen 
kein Problem für dich sein. Das drum herum... schon.
#5965972
Lesenswert?

S. R. schrieb:
> Maxim B. schrieb:

> Denn sowas:
>
>> Ich möchte lediglich:__Spiram int a = 0;
>> for(char i=0;i<10;i++){
>>    PORTA = (char)a++;
>> }
>
> ist nicht möglich.

Ich sehe da gar kein Problem, das so in C++ zu abstrahieren.

Und ich finde, das der TO hier absolut genau die richtige Frage stellt: 
er möchte einen DT, der einen Zugriff auf SPI-Ram kapselt. Und 
andererseits einen Typumwandlungs-ctor, einen Kopierzuweisung-Op, einen 
Post-Inkrement-Op, ... zur Verfügung stellt.

Zwar scheint der TO in C++ noch(!) nicht die nötigen Fähigkeiten zu 
haben, doch nachdem er RAII kennengelernt hat, sollte er dazu in der 
Lage zu sein, einen ersten Versuch zu starten. Jedenfalls denkt er wohl 
abstrakt genug ...
#5967009
Lesenswert?

Raoul D. schrieb:
> Ich sehe da gar kein Problem, das so in C++ zu abstrahieren.

>>> __Spiram int a = 0;

Das geht nicht so einfach, zumindest wüsste ich nicht, wie man das mit 
der Syntax hinbekommen soll. Etwas in der Art "SPIRAM<int> a = 0;" 
ginge.

Also ja, grundsätzlich kann man sowas in C++ machen und das 
funktioniert auch sehr gut. Die Frage bezog sich aber auf C und da geht 
das nicht.

Außerdem hat prx den wesentlichen Punkt bereits genannt: Man muss 
erstmal sehr viel Arbeit investieren, bis es in C++ effizient läuft 
und das tut, was man will. Insbesondere als Neuling.
#5967019
Lesenswert?

S. R. schrieb:
> Raoul D. schrieb:
>> Ich sehe da gar kein Problem, das so in C++ zu abstrahieren.
>
>>>> __Spiram int a = 0;
>
> Das geht nicht so einfach, zumindest wüsste ich nicht, wie man das mit
> der Syntax hinbekommen soll. Etwas in der Art "SPIRAM<int> a = 0;"
> ginge.

Das hatte ich doch alles schon oben dargestellt:

Beitrag "Re: Ist es möglich, etwas wie EEMEM und PROGMEM für externe RAM?"

> Außerdem hat prx den wesentlichen Punkt bereits genannt: Man muss
> erstmal sehr viel Arbeit investieren, bis es in C++ effizient läuft

Effizienz ist weniger das Problem

> und das tut, was man will. Insbesondere als Neuling.

Das schon eher ;-) Aber es wäre m.E. ein lohnendes Ziel.

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