Nice update Dave!
So,
using the hardware timer as Dave suggested looks like it works.
I have slightly changed Bianco's project and make FreeRTOS a module that will be started by the main XC file but I don't think that this can affect the project anyway.
However there are still the 21s problem
The FreeRTOS core is halting every 21 seconds. As I excpected, that is caused by a timer overflowing. The XMOS data sheets refer to timers being unsigned 32-bit, however the maximum time interval they can handle is 21.xxx secs (I would expect 42.xxx for a 32bit timer). After 21 seconds you can see $r2 (which holds the time for the next interrupt) having a negative value. This is something that the FreeRTOS doesn't not handle.
There is also another strange behaviour when FreeRTOS is running a single task. I have a single task toggling a led, with a vTaskDelay(500) sitting on top of it. The function does trigger every 500ms but the leds won't stay on for that period of time. I have to check that again though.
FreeRTOS
Timers have two modes: UNCOND and AFTER. In UNCOND
mode the timer is always ready; in AFTER mode it is ready
when (value-data) (computed in 32-bit two's complement,
wrap-around arithmetic) has the high bit clear. "data" is the
value you program with SETD, "value" is the current value
of the timer, ticking at the reference clock.
So yes, the maximum time before a timer becomes ready
is about 21s (with a 100MHz reference clock). If your RTOS
wants to provide bigger timeouts it should implement e.g. a
64-bit clock in software: if it wants to sleep more than N ticks,
sleep N ticks and repeat.
mode the timer is always ready; in AFTER mode it is ready
when (value-data) (computed in 32-bit two's complement,
wrap-around arithmetic) has the high bit clear. "data" is the
value you program with SETD, "value" is the current value
of the timer, ticking at the reference clock.
So yes, the maximum time before a timer becomes ready
is about 21s (with a 100MHz reference clock). If your RTOS
wants to provide bigger timeouts it should implement e.g. a
64-bit clock in software: if it wants to sleep more than N ticks,
sleep N ticks and repeat.
Let me rephrase that.
This is the body of the interrupt routine that Bianco provided with FreeRTOS.
tickclock is now a hardware timer as suggested earlier and next_int is just an unsigned int. What I understand is that the xTaskIncrementTick is called every timertick so it shouldn't matter if the timer wraps or not since that is not transparent to FreeRTOS (next_int is not used anywhere else but the assembler). However. FreeRTOS halts every 21s for 21s and I really try to figure out if that is something comming from the XMOS architecture or if it is a FreeRTOS bug.
Code: Select all
ldw r1, dp[tickclock] // get timer resource
ldw r2, dp[next_int] // get timer value of current interrupt
ldw r3, cp[timertick] // save value to add to the time at which the interrupt happened
add r2, r2, r3 // calculate the time for the next interrupt
setd res[r1], r2 // set up the timer value for the next interrupt
stw r2, dp[next_int] // store this value in next_int
kentsp 1 // switch over to kernel stack pointer, saving the current SP
bl xTaskIncrementTick // increment tick and check for expired delays
tickclock is now a hardware timer as suggested earlier and next_int is just an unsigned int. What I understand is that the xTaskIncrementTick is called every timertick so it shouldn't matter if the timer wraps or not since that is not transparent to FreeRTOS (next_int is not used anywhere else but the assembler). However. FreeRTOS halts every 21s for 21s and I really try to figure out if that is something comming from the XMOS architecture or if it is a FreeRTOS bug.