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
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.
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
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
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.
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
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
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 | }
|
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.
> 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?
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 :)
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...
> 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
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.