I have an application using FreeRTOS in an MSP430F5438A that is configured with Code Memory large, data memory model restricted,
and data near as globals.
I am seeing two failures in the application:
1) The vApplicationStackOverflowHook is called with pcTaskName IDLE. So supposedly the IDLE task is having an overflow
2) At times the MSP430 will end up no where, basically no longer executing the FreeRTOS, with the program counter pointing to 0x4 or some other very high location that is basically illegal
A brief description of my application:
I have a total of 8 user created tasks. These tasks basically process UART, I2C and a few other things. The majority of them
are blocking on queues (one or two are using vTaskDelay to wait a certain amount of time). These queues are being filled from ISRs that
trigger on data from UART and I2C if certain conditions are met. The ISRs don't call any other functions except xQueueSendFromISR so as to keep the ISRs short.
Here is the main stuff from FreeRTOSConfig.h
define configUSE_PREEMPTION 0
define configUSEIDLEHOOK 1
define configUSETICKHOOK 0
define configCPUCLOCKHZ ( 25000000UL )
define configLFXTCLOCKHZ ( 32768L )
define configTICKRATEHZ ( ( portTickType ) 1000 )
define configMAXPRIORITIES ( ( unsigned portBASETYPE ) 10 )
define configTOTALHEAPSIZE ( ( size_t ) ( 12 * 1024 ) )
define configMAXTASKNAME_LEN ( 10 )
define configUSETRACEFACILITY 0
define configUSE16BIT_TICKS 1
define configIDLESHOULDYIELD 1
define configUSE_MUTEXES 1
define configQUEUEREGISTRYSIZE 1
define configGENERATERUNTIME_STATS 0
define configCHECKFORSTACK_OVERFLOW 2
define configUSERECURSIVEMUTEXES 1
define configUSEMALLOCFAILED_HOOK 1
define configUSEAPPLICATIONTASK_TAG 0
define configUSECOUNTINGSEMAPHORES 1
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 80 )
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 480 )
/* Co-routine definitions. */
define configUSECOROUTINES 0
define configMAXCOROUTINE_PRIORITIES ( 2 )
/* Software timer definitions. */
define configUSE_TIMERS 1
define configTIMERTASKPRIORITY ( 3 )
define configTIMERQUEUELENGTH 10
define configTIMERTASKSTACKDEPTH ( configMINIMALSTACK_SIZE )
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
define INCLUDE_vTaskPrioritySet 1
define INCLUDE_uxTaskPriorityGet 1
define INCLUDE_vTaskDelete 1
define INCLUDE_vTaskCleanUpResources 0
define INCLUDE_vTaskSuspend 1
define INCLUDE_vTaskDelayUntil 1
define INCLUDE_vTaskDelay 1
define INCLUDE_uxTaskGetStackHighWaterMark 1
I first thought that I actually had some ISRs triggering and causing a stack overflow in the IDLE task, but I am not sure this is
the actual cause. I say this because when the failure occurs, the pxCurrentTCB shows that the top of the stack is above the pxStack variable, and the pxStack points to an area of memory with more than 25 bytes of the 0x5A filler, so in fact the conditions for stack overflow don't seem to be present, and yet I still get an overflow.
In any case, I increased the IDLE task's stack size by increasing configMINIMALSTACKSIZE to 480 as you can see above, although my tasks are not deriving their stack size from this variable otherwise I wouldn't be able to fit everything. My tasks don't seem to need more stack.
I've added uxEnforaHighWaterMark checks in all my tasks and I never see them drop below 200 or so. I realize its not checking it all the time since I check this after the queue is read. In fact, I created a table with pointers to all the tasks when they're created and looked at their TCBs.I don't see any stack overflow conditions.
One suspicious occurrence I see is that I sometimes see the Stack Pointer of the CPU to point at a location above the top of the stack of one task,
but below the pxTask of the next task. This is seen at least in failure #2 above, but maybe also in failure #1.
Any help would be appreciated and if there is a detail missing please let me know.
There is nothing that stands out as being wrong. I would make the comment that sending individual characters on a queue in this manner is not very efficient. If you have a low baud rate it will be ok, but it might struggle at higher baud rates. Although the demo applications do this it is only to demonstrate using API functions from an interrupt - real applications are better off using a circular buffer or DMA, then a single semaphore to wake a task when a complete message is ready to process.
Which compiler are you using?
Out of interest, as the stack overflow seems to be incorrect, have you tried running the application with configCHECKFORSTACK_OVERFLOW set to 0? I'm just wondering if there might possibly be a problem with the overflow checks when the large data model is used - I know overflow detection cannot be used on segmented memory architectures such as x86. Having said that, I have checked the official demos and they seem to be using overflow detection.
Thanks for the quick response. The queue is not to send the characters individually. It simply indicates when a TX or RX operation is done. The characters are sent in the ISR automatically and this data is placed on a buffer which the ISR reads. Once the count is done, the task is informed that it is sent, or that a message was received. The same with I2C.
I am using Code Composer Studio Version: 5.4.0.00091 with compiler V4.1.5.
I'll try disabling it and see whether that makes a difference.