Hallo zusammen, ich hoffe, dass ich nicht verbal gesteinigt werde, falls ich die ein oder andere dumme Frage stelle. Aber falls doch, dann bin ich mental bereit :D Ich weiß nicht ob ich ein grundsätzliches Verständnisproblem habe was die Ansteuerung von SDRAMs betrifft. Ich verwende den SDRAM ISSI IS42S81600F-7TLI und den µC STM32H753ZIT. Der SDRAM ist an der SDRAM-Bank#1 des µC angeschlossen. Die FMC-Schnittstelle des µC habe ich auch bereits erfolgreich konfiguriert und ich kann auch bereits auf den SDRAM lesen und schreiben. Zum Lesen und Schreiben nutze ich die HAL-Funktionen. Frage: Laut Datenblatt hat der SDRAM vier interne Bänke mit jeweils 32Mbit und ich verstehe noch nicht ganz, wie ich mit den HAL-Funktionen zwischen den Bänken wechseln kann. Mit den Pins BA0 und BA1 kann man wohl die jeweilige Bank auswählen aber wie mache ich das aus den HAL-Funktionen heraus? Kann es sein, dass ich da mit der Funktion "HAL_SDRAM_SendCommand(...)" irgendwie hantieren muss? Also ich sehe einfach nicht die Möglichkeit die Pins BA0 und BA1 anzusteuern über HAL. Danke für eure Hilfe und einen schönen Start in die Woche!
Moe E. schrieb: > Zum Lesen und Schreiben nutze ich die > HAL-Funktionen. Warum? Du kannst den Speicher ganz normal wie jedes andere RAM ansprechen. Allerdings musst du im Linker-Scruipt eine Region dafür anlegen, und via "__attrbute__" deine gewünschten Variablen auch in diesen Bereich legen. Mit HAL hat das rein gar nichts zu tun. Moe E. schrieb: > Mit den Pins BA0 und BA1 kann man > wohl die jeweilige Bank auswählen Die legt man einfach auf die oberen Adressleitungen. Moe E. schrieb: > aber wie mache ich das aus den > HAL-Funktionen heraus? s.o.: das hat absolut nichts mit HAL zu tun.
:
Bearbeitet durch User
Moe E. schrieb: > Kann es sein, dass ich da mit der Funktion > "HAL_SDRAM_SendCommand(...)" irgendwie hantieren muss? Also ich sehe > einfach nicht die Möglichkeit die Pins BA0 und BA1 anzusteuern über HAL. Nö. BA0 und BA1 steuert der FMC komplett automatisch an, da hat die Software rein gar nichts zu tun.
Harry L. schrieb: > Moe E. schrieb: >> Mit den Pins BA0 und BA1 kann man >> wohl die jeweilige Bank auswählen > > Die legt man einfach auf die oberen Adressleitungen. Unsinn. Das ist SDRAM und kein Bastler-SRAM. BA0 und BA1 kommen, Surprise, Surprise, an die genau gleichnamigen Pins am Controller!
Falk B. schrieb: > Unsinn. Das ist SDRAM und kein Bastler-SRAM. BA0 und BA1 kommen, > Surprise, Surprise, an die genau gleichnamigen Pins am Controller! Hast recht! Sorry, war ein Schnellschuss...
Falk B. schrieb: > Moe E. schrieb: >> Kann es sein, dass ich da mit der Funktion >> "HAL_SDRAM_SendCommand(...)" irgendwie hantieren muss? Also ich sehe >> einfach nicht die Möglichkeit die Pins BA0 und BA1 anzusteuern über HAL. > > Nö. BA0 und BA1 steuert der FMC komplett automatisch an, da hat die > Software rein gar nichts zu tun. Ich glaube da ist mein Denkfehler. Woher weiß der FMC welche Bank er ansteuern muss? Oder übergebe ich dem µC die Daten und er kümmert sich vollkommen alleine darum in welche Bank er die Daten ablegt? Das habe ich nämlich aus dem Datenblatt irgendwie anders verstanden.
:
Bearbeitet durch User
Moe E. schrieb: > Ich glaube da ist mein Denkfehler. Woher weiß der FMC welche Bank er > ansteuern muss? Aufgrund der Zieladresse. Moe E. schrieb: > Oder übergebe ich dem µC die Daten und er kümmert sich > vollkommen alleine darum in welche Bank er die Daten ablegt? Genau so.
Harry L. schrieb: > Moe E. schrieb: >> Oder übergebe ich dem µC die Daten und er kümmert sich >> vollkommen alleine darum in welche Bank er die Daten ablegt? > > Genau so. Okay, dann macht alles wieder Sinn. Danke dir und auch danke an Falk für die selbe Antwort. Der SDRAM, den ich verwende, hat eine Kapazität von 128Mbit. Die Startadresse der SDRAM Bank#1 am µC ist 0xC0000000. Demnach wäre also der Adressbereich von 0xC000000 bis 0xC8000000 der Bereich in dem ich die 128Mbit beschreiben kann. Habe ich einen Denkfehler? Denn bei dem Versuch auf die Speicherzelle 0xC100000 zu schreiben wird der HardFault_Handler() ausgelöst. Der Zugriff sieht folgendermaßen aus:
1 | void FMC_Test() |
2 | {
|
3 | uint32_t i; |
4 | uint32_t* SDRAM_START_ADDRESS = (uint32_t*)0xC1000000; |
5 | uint8_t SDRAM_DATA[] = {0xFF,0xFF,0xFF,0xFF}; |
6 | uint8_t SDRAM_ERASE[] = {0x00,0x00,0x00,0x00}; |
7 | |
8 | for( i=0; i<256; i++) |
9 | {
|
10 | HAL_SDRAM_Write_8b(&hsdram1,SDRAM_START_ADDRESS, &SDRAM_DATA, sizeof(SDRAM_DATA)); |
11 | SDRAM_START_ADDRESS++; |
12 | }
|
13 | HAL_Delay(50); |
14 | }
|
Moe E. schrieb: > Der SDRAM, den ich verwende, hat eine Kapazität von 128Mbit. Naja, traditionell wwerden Speicher in Bit angegeben, so ganz praktisch ist das aber nicht. Das sind 16 MByte, aufgeteilt auf 4 Bänke a 4 MByte. > Die > Startadresse der SDRAM Bank#1 am µC ist 0xC0000000. Wenn das pasend konfiguriert ist. > Demnach wäre also > der Adressbereich von 0xC000000 bis 0xC8000000 der Bereich in dem ich > die 128Mbit beschreiben kann. Nö. 16 MByte sind 0x0100 0000, macht bei Startadresse 0xC000 0000 eine obere Adresse von 0xC0FF FFFF. Du würfelst Bits und Bytes durcheinander! Außerdem endet so ein Speicherbereich immer mit FFFF auf den unteren Adressen! > Habe ich einen Denkfehler? JA!! > Denn bei dem Versuch auf die Speicherzelle > 0xC100000 zu schreiben wird der HardFault_Handler() ausgelöst. Warum in aller Welt Fängst du deinen Test nicht bei der Startadresse an? > Der Zugriff sieht folgendermaßen aus: > void FMC_Test() > { > uint32_t i; > uint32_t* SDRAM_START_ADDRESS = (uint32_t*)0xC1000000; > uint8_t SDRAM_DATA[] = {0xFF,0xFF,0xFF,0xFF}; > uint8_t SDRAM_ERASE[] = {0x00,0x00,0x00,0x00}; > for( i=0; i<256; i++) > { > HAL_SDRAM_Write_8b(&hsdram1,SDRAM_START_ADDRESS, &SDRAM_DATA, > sizeof(SDRAM_DATA)); > SDRAM_START_ADDRESS++; > } > HAL_Delay(50); > } Was soll der Käse? Du hast IMMMER noch nicht verstanden, wie externer SDRAM funktioniert! Aus Sicht des C-Programmierers genau so wie interner RAM! Da braucht es keine Spezialfunktion! Du kannst einfach mit einem Pointer drauf zugreifen! So wie das oben mit SDRAM_START_ADDRESS gemacht wird. Aber im Normalfall schreibt man Variablen mit Kleinbuchstaben. Alles in Großbuchstaben sind #defines. Das ist eine recht weit verbreitete Regel.
Falk B. schrieb: > Was soll der Käse? Du hast IMMMER noch nicht verstanden, wie externer > SDRAM funktioniert! Aus Sicht des C-Programmierers genau so wie interner > RAM! Da braucht es keine Spezialfunktion! Es ist nicht sinnvoll, den TE dafür zu beschimpfen, dass er sich offenbar strikt an die Dokumentation des HAL hält. Demnach sollen tatsächlich alle Zugriffe über die besagten Funktionen HAL_SDRAM_* erfolgen, weil darin auch eine Zustandsvariable und eine Verriegelung konkurrierender Zugriffe enthalten sind. Der eigentliche Kopiervorgang ist ein memcpy() für Arme. Es ist sogar ein "Speicherschutz" vorgesehen, der aber keineswegs einen Zugriff auf ein entsprechendes FMC-Register beinhaltet, sondern nur über die o.a. Zustandsvariable realisiert wird. Vermutlich versucht ST damit, ein einheitliches Interface für alle möglichen externen Speicher zu schaffen, d.h. auch serielle Flashes usw.. Bei parallel angebundenem SDRAM ist das natürlich völlig sinnfrei. Es gibt durchaus manche Softwarearchitekten, denen besonders einheitliche und schicke Diagramme wichtiger sind als die technische Funktionalität; ich kann mir sehr gut vorstellen, dass solche elektronischen Hochglanzfolien dann als Implementierungsgrundlage dienten. Natürlich sieht das zunächst schön einheitlich und stimmig aus, so dass man damit ab einer gewisser Entscheiderebene punkten kann. Und man kann auch in den Werbeprospekt reinschreiben, dass es einheitliche APIs für alle externen Speicher gibt, unabhängig von ihren physikalischen Eigenschaften. Und so etwas finden auch manche Entscheider auf Kundenseite hochgradig attraktiv. Ggf. war sogar mal in der technischen Beschreibung ein Hinweis auf die direkte Adressierbarkeit des SDRAM-Bereich enthalten, aber bei irgendeiner QS-Runde wurde dann festgestellt, dass hierdurch von der definierten Softwarearchitektur abgewichen würde. Zwecks Einheitlichkeit dürften dann solche dreisten Umgehungen nicht mehr Kunden gegenüber beschrieben werden. Außerdem wird dadurch ja der o.a. "Speicherschutz" umgangen. Ein winziges Fünkchen Sinn könnte ich noch erkennen, wenn die Adresse im SDRAM relativ zur Startadresse angegeben würde. Hier ist ST aber inkonsequent und verlangt tatsächlich einen Pointer im gesamten Adressraum. > Du kannst einfach mit einem Pointer drauf zugreifen! Exakt. Man konfiguriert das SDRAM ja auch nicht ständig um. > So wie das oben mit SDRAM_START_ADDRESS gemacht > wird. Aber im Normalfall schreibt man Variablen mit Kleinbuchstaben. > Alles in Großbuchstaben sind #defines. Das ist eine recht weit > verbreitete Regel. Volle Zustimmung. Ggf. wäre es sinnvoll, einen Pointer (kleingeschrieben) mit einer Konstanten (z.B. großgeschrieben) zu initialisieren, sofern man z.B. einen Pufferbereich referenzieren will. Dennoch ist es WESENTLICH sinnvoller, nicht direkt mit den Adressen zu hantieren, sondern über den Linker die Platzierung der entsprechenden Variable im SDRAM zu steuern. Eine ähnliche Diskussion hatte ich vor ca. 26 Jahren mit einem Hardwareentwickler, der auch nicht einsehen wollte, dass ich in meinem Programmcode keine expliziten Zugriffsfunktionen für den Speicher definieren muss, sondern dass der Programmcode direkt aus dem Speicher ausgeführt wird und ich auch für Datenzugriffe nicht explizit an den Steuerleitungen (/CS, /WR, /RD, o.ä.) wackeln muss.
:
Bearbeitet durch User
Andreas S. schrieb: > sondern dass der Programmcode direkt aus dem Speicher > ausgeführt wird und ich auch für Datenzugriffe nicht explizit an den > Steuerleitungen (/CS, /WR, /RD, o.ä.) wackeln muss. ... was irgendwo der Inhalt des Begriffs HAL ist. Wenn sich der Programmierer auf der Ebene noch mit einzelnen Leitungen befassen müsste, deren Bedienung Aufgabe des beteiligten Controllers ist, dann gäbe es an jedem I2C und SPI-Baustein einiges zu zuppeln. Maximmal um eine geeigente Einstellung des CS sollte man sich kümmern (müssen).
Georg B. schrieb: > Andreas S. schrieb: >> sondern dass der Programmcode direkt aus dem Speicher >> ausgeführt wird und ich auch für Datenzugriffe nicht explizit an den >> Steuerleitungen (/CS, /WR, /RD, o.ä.) wackeln muss. > > ... was irgendwo der Inhalt des Begriffs HAL ist. Nein, das ist etwas ganz anderes, da ja der Programmcode des HAL ebenfalls nicht ausgeführt werden könnte. Es ging um das grundsätzliche Verständnisproblem des damaligen Hardwareentwicklers, der in seiner Karriere noch niemals auch nur ein Stück Programmcode, insbesondere Assembler- oder Maschinencode gesehen hatte und einen Mikroprozessor nur aus der Sicht seiner externen Pins kannte.. > Wenn sich der > Programmierer auf der Ebene noch mit einzelnen Leitungen befassen > müsste, deren Bedienung Aufgabe des beteiligten Controllers ist, dann > gäbe es an jedem I2C und SPI-Baustein einiges zu zuppeln. Dann fühlt man sich gleich wieder wie auf dem Atmel AT91RM9200, dessen Peripherieblöcke so fehlerhaft waren, dass man I2C lieber per Bitbanging betrieb. Hierfür gibt es im Linux-Kernel zu auch explizit die Umschaltmöglichkeit. Die USARTs waren im ISO7816-Modus ähnlich katastrophal. Erst bei den AT91SAM9 wurden dann etliche Fehler behoben.
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.