Hallo, ich habe mit CubeMX einen STM32H7 als SPI Slave mit Hardware NSS konfiguriert. Der Mikrocontroller misst mit 100Hz Sensoren über den ADC ein. Ein Raspberry kann dann "irgendwann" die Sensoren über SPI abfragen. Die Sensorwerte werden in ein globales Struct gespeichert. Um die Slave Funktion zu aktivieren übergebe ich vor der Main Schleife die Adresse des Structs an die HAL_SPI_transceive_DMA(). Nach der Übertragung starte ich um Interrupt wieder die gleiche Funktion mit dem gleichen Pointer. Bisher dachte ich, dass einfach nur die Adresse genommen wird und die Daten von dort zum Zeitpunkt der SPI Übertragung genommen werden. Nun ist es aber so, dass bei der ersten Übertragung tatsächlich die Nullen, mit denen das Array initialisiert wird, übertragen werden, obwohl ich in der Zwischenzeit (aber erst nach der Initialisierung) mehrfach neue Werte in das Struct hineingeschrieben habe. Ist das das normale Verhalten? Gibt es eine Variante mit der ich wirklich die aktuellen Daten übertrage? Oder muss ich nach jeder Datanaktualisierung wieder die HAL_SPI_transceive_DMA Funktion ausführen? Gibt es auch eine Variante, bei der ich die Funktion nur zur Initialisierung aufgerufen werden muss, und ab da werden immer die Daten bei jeder SPI Abfrage übertragen? Ich meine ich hatte das schon einmal im DMA_Circular Mode getestet, da hat die Funktion aber auch immer nur einmal die Daten übertragen. In kurz: Gewünschtes Verhalten: Funktionsaufruf bei dem ich die Adresse und die Länge des Speicherbereiches definiere. Ab dann wird bei jeder SPI-Clock das aktuelle Bit des Speichers übertragen, wenn die Länge des Structs erreicht wird geht der Pointer wieder auf die ursprüngliche Adresse zurück. CS brauche ich eigentlich nicht, da nur die beiden Teilnehmer existieren. Ich nutze ihn um zu erkennen ob gerade ein Transfer stattfindet, dann ändere ich die Daten natürlich nicht. Idealerweise würde der Pointer wieder auf die Anfangsadresse gesetzt werden wenn eine falling Edge am CS-Pin passiert, falls doch etwas bei der Kommunikation schief geht, sonst komme ich da ja nie mehr raus.
Es ist ganz sicher nicht normal, wenn dein DMA Transfer Daten sendet, die gar nicht mehr im Speicher existieren. Dazu bräuchte er einen Zwischenspeicher, der den Zustand der Vergangenheit kennt. So einen Speicher gibt es nicht. Ich würde das mal debuggen und dabei kontrollieren, wann auf welche Speicheradressen zugegriffen wird und ob da wirklich die erwarteten Daten drin stehen. Wenn dir die Funktionsweise des Framework zu unklar ist, fällt es dir womöglich leichter, die Register anhand des Referenzhandbuches zu programmieren. Dann hast du keinen unbekannten Code dazwischen, den und dessen Doku du zusätzlich zur Beschreibung der Register verstehen musst. Selbst wenn du am Ende doch die HAL nimmst, wird es dir helfen, dich vorher mit den Registern und deren Möglichkeiten zu befassen.
Der H7 hat einen Cache von dem dein DMA nichts mitbekommt. Er hat aber auch eine MPU, mit der du de Speicher, den dein DMA anpackt vom Caching ausnehmen kannst. Das ist der Weg.
Stefan F. schrieb: > Dann hast du keinen unbekannten Code dazwischen, den und > dessen Doku du zusätzlich zur Beschreibung der Register verstehen musst. Tatsächlich ist die HAL Funktion nicht übermäßig lang und außerdem recht verständlich geschrieben. Es lag auch daran: Harry L. schrieb: > Der H7 hat einen Cache von dem dein DMA nichts mitbekommt. Die Lösung war zwar etwas kryptisch hier herauszulesen, aber ich habe nun das Struct in den D2 RAM "verschoben" und jetzt geht es tatsächlich. Hierfür habe ich
1 | __attribute__((section(".dma_buffer"))) |
vor das Struct geschrieben und im Linkerfile:
1 | .dma_buffer : |
2 | {
|
3 | *(.dma_buffer) |
4 | } >RAM_D2 |
hinzugefügt. So läuft alles im Circular Mode und ich muss nur zu Beginn die HAL_SPI_TransmitReceive_DMA Funktion einmal aufrufen und ab dann kann der Raspberry dauerhaft die Daten aufrufen.
Gerald M. schrieb: > Die Lösung war zwar etwas kryptisch hier herauszulesen, aber ich habe > nun das Struct in den D2 RAM "verschoben" und jetzt geht es tatsächlich. Das ist weder kryptisch noch hat es etwas mit caching zu tun. Der normale DMA bzw. der BDMA kommt beim H7 nicht in jeden Speicher-Bereich. Ein Blick ins Datenblatt / Reference Manual und man weiß das.
Es kann definitiv mit dem Cache zusammenhängen, die Speicherbereiche werden da auch unterschiedlich behandelt.
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.