Functioning FreeRTOS Project within MPLAB Harmony Framework

fabianlu wrote on Thursday, July 24, 2014:

Hi,

I have started working with FreeRTOS and the PIC32MZ EC StarterKit ( PIC32MZ2048ECH144 onboard ) about a month ago.
I wrote a working application that uses ADC inputs and outputs data to a LCD. The drivers are custom since the XC32 plib is not supported for the MZ family as far as I understood.

At this point i wanted to send data from the application to my PC and store this data in a .txt file to use it i.e. in Excel. For any keywords that came to my mind Google wanted me to use the Harmony Framework with its new plib and drivers. I downloaded Harmony and setup the provided FreeRTOS demo that worked fine. I cleaned this demo application and fit my own application into the Harmony structure.

After I managed it to compile with no errors or warnings, I ran the app and saw …nothing…

Before I start listing any code: I use MPLAB X IDE v2.05, XC32 v1.32 Compiler, MPLAB Harmony v0_80_02b with the stated PIC32MZ2048ECH144 on the EC StarterKit. Before using the integrated FreeRTOS version, my application was running with FreeRTOSV8.0.0

While debugging I found that the application initializes, runs, resets and starts over again from main(). This is caused by a “Simple Tlb Refill Exception” which I caught overwriting the weak _simple_tlb_refill_exception_handler(void) provided by ?! MIPS32 ?!.
I stepped out of this handler and returned to the FreeRTOS queue.c function “xQueueGenericSend( […] )”. Further single step tells me this function is called by a
“xSemaphoreGive( xASemaphoreHandle );” function that is NOT located in an ISR ( unless Harmony does smt. creepy ).

The exact line that throws this exception is:

if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )

Single step from entering “xQueueGenericSend” function is like the following sequence of code lines ( those are single code lines copied out of the FreeRTOS file queue.c ):

/* first: (Line: 597) */
Queue_t * const pxQueue = ( Queue_t * ) xQueue;
/* than back to: (Line: 595) */
BaseType_t xEntryTimeSet = pdFALSE;
/* than: (Line: 620) */
if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
/* than jumps to: (Line: 731) */
prvLockQueue( pxQueue );
/* than: (Line: 739) */
vTaskPlaceOnEventList( &( pxQueue->xTasksWaitingToSend ), xTicksToWait );
/* now back to: (Line: 614) */
taskENTER_CRITICAL();
/* here again: (Line: 620) */
if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )
	
/* and this throws the exception: */
void _simple_tlb_refill_exception_handler( void )
{
    Nop();
}

I honestly dont really understand this behaviour thats why im listing it here.

For information: I used heap_4.c since this worked with my application before!

Any suggestions would be highly appreciated.

Thanks
Fabian

rtel wrote on Thursday, July 24, 2014:

From the way your line numbers are jumping around, am I right in assuming that compiler optimisation is being used, at least in the part that is building the FreeRTOS source files. If so I would recommend turning optimisation off while you are debugging, otherwise you may find what you are viewing in the debugger confusing or misleading, and not really know which line of code is causing the exception.

It may be related to the compiler optimisation, if that is being used, but it would seem unlikely that the exception came from:


if( ( pxQueue->uxMessagesWaiting < pxQueue->uxLength ) || ( xCopyPosition == queueOVERWRITE ) )

unless pxQueue was not actually pointing to a queue, as all the code is doing is dereferencing the point twice to perform a comparison.

Do you have configASSERT() defined? If so then an assert would be triggered if pxQueue was null, which would leave the possibility of it being corrupted, but with a value other than NULL. What do you see if you view pxQueue in the debugger - does it look feasible?

Regards,
Richard Barry.

fabianlu wrote on Thursday, July 24, 2014:

Thanks for the fast reply!

Let me first thank you for providing FreeRTOS. I very much also enjoyed reading the Tutorial book.

You where right and again right!

I turned off the optimization-level ( to 0 ). Also I forgot that I before had commented out the configAssert( x ) link to vAssertCalled( […] ) in FreeRTOSConfig.h.

Now as you expected the lines are executed in an proper order, also configAssert( x ) is called and hangs in a loop now.

This means the SemaphoreHandle must be NULL in that point…

While writing this I found the bug and the problem is solved! The application is running. But I want to explain what was the problem even though I dont think somebody else would run into the wall as I did now:

I need to explain a bit more about what I’m doing with this Semaphore:

I have two tasks that can send information to a GateKeeperTask for LCD output via a queue. Just one of them should send information at a time. Therefore another task that queries the digital inputs, hands out a Semaphore to just one of those two tasks (I called the Semaphores as “Token”). Now there is a kind of Context switch performed when pressing a hardware switch on the starter board. I use this functionality to toggle between a TaskManager output and my analog measurements output on the LCD. The time between a Semaphore beeing handed out and the task actually taking it ( I used vTaskDelayUntil( […] ) since a Task resumes working, just the LCD output requires the Semaphore ), can be perfectly used for a Loading screen or the like.

Now it is correct that this Semaphore that creates the assert is initialised as NULL!
This is because my Semaphore is created when “prvTaskManager( void *pvParam )” is called the first time (before entering the loop).

While copying the initialization from the old application to the new Harmony “APP_Initialize()” I forgot to start the TaskManager task, so the semaphore was never created. Unfortunately the application is also set to initially switch the Display to TaskManager so I can read the cpu and heap, otherwise this error would have occured after pressing a hardware switch.

I’m really glad I posted on this issue, I spent 2 whole days on it.

Many Thanks!
Fabian