Hi,
I am using FreeRTOS in a c++ project, where I have a c++ wrapper on top of the functions i use in FreeRTOS so that I can mock FreeRTOS in unit tests.
E.g. this is how I create a thread
void thread::start(
size_t stack_size,
size_t priority,
const char * name,
thread_delegate run,
void * parameter)
{
project_assert(is_idle() , error_code_thread_already_running);
_state = thread_state::running;
_parameter = parameter;
_delegate = run;
xTaskCreate(
task_callback,
name,
stack_size,
this,
priority,
&_handle);
}
Where the mocked method is as simple as
MOCK_METHOD((void), start, (size_t, size_t, const char *, thread_delegate, void *), (override));
The beauty here is, that the FreeRTOS callback for a task, provides the argument I passed as void *. I can smash my c++ object in there, and cast it back when FreeRTOS calls the callback.
The Timer looks similar, but instead of an argument I can pass a void * timerID
. The problem I have, is that the timer id is not passed with the callback. I need to retrieve it through a pvTimerGetTimerID
. And that is exactly what i need to mock out.
Maybe a code example makes it somewhat more clear
_timer = _free_rtos.timer_create("VMC Sim", pdMS_TO_TICKS(1000), true, this, [](TimerHandle_t timer)
{
// Since C does not support capturing lambdas, I can't capture the _free_rtos interface here
// I also can't call the pvTimerGetTimerID function, because FreeRTOS is not compiled in unit tests
auto simulator = static_cast<vending_machine_simulator*>(gameover);
simulator->run_state_machine();
});
What would be brilliant for my case, is if the callback would also pass along the timer id (like the callback of a Task does with the parameter argument). Then I would be able to do this
_timer = _free_rtos.timer_create("VMC Sim", pdMS_TO_TICKS(1000), true, this, [](TimerHandle_t timer, void * pvTimerID)
{
auto simulator = static_cast<vending_machine_simulator*>(pvTimerID);
simulator->run_state_machine();
});
So I added this myself in FreeRTOS
from:
typedef void (* TimerCallbackFunction_t)( TimerHandle_t xTimer );
to:
typedef void (* TimerCallbackFunction_t)( TimerHandle_t xTimer, void * pvTimerID );
, but that is kind of annoying, because now the next time I upgrade FreeRTOS I need to manually merge this.
Can you follow this story?
Am I making a mistake in the train of thoughts?
Can you think of an easier work around?
Would it be a problem to extend FreeRTOS with another timer callback which does fit better in C++ projejcts with the need to mock out FreeRTOS?