Forum: Mikrocontroller und Digitale Elektronik STM32f767zi: HAL_UART_Transmit_DMA funktioniert nicht


von Frank B. (fbergemann)


Lesenswert?

Für mein https://github.com/FBergemann/STM32-FreeRTOS-Framework versuche 
ich die Ausgabe auf die Console zu verbessern.
Auf DMA zu wechseln funktioniert leider nicht.
Siehe im dev-v2 branch 
https://github.com/FBergemann/STM32-FreeRTOS-Framework/tree/dev-v2, 
https://github.com/FBergemann/STM32-FreeRTOS-Framework/blob/dev-v2/User/UserSrc/Tasks/TaskConsole/TaskConsole.c

Ein DMA write geht raus, aber die Schleife
1
while ( HAL_UART_GetState(&huart3) != HAL_UART_STATE_READY);
hängt.
in stm32f7xx_hal_uart.c hier
1
HAL_UART_StateTypeDef HAL_UART_GetState(UART_HandleTypeDef *huart)
2
{
3
  uint32_t temp1;
4
  uint32_t temp2;
5
  temp1 = huart->gState;
6
  temp2 = huart->RxState;
7
8
  return (HAL_UART_StateTypeDef)(temp1 | temp2);
9
}

bekomme ich den Wert 0x21 = #33 für temp1 = huart->gState.

Während der erwartete Wert HAL_UART_STATE_READY = 0x20 = #32

Mit
1
...
2
#define  HAL_UART_STATE_READY         0x00000020U    /*!< Peripheral Initialized and ready for use
3
                                                          Value is allowed for gState and RxState */
4
...
5
#define  HAL_UART_STATE_BUSY_TX       0x00000021U    /*!< Data Transmission process is ongoing
6
                                                          Value is allowed for gState only */
7
...

Ich habe im Netz gesucht und fand Hinweise, dass man 
HAL_UART_STATE_READY selbst setzen muss? (wo und warum? liegt's an 
circular vs. nicht-circular und dass beide über denselben Mechanismus 
laufen?)

Letztendlich ist die loop
1
while ( HAL_UART_GetState(&huart3) != HAL_UART_STATE_READY);
Sowieso nicht sinnvoll. Ich mache ja kein dma, damit ich parallel dann 
doch wieder cpu verbrate. Aber da kann man hinterher durch eine 
Semaphore austauschen.


MIch würde ausserdem noch interessieren, ob so eine Konstruktion
1
    vTaskSuspendAll();
2
      writePtr += len;
3
      if (writePtr > endPtr) writePtr = logBuffer;
4
    xTaskResumeAll();
sinnvoll/zulässig ist, um ein konsistenten update vom writePtr für 
TaskConsole_Run() zu gewährleiste.

Und: Kann man sich darauf verlassen, dass in TaskConsole_Run() wiederum 
das Holen des Wertes
1
char *writePtrCopy = writePtr;
atomar ist?

: Bearbeitet durch User
Beitrag #6718886 wurde vom Autor gelöscht.
von Frank B. (fbergemann)


Lesenswert?

> MIch würde ausserdem noch interessieren, ob so eine Konstruktion
1
vTaskSuspendAll();
2
  writePtr += len;
3
  If (writePtr > endPtr) writePtr = logBuffer;
4
xTaskResumeAll();
> sinnvoll/zulässig ist, um ein konsistenten update vom writePtr für
> TaskConsole_Run() zu gewährleiste.
>
> Und: Kann man sich darauf verlassen, dass in TaskConsole_Run() wiederum das
> Holen des Wertes
1
char *writePtrCopy = writePtr;
> atomar ist?

Laut 
https://stackoverflow.com/questions/52784613/which-variable-types-sizes-are-atomic-on-stm32-microcontrollers 
(mit Verweis auf Spec) ist
1
char *writePtrCopy = writePtr;
Bereits ok.

Und aus
1
vTaskSuspendAll();
2
  writePtr += len;
3
  If (writePtr > endPtr) writePtr = logBuffer;
4
xTaskResumeAll();
Muss ich machen
1
writePtrCopy = writePtr + len;
2
If (writePtrCopy > endPtr) writePtrCopy = logBuffer;
3
writePtr = writePtrCopy

Mit jeweils eigenen (nicht globalen) writePtrCopy Instanzen.

: Bearbeitet durch User
von Frank B. (fbergemann)


Lesenswert?

Hat sich erledigt.
Ich hatte vergessen: 
https://stackoverflow.com/questions/43298708/stm32-implementing-uart-in-dma-mode
Aber nicht manuell, sondern über's *.ioc file auzuwählen unter
1
Connectivity
2
 USART3 # in meinem Fall
3
  NVIC Settings
4
   USART3 global interrupt [x] # ist zu aktivieren

So jetzt noch Feinschliff, und dann ran an's USB MSD I/F.

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
Noch kein Account? Hier anmelden.