FreeRTOS Multiple Timer Issue

deac3 wrote on Wednesday, March 01, 2017:

Hi All,

I’m creating and starting 9 timers as part of a constructor for my class. I am creating 4 instances of this class and it looks like only the timers for the first couple are running. My constructor is as follows:

SDM220( int mod_id )
        {
            this->meter_id = mod_id;
            printf("SDM220 #%d\n", this->meter_id );
            
            // begin all the timers
            for( int i = 0; i < NUM_TIMERS; i++ )
            {
                // configure a token for timer i 
                my_tokens[ i ].meter_id = mod_id;
                my_tokens[ i ].read_type = sdm_sensor_configs[ i ].identifier;
                my_tokens[ i ].config_idx = i;

                void* token_ptr = &my_tokens[ i ];

                // create and start timer i
                xTimers[ i ] = xTimerCreate(    "sdm_timer",                                                // text name of timer, store tag?
                                                sdm_sensor_configs[ i ].sensor_delay / portTICK_PERIOD_MS,  // timer interval
                                                pdTRUE,                                                     // reset timer?
                                                token_ptr,                                                  // timer id, in this case token object
                                                this->vTimerCallback );                                     // timer callback function

                if( xTimers[ i ] != NULL )
                {
                    if( xTimerStart( xTimers[ i ], 0 ) != pdPASS )
                        {
                            printf( "timer not activated\n" );
                        }
                }
                else
                {
                    printf( "sdm220 constructor goofed\n" );
                }
            }

            // create recipient queue for all the meters
            xSDMQueue = xQueueCreate( 10, sizeof( sdm_read_token ) );
        }

None of the xTimerStart() != pdPASS checks fail, but the timers for the later declared instances do not trigger.

For example if i declare the objects like this

// instantiate sdm meters
struct SDM220 my_sdm_1( 1 );
struct SDM220 my_sdm_2( 2 );
struct SDM220 my_sdm_3( 3 );
struct SDM220 my_sdm_4( 4 ); 

Then events for 1 and 2 come through fine, but 3 is spotty and 4 is nonexistent.

If I declare them like this:

// instantiate sdm meters
struct SDM220 my_sdm_2( 2 );
struct SDM220 my_sdm_3( 3 );
struct SDM220 my_sdm_4( 4 ); 
struct SDM220 my_sdm_1( 1 );

Then 2 and 3 come through fine, 4 is spotty, and 1 is nonexistent.

I thought it might be a stack issue on the timer service task but I increased the stack in FreeRTOSconfig.h and it remained unused! Any advice would be much appreciated!

rtel wrote on Wednesday, March 01, 2017:

I’m not sure what the problem could be if xTimers[ i ] is never being
set to NULL within the loop.

Do you have configASSERT() defined?
What is configTIMER_QUEUE_LENGTH set to?
Are the constructors called before the scheduler is started?

deac3 wrote on Wednesday, March 01, 2017:

Thanks for the quick reply!

I am using the esp32 port of freeRTOS in the esp-idf. Looks like it is defined here


#if defined(CONFIG_FREERTOS_ASSERT_DISABLE)
#define configASSERT(a) /* assertions disabled */
#elif defined(CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE)
#define configASSERT(a) if (!(a)) {                                     \
        ets_printf("%s:%d (%s)- assert failed!\n", __FILE__, __LINE__,  \
                   __FUNCTION__);                                       \
    }
#else /* CONFIG_FREERTOS_ASSERT_FAIL_ABORT */
#define configASSERT(a) if (!(a)) {                                     \
        ets_printf("%s:%d (%s)- assert failed!\n", __FILE__, __LINE__,  \
                   __FUNCTION__);                                       \
        abort();                                                        \
        }
#endif

configTIMER_QUEUE_LENGTH was originally 10, I bumped it up to 200.

Yes the constructors are called before the RTOS scheduler. I had the timeout for xTimerStart() at 1000 for a bit, but learned that it doesnt matter if its called before the scheduler starts.

I am not sure what you mean about xTimers[ i ] being set to NULL

rtel wrote on Wednesday, March 01, 2017:

I am using the esp32 port of freeRTOS in the esp-idf. Looks like it is
defined here

#if defined(CONFIG_FREERTOS_ASSERT_DISABLE)

I should double check which of these is actually being compiled in.

configTIMER_QUEUE_LENGTH was originally 10, I bumped it up to 200.

Yes the constructors are called before the RTOS scheduler. I had the
timeout for xTimerStart() at 1000 for a bit, but learned that it doesnt
matter if its called before the scheduler starts.

When a timer is started a command is sent to the timer command queue.
If the scheduler is not started then the command will sit in the command
queue until the scheduler is started - which is why I was asking how
long the queue was.

In your case, all the start commands should be in the timer command
queue when the timer task is started.

Open the file FreeRTOS/source/timers.c, and find the line

static void prvTimerTask( void *pvParameters )

which is on line 544 in my current version of the file, but will no
doubt be different in yours. Put a breakpoint on that line. It will
get hit when the timer task starts. When the break point is hit inspect
the xTimerQueue variable. You may need to cast it in the debugger to
something like:

( xQUEUE ) xTimerQueue

otherwise the debugger might just see it as a void * and not show you
its internals.

In the debugger you should be able to see the number of items in the
queue. Does it look reasonable for the number of timers you started?

I am not sure what you mean about xTimers[ i ] being set to NULL

You said (if I recall correctly) that the line xTimers[ i ] =
xTimerCreate( … ) never returns NULL, which indicates the timer is
being created.