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
voidinit_sram(void){
4
MCUCR=_BV(SRE);//enable XRAM
5
}
6
7
voidwr_ram(BYTE*adr,BYTEdata){
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
voidwr_ram_i(BYTE*adr,BYTEdata){
21
*adr=data;
22
}
23
24
BYTErd_ram(BYTE*adr){
25
BYTEdta;
26
adr+=layeroffset;
27
if((adr)<(BYTE*)RAM_OFFSET){
28
PORTC=0;
29
XMCRB=_BV(XMM1)|_BV(XMM0);//Maskiere obere Adr-Bits zu Null
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?
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.