STM DMA überträgt nicht kontinuierlich auf der UART-Leitung

Ich verwende ein STM32L4R5-Board und versuche, den DMA auf der UART2-Leitung zu konfigurieren. Ich habe es geschafft, die RX-Leitung so zu betreiben, wie ich es möchte, aber wenn ich der „Übertragung mit DMA“ in Abschnitt 44.5.19 des „RM0432-Referenzhandbuchs“ folge, wird nur ein Byte übertragen und sonst nichts. Dieses Byte wird nur gesendet, wenn ich explizit ein Byte in das TDR-Register schreibe. Danach kann ich sehen, dass das TC-Flag gelöscht ist und das erste Byte meines DMA-Registers betroffen ist. Wie bringe ich den DMA dazu, die Daten kontinuierlich zur Übertragung an den TDR zu senden?

Hinweis: Dieses Problem scheint einer unbeantworteten Frage hier ähnlich zu sein

Die im Datenblatt erwähnten Schritte sind wie folgt:

  1. Schreiben Sie die USART_TDR-Registeradresse in das DMA-Steuerregister, um es als Ziel der Übertragung zu konfigurieren. Die Daten werden nach jedem TXE-Ereignis (oder TXFNF, wenn der FIFO-Modus aktiviert ist) aus dem Speicher an diese Adresse verschoben.
  2. Schreiben Sie die Speicheradresse in das DMA-Steuerregister, um es als Quelle der Übertragung zu konfigurieren. Die Daten werden nach jedem TXE-Ereignis (oder TXFNF, wenn der FIFO-Modus aktiviert ist) aus diesem Speicherbereich in das USART_TDR-Register geladen.
  3. Konfigurieren Sie die Gesamtzahl der an das DMA-Steuerregister zu übertragenden Bytes.
  4. Konfigurieren Sie die Kanalpriorität im DMA-Register
  5. Konfigurieren Sie die DMA-Interrupt-Erzeugung nach halber/vollständiger Übertragung wie von der Anwendung gefordert.
  6. Löschen Sie das TC-Flag im USART_ISR-Register, indem Sie das TCCF-Bit im USART_ICR-Register setzen.
  7. Aktivieren Sie den Kanal im DMA-Register.

Mein Code ist hier:

    //filling in dummy info into my DMA TX buffer
    memset((void*)DMA_USB_TXbuf, 0x55, 16);

    //ensuring my UART is configured for DMA Transfer
    huart2.Instance->CR3 |= USART_CR3_DMAT;

    //steps 1-4 taken care of within this funciton
    HAL_DMA_Start_IT(&hdma_usart2_tx, (uint32_t)&huart2.Instance->TDR, (uint32_t)&DMA_USB_TXbuf[0], DMA_USB_TX_SIZE);

    //step 5 (just ensuring that we have the flags we want after the previous function)
    __HAL_DMA_DISABLE(&hdma_usart2_tx);
    __HAL_DMA_ENABLE_IT(&hdma_usart2_tx, DMA_IT_HT);
    __HAL_DMA_ENABLE_IT(&hdma_usart2_tx, DMA_IT_TC);

    //step 6
    __HAL_UART_CLEAR_FLAG(&huart2, UART_CLEAR_TCF);

    //step 7
    __HAL_DMA_ENABLE(&hdma_usart2_tx);

    //I shouldn't need to do this, but this seems to be the only way
    // I get even 1 trasmission from DMA register
    WRITE_REG(huart2.Instance->TDR, 0x55);
Warum benutzt du nicht HAL_USART_Transmit_DMA()?
@Codo Ich glaube, die Funktion heißt HAL_UART_Transmit_DMA ()
Etwas suspekt ist hier die Mischung aus direktem Registerzugriff und Bibliotheksaufrufen. Gibt es keine DMA-UART-Beispiele für Ihr Board? Im Allgemeinen sind die xxx_IT-Funktionen von HAL besonders berüchtigt dafür, etwas anderes zu tun, als es ihr Name oder die Perspektive typischer Anwendungsanforderungen vermuten lassen würden, so dass viele Leute versuchen, sie auf eine Weise zu verwenden, die nicht das tut, was sie wollen.
@Codo Ich hatte ursprünglich den Eindruck, dass die Funktion ein unerwünschtes Ende bewirken könnte, aber wenn ich mir jetzt den Bauch der Funktion ansehe, sehe ich, dass dies nicht der Fall ist. Ich werde das ausprobieren

Antworten (1)

Es gab zwei Gründe, warum dies nicht so funktionierte, wie es sollte.

  1. Laut Kommentar von Codo funktionierte die einfache Verwendung dieser Funktion zum Einrichten und Übertragen des UART-DMA auf der UART-Leitung
  2. Mein UART ist mit RTS/CTS-Flusskontrolle konfiguriert und meine Empfangsleitung war nicht bereit, was das Senden weiterer Zeichen verhinderte.

Danke Codo