Forum: Mikrocontroller und Digitale Elektronik STM32F4 USART DMA Inhalt löschen


von Mach F. (machfax)


Lesenswert?

Hallo

Ich empfange mit einem STM32F4 über die USART1 mit dem DMA Datenpakete, 
die 16Bytes lang sein müssen. Es kommt jetzt beim Aufstarten aber vor, 
dass vom Sender aus schon ein 0x00 geschickt wird, das ich ausfiltern 
möchte.
Ich habe jetzt den idle IRQ vom USART1 konfiguriert, um in so einem Fall 
den Inhalt des DMA zu löschen. Leider weiss ich jetzt nicht wie man ins 
Register vom DMA kommt, denn in "meinem" Register liegen die Daten erst, 
wenn 16 Bytes im Buffer sind.

DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)&RS485_RX_Buffer;

Ich müsste also bei einem idle IRQ von UASART1 den DMA Inhalt löschen um 
bei den korrekt eintreffenden 16Bytes wieder einen leeren Buffer zu 
haben, da ansonsten die 16Bytes um 1 Stelle verschoben werden und ich 
das Kommando nicht mehr kenne.

Danke für Inputs

von Markus R. (maggus)


Lesenswert?

Das unerwünschte 0x00 Paket kommt nur nach einem Reset? Hast du schon 
probiert, nach dem Empfang des Pakets den DMA Controller zurückzusetzen 
(Enable->Disable->Enable) oder die DMA_Memory0BaseAddr neu zu schreiben? 
Wann der interne DMA-Zähler auf null zurückspringt sollte ja im 
Datenblatt stehen. Oder gibt es vielleicht ein Register, in dem der 
akutelle Zählwert steht?

Dem Sender das Verschicken des unerwünschten Pakets abzügewöhnen ist 
keine Alternative?

von Mach F. (machfax)


Lesenswert?

Markus R. schrieb:
> Das unerwünschte 0x00 Paket kommt nur nach einem Reset? Hast du schon
> probiert, nach dem Empfang des Pakets den DMA Controller zurückzusetzen
> (Enable->Disable->Enable) oder die DMA_Memory0BaseAddr neu zu schreiben?
> Wann der interne DMA-Zähler auf null zurückspringt sollte ja im
> Datenblatt stehen. Oder gibt es vielleicht ein Register, in dem der
> akutelle Zählwert steht?
>
> Dem Sender das Verschicken des unerwünschten Pakets abzügewöhnen ist
> keine Alternative?

nein leider nicht denn Störungen können dasselbe bewirken

von Uwe B. (derexponent)


Lesenswert?

Mach Fax schrieb:
> nein leider nicht denn Störungen können dasselbe bewirken

wenn du von Störungen bei der Kommunikation ausgehen musst,
können die zu jedem Zeitpunkt zuschlagen und nicht nur beim start

somit kommst du um eine Verifizierung der Daten mit entsprechendem
Protokoll nicht drum rum

bedeutet :

A. Daten per Checksumme sichern und bei Fehler neu anfordern
B. Daten nach RX-Timeout verwerfen und neu anfordern
C. was dir sonst noch so einfällt

Gruss Uwe

: Bearbeitet durch User
von Mach F. (machfax)


Lesenswert?

mache ich schon mit checksum usw, alles geklärt. Das Problem ist dass 
mir der IRQ der Kommunikation erst kommt wenn die 16Bytes des DMA voll 
sind und wenn jetzt der Buffer schon mit "Müll" gefüllt ist bekomme ich 
beim IRQ vom DMA nur die Hälfte der Daten

von Uwe B. (derexponent)


Lesenswert?

so wie ich es verstanden habe, hast du einen Buffer (und einen IRQ)
für 16 Bytes Daten

und bei einem Fehler kommen mehr als die 16 Bytes an
(z.B. durch ein Fehlerhaftes 0x00 am Anfang vom Packet)

dann bekommst du aber doch einen IRQ,
nämlich nach dem 15ten richtigen Zeichen

was du dann machen kannst

in der ISR
1. erkennen das das Packet falsch ist (z.B. durch Checksumme)
2. Packet verwerfen
3. DMA reseten (damit ist auch ein etwaiger "rest" gelöscht)
4. Packet neu anfordern

oder versteh ich da noch was falsch

von Mach F. (machfax)


Lesenswert?

Uwe B. schrieb:
> so wie ich es verstanden habe, hast du einen Buffer (und einen IRQ)
> für 16 Bytes Daten
>
> und bei einem Fehler kommen mehr als die 16 Bytes an
> (z.B. durch ein Fehlerhaftes 0x00 am Anfang vom Packet)
>
> dann bekommst du aber doch einen IRQ,
> nämlich nach dem 15ten richtigen Zeichen
>
> was du dann machen kannst
>
> in der ISR
> 1. erkennen das das Packet falsch ist (z.B. durch Checksumme)
> 2. Packet verwerfen
> 3. DMA reseten (damit ist auch ein etwaiger "rest" gelöscht)
> 4. Packet neu anfordern
>
> oder versteh ich da noch was falsch

Nein genau so muss es sein. Ich bekomme einen Interrupt wenn der DMA 
auslöst (nach 16 Zeichen) und einen wenn die UART in einen Timeout geht 
(nach jeder Übertragung von Bytes, die irgendwann fertig ist)
Ich muss jetzt in dieser Routine vom Timeout, (der nach dem einen Byte 
kommt)
den DMA Inhalt löschgen, nur weiss ich nicht wie...

von Uwe B. (derexponent)


Lesenswert?

so wie es Markus oben schon geschrieben hat,
probier mal:

DMA-Disable
Interrupt-Flags löschen
DMA-Enable

von Mach F. (machfax)


Lesenswert?

Hier die Lösung:

Beim Idle IRQ muss die USART1 ausgelesen werden um diesen IRQ zu 
löschen, dann DMA deaktivieren und wieder aktivieren um DMA Buffer zu 
löschen.

//RS485 receive IRQ
void DMA2_Stream5_IRQHandler (void)
  {
  /* Test on DMA Stream Receive Complete interrupt */
  if (DMA_GetITStatus(DMA2_Stream5, DMA_IT_TCIF5))
    {
    /* Clear DMA Stream Receive Complete interrupt pending bit */
    DMA_ClearITPendingBit(DMA2_Stream5, DMA_IT_TCIF5);
    RS485_GetData();
    RS485_RX_Init();

    DMA_Cmd(DMA2_Stream5, ENABLE);  //RX enable  -> receive
    }
  }

void USART1_IRQHandler(void)
{
  if (USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
    {
    USART_ReceiveData(USART1);  //read to clear the IRQ

    //diable and enable the DMA to clear the Buffer
    DMA_Cmd(DMA2_Stream5, DISABLE);  //RX disable
    DMA_Cmd(DMA2_Stream5, ENABLE);  //RX enable  -> receive
    }
}

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.