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

Weird task switch after non-ISR call to xQueueReceive()

Posted by martin72216 on October 30, 2013

Hi I'm porting a small project from embOS to FreeRTOS. I'm running FreeRTOS on an STM32F207IG (STM3220G-EVAL) and I'm encountering some odd behavior with a semaphore I'm using to synchronize tasks. Task 1 (SPCRootTask) puts a command into Task 2's (RedpineTask) command queue. Task 1 also increments a counting semaphore to signal that there is something to do. (The additional semaphore exists because there are more events that shall wake Task 2 besides a command.) The command contains another semaphore that is signalled by Task 2 as soon as command execution is finished. Task 1 waits for this semaphore. This is done to implement a synchronous interface for the services offered by Task 2.


Below you see Eclipse Debug output for the function that eventually calls "take()" on the command semaphore.

marTouchWireless Debug [GDB Hardware Debugging]	
    GDB Hardware Debugger (30.10.13 16:51) (Suspended)	
            Thread [1] (Suspended)	
                5 RedpineTask::queryFirmwareVersion() RedpineTask.cpp:761 0x080120b8	
                4 RedpineTask::redpineStartup() RedpineTask.cpp:2914 0x0801424e
                3 SPCRootTask::run() SPCRootTask.cpp:143 0x08014e0c	
                2 taskFunc() IRunnable.cpp:19 0x0800c81e	
                1 <symbol is not available> 0x00000000	
    arm-none-eabi-gdb (30.10.13 16:51)	

This call stack would be totally fine for Task 1 but according to pcGetTaskName() this is actually the call stack of Task 2.


This is the function I'm looking at in the debugger. Although it's a method of the RedpineTask class it is meant to be called by other tasks (the sychronous interface i talked about). "PC->" marks the program counter...

SINT32 RedpineTask::queryFirmwareVersion(UINT8* pui8FwVersion) {
    ComQueryFirmwareVersion _command(this);
    deliverCommand(&_command); //puts command to queue, queue was empty before

    xTaskHandle curTask = xTaskGetCurrentTaskHandle(); //<--OOPS to show the effect
    signed char* task = pcTaskGetTaskName(curTask); //to show the effect
    _command.waitCompletion();//<--PC of debug window

    _command.getFirmwareVersion(pui8FwVersion); //i never get here due to the resulting deadlock
    return _command.getRetval();
}

When Task 1 calls the function above the command is delivered and the semaphore tells Task 2 to wake up. Task 2 wakes up and checks if there are any commands in the queue. It takes the command from the queue in a function collectCommand() similar to deliverDommand() which just puts the pointer passed to it into a defined byte order. As soon as this function returns I get thrown to the place marked with "OOPS". Actually I get thrown to the next instruction right after "deliverCommand". The debugger tells me that I'm executing in the context of SPCRootTask. However, looking at the string named task I see that the current task is "RedpineTask" (Task 2) which never calls "queryFirmwareVersion()".

I hope this is some known issue that can be quickly resolved. I also want to add that I have been through all CM3 specifics and I think that my settings (full interrupt preemption, Kernel Prio 0xF0, Syscall Prio = API call Prio = 0xB0) should all be correct. I'm currently not using any interrupts besides the ones the portPackage enabled.

Cheers

Martin

So it seems that a non-trivial mixup is happening somewhere


Weird task switch after non-ISR call to xQueueReceive()

Posted by richardbarry on October 30, 2013

Wow - there is a lot to comprehend here. A few simple questions first:

1) You say it deadlocks - but am I right in thinking it does not crash?

2) Do you have stack overflow protection on?

3) Are you generating task specific call stacks? If so, how? By default GDB will normally only show you the call stack of the currently executing task. [point of interest].

4) Are you using the latest FreeRTOS version with configASSERT() defined? [some additional assert points were put in recently]

Regards.


Weird task switch after non-ISR call to xQueueReceive()

Posted by martin72216 on October 30, 2013

Hi Richard,

1) Correct, no crash... Task 1 and Task 2 are both blocked so the Idle task is the only one running. This is because Task 2 is trying to take from the command semaphore, the one it should actually give;-) I know.. a lot to understand. Here is a few lines of code that give you the other half of the picture.

...

while (true) {
    // Wait for something to happen.
    pWakeupSemaphore->wait();

    // If there is a pending command we cannot service a further command. So
    // only if there is no further command we collect a new command from the
    // mailbox and execute it.
    if (!isCommandPending()) {
        if ((IRedpineCommand*) NULL != (_pRedpineCommand = collectCommand())) {
            SINT32 _si32Ret((SINT32) COMM_ERR_OK);
            pendingCommand = _pRedpineCommand;
            // if we have an error executing the command we immediately destroy the
            // command; handleResponse() discards unexpected commands, so this is no
            // problem.
            if (0 != (_si32Ret = pendingCommand->execute())) {
                pendingCommand->setRetval(_si32Ret);
                pendingCommand->signalCompletion();
                pendingCommand = (IRedpineCommand*) NULL;
            }
        }
    }

...

2) No stack overflow protection is in place however the code already ran on embOS using the same libc and the stacks are dimensioned with a 50% security margin

3) No the call stacks are not task specific. I only have one Task callback (taskFunc()) which all task implementations use. They pass a this pointer as argument when creating the task. taskFunc() then calls the virtual run() method of the IRunnable() base class for all tasks. This is like the first hit when googling "FreeRTOS and C++".

4) I'm running FreeRTOS V7.5.2 which i downloaded about 6 weeks ago.

Thanks for taking interest.

Martin


Weird task switch after non-ISR call to xQueueReceive()

Posted by martin72216 on October 30, 2013

I updated to the latest version and enabled stack overflow checking. The problem persists.


Weird task switch after non-ISR call to xQueueReceive()

Posted by martin72216 on October 30, 2013

Nevermind, i mixed up the arguments for size and count when initializing the message queue, so the memcpy() in the queue messed up my stack... another 3 hrs worthlessly spent ;-)


Weird task switch after non-ISR call to xQueueReceive()

Posted by richardbarry on October 30, 2013

Its a well known attribute of embedded system programming that the jobs you think are going to be hard take a few hours, and the jobs you think are going to take a few minutes take a few days.

Glad you got your problem fixed.

Regards.


[ 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