I’m a first-timer in this forum, so please bear with me if I’m asking about something well known since years, or if this is the completely wrong place at all. I’d like to report a bug within one of the AVR demos that has the potential of exist in every port where the Tick counter is only 16 bits wide (configUSE_16_BIT_TICKS = 1).
Some days ago I started playing around with FreeRTOS on an Mega32 AVR and the AVR_ATMega323_WinAVR demo. After adapting the clock speed and remapping the LEDs from Port B (where the SPI interfase resides) to Port C, most of the tasks did run successfully. The 3-second check routine prvCheckOtherTasksAreStillRunning() however did fail due to xArePollingQueuesStillRunning() failing, because the activity counter xPollingConsumerCount didn’t change within the 3-second test interval. Instead, the consumer task is running only about once a minute.
Further testing showed that the producer task did run fine but experienced a Queue Full condition, a second proof that the consumer task didn’t run at the expected intervals.
Now, both tasks are calling vTaskDelay before looping again with parameters pollqPRODUCER_DELAY and pollqCONSUMER_DELAY, which are constants defined as follows:
#define pollqPRODUCER_DELAY ( pdMS_TO_TICKS( ( TickType_t ) 200 ) )
#define pollqCONSUMER_DELAY ( pollqPRODUCER_DELAY - ( TickType_t ) ( 20 / portTICK_PERIOD_MS ) )
#define portTICK_PERIOD_MS ((TickType_t) 1000 / configTICK_RATE_HZ )
#define pdMS_TO_TICKS(xTimeInMs) ((TickType_t) (((TickType_t) (xTimeInMs) * (TickType_t) configTICK_RATE_HZ) / (TickType_t) 1000U))
Therefore, the Producer task should run every 200 ms, the Consumer task should run every 200 - 20 = 180 ms.
Now, expanding the pollqCONSUMER_DELAY definition does the following 200 * 1000 / 1000 - 20 / 1.
Due to the casts, this is performed in 16bit math:
200 * 1000 mod 65536 = 3392
3392 / 1000 = 3
3 - 20 = -17
-17 in 16bits = 65536 - 17 = 65519
65519 Ticks to wait is just the initially observed “about a minute”.
Changing the definition of pdMS_TO_TICKS as follows resolves the 16 bit truncation error:
#define pdMS_TO_TICKS(xTimeInMs) ((TickType_t) (((uint32_t) (xTimeInMs) * configTICK_RATE_HZ) / 1000U))
Is this something already known to the maintainers of the demos? This part of the demo could have never run with this bug. Plus, as said above, this bug could potentially pop up in any implementation with Ticks being held in a 16bit variable.
Please excuse if this was a bit long-winded, but I wanted to provide a conclusive error analysis and solution. And if this is all old news, just feel free to delete this post completely.
Thanks,
– Thilo