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

Problem with blocking a task

Posted by Ricky on April 23, 2007
I have a project I'm developing that currently has only one task, a command processor that reads commands from the serial port, acts on them, and sends a response back out the serial port.

I've been having problems with transmitting the response back. It appeared that the transmit FIFO was overflowing and I was losing characters, even though I was blocking when the transmit FIFO became full (I used the STR912F demo for IAR as the template). Debugging showed that the task would correctly block when taking a semaphore when the FIFO filled and then wait for the semaphore to be given back by the UART ISR when the FIFO became free. But when running full bore, the FIFO overflowed as if the semaphore weren't there.

I then had an idea that maybe the task was blocking on the semaphore and then immediately awakening again because it was the only task in the system and the scheduler had to wake somebody after the lone task went to sleep. This occurred to me once before with the uCOS RTOS, and I was wondering if it was happening in FreeRTOS as well.

Here's the code in the Send Character function I use to block on, which doesn't work:

___if (UART_GetFlagStatus (mkapsUARTBase [ziUART], UART_FLAG_TxFIFOFull)) {
______xSemaphoreTake (mapsTxSemaphore [ziUART], portMAX_DELAY);
___}

But when I make it a loop to force it to go back to sleep if the FIFO is still full, it works very well:

while (UART_GetFlagStatus (mkapsUARTBase [ziUART], UART_FLAG_TxFIFOFull)) {
xSemaphoreTake (mapsTxSemaphore [ziUART], portMAX_DELAY);
}

Is this what could be happening? Why doesn't the Idle Task run while waiting for the FIFO to become free?

RE: Problem with blocking a task

Posted by Nobody/Anonymous on April 23, 2007
The idle task will run if there are not other tasks, no doubt about that. Maybe you have a race condition on the checking of the FIFO. I'm not sure why you are checking the fifo before calling the semaphore function. You should just be able to check the semaphore on the assumption that it is given by the interrupt service routine. This way the race condition will be avoided. Maybe I am missing the point?

RE: Problem with blocking a task

Posted by Ricky on April 24, 2007
The semaphore is there to let me know when the FIFO becomes empty (actually, the number of bytes left in the FIFO goes below a certain threshold).

Here's the function to send a character in its entirety:

void Serial_SendChar (int ziUART, const char zcChar) {

// If the transmit FIFO is full, the task blocks to wait for space to become
// free. It's okay to block in a critical section since interrupts will be
// enabled for other tasks once a switch is forced.

___portENTER_CRITICAL();
___while (UART_GetFlagStatus (mkapsUARTBase [ziUART], UART_FLAG_TxFIFOFull)) {
______xSemaphoreTake (mapsTxSemaphore [ziUART], portMAX_DELAY);
___}

// The character is transmitted.

___UART_SendData (mkapsUARTBase [ziUART], zcChar);
___portEXIT_CRITICAL();
}

I make sure that the FIFO has space available before sending a character to it. Once the FIFO is full, I take the semaphore which has already been taken when the UART was initialized, so the task blocks waiting for it to be given back. When the FIFO becomes free again, the UART causes a serial transmit interrupt. The code that handles this interrupt is shown here:

___if (UART_GetFlagStatus (mkapsUARTBase [ziUART], UART_RawIT_Transmit)) {
______xlWakeTask = xSemaphoreGiveFromISR (mapsTxSemaphore [ziUART], xlWakeTask);
______UART_ClearITPendingBit (mkapsUARTBase [ziUART], UART_IT_Transmit);
___}

The semaphore is given back in the interrupt, and the task that called Serial_SendChar is awakened. The semaphore is taken again and the character is sent to the UART.

So the interrupt does nothing but unblock the task when the FIFO becomes free. The task is responsible for sending the character and checking to see if the FIFO is full. Granted, it's not exactly your standard serial port functionality, but it saves some code and it works.


[ 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