Hi, ich bin am überlegen wie man 128kByte Ram am sinnvollsten an einen AVR anschließt. Oder genauer wie man den Speicher aufteilt. Möglichkeiten gibt es verschiedene: - 2x 64kB die umgeschaltet werden - 4x 32kB die umgeschaltet werden (und wo sollten die dann liegen? besser von 0000-7FFF oder ab 8000?) Die anderen 32kB bleiben frei für Memory Mapped I/O - 1x 32kB die immer fest eingeblendet sind (zb von 0000-7FFF) und 3x 32kB die abwechselnd eingeblendet werden können (ab 8000) Welche Aufteilung macht Sinn? Oder vielleicht eine ganz andere? Gruß Markus
wie wäre es mit 4 * 128k nein spass beiseite, am einfachsten ist ihn am Stück anzuschließen, was willst du denn genau ereichen ???
meiner meinung nach ist es sinnvoll, einen gewissen bereich immer fest eingeblendet zu lassen, vielleicht die unteren 16k. dann 32K mit banking, dann hast immer noch 16K für erweiterungen. wo die blöcke liegen, ist aber eigentlich egal.
die Größe der Bänke solltest du an der Aufgabenstellung festmachen, sofern vorhanden. Ich denke mal so pauschal kann man die Frage wohl schlecht beantworten, aber das ganze in 16k oder 32k Blöcke aufzuteilen, ist wohl eine gute Idee. noch kleiner ist wohl zu fein.
Hi, schonmal danke für die Antworten. Es gibt keine spezielle Aufgabe sondern es soll möglichst allgemein sein. Die Aufteilung des Speichers ist jedoch nicht unwichtig. z.B. gehen 4kB verloren wenn man das externe Ram ab $0000 ablegt (oder kann man das Schatten Ram auch irgendwie adressieren? Ich hab zumindest noch nicht rausgefunden wie.). Wenn man also 32kB in die untere Hälfte legen würde gingen 12,5% davon verloren was eigentlich nicht wünschenswert ist. Auf der anderen Seite kann es wichtig sein möglichst große, zusammenhängende Bereiche im Speicher zu haben. Ich wüsste zwar im Moment nicht wofür, aber vielleicht gibt es ja Anwendungen wo man das braucht. Braucht man überhaupt noch einen permanenten Speicherbereich für Variablen oder reichen die internen 4kB vielleicht sogar aus? Vielleicht hat ja einer der Programmierprofis Erfahrungen und kann mir Tips geben Gruß Markus
Nun ja, das hängt von deiner Aufgabenstellung ab. 4KB sind eigentlich schon recht viel. Externen Speicher braucht man meistens für "Massendaten", also grosse arrays, Puffer u.ä. Mit paar globalen Variablen hier und da kriegt man jedenfalls die 4KB nicht so schnell zu.
dann mache es doch so, dass du die unteren 4k noch wo anders einblenden kannst ! hast du dir mal das Kapitel Using all 64KB Locations of External Memory durchgelesen und das Programm hinterher ! werde es mal lesen, aber demnach soll es gehen !
Argh, schon wieder zwei verschiedene Mail Adressen in einem Beitrag grml Wie bereits gesagt ist das nicht für eine spezielle Aufgabe gedacht sondern soll möglichst allgemein gehalten werden. Das es dann immer noch Fälle gibt bei denen das nicht passt ist klar. Desshalb soll es MÖGLICHST universell sein, nicht allumfassend. Ein GAL/CPLD wollte ich vermeiden Gruß Markus
wie willst du sonst ein Mapping realisieren ? Oder willst du hierfür Portpins opfern ? Ist auch ne Idee. Also ich sags ganz ehrlich ich verstehe nicht wie man mit dem Beispiel auf ext. Ram zugreifen können soll (im Bereich von 0x0 - 0x1FFF. Hat einer einen Tip ?
Dachte schon an Portpins. So viele braucht man ja nicht. Je nach Größe der Banks 2 oder 3 Portpins. Es gab mal irgendwo nen Beitrag zum Thema Ram Adressierung ab $0000, weiß aber nicht mehr wo und was rausgekommen ist :(
nun ja, bei 2 kannst du schon 4(3) verschiedene Bänke ansteuern und bei 3 Pins schon 8(7), das sollte auf alle Fälle reichen ! hast du verstanden, wie das Progrämmchen arbeitet ?
Gaaaaanz einfach: Angenommen du willst auf die Speicherzelle 0x0042 im externen Speicher zugreifen. Nun setzt du den Pointer aber z.B. auf 0x2042 und deaktivierst dann aber die oberen Adressleitungen und setzt sie manuell auf Null... Dann wird aus den 0x2042 nämlich 0x0042 und du greifst auf die gewünschte Speicherzelle zu, weil für den AVR die Adresse des Pointers ja hoch genug ist, so dass er das EXTMEM-Interface benutzt, du ihm aber nachhder die oberen Adressbits wegmaskierst. Allerdings ist das ziemlich umständlich...
Lieber den Speicher in eine Größenordnung kleinere Bänke aufteilen, also 32K
Du könntest in 32Kb Blöcke teilen. Der Addressbereich des AVRs wird ebenfalls in 2x 32Kb geteilt. Das Bankswitching hätte 2 Register in denen variabel die einzublendenen 32Kb Bänke angegeben werden. Jedes Register ist 3 Bit breit und spezifiziert die obersten 3 Addressbits der 17 Addressleitungen zum SRAM als XOR Maske. In diesem Falle wäre es möglich die unteren 32Kb des externen SRAMs in den oberen 32Kb des AVR Addressraumes einzublenden, und somit auf die Addressen 0x0000 - 0x1500 zuzugreifen. Allerdings in der Realisierung lohnt sich das nur mit einem CPLD. Ich bastle zZ. an einem ähnlichem Problem und habe mich für diese Logik entschieden. Der CPLD ist selber wie ein Memory Mapped Device angeschlossen und die Bankswitching Register können so programmiert werden. Der CPLD enthält auch den nötigen Addresslatch und eine Addressdekodierungslogik für externe memory mapped Devices. Die 4 32Kb Blöcke des 128Kb SRAMs können über die 2 Bankregister in den 64Kb Addressraum des AVR's eingeblendet werden. Dabei kann jede dieser 32Kb Bänke entweder im oberen oder unteren 32Kb Addressraum des AVRs eingeblendet werden. Der CPLD erledigt dies indem er in seinem internen Addresslatch die obersten 3 Addressleitungen zum SRAM manipuliert. Gruß Hagen
@ C3PO: danke für den Tip. Hab ich tatsächlich übersehen. Ist aber etwas umständlich, aber es ist ne Möglichkeit. @ Hagen: welchen CPLD verwendest Du dafür? Nur für den Fall das ich mich doch entschließen sollte sowas abgedrehtes zu machen ;) Nur das mit den Registern hab ich nicht so ganz kapiert. Die liegen auch im CPLD? Und die werden wie externer Memory Mapped Speicher angesprochen? Das würde bedeuten das die beiden Register immer die darunterliegenden Speicherstellen überdeckt, stimmt das? Was mich daran stört ist der langsame Zugriff. Schließlich müssen die Register über den gleichen "Flaschenhals" des externen Speicherinterfaces beschrieben werden was mehrere Takte dauern würde. Dadurch kann bei einigen Anwendungen die Performance leiden. Schonmal danke für die Tips Gruß Markus
@Christof Krüger: bitte, aber mich würde immer noch die elegantere Art interessieren !!! @Markus: ja die Adressen wären dann nicht zu benutzen, allerdings könnte man die, wenn du sowieso ein CPLD einsetzt anders zur Verfügung stellen... Aber bei max. einer Handvoll adressen, ist das wohl nicht unbedingt sinnvoll ! hmm um das schneller hinzubekommen fällt mir nix ein, da das SW-technische reinschreiben ja noch länger dauert, aber evtl. so: spendierst einen Portpin, um ins CPLD zu schreiben (als CS sozusagen) und machst einen lesezyklus auf eine Adresse die dem ins CPLD zu schreibende Datum entspricht. Damit kannst du dann 16Bit auf einmal reinschreiben !!! Das ist dann schneller als 2*8Bit ins CPLD zu schreiben ! Ich hoffe du konntest folgen ...
Habs schon kapiert. Was mich an der Lösung mit den Registern im CPLD aber trotzdem immer noch irgendwie stört ist die zusätzliche Zeit die man für den Schreibzyklus braucht. Bei den meisten Anwendungen würde das vermutlich nicht mal in's Gewicht fallen, aber wenn man zb bei einer Block Copy Funktion o.ä. häufiger hin und her schalten müsste könnte es sich irgendwann doch bemerkbar machen. Klar hätte so ein flexibles System was, macht aber auch mehr Arbeit. Irgendwo muß man immer mit Einschränkungen leben. Ein wichtiger Punkt ist immer noch: sollte man einen gewissen Teil des Rams fest in einen bestimmten Bereich des Adressraums legen den man nicht wegschalten kann? Schließlich kann es auch mal passieren das die internen 4kByte für Stack oder Variablen doch mal nicht ausreicht. Hier bräuchte man dann halt einen Speicherbereich der immer vorhanden ist. Die Lösung von Hagen ist da recht flexibel was das angeht, aber durch den CPLD wird's halt wieder etwas aufwändiger. Na mal weiterschauen Gruß Markus
ich würde schon einen gemeinsamen Speicherbereich vorsehen, falls du mal, wat weis ich, du programmierst ein RealtimeOS und willst zwischen 2 Applikationen Daten hin und herschaufeln oder so. Da hätte jeder Thread seine eigenen x kb aber es gibt trotzdem einen gemeinsamen Bereich. ISt eben schwer vom Einsatzbereich abhängig. nun ja ein ext. Speicherzugriff dauert ja auch schon 3 Zyklen. (im gegensatz zum Zugriff auf internen) da kann man nun nicht wirklich viel beschleunigen. in 1/2 Zyklen bekommst du eben keinen Mechanismus, mit dem du ext. Register beschreiben kannst, das wären gerade mal 1/2 Befehle Zeit, das ginge schon, aber da gibt es auch wieder nachteile...
Naja, ich meine ja damit nur das das Beschreiben eines internen Port Registers zur Bankauswahl schneller geht als das Beschreiben des Memory Mapped Registers. Mal weiterschauen. btw: welchen CPLD könnt Ihr da empfehlen? Gruß Markus
tja das interface nach draussen ist eben nicht schneller, aber immer noch schneller als in SW.
ich denke mal dass die heutigen CPLDs sich nicht viel geben, die meisten kann man wohl sehr einfach programmieren, die SW gibt es im NET, dürfte wohl nur noch der Preis entscheidend sein.
ein kleiner Xilinx mit 44 Pins reicht vollkommen. Die Bankauswahl erfolgt tatsächlich über den CPLD. Der CPLD enthält ja den nötigen Addresslatch um die unteren 8 Bit AD0-AD7 zu latchen. In dem Moment wo ALE des AVR's aktiv wird, speichert der CPLD diese unteren Addressen. Zusätzlich führt er die Addressdekodierung durch. D.h. er setzt seine 3 CS~, Chip Select Ausgänge je nach angegebener Addresse. Dabei habe ich es für mein projekt so vorgesehen das hardcoded die Addressen 0x1500 bis 0x15FF, 0x1600-0x16FF, 0x1700-0x17FF und 0x1800 - 0xFFFF auf die CS Ausgänge gemappt werden. 0x1800-0xFFFF ist für den 128 KB SRAM, 0x1500-0x15FF für die internen Register des CPLDs, d.h. in diesem Falle sind alle CS Ausgänge inaktiv. Der CPLD hat nun als Address-Ausgänge die gelatchten A0-A7, und A15, A16. Als Input AD0-AD7 und A8-A15 um zuerkennen ob der AVR die unteren 32Kb oder oberen 32Kb ansprechen möchte und zur Addressdekodierung. Falls nun CS2 für den SRAM aktiv ist, der AVR also auf den SRAM zugreifen will steuert der CPLD die A15-A16 Ausgänge abhängig mit den 2 Bit Werten der Bankregister an. Falls der A15 Input Low ist == untere 32Kb so wird an diesen A15-A16 Ausgängen das Bank Register 0 genommen ansonsten eben Register 1. Falls CS0 = 0x1500-0x15FF aktiv ist so werden die Daten an AD0-AD7 bei einem Lese/Schreibzugriff intern im CPLD in 4 FF's gespeichert bzw. gelesen. Die beiden 2Bit Register liegen in einem Byte. Der Zugriff auf diese beiden Register ist also ein schreib/lese Zugriff auf die Speicheraddresse 0x1500. Dieser dauert 3 AVR Taktzyklen und aus meiner Sicht die schnellste Methode mit dem geringsten Resourcenverbrauch. Werden die Ports des AVR's benutzt so benötigt man minimal auch 2 Takte. Dafür verschwendet man aber keine wertvollen Pins, wenn die zusätzliche Logik sowieso in einen kleinen Xilinx reinpasst. Falls du es noch schneller benötigst, immerhin ein SRAM Zugriff benötigt auch 3 Takte dann solltest du mal überlegen wie groß das Ratio ist zwischen Daten im SRAM Lesen/Schreiben mit x mal 3 Takten innerhalb von zwei eingeblendeten Bänken und das dazu einmal nötige Bankswitching von 3 Taktzyklen. Kurz gesagt: wenn dir 3 Takte zuviel sind um 2x 32Kb Bänke zu switchen dann sollte dir der langsamme 3 Takte SRAM Zugriff des AVR's ebenfalls viel zu langsam sein. Da bei meiner Methode JEDE der 32Kb Banken wahlfrei in jede der 2x 32Kb Banken im AVR gemappt werden kann, also auch zB. die untersten 32Kb des SRAMs in der 1. und 2. AVR Bank, erübrigt es sich das man bei JEDEM Byte Zugriff auch einen Bankswitch durchführen muß. Du organisiert deine Kopieroperationen eben einfach so das du von einer 32Kb Bank zur anderen 32Kb Bank kopierst und dafür nur einmalig 3 Takte Bankswitch benötigst. Man könnte auch A15 und/oder A16 des SRAMs über einen Pin am AVR steuern und hätte so 1-2 Takte pro Switching. Allerdings hast du NICHT die automatische Addressdekodierung + Chip Select Generierung + Bankauswahl. D.h. jedesmal bevor du eine Speicheraddresse im externen SRAM ansprechen willst musst du vorher die A15/A16 Pins am AVR setzen, abhägnig von der zu lesenden/schreibenden SRAM Adresse. Exakt das macht aber der CPLD automatisch, wie oben beschrieben. Alleine dieser Softwaremäßige Overhead dürfte nochmals Takte kosten und macht die Software nicht einfacher. Soweit so gut. Ich selber bin erst noch in der Experimentierphase und dieses "kleine" Projekt ist auch nur die Vorstufe zu nächst höherem. Der nächste Schritt wird dann einen größeren Xilinx benötigen da dann der CPLD den SRAM komplett kontrollieren soll. Der CPLD wird dann in der Lage sein mit einem 15ns SRAM diesen quasi in parallel zum AVR zu lesen und zu schreiben. D.h. CPLD und auch AVR können ohne Zeitverlust auf den SRAM zugreifen. Der CPLD soll dabei die 5 fache Lesegeschwindigkeit im Gegensatz zum AVR erlangen. Benötigt wird dies weil er CPLD als Display Controller dienen soll und somit sehr schnell den DisplayRAM im SRAM auslesen können muß und dessen Daten umkodiert an seinen Ausgängen zur Verfügung stellen soll. Obige Vorschläge sind also nur der erste Versuchsaufbau um dann eventuell noch komplizierter Sachen machen zu können. Gruß Hagen
Nochmal zum Banking. Der AVR hat 64Kb Addressraum. Dieser teilt sich in 2 AVR-Bänke a 32Kb, nennen wir sie mal AVR_0 und AVR_1. AVR_0 geht von 0x0000-0x7FFF, und AVR_1 von 0x8000-0xFFFF. Es ist klar das je nach AVR Prozessor in der AVR_0 Bank der interne SRAM überblendet wird und auch die externen memory mapped Devices liegen sollten. Beim ATMega162 geht der interne SRAM bis 0x14FF, und ab 0x1500-0x17FF liegen bei mir die memory mapped Devices. Der externe 128Kb SRAM hat logischerweise eine Addressleitung mehr, A16 und diese muß so oder so irgendwie gesteuert werden. Der SRAM wird in 32Kb Bänke zerteilt, also SRAM_0, SRAM_1, SRAM_2, SRAM_3 und falls 256Kb abgeschlossen werden geht das weiter so. Die Bänke AVR_0 und AVR_1 unterscheiden sich nur über die Addressleitung A15, also sehr leicht auszuwerten im CPLD da 1.) 1 Bit groß und 2.) die Addressleitungen A8-A15 am AVR nicht gelatcht werden müssen, sie sind also innerhalb der 3 Takte SRAM Zugriff stabil. Man benötigt also nur die Information welche Bitmuster die zusätzlichen Addressleitungen am SRAM -> A15,A16 usw. bis A18 am SRAM angelegt werden müssen für die Bänke AVR_0 und AVR_1. Diese zwei Informationen stehen in zwei 4 Bit register. 4 Bit für A15,A16,A17,A18 bei einem 256Kb SRAM. Nun muß nur noch abhängig von A15 am AVR das entsprechende 4 Bit register an diese SRAM Addressleitungen gelegt werden. Diese Kodierung müsstest du normalerweise in Software vor jedem Lesen/Schreiben durchführen. Nun kann man über diese Bankswitching Byte die 2*4 Bit die 2 Bänke AVR_0 und AVR_1 in einem Rutsch programmieren. Es wird auch logisch das das sehr variabel ist und das man sogar die gleiche SRAM Bank, Zb. SRAM_0 in die Bänke AVR_0 und AVR_1 gleichzeitig einblenden kann. Vorstellbar ist also jede Kombination zb. AVR_0 <= SRAM_0 AVR_1 <= SRAM_1 nun kopiert man aus AVR_0 nach AVR_1, dann Bankswitch mit AVR_0 <= SRAM_2 AVR_1 <= SRAM_1 und kopierwiederum von AVR_1 nach AVR_0. Oder eben AVR_0 <= SRAM_0 AVR_1 <= SRAM_0 und schon hat man Zugriff über AVR_1 Addresse 0x8000 bis 0x97FF auf SRAM_0 Addresse 0x0000-0x17FF, also dem Shadow Memory der mit dem internen SRAM + memory mapped Devices überblendet wird. Aber jetzt wo ich das alles mal so schreibe fällt mir auf das ich meine Memory Mapped Devices in Zukunft auf die Addressen < 0x8000 mappen werde. Damit wird das VHLD unabhängig vom AVR Prozessortyp, der ja je nach Typ unterschiedlich größen SRAM in die unteren Adressen einblendet. Die hardcoded Addressdekodierung im CPLD muß dann nicht ständig an den AVR Typ angepasst werden. Gruß Hagen
Hossa, dankedanke. Ich muß jetzt mal schauen ob so ein CPLD überhaupt nötig ist oder ob man das auch noch etwas kleiner realisieren kann. Könnte ein GAL 22V10 da nicht schon ausreichen? So ein CPLD kostet ja mindestens das doppelte. Oder reicht zumindest ein XC9572? Gibt es dafür kostenlose Software und Selbstbau Programmer oder muß/sollte man sich da ein Entwicklertool kaufen? Ich danke dir für die ausführliche Antwort. Gruß Markus
Ich fürchte, Du verzettelst Dich total. Eine EiWoMiSa kann man erst entwickeln, wenn man weiß, wozu. Trotzdem wird eine EiWoMiSa nie fertig. Klemm ihn einfach ran und A16 an einen Portpin. Dann hast Du 2*60kB und gut is. Peter
Hi Peter, dont Panic, ich hab schon ein konkretes Ziel und das soll, wie ich schonmal erwänt hab, nur eine EiWoSa werden ;) Ich muß jetzt nur noch wissen wo der Weg zu dem Ziel in etwa langläuft, gehen kann ich den alleine. Und wenn der zu Fuß zu weit ist kann ich mir immer noch ein Auto kaufen. Die Möglichkeit hab ich und werd ich auch nutzen. So, genug Metaphern :) Gruß Markus
Anbei ein fertiges VHDL eines MMB. Es unterstützt SRAMs bis 512Kb und 2 memory mapped Devices. Fertig compiliert passt es mit 27 Makrozellen und 34 Pins exakt in einen kleinen Xilinx XC9536XL PLCC44 oder TQPF44 rein. Bei Reichelt kannst du diesen für 1,80 Euro kaufen. Die 5V Version gibts dort auch ist aber bischen teurer. Der Addressdekoder im VHDL ist angepasst auf den ATMega162. Gruß hagen
Die 5V Version ist leider um einiges teurer. 5,25 statt 1,80 :( Trotzdem hab ich jetzt Blut geleckt und würde mich gerne mal damit befassen. Welche Soft- und Hardware brauche ich denn dafür und hat jemand nen Buchtip zu dem Thema?
Ich habe bei Altera die Quartus II Web Edition und bei Xilinx den ISE kostenlos gedownloaded. Man muß sich nur registrieren und die Freischaltcodes eingeben. Entwickeln tue ich mit Quartus II, da mir besonders dort der Simulator viel besser gefällt. Wenn das VHDL fertig ist übertrage ich's in den Xilinx ISE und erzeuge dort das Pinning und die Binaries. Bei der Installation unbedingt dieser Software den WEB Zugriff freischalten. Nach der Registration kannste dann die Software über die Firewall komplett blocken. Beide Softwares sind reine ET Lösungen und wollen permanent nach Hause telefonieren. Achtung! der Download ist glaube ich 200Mb groß. Als Programmer habe ich den Vorschlag von Peter Dannegger mit dem einfachen Parallelkabel benutzt. Der XC9500 XL Typ ist zwar 3.3V aber 5V kompatibel. Bei eBay gibts für rund 20 Euro ein fertiges Developementboard mit zusätzlichen CPLDs. Aber suche mal hier im CPLD Forum, da findest du auch preiswerte Anbieter. Allerdings ist Peters Einwand schon richtig. Die einfachste Methode ist es einen 8Bit Latch + Addressdekodierung an den AVR anzuschliesen. VHDL ansich ist zwar ziemlich einfach, aber der zusätzliche Overhead das Design in einen CPLD zu bekommen, das Routing zu definieren und alles zu testen ist schon höher. Ich mach das alles weil ichs einfach lernen möchte und Spaß macht. Gruß Hagen
Achso: Bücher ?? habe ich keines benutzt und braucht man auch nicht meiner Meinung nach. Im WEB fand ich zwei sehr gute PDF's, sogar in Deutsch falls dir Englische Dokus nicht so liegen sollten. HaReddmann AT T-Online DOT de. Gruß Hagen
Hi Hagen, um Lieferanten mach ich mir nicht wirklich sorgen. Da find ich schon die richtigen Quellen. Ich war nur über den gravierenden Preisunterschied bei Reichelt erschrocken. Vor den 200MB und "Nach Hause telefonieren" hab ich auch keine Angst, da bin ich hinreichend ausgestattet. Google hat mir schon ein paar Links ausgespuckt und den Rest krieg ich auch noch zusammen. Ich denke mal jetzt komm ich erstmal selbst weiter. Jetzt muß ich nur noch eine Lücke in meinem Tagesprogramm finden um mich auch noch damit zu befassen ;) Ich danke Dir vielmals für Deine Hilfe Viele Grüße Markus
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.