STM32F411 Callback wird nicht aufgerufen

#7085430
Lesenswert?

Hallo Zusammen,

Ich habe aktuell ein Problem mit dem USART. Ich versuche Daten über 
USART1 mit dem DMA zu empfangen und in einer Variable abzuspeichern.

Die Variabel befindet sich in einer Struktur, welche wie folgt aussieht:
1
typedef struct
2
{
3
  uint8_t mb_rx_buffer[BUFFER_MAX_LEN];
4
  uint8_t mb_tx_buffer[BUFFER_MAX_LEN];
5
  uint8_t mb_cmd_available;
6
}st_modbus;

Den DMA Starten tu ich mit der folgenden Funktion im Init:
1
state = HAL_UART_Receive_DMA(&huart1, pst_modbus->mb_rx_buffer, 100);

Im UART Callback möchte ich mir ein Flag setzten um im Code die Daten 
aus dem Buffer zu holen:
1
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
2
{
3
  st_modbus *pst_modbus = &gst_modbus;
4

5
  if(huart->Instance == USART1)
6
  {
7
    pst_modbus->mb_cmd_available = 1;
8
  }
9
}

Nun das Problem:
Ich komme nie in die Funktion. Auch wenn ich im Interrupt handler einen 
Break Point setzte kommt er nie dort durch.

Hat da jemand eine Idee was ich flasch mache?
Gast #7085841
Lesenswert?

Moot S. schrieb:
> Die Funktion wird aufgerufen, aber danach stehen keine Daten in meinem
> RX-Buffer.

Wie bedauerlich.

Wieso kommst du nicht von selbst auf die Idee, das Ganze tatsächlich 
verstehen zu wollen oder dir ein sinnvolles Interface zwischen einem 
UART-Treiber und dem Rest der Firmware auszusuchen? Sowas gibt es ja 
seit Adam&Eva, da brauchst du es nur zu verstehen und mußt es dir nicht 
selbst ausdenken.

Und nein, ich geb dir hier keinen zum x-ten Mal wiederholten Ratschlag, 
denn dazu gibt es in diesem Forum schon genug. Da mußt du nur selbst 
ein wenig lesen.

W.S.
Gast #7085965
Lesenswert?

ok, der F411 hat keinen CCM, im Linkerfile gibt es auch nur die eine 
SRAM Section, das ist es also auch nicht.
Stimmen die seriellen Parameter? Die ISR macht auch eine ausführliche 
Fehlerbehandlung und evtl. werden die Daten wegen falschem Format nicht 
gespeichert. Das wäre auch eine Erklärung warum der RxComplete Callback 
nicht aufgerufen wurde. Dieser generierte HAL Code funktioniert 
mittlerweile sehr gut, typische Fehler sind nicht den kompletten Code zu 
benutzen (ISR vergessen), Callbacks in C++ Modulen ohne extern, Buffer 
im nicht für DMA zugänglichen Speicher.
#7085977
Lesenswert?

JS schrieb:
> ok, der F411 hat keinen CCM, im Linkerfile gibt es auch nur die eine
> SRAM Section, das ist es also auch nicht.
> Stimmen die seriellen Parameter? Die ISR macht auch eine ausführliche
> Fehlerbehandlung und evtl. werden die Daten wegen falschem Format nicht
> gespeichert. Das wäre auch eine Erklärung warum der RxComplete Callback
> nicht aufgerufen wurde. Dieser generierte HAL Code funktioniert
> mittlerweile sehr gut, typische Fehler sind nicht den kompletten Code zu
> benutzen (ISR vergessen), Callbacks in C++ Modulen ohne extern, Buffer
> im nicht für DMA zugänglichen Speicher.

Ja Parameter stimmen alle. Der Buffer liegt in einem Struct, auf das 
sollte der DMA mit dem Struktur Pointer zugriff haben.

pegel schrieb:
> Wenn ich Interrupt und Variable höre, muss ich automatisch an volatile
> denken.

Ja dachte ich auch mal, hatte aber nichts gebraucht, gibt nur ein 
warning:
 warning: passing argument 2 of 'HAL_UART_Receive_DMA' discards 
'volatile' qualifier from pointer target type [-Wdiscarded-qualifiers]
#7085990
Lesenswert?

Moot S. schrieb:
> Ja dachte ich auch mal, hatte aber nichts gebraucht, gibt nur ein
> warning:

Macht ja auch keinen Sinn, die DMA-Engine schreibt das ganz an 
CPU&Compiler vorbei in den RAM, der Compiler hat also gar keine 
Möglichkeit, da über volatile&co irgendwas an der DMA-Arbeitsweise zu 
ändern.

Beim Auslesen der Daten im C-Code hingegen kann es einen Unterschied 
machen, muss aber schon ein ganz "spezielles" Konstrukt sein.
z.B. wenn man den DMA-Buffer statt Interrupt per Polling überwachen 
will.
#7089616
Lesenswert?

Ich konnte das Problem lösen.
Leider habe ich mich auf dem MCU etwas verlesen, anstelle von 
STM32F411RCT6 habe ich STM32F411RET6 gelesen.

Dies entdeckte ich, als mein Beispiel auf dem Nucleo mit dem RET6 
funktionierte aber auf meiner eigenen Schaltung mit dem RCT6 nicht.

Naja nun funktioniert mein vorgehen, danke für eure Vorschläge und Zeit 
:)
Gast #7089631
Lesenswert?

Εrnst B. schrieb:

> Macht ja auch keinen Sinn, die DMA-Engine schreibt das ganz an
> CPU&Compiler vorbei in den RAM

Und genau deswegen sollte das volatile sein, weil das dem Compiler sagt, 
daß es sich auf nicht-programmatische Weise ändern könnte.

> der Compiler hat also gar keine
> Möglichkeit, da über volatile&co irgendwas an der DMA-Arbeitsweise zu
> ändern.

Er sollte aber wissen, daß er bestimmte Optimierungen nicht machen darf.
#7089723
Lesenswert?

Nop schrieb:
> Und genau deswegen sollte das volatile sein, weil das dem Compiler sagt,
> daß es sich auf nicht-programmatische Weise ändern könnte.

Aber nur an der Stelle, wo es ausgelesen wird, nicht da wo der Pointer 
an die DMA-Engine übertragen wird.

Und auch beim Auslesen braucht's es nur, wenn der Compiler irgendeine 
reale Möglichkeit hat den Speicherzugriff wegzuoptimieren.

Beim DMA-Complete Callback ist das nicht der Fall. Da ist der "DMA 
Complete", d.H. während dein Callback ausgeführt wird, erfolgen keine 
weiteren Schreibzugriffe an der CPU vorbei. Zum anderen erfolgt der 
Aufruf des Handlers indirekt aus der Library, insofern kann und darf 
der Compiler keinerlei Annahmen treffen, was bei Eintritt in den Handler 
im RAM steht.

Wie geschrieben, es gibt ein paar Sonder-/Grenzfälle, wo ein "volatile" 
nötig sein könnte. Aber beim 08/15 Vorgehen: DMA-Start und im 
Cplt-Handler Buffer auslesen, ist es überflüssig.
Gast #7089740
Lesenswert?

Εrnst B. schrieb:
> Zum anderen erfolgt der
> Aufruf des Handlers indirekt aus der Library, insofern kann und darf
> der Compiler keinerlei Annahmen treffen, was bei Eintritt in den Handler
> im RAM steht.

Doch, das darf er, denn auch wenn das eine andere translation unit ist, 
gilt der C-Standard immer noch. Die andere Frage ist, ob er denn kann - 
und das ist jedenfalls mit LTO durchaus denkbar. Jedenfalls ist es 
sauberer Stil, an solche Buffer dann auch das volatile dazuzuschreiben.
#7089758
Lesenswert?

Nop schrieb:
> Doch, das darf er

Bei einer Nicht-Inlinebaren Funktion, die per Funktionspointer in einer 
Struct ausgeführt wird?

Selbst wenn du davon ausgehst, dass irgendein hyperintelligenter 
Compiler das in der Zukunft kann, ist "volatile" für den ganzen Buffer 
an der Stelle overkill.
Eine simple compiler barrier ( asm volatile ("" ::: "memory") ) am 
Anfang des Handlers erfüllt denselben Zweck, aber raubt dem Compiler 
nicht alle Optimierungsmöglichkeiten innerhalb des Handlers selber.
Und ändert (Stand jetzt) absolut nichts am erzeugten Maschinencode.
Gast #7089777
Lesenswert?

Εrnst B. schrieb:

> Bei einer Nicht-Inlinebaren Funktion, die per Funktionspointer in einer
> Struct ausgeführt wird?

Ja, darf er, weil das nach Standard keine Rolle spielt.

> Selbst wenn du davon ausgehst, dass irgendein hyperintelligenter
> Compiler das in der Zukunft kann

Das Können ist ja eine ganz andere Frage - aber es gibt einiges an 
altem, nicht konformem C-Code, der mit den damals laxeren Compilern 
lief, aber mit heutigen nicht mehr. Und eben aus solchen Erfahrungen bin 
ich da vorsichtig.

> Eine simple compiler barrier ( asm volatile ("" ::: "memory") ) am
> Anfang des Handlers erfüllt denselben Zweck

Ja, das ist für diesen Fall eine gute Idee, weil sich während des 
Handlers nichts mehr ändert.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren