FreeRTOS +UART TX DMA+ UART RX Size variant buffer

Here are some inputs:
  • MCU: STM32L053 (Host)
  • GSM Module: handles GSM network connecctions and notifify via UART the MCU. It also receives MCU commands.
  • UART-USB converters: They let me monitor what happens in each pin (RX and TX) by means of hiperterminals
  • UART TX +DMA for transmissions of AT commands
  • UART RX for reception of messages of different sizes.
  • I don t use the hal library for the uart IRQ. (unfortunately, ST doesn’t provide std firmware neither! so i do a mix and my own…based on my needs …)
  • gcc-arm compiler + Eclipse AC6 plugin
My purpose is as follows: trigger 2 different threads depending on a received buffer pattern. For this, i will use a preemptive scheduler (FreeRTOS V8.2.3+ cmis os interface). Here are some code snippets with brief some brief explanation: ~~~ static void EmergencyButtonEventProcess(void) {
DelSMS();
} void DelSMS(void) { SendATCommand(eDeleteAllSms); } static void SendATCommand(ATCommandIdtE CmdIdtE) { … U8 source[MAXSIZEFORBUFFER]; switch(CmdIdtE) { case eCheckGsmModule: strcpy(source, CHECKGSMMODULE); sizeOfBuffer = LibTypStrLen(&source); HUartTransmit( HUarteUart2, source, sizeOfBuffer ); break; case eReadSMS: strcpy(source, READSMSCOMAND); sizeOfBuffer = LibTypStrLen(&source); HUartTransmit( HUarteUart2, source, sizeOfBuffer ); break; case eDeleteAllSms: strcpy(source, DELETEALLSMSCOMAND); sizeOfBuffer = LibTypStrLen(&source); HUartTransmit( HUarteUart2, source, sizeOfBuffer ); break; default: break; } } ~~~ These functions(above) are called when a button is pressed and after a debounce time has passed. I used the IRQ of a GPIO and IRQ of a timer. When the button is pressed more than 5 seconds a command is sent to the GSM module and this one responds with an OK. The transmition is done with a uart peripheral of the MCU and DMA. All works correctly and as expected. In this case i have not used any of the OS services but maybe in the future, i would sync with a semaphore. I don’t think this is necessary. ~~~ void USART2_IRQHandler (void) { //Store DR //Detect patern and store it in appropiate buffers… if(TXRXBufferFlagtb ==TRUE) { … //more pattern tests… //store TXRXBuffer[] TXRXBufferFlagtb =FALSE; osSignalSet(ThreadId2, BIT2 ); } if(RXBufferFlagtb==TRUE) { … more process //store RXBuffer[]
osSignalSet(ThreadId1, BIT1); } } ~~~ In the UART IRQ, i fill up 2 buffers depending on the start of the message. Basically, we have 2 types:
  • TXRXBuffer[] = “AT+something n” pattern corresponds to a answer of the gsm module after a command has been sent.
  • RX_Buffer[] = “r something n” pattern corresponds to a notification of the gsm module.
A event flag is set and notified to the OS. A related thread (depending on the buffer patern detected) has to be triggered ~~~ static void Thread1RXBuffer(void const *argument) {
  osEvent event;

  for(;;)

  {

    event = osSignalWait( BIT_1, osWaitForever);

    if(event.value.signals == BIT_1)

    {

        Send_AT_Command(eRead_SMS); //UART Transmit with DMA is called

       }
} static void Thread2TXRX_Buffer (void const *argument) { (void) argument; osEvent event; RelayIdtE IdtE; for(;;) {
event = osSignalWait( BIT_2 , osWaitForever);

if(event.value.signals == (BIT_2 ))

{

    Send_AT_Command(eMakeCall);  //UART Transmit with DMA is called

}
} } ~~~ Here the Threads are triggered as expected. The problem is that only 3 characters are transmitted and the rest are incoherent (i.e AT+Cÿÿÿÿ[02][00]). On the other hand, the same transmission function is called when the button is pressed and all is ok. I think that the tick interrupt related to the OS corrupts the UART DMA transmission. How can i sort this out ? Any suggestions? PS: Any suggestions are welcome concerning the design/implementation. There are still some improvements to do like copy the buffer for deferred processing …. I posted my issue also in stm forum but i think the issue is more related to the OS api Regards Rafa

FreeRTOS +UART TX DMA+ UART RX Size variant buffer

Is HUart_Transmit() thread-safe ? Seems it could be invoked concurrently. If not and since you dispatch the events to task level you could use a e.g. a mutex to properly serialize the UART-DMA accesses.