Forum: Compiler & IDEs XMEM - Mega1281 - Ganzen exterenen 64kB SRAm nutzen


von Georg (Gast)


Lesenswert?

Hallo an alle,

Ich hab da mal eine Frage zum XMEM Interface des Mega1281 und Mega2561.

Ich hab nun einen 64kB SRAM an das Interface anghängt. Davon kann ich ja 
normal nur auf 56kB zugreifen, da die unteren 8kB die des internen SRAMs 
sind.

Ist es möglich de ganzen externen externen Ram zu nutzen?
Der Adresszeiger ist ja nur 16 Bit. Deshalb die Frage. Es steht ja dazu 
etwas im Datenblatt, aber das verstehe ich nicht wirklich.

Danke im Voraus
mfg Georg

von Benedikt K. (benedikt)


Lesenswert?

Das ist leider nicht (direkt) möglich, da u.a. alle IO Register des AVRs 
diesen Platz belegen.
Verwendet man nur 32kB und schaltet A15 per Hand um (also quasi 
Banking), dann geht es.

von kosmonaut_pirx (Gast)


Lesenswert?

hallo,

bin zufällig beim can128 drüber gestolpert, aber bei deiner mcu ist es 
nicht anders. PORTC wird benutzt, um das höherwertige adress-byte für 
den externen sram zu definieren. mittels der xmm-bits kannst du nun 
definieren, welche bits davon verwendet werden. wenn du (wie default 
vermutlich) alle 8 bits verwendet, gehen dir 8 kb ab wg internal sram. 
benutzt du weniger, so greift das nicht mehr und du hast zugriff auf die 
unteren bereiche des externen srams.

am beispiel des can128: der hat 4k sram == 0x0000 bis 0x1FFF. dafür 
müssen die obersten 3 bits ignoriert werden (bei 0x1FFF sind diese ja 
unbenutzt). ergo gibt die doku an, lediglich 5 bits des PORTC zu 
benutzen.

für den 1281: der hat wohl 8k sram == 0x0000 bis 0x2FFF. dafür müssen 
nur die obersten beiden bits von PORTC ignoriert werden. entsprechend 6 
nutz-bits dieses ports (XMM1 gesetzt, der rest 0).

hth,
bye kosmo

von Georg (Gast)


Lesenswert?

Ok das hab ich einmal verstanden.

Jetzt in der PRaxis. Muss ich immer im XMM Register das umstellen, damit 
ich auf die unteren 8kB zugreife kann?

Ist so etwas sinnvoll??

mfg Georg

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Georg wrote:

> Jetzt in der PRaxis. Muss ich immer im XMM Register das umstellen, damit
> ich auf die unteren 8kB zugreife kann?

Ja.

> Ist so etwas sinnvoll??

Vermutlich nur im Ausnahmefall.

von Peter D. (peda)


Lesenswert?

Jörg Wunsch wrote:

>> Ist so etwas sinnvoll??
>
> Vermutlich nur im Ausnahmefall.


Ich denke auch, die Anwendung, die mit 72kB SRAM läuft, aber mit 63,5kB 
nicht mehr, die mußt Du schon mit der Lupe suchen.


Peter

von Georg (Gast)


Lesenswert?

Hi, wie macht man das bitte nit dem Umschalten? Wenn zB im unterren 
Bereich gearbeitet wird, und Interrupt auftritt dann muss ich daten am 
Stack ablegen...

Naja Ram brauch ich schon viel: TCP/IP, FAT, Display und AD-Wandler am 
XMEM Interface...

mfg

von Frank N. (betafrank)


Lesenswert?

So sollte es gehen: Zur gewünschten XRAM-Adresse ggf. einen Offset 
addieren, um nicht im internen SRAM zu landen. Dann noch die höheren 
Adressleitungen mit 0 maskieren und es landet im XRAM an gewünschter 
Position.
1
#define RAM_OFFSET 0x2000
2
3
void init_sram(void){    
4
    MCUCR = _BV(SRE);//enable XRAM
5
}
6
7
void wr_ram(BYTE* adr, BYTE data){
8
   if(adr<(BYTE*)RAM_OFFSET){
9
      PORTC = 0;
10
      XMCRB = _BV(XMM1) | _BV(XMM0); //Maskiere obere Adr-Bits zu Null
11
      adr += RAM_OFFSET;         //Gültige XRAM-Adr vorgaukeln
12
      *adr = data;
13
      XMCRB = 0;
14
      return;
15
   }
16
   *adr = data;
17
}
18
19
//Wenn sicher ist, dass adr>=RAM_OFFSET ist
20
void wr_ram_i(BYTE* adr, BYTE data){
21
   *adr = data;
22
}
23
24
BYTE rd_ram(BYTE* adr){
25
   BYTE dta;
26
   adr+=layeroffset;
27
   if((adr)<(BYTE*)RAM_OFFSET){
28
      PORTC = 0;
29
      XMCRB = _BV(XMM1) | _BV(XMM0); //Maskiere obere Adr-Bits zu Null
30
      adr += RAM_OFFSET;         //Gültige XRAM-Adr vorgaukeln
31
      dta=*adr;
32
      XMCRB = 0;
33
      return(dta);
34
   }
35
   dta=*adr;
36
   return(dta);
37
}
38
39
//Wenn sicher ist, dass adr>=RAM_OFFSET ist
40
BYTE rd_ram_i(BYTE* adr){
41
   return(*adr);
42
}

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Georg wrote:

> Hi, wie macht man das bitte nit dem Umschalten? ...

> Naja Ram brauch ich schon viel: TCP/IP, FAT, ...

Du kannst ja einen der entsprechenden Puffer in diesen Bereich
auslagern.

von Georg (Gast)


Lesenswert?

> Du kannst ja einen der entsprechenden Puffer in diesen Bereich
> auslagern.

Das hab ich mir auch gedacht. Nur wie schaut es aus, wenn ich auf den 
Puffer zugreife und dann ein IRQ auftritt?

von kosmonaut pirx (Gast)


Lesenswert?

wenn ich mich recht an die doku von heut' vormittag erinnere ist das
1
      XMCRB = _BV(XMM1) | _BV(XMM0);

aber nicht korrekt, sollte
1
      XMCRB = _BV(XMM1);

lauten, kann mich aber auch irren, steht aber in der doku. binnur zu 
faul, grad bei atmel rumzuklickern :)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Georg wrote:

>> Du kannst ja einen der entsprechenden Puffer in diesen Bereich
>> auslagern.

> Das hab ich mir auch gedacht. Nur wie schaut es aus, wenn ich auf den
> Puffer zugreife und dann ein IRQ auftritt?

Du musst natürlich die Interrupts (oder die kritischen Interrupts)
für die Zeit blocken, während die Bänke umgeschaltet sind.  Das
betrifft ja in erster Linie den Bereich, der nach der Umschaltung
wirklich anders ist.  Der Bereich 8,5 KiB ... 32 KiB ist ja nicht
betroffen, den kannst du also für interruptfähige Daten benutzen.

Jaja, es gab mal Zeiten, da waren Bankumschaltungen bei Z80-Computern
sehr beliebt...

von Georg (Gast)


Lesenswert?

> Du musst natürlich die Interrupts (oder die kritischen Interrupts)
> für die Zeit blocken, während die Bänke umgeschaltet sind.

Warum nur bei den kritischen? Sobald ein IRQ auftritt wird ja die 
dazugehörige ISR aufgerufen, und der Stack wird verändert...

Aber ich denke ich werde das ganze lassen... Das ganze wird sonst sehr 
aufwändig und beschränkt nutzbar...

Danek für die Antworten
mfg Georg

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Georg wrote:

>> Du musst natürlich die Interrupts (oder die kritischen Interrupts)
>> für die Zeit blocken, während die Bänke umgeschaltet sind.

> Warum nur bei den kritischen? Sobald ein IRQ auftritt wird ja die
> dazugehörige ISR aufgerufen, und der Stack wird verändert...

Den Stack lässt du sowieso am besten immer im internen RAM, schon
aus Geschwindigkeitsgründen.

von kosmonaut_pirx (Gast)


Lesenswert?

hallo,

>> Warum nur bei den kritischen? Sobald ein IRQ auftritt wird ja die
>> dazugehörige ISR aufgerufen, und der Stack wird verändert...

>Den Stack lässt du sowieso am besten immer im internen RAM, schon
>aus Geschwindigkeitsgründen.

womit sich mir folgende, selbstverständlich hypothetische frage 
aufdrängt:
was passiert, wenn man den SP dennoch auf eine externe adresse setzt, 
der stack jedoch in den bereich des internen srams wächst?
vermutlich wird dann der interne sram verwendet. gäbe es eine 
möglichkeit, das zu ändern?

bin nur neugierig,
danke, bye kosmo

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

kosmonaut_pirx wrote:

> was passiert, wenn man den SP dennoch auf eine externe adresse setzt,
> der stack jedoch in den bereich des internen srams wächst?

Der interne SRAM ist immer eindeutig adressiert, insofern ist das
kein Problem.  Der Trick, um die unteren 8,5 KiB deines externen
Speichers zuzugreifen besteht ja darin, dass du die ganze untere
Hälfte des RAMs auf die 32-KiB-Grenze ,,umleitest''.  Der Bereich
oberhalb 40,5 KiB ist dann gespiegelt mit dem Bereich oberhalb
8,5 KiB, beide greifen also die gleichen Zellen zu.  Der Bereich
oberhalb 32 KiB (bezogen auf die tatsächlichen externen Adressen)
ist in diesem Modus komplett ausgeblendet.

Du kannst natürlich auf diese Weise auch den externen RAM einfach
in zwei 32 KiB große Speicherbänke aufteilen, die du dann manuell
(durch Setzen oder Löschen von A15 über den Portpin) umschaltest.
Die jeweils aktive Bank wird dann ab logischer Adresse 32 KiB
zugreifbar.  Die Applikation benutzt für Stack und normale Daten
den internen RAM.  Der logische Adressbereich von 8,5...32 KiB
wird nicht benutzt.  Damit könntest du z. B. in der einen
Speicherbank die Puffer für das FAT-Filesystem unterbringen und
in der anderen Bank die Puffer für den Netzwerkstack.

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.