Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Real time embedded FreeRTOS mailing list 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT Training




Loading

Implementation of Polling UART

Posted by groger57 on June 22, 2017

I currently have a function that can be called from 3 tasks. The function includes some string formatting for a screen. Inside this function is a semaphore that encapsulates all the formatting. From within that, I use sendQueue to send messages to a UART. I have a dedicated structure for the send and receive queues. It contains a string buffer of 50, and a single uint8. However - it is failing to take the semaphore quite often, even with a 1000ms wait.

aFunction( ... ) { if( xSemaphoreTake( xMutexUARTaccess, 1000 ) == pdPASS )
{ //...some stuff xQueueSend( mssgQueue, (void*)&queMssg, 500); } else { //...semaphore was not obtained... printf("Semaphore not taken.n"); } }

The receiveQueue task uses a send and poll, like this:

xStatus = xQueueReceive( xQueue, &queMssg, 1000 );   

    if( xStatus == pdPASS )
    {
        volatile uint16_t rxCode = 0x0;
        char *s = &queMssg.message[0];

        while(*s)
        {
            while( USART_GetFlagStatus(USART2, USART_FLAG_TXE ) == RESET); 
            USART_SendData(USART2, *s++);
        }    

        while(1) // poll response
        {
            while( USART_GetFlagStatus( USART2, USART_FLAG_RXNE) == RESET ); 
            rxCode = USART_ReceiveData( USART2 ); 

            if( rxCode == RCVD_PROMPT )
            {
                //one more for 0xD (end of message)
                while( USART_GetFlagStatus( USART2, USART_FLAG_RXNE) == RESET ); 
                rxCode = USART_ReceiveData( USART2 );                         
                break;
            } 
        }
    }

Using this method, what could be the reason for the semaphore not to be taken so often, given the long number of ticks to wait? Further, is there a better way to implement the UART send and receive? Should they use a send and receive queue on their own, rather than encapsulating them as above?

Thank you for any advice or help.


Implementation of Polling UART

Posted by heinbali01 on June 22, 2017

Hi Roger,

you take xMutexUARTaccess, but in the code shown, you never release it?

Beside that, queues do not need to be protected by a mutex. All queue access functions are "thread safe", they will temporarily suspend the scheduler, or enter a critical section when necessary.

~~~

aFunction( ... ) { //...some stuff /* xQueueSend will either send the message, or it will time-out after 500 clock-ticks. / xQueueSend( mssgQueue, (void)&queMssg, 500); }

~~~

Your server will only become available in case it receives a character RCVD_PROMPT. Are you sure that it will always be received? Doesn't that loop need a time-out protection?


Implementation of Polling UART

Posted by groger57 on June 23, 2017

Hi, thank you for the response. I removed the mutex and now the function only uses xQueueSend. To be clear, I have 9 tasks running, and 2 of them will call the function that formats the message strings and the sends them using xQueueSend. Each message requires formatting before it's ready to xQueueSend, and that's why I can't use xQueueSend directly from the task. Is calling the function that formats and then xQueueSend safe to do from the 2 running tasks?

There's still a problem somewhere...I have a message that is on the else side of this: xStatus = xQueueReceive( xQueue, &queMssg, 500 ); uint8_t qsr = uxQueueSpacesAvailable( xQueue ); if( qsr == 1) printf("Only 1 Queue Space Left!n" );

if( (xStatus == pdPASS) ) { sendToUART( &queMssg.mssg[0] ) ;
} else { printf("Didn't get a Queuen"); }

The if( qsr == 1 )never prints so available queue space doesn't appear to be the problem. From the time it starts running, I start getting the message in the else braces. Also, at the start of each task, I have a printf statement there. Initially, all of them print, but within a few seconds all but one is remaining. It's like the other tasks stop running. In the one task that stays running, I have this : printf("Number of tasks = %in", uxTaskGetNumberOfTasks()); Which starts at 9 and doesn't change. The xPortGetFreeHeapSize() shows 10600 at the start of the scheduler. I have lots of stack and heap allocated, and lots of words/bytes on each running task.

What would cause this strange behaviour?

Thanks.


Implementation of Polling UART

Posted by heinbali01 on June 23, 2017

There's still a problem somewhere...I have a message that is on the else side of this:

xStatus = xQueueReceive( xQueue, &queMssg, 500 ); uint8_t qsr = uxQueueSpacesAvailable( xQueue ); if( qsr == 1) printf("Only 1 Queue Space Left!n" );

if( (xStatus == pdPASS) ) { sendToUART( &queMssg.mssg[0] ) ; } else { printf("Didn't get a Queuen"); }

Aren't you mistaken here? The task is receiving from a queue, with a time-out of 500 clock ticks. When the time-out is reached, the function xQueueReceive() returns pdFAIL and your message will be printed.

Is calling the function that formats and then xQueueSend safe to do from the 2 running tasks?

The function xQueueSend() is well protected and can be called simultaneously. I can not see your message formatting, so I don't know if that is re-entrant safe code


Implementation of Polling UART

Posted by groger57 on June 23, 2017

Hein, Thank you for taking the time to reply. Instead of continuing down this path, let me ask this a different way. I now understand the problem space so I need now to understand implementation.

Let's say I have 3 concurrent tasks (TaskA, TaskB, TaskC). I have 15 different structure (SCROBJ) instances that are malloc'd at initialization. Each one has different information about it's "object" (obj1, obj2...obj14). Each task can (and will) access and modify and particular object, at any time in concurrency. "Access" means to send information to a function that will then send that object's data through the UART. In truth, a single call to the function requires several UART sends to complete the "transaction". Additionally, the UART response is polled (I have done that part and works OK) As you expect, it's not possible to have a single function to service these Task calls without something getting corrupted. For example, if TaskA has called the function for sending Obj5, and TaskB begins formatting the string for Obj5 at the same time, trouble is imminent.

Clearly the way to fix this is using a FreeRTOS message queue. But this raises questions. I could create a message structure that is of type SCROBJ that the RTOS function QueueSend will use (stack allocated). But at some point, I need to modify (change) the members of that structure to match the object that I am sending through the UART. I understand that QueueReceive makes a copy of the incoming structure. Can I use a pointer of the obj in QueueSend ? Will QueueReceive make a copy of the sending structure's members? Should the QueueSend and QueueReceive structure be created and heap allocated, same as the "obj1...etc, structures, instead of stck allocation? If receive does make a copy, this would be safe as QueueReceive would protect the structure until it's completed and shouldn't get corrupted by another task. From within the QueueReceive function, on pdPass, I would begin sending the various structure elements into the UART.

I appreciate your feedback to figure this out.

Thanks, Roger


Implementation of Polling UART

Posted by groger57 on June 23, 2017

Hi, I was able to figure it out, and get it working. I created an instance of the structure I was using for the various screen I/O devices. Whenever I call QueueSend, I cast in the specific instance of the object to be formatted and sent (void * ) and then the same on the xQueueReceive side. Just a bit of clean up in the code and all is well. I was able to get all the updates into a single task, so that itself removed conflicting access.

Thanks again! Gary


Implementation of Polling UART

Posted by heinbali01 on June 24, 2017

if TaskA has called the function for sending Obj5, and TaskB begins formatting the string for Obj5 at the same time, trouble is imminent.

You can create an array of these objects, and send these objects to a QueueFree. When you need such an object, take from QueueFree and pass it the the UART task. After handling the message, the object will be returned to QueueFree.

I understand that QueueReceive makes a copy of the incoming structure. Can I use a pointer of the obj in QueueSend ?

Yes, do not store the entire object ( of N bytes ) in a queue, but store a pointer. And the 4 bytes of a pointer will get copied.

Should the QueueSend and QueueReceive structure be created and heap allocated

I would think of QueueFree and QueueUart. Initially ( a pointer to ) each object is linked to QueueFree. grab one from there, change the contents and pass it to QueueUart. The Uart task will handle the message and return the object to QueueFree?

Just a bit of clean up in the code and all is well

Good to hear. You're welcome, Hein


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.


Free TCP/IP and file system demos for the RTOS


Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists