espressif / ESP8266_RTOS_SDK

Latest ESP8266 SDK based on FreeRTOS, esp-idf style.
http://bbs.espressif.com
Apache License 2.0
3.34k stars 1.57k forks source link

configASSERT is not defined for Freertos (GIT8266O-37) #346

Open jhinklejr opened 6 years ago

jhinklejr commented 6 years ago

In exploring rootcause for issue #345 I have found an assert in one of the FreeRtos files will lock the thread and produce the type of failure I am seeing.

I found that you have not defined configASSERT in FreeRTOSconfig.h.

I consider this an issue because all the error checking for function arguments in FreeRTOS is being bypassed.

I have added The following to my FreeRTOSconfig.h and suggest you look into doing something similar.

ifndef In_Xtensa_Assembler

void My_printf_NoBlock(char* fmt, ...);

define configASSERT(x) do { if (!(x)) {My_printf_NoBlock("RTOS Assert %s Line %u\n", FILE, LINE); while(1){}; }} while (0)

221

Most implementations of configASSERT just use a infinite loop.

I suggest adding a printf to report the assert. You need to make sure you DON'T use ets_printf() or any other printf that uses the heap or a mutex/semaphore.

My My_printf_NoBlock() by passes my gating semaphore, uses not malloc calls, and only uses 20 bytes of stack space - printing directly to the uart.

I can see why you folks may have excluded it because FreeRTOSconfig.h is passed to your assembler and it does not understand token like "void", etc

The way around this is to add the surround the definition of configASSERT() in FreeRTOS.h with the statement:

ifndef In_Xtensa_Assembler

As shown above.

The add the following line to the beginning of the includes in "etensa_rtos.h"

define In_Xtensa_Assembler

This removes the definition of configASSERT() in all the xtensa assembler files associated with FreeRTOS.

jhinklejr commented 6 years ago

I implement the above changes -- and I get a FreeRTOS Assert:

BaseType_t xQueueGenericSend( QueueHandle_t xQueue, const void const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition ) { BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired; TimeOut_t xTimeOut; Queue_t const pxQueue = ( Queue_t * ) xQueue;

configASSERT( pxQueue );
configASSERT( !( ( pvItemToQueue == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
configASSERT( !( ( xCopyPosition == queueOVERWRITE ) && ( pxQueue->uxLength != 1 ) ) );
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
{
    configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );  ****** this line asserts
}
#endif

The line noted with **** asserts

RTOS Assert C:/msys32/home/Joe/esp/Virgin/components/freertos/freertos/queue.c
Line 736

That means your SDK has an issue ... now to find out where

jhinklejr commented 6 years ago

I added some more code configAssert to report the associated task.

RTOS Assert C:/msys32/home/Joe/esp/Virgin/components/freertos/freertos/queue.c
Line 736 Calling Task rtT

I've search all the IDF files for THAT task name and found none which means it's an Espressif task contained in a binary blob.

Can you look into this please since I can not.

Thanks.

jhinklejr commented 6 years ago

I removed the infinite loop from configASSERT to see what else would assert and ..

RTOS Assert C:/msys32/home/Joe/esp/Virgin/components/freertos/freertos/queue.c
Line 736

Calling Task pmT

Task pmT is also in an Espressif binary blob

jhinklejr commented 6 years ago

Another Assert in your task "ppT"

RTOS Assert C:/msys32/home/Joe/esp/Virgin/components/freertos/freertos/queue.c
Line 1401

Calling Task ppT

This one is in:

BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait ) { BaseType_t xEntryTimeSet = pdFALSE; TimeOut_t xTimeOut; Queue_t const pxQueue = ( Queue_t ) xQueue;

if( configUSE_MUTEXES == 1 )

BaseType_t xInheritanceOccurred = pdFALSE;

endif

/* Check the queue pointer is not NULL. */
configASSERT( ( pxQueue ) );

/* Check this really is a semaphore, in which case the item size will be
0. */
configASSERT( pxQueue->uxItemSize == 0 );

/* Cannot block if the scheduler is suspended. */
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
{
    configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );   ***** this line asserts
}
#endif
donghengqaz commented 6 years ago

These are troubling legacies of history. We have been trying to fix them, but these associations are too many, so now we keep as they are, and just fix one by one carefully.

jhinklejr commented 6 years ago

In porting a new stack to replace lwip, I have created similar asserts to the ones I have identified above. I have figured out what was causing mine and thought I would share a few thoughts to help you when you decide to fix the bug.

Here is one of you asserts that occur all the time:

RTOS Assert C:/msys32/home/Joe/esp/esp8266_tcp/components/freertos/freertos/queue.c Line 1401 Called from Task ppT

Here is some code lines from queue.c -- for line 1401


BaseType_t xQueueSemaphoreTake( QueueHandle_t xQueue, TickType_t xTicksToWait ) { BaseType_t xEntryTimeSet = pdFALSE; TimeOut_t xTimeOut; Queue_t const pxQueue = ( Queue_t ) xQueue;

if( configUSE_MUTEXES == 1 )

BaseType_t xInheritanceOccurred = pdFALSE;

endif

/* Check the queue pointer is not NULL. */
configASSERT( ( pxQueue ) );

/* Check this really is a semaphore, in which case the item size will be
0. */
configASSERT( pxQueue->uxItemSize == 0 );

/* Cannot block if the scheduler is suspended. */
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
{
    configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
}
#endif

The specific assert is

    configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );

Espressif has made configUSE_TIMERS active which enables this line of code.

I have the assert occurs when "in a system callback" of some sort - there exists a xSemaphoreTake() with a delay specified.

In my case, I have replaced your est_printf() with my own that uses no heap and little stack. I use a semphore in my version to control thread access. I had placed a My_printf() in a callback from the get_dns() function. -- I removed the My_printf() from the callback by setting a flag and doing work outside the callback based on the flag.

I suggest you look for code with any callback that may directly contain a xSemaphoreTake() or functions called within (look into deep calls) that contains a xSemaphoreTake();

Just because you currently ignore the asserts by disabling them all together - it does not mean they are not causing problems that are not readily apparent.

Hope this info will help you

hongdakahasi commented 3 years ago

after call configASSERT how to release or start RTOS excution again?