diff --git a/libs/3rdparty/freeRtos/mock/include/os/FreeRtosMock.h b/libs/3rdparty/freeRtos/mock/include/os/FreeRtosMock.h index 64343ae75a..83d32c3d7f 100644 --- a/libs/3rdparty/freeRtos/mock/include/os/FreeRtosMock.h +++ b/libs/3rdparty/freeRtos/mock/include/os/FreeRtosMock.h @@ -23,7 +23,7 @@ namespace os MOCK_METHOD0(xTaskGetIdleTaskHandle, TaskHandle_t()); MOCK_METHOD3(xTaskNotify, void(TaskHandle_t taskHandle, uint32_t ulValue, eNotifyAction eAction)); MOCK_METHOD4(xTaskNotifyFromISR, void(TaskHandle_t taskHandle, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken)); - MOCK_METHOD4(xTaskNotifyWait, void(uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait)); + MOCK_METHOD4(xTaskNotifyWait, BaseType_t(uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait)); MOCK_METHOD0(vTaskStartScheduler, void()); MOCK_METHOD1(uxTaskGetTaskNumber, UBaseType_t(TaskHandle_t xTask)); MOCK_METHOD1(uxTaskGetStackHighWaterMark, BaseType_t(TaskHandle_t taskHandle)); diff --git a/libs/3rdparty/freeRtos/mock/include/task.h b/libs/3rdparty/freeRtos/mock/include/task.h index 4c99258ee2..dd5cf484ab 100644 --- a/libs/3rdparty/freeRtos/mock/include/task.h +++ b/libs/3rdparty/freeRtos/mock/include/task.h @@ -11,7 +11,7 @@ TaskHandle_t xTaskCreateStatic(TaskFunction_t pxTaskCode, const char * pcName, c void * pvParameters, UBaseType_t uxPriority, StackType_t * puxStackBuffer, StaticTask_t * pxTaskBuffer); void xTaskNotify(TaskHandle_t taskHandle, uint32_t ulValue, eNotifyAction eAction); void xTaskNotifyFromISR(TaskHandle_t taskHandle, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken); -void xTaskNotifyWait(uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait); +BaseType_t xTaskNotifyWait(uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait); const char* pcTaskGetName(TaskHandle_t taskHandle); BaseType_t uxTaskGetStackHighWaterMark(TaskHandle_t taskHandle); void vTaskStartScheduler(); diff --git a/libs/3rdparty/freeRtos/mock/src/os/FreeRtosMock.cpp b/libs/3rdparty/freeRtos/mock/src/os/FreeRtosMock.cpp index 282dbd928b..c0cf273581 100644 --- a/libs/3rdparty/freeRtos/mock/src/os/FreeRtosMock.cpp +++ b/libs/3rdparty/freeRtos/mock/src/os/FreeRtosMock.cpp @@ -45,14 +45,14 @@ xTaskNotifyFromISR( taskHandle, ulValue, eAction, pxHigherPriorityTaskWoken); } -void +BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t* pulNotificationValue, TickType_t xTicksToWait) { - FreeRtosMock::instance().xTaskNotifyWait( + return FreeRtosMock::instance().xTaskNotifyWait( ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait); } diff --git a/libs/bsw/asyncFreeRtos/include/async/FreeRtosAdapter.h b/libs/bsw/asyncFreeRtos/include/async/FreeRtosAdapter.h index fe7eb780be..4a16bb9f7c 100644 --- a/libs/bsw/asyncFreeRtos/include/async/FreeRtosAdapter.h +++ b/libs/bsw/asyncFreeRtos/include/async/FreeRtosAdapter.h @@ -237,7 +237,7 @@ class FreeRtosAdapter static void initTask(TaskInitializer& initializer); - static void initTask(ContextType context, char const* name, StaticTimer_t& timer); + static void initTask(ContextType context); static void TaskFunction(void* param); @@ -353,12 +353,12 @@ void FreeRtosAdapter::initTask(TaskInitializer& initializer) } else { - initTask(context, initializer._name, initializer._timer); + initTask(context); TaskContextType& taskContext = _taskContexts[static_cast(context)]; if (context == TASK_IDLE) { _idleTaskInitializer = &initializer; - taskContext.initTask(TASK_IDLE, initializer._taskFunction); + taskContext.initTask(TASK_IDLE, initializer._name, initializer._taskFunction); } else { @@ -374,11 +374,8 @@ void FreeRtosAdapter::initTask(TaskInitializer& initializer) } template -void FreeRtosAdapter::initTask( - ContextType const context, char const* const name, StaticTimer_t& timer) +void FreeRtosAdapter::initTask(ContextType const context) { - TaskContextType& taskContext = _taskContexts[static_cast(context)]; - taskContext.createTimer(timer, name); #ifndef ASYNC_TIMEOUTMANAGER2_DISABLE _timeoutManagers[static_cast(context)].init(context); #endif // ASYNC_TIMEOUTMANAGER2_DISABLE diff --git a/libs/bsw/asyncFreeRtos/include/async/TaskContext.h b/libs/bsw/asyncFreeRtos/include/async/TaskContext.h index 5c571aab6f..70cf5ce7d7 100644 --- a/libs/bsw/asyncFreeRtos/include/async/TaskContext.h +++ b/libs/bsw/asyncFreeRtos/include/async/TaskContext.h @@ -19,7 +19,6 @@ #include #include -#include namespace async { @@ -46,9 +45,10 @@ class TaskContext : public EventDispatcher<2U, LockType> /** * Initializes a task with a specified context and task function. * \param context The context associated with this task. + * \param name The name of this task. * \param taskFunction The function to execute in this task. */ - void initTask(ContextType context, TaskFunctionType taskFunction); + void initTask(ContextType context, char const* const name, TaskFunctionType taskFunction); /** * Sets the FreeRTOS task handle for this context. @@ -73,13 +73,6 @@ class TaskContext : public EventDispatcher<2U, LockType> StackType const& stack, TaskFunctionType taskFunction); - /** - * Creates a FreeRTOS timer. - * \param timer The static timer storage structure. - * \param name The name of the timer. - */ - void createTimer(StaticTimer_t& timer, char const* name); - char const* getName() const; TaskHandle_t getTaskHandle() const; @@ -129,12 +122,6 @@ class TaskContext : public EventDispatcher<2U, LockType> /// Dispatches events while runnable is executing. void dispatchWhileWork(); - /** - * Sets a timeout value in microseconds. - * \param timeInUs The timeout duration in microseconds. - */ - void setTimeout(uint32_t timeInUs); - /** * Retrieves the amount of unused stack space for a specified task. * \param taskHandle The handle of the task. @@ -152,29 +139,28 @@ class TaskContext : public EventDispatcher<2U, LockType> friend class EventPolicy, 0U>; friend class EventPolicy, 1U>; - void setEvents(EventMaskType eventMask); - EventMaskType waitEvents(); - EventMaskType peekEvents(); - -private: - using TimerType = ::timer::Timer; + using ExecuteEventPolicyType = EventPolicy, 0U>; + using TimerEventPolicyType = EventPolicy, 1U>; + using TimerType = ::timer::Timer; static EventMaskType const STOP_EVENT_MASK = static_cast( static_cast(1U) << static_cast(EVENT_COUNT)); static EventMaskType const WAIT_EVENT_MASK = (STOP_EVENT_MASK << 1U) - 1U; + void setEvents(EventMaskType eventMask); + EventMaskType waitEvents(); + EventMaskType peekEvents(); + void handleTimeout(); static void staticTaskFunction(void* param); - static void staticTimerFunction(TimerHandle_t handle); - RunnableExecutor, 0U>, LockType> - _runnableExecutor; + RunnableExecutor _runnableExecutor; TimerType _timer; - EventPolicy, 1U> _timerEventPolicy; + TimerEventPolicyType _timerEventPolicy; TaskFunctionType _taskFunction; TaskHandle_t _taskHandle; - TimerHandle_t _timerHandle; + char const* _name; ContextType _context; }; @@ -184,11 +170,10 @@ class TaskContext : public EventDispatcher<2U, LockType> template inline TaskContext::TaskContext() : _runnableExecutor(*this) -, _timer() , _timerEventPolicy(*this) , _taskFunction() , _taskHandle(nullptr) -, _timerHandle(nullptr) +, _name(nullptr) , _context(CONTEXT_INVALID) { _timerEventPolicy.setEventHandler( @@ -197,9 +182,11 @@ inline TaskContext::TaskContext() } template -void TaskContext::initTask(ContextType const context, TaskFunctionType const taskFunction) +void TaskContext::initTask( + ContextType const context, char const* const name, TaskFunctionType const taskFunction) { _context = context; + _name = name; _taskFunction = taskFunction; } @@ -219,6 +206,7 @@ void TaskContext::createTask( TaskFunctionType const taskFunction) { _context = context; + _name = name; _taskFunction = taskFunction.has_value() ? taskFunction : TaskFunctionType::template create<&TaskContext::defaultTaskFunction>(); @@ -232,17 +220,10 @@ void TaskContext::createTask( &task); } -template -void TaskContext::createTimer(StaticTimer_t& timer, char const* const name) -{ - _timerHandle = xTimerCreateStatic( - name, 1U, static_cast(pdFALSE), this, &staticTimerFunction, &timer); -} - template inline char const* TaskContext::getName() const { - return (_timerHandle != nullptr) ? pcTimerGetName(_timerHandle) : nullptr; + return _name; } template @@ -317,33 +298,35 @@ template inline EventMaskType TaskContext::waitEvents() { EventMaskType eventMask = 0U; - xTaskNotifyWait(0U, WAIT_EVENT_MASK, &eventMask, Binding::WAIT_EVENTS_TICK_COUNT); - return eventMask; + uint32_t ticks = Binding::WAIT_EVENTS_TICK_COUNT; + uint32_t nextDelta; + bool const hasDelta = _timer.getNextDelta(getSystemTimeUs32Bit(), nextDelta); + if (hasDelta) + { + ticks = static_cast((nextDelta + (Config::TICK_IN_US - 1U)) / Config::TICK_IN_US); + } + if (xTaskNotifyWait(0U, WAIT_EVENT_MASK, &eventMask, ticks) != 0) + { + return eventMask; + } + else if (hasDelta) + { + return TimerEventPolicyType::EVENT_MASK; + } + else + { + return 0U; + } } template inline EventMaskType TaskContext::peekEvents() { EventMaskType eventMask = 0U; - xTaskNotifyWait(0U, WAIT_EVENT_MASK, &eventMask, 0U); + (void)xTaskNotifyWait(0U, WAIT_EVENT_MASK, &eventMask, 0U); return eventMask; } -template -void TaskContext::setTimeout(uint32_t const timeInUs) -{ - if (timeInUs > 0U) - { - uint32_t const ticks - = static_cast((timeInUs + (Config::TICK_IN_US - 1U)) / Config::TICK_IN_US); - (void)xTimerChangePeriod(_timerHandle, ticks, 0U); - } - else - { - (void)_timerEventPolicy.setEvent(); - } -} - template void TaskContext::callTaskFunction() { @@ -364,7 +347,6 @@ void TaskContext::dispatch() template inline void TaskContext::stopDispatch() { - _runnableExecutor.shutdown(); setEvents(STOP_EVENT_MASK); } @@ -373,6 +355,7 @@ void TaskContext::dispatchWhileWork() { while (true) { + handleTimeout(); EventMaskType const eventMask = peekEvents(); if (eventMask != 0U) { @@ -402,11 +385,6 @@ template void TaskContext::handleTimeout() { while (_timer.processNextTimeout(getSystemTimeUs32Bit())) {} - uint32_t nextDelta; - if (_timer.getNextDelta(getSystemTimeUs32Bit(), nextDelta)) - { - setTimeout(nextDelta); - } } template @@ -416,13 +394,6 @@ void TaskContext::staticTaskFunction(void* const param) taskContext.callTaskFunction(); } -template -void TaskContext::staticTimerFunction(TimerHandle_t const handle) -{ - TaskContext& taskContext = *reinterpret_cast(pvTimerGetTimerID(handle)); - taskContext._timerEventPolicy.setEvent(); -} - } // namespace async #endif // GUARD_60674D25_51E0_4A73_8CD1_9C6C6138C877 diff --git a/libs/bsw/asyncFreeRtos/include/async/TaskInitializer.h b/libs/bsw/asyncFreeRtos/include/async/TaskInitializer.h index 6eebd05439..9784d94d98 100644 --- a/libs/bsw/asyncFreeRtos/include/async/TaskInitializer.h +++ b/libs/bsw/asyncFreeRtos/include/async/TaskInitializer.h @@ -50,7 +50,6 @@ struct TaskInitializer : public StaticRunnable> using TaskConfigType = typename AdapterType::TaskConfigType; using TaskFunctionType = typename AdapterType::TaskFunctionType; using TaskObjectType = StaticTask_t; - using TimerObjectType = StaticTimer_t; /** * Creates and initializes a task with the specified parameters. @@ -73,7 +72,6 @@ struct TaskInitializer : public StaticRunnable> ContextType context, char const* name, TaskObjectType& task, - TimerObjectType& timer, T& stack, TaskFunctionType taskFunction, TaskConfigType const& config); @@ -83,7 +81,6 @@ struct TaskInitializer : public StaticRunnable> ContextType context, char const* name, TaskObjectType& task, - TimerObjectType& timer, StackSliceType const& stack, TaskFunctionType taskFunction, TaskConfigType const& config); @@ -100,10 +97,6 @@ struct TaskInitializer : public StaticRunnable> /// Reference to the static task object. TaskObjectType& _task; - - /// Reference to the static timer object associated with the task. - TimerObjectType& _timer; - /// The name of the task. char const* _name; @@ -136,7 +129,6 @@ class TaskImpl using TaskConfigType = typename AdapterType::TaskConfigType; using TaskFunctionType = typename AdapterType::TaskFunctionType; using TaskObjectType = StaticTask_t; - using TimerObjectType = StaticTimer_t; TaskImpl(char const* name, TaskFunctionType taskFunction, TaskConfigType const& taskConfig); @@ -146,7 +138,6 @@ class TaskImpl private: Stack _stack; TaskObjectType _task; - TimerObjectType _timer; }; template @@ -158,7 +149,6 @@ class TaskImpl using TaskConfigType = typename AdapterType::TaskConfigType; using TaskFunctionType = typename AdapterType::TaskFunctionType; using TaskObjectType = StaticTask_t; - using TimerObjectType = StaticTimer_t; template TaskImpl( @@ -172,7 +162,6 @@ class TaskImpl private: TaskObjectType _task; - TimerObjectType _timer; }; template @@ -255,7 +244,6 @@ void TaskInitializer::create( ContextType const context, char const* const name, TaskObjectType& task, - TimerObjectType& timer, T& stack, TaskFunctionType const taskFunction, TaskConfigType const& config) @@ -264,8 +252,7 @@ void TaskInitializer::create( ::estd::memory::align(alignof(StackType_t), bytes); StackSliceType const stackSlice = bytes.template reinterpret_as(); estd_assert((stackSlice.size() * sizeof(StackType_t)) >= sizeof(TaskInitializer)); - new (stackSlice.data()) - TaskInitializer(context, name, task, timer, stackSlice, taskFunction, config); + new (stackSlice.data()) TaskInitializer(context, name, task, stackSlice, taskFunction, config); } template @@ -273,14 +260,12 @@ TaskInitializer::TaskInitializer( ContextType const context, char const* const name, TaskObjectType& task, - TimerObjectType& timer, StackSliceType const& stack, TaskFunctionType const taskFunction, TaskConfigType const& config) : _stack(stack) , _taskFunction(taskFunction) , _task(task) -, _timer(timer) , _name(name) , _context(context) , _config(config) @@ -296,8 +281,7 @@ template TaskImpl::TaskImpl( char const* const name, TaskFunctionType const taskFunction, TaskConfigType const& taskConfig) { - TaskInitializer::create( - Context, name, _task, _timer, _stack, taskFunction, taskConfig); + TaskInitializer::create(Context, name, _task, _stack, taskFunction, taskConfig); } template @@ -308,7 +292,7 @@ TaskImpl::TaskImpl( TaskFunctionType const taskFunction, TaskConfigType const& taskConfig) { - TaskInitializer::create(Context, name, _task, _timer, stack, taskFunction, taskConfig); + TaskInitializer::create(Context, name, _task, stack, taskFunction, taskConfig); } template diff --git a/libs/bsw/asyncFreeRtos/test/gtest/src/async/AsyncTest.cpp b/libs/bsw/asyncFreeRtos/test/gtest/src/async/AsyncTest.cpp index 69df090632..59adfccb41 100644 --- a/libs/bsw/asyncFreeRtos/test/gtest/src/async/AsyncTest.cpp +++ b/libs/bsw/asyncFreeRtos/test/gtest/src/async/AsyncTest.cpp @@ -62,7 +62,6 @@ TEST_F(AsyncTest, testExecuteAndScheduleCalls) xTaskCreateStatic( NotNull(), name, 256U / sizeof(StackType_t), NotNull(), 1U, NotNull(), NotNull())) .WillOnce(Return(&taskHandle)); - EXPECT_CALL(_freeRtosMock, xTimerCreateStatic(name, _, 0U, NotNull(), NotNull(), NotNull())); AdapterType::Task<1U, 256U> task(name); AdapterType::init(); { @@ -98,11 +97,7 @@ TEST_F(AsyncTest, testInitIdleTask) AdapterType::IdleTask<384U> idleTask( name, AdapterType::TaskFunctionType::create(*this)); { - uint32_t timerHandle = 13U; - EXPECT_CALL(_freeRtosMock, xTimerCreateStatic(name, _, 0U, NotNull(), NotNull(), NotNull())) - .WillOnce(Return(&timerHandle)); AdapterType::init(); - EXPECT_CALL(_freeRtosMock, pcTimerGetName(&timerHandle)).WillOnce(Return(name)); EXPECT_EQ(name, AdapterType::getTaskName(AdapterType::TASK_IDLE)); } { diff --git a/libs/bsw/asyncFreeRtos/test/gtest/src/async/FreeRtosAdapterTest.cpp b/libs/bsw/asyncFreeRtos/test/gtest/src/async/FreeRtosAdapterTest.cpp index b3eb4837c8..30b77bddf3 100644 --- a/libs/bsw/asyncFreeRtos/test/gtest/src/async/FreeRtosAdapterTest.cpp +++ b/libs/bsw/asyncFreeRtos/test/gtest/src/async/FreeRtosAdapterTest.cpp @@ -57,8 +57,6 @@ TEST_F(FreeRtosAdapterTest, testCreateTask) xTaskCreateStatic( NotNull(), name, 256U / sizeof(StackType_t), NotNull(), 1U, NotNull(), NotNull())) .WillOnce(Return(&taskHandle)); - EXPECT_CALL( - _freeRtosMock, xTimerCreateStatic(name, _, 0U, NotNull(), NotNull(), NotNull())); CutType::init(); } { @@ -68,19 +66,15 @@ TEST_F(FreeRtosAdapterTest, testCreateTask) CutType::TaskFunctionType:: create(*this)); - uint32_t taskHandle = 13U; - uint32_t timerHandle = 14U; + uint32_t taskHandle = 13U; EXPECT_CALL( _freeRtosMock, xTaskCreateStatic( NotNull(), name, 512U / sizeof(StackType_t), NotNull(), 2U, NotNull(), NotNull())) .WillOnce(Return(&taskHandle)); - EXPECT_CALL(_freeRtosMock, xTimerCreateStatic(name, _, 0U, NotNull(), NotNull(), NotNull())) - .WillOnce(Return(&timerHandle)); CutType::init(); { // Test get name - EXPECT_CALL(_freeRtosMock, pcTimerGetName(&timerHandle)).WillOnce(Return(name)); EXPECT_EQ(name, CutType::getTaskName(2U)); } } @@ -106,18 +100,14 @@ TEST_F(FreeRtosAdapterTest, testStackUsage) CutType::TaskFunctionType:: create(*this)); - uint32_t taskHandle = 13U; - uint32_t timerHandle = 14U; + uint32_t taskHandle = 13U; EXPECT_CALL( _freeRtosMock, xTaskCreateStatic( NotNull(), name, 128U / sizeof(StackType_t), NotNull(), 2U, NotNull(), NotNull())) .WillOnce(Return(&taskHandle)); - EXPECT_CALL(_freeRtosMock, xTimerCreateStatic(name, _, 0U, NotNull(), NotNull(), NotNull())) - .WillOnce(Return(&timerHandle)); CutType::init(); { - EXPECT_CALL(_freeRtosMock, pcTimerGetName(&timerHandle)).WillOnce(Return(name)); EXPECT_EQ(name, CutType::getTaskName(2U)); EXPECT_CALL(_freeRtosMock, uxTaskGetStackHighWaterMark(&taskHandle)) @@ -244,7 +234,6 @@ TEST_F(FreeRtosAdapterTest, testExecuteAndScheduleCalls) xTaskCreateStatic( NotNull(), name, 256U / sizeof(StackType_t), NotNull(), 1U, NotNull(), NotNull())) .WillOnce(Return(&taskHandle)); - EXPECT_CALL(_freeRtosMock, xTimerCreateStatic(name, _, 0U, NotNull(), NotNull(), NotNull())); CutType::init(); { EXPECT_CALL(_freeRtosMock, xTaskNotify(&taskHandle, _, eSetBits)); diff --git a/libs/bsw/asyncFreeRtos/test/gtest/src/async/TaskContextTest.cpp b/libs/bsw/asyncFreeRtos/test/gtest/src/async/TaskContextTest.cpp index 6d53e89127..5241d435d6 100644 --- a/libs/bsw/asyncFreeRtos/test/gtest/src/async/TaskContextTest.cpp +++ b/libs/bsw/asyncFreeRtos/test/gtest/src/async/TaskContextTest.cpp @@ -38,7 +38,7 @@ class TestBindingMock : public ::estd::singleton class TaskContextTest : public Test { public: - TaskContextTest() : _name("test"), _taskHandle(10U), _timerHandle(14U) {} + TaskContextTest() : _name("test"), _taskHandle(10U) {} protected: StrictMock<::os::FreeRtosMock> _freeRtosMock; @@ -53,12 +53,12 @@ class TaskContextTest : public Test StackType_t _stack[100]; char const* _name; uint32_t _taskHandle; - uint32_t _timerHandle; }; /** * \req: [BSW_ASFR_39], [BSW_ASFR_52], [BSW_ASFR_54], [BSW_ASFR_57] - * \refs: SMD_asyncFreeRtos_TaskContext, SMD_asyncFreeRtos_TaskContextEventHandling + * \refs: SMD_asyncFreeRtos_TaskContext, SMD_asyncFreeRtos_TaskContextEventHandling, + * SMD_asyncFreeRtos_TaskContextInitialization * \desc: To test task creation and execution */ TEST_F(TaskContextTest, testCreateAndRunTask) @@ -76,17 +76,18 @@ TEST_F(TaskContextTest, testCreateAndRunTask) EXPECT_TRUE(osTaskFunction != 0L); // expect notify wait Sequence seq; + EXPECT_CALL(_systemTimerMock, getSystemTimeUs32Bit()).WillRepeatedly(Return(100000U)); EXPECT_CALL( _freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), TestBindingMock::WAIT_EVENTS_TICK_COUNT)) .InSequence(seq) - .WillOnce(SetArgPointee<2>(0U)); + .WillOnce(DoAll(SetArgPointee<2>(0U), Return(false))); // second time do nothing again EXPECT_CALL( _freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), TestBindingMock::WAIT_EVENTS_TICK_COUNT)) .InSequence(seq) - .WillOnce(DoAll(SetArgPointee<2>(0U), StopDispatch(&cut))); + .WillOnce(DoAll(SetArgPointee<2>(0U), StopDispatch(&cut), Return(false))); // trigger shutdown on next iteration uint32_t eventMask = 0U; EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) @@ -98,7 +99,7 @@ TEST_F(TaskContextTest, testCreateAndRunTask) _freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), TestBindingMock::WAIT_EVENTS_TICK_COUNT)) .InSequence(seq) - .WillOnce(CopyArgPointee2(&eventMask)); + .WillOnce(DoAll(CopyArgPointee2(&eventMask), Return(true))); osTaskFunction(param); Mock::VerifyAndClearExpectations(&_freeRtosMock); } @@ -120,24 +121,6 @@ TEST_F(TaskContextTest, testCreateAndRunTask) } } -/** - * \refs: SMD_asyncFreeRtos_TaskContextInitialization - * \desc: To test timer creation - */ -TEST_F(TaskContextTest, testCreateTimer) -{ - TaskContext cut; - EXPECT_EQ(0L, cut.getName()); - StaticTimer_t timer; - char const* name = "test"; - uint32_t timerHandle = 12U; - EXPECT_CALL(_freeRtosMock, xTimerCreateStatic(name, 1U, 0U, NotNull(), NotNull(), &timer)) - .WillOnce(Return(&timerHandle)); - EXPECT_CALL(_freeRtosMock, pcTimerGetName(&timerHandle)).WillOnce(Return(name)); - cut.createTimer(timer, name); - EXPECT_EQ(name, cut.getName()); -} - /** * \req: [BSW_ASFR_51], [BSW_ASFR_52], [BSW_ASFR_53] * \refs: SMD_asyncFreeRtos_TaskContextAsyncApi @@ -146,9 +129,13 @@ TEST_F(TaskContextTest, testCreateTimer) TEST_F(TaskContextTest, testExecute) { TaskContext cut; + + EXPECT_CALL(_systemTimerMock, getSystemTimeUs32Bit()).WillRepeatedly(Return(100000U)); + + TaskFunction_t* osTaskFunction = 0L; EXPECT_CALL( _freeRtosMock, xTaskCreateStatic(NotNull(), _name, 100, NotNull(), 12U, _stack, &_task)) - .WillOnce(Return(&_taskHandle)); + .WillOnce(DoAll(SaveArg<0>(&osTaskFunction), Return(&_taskHandle))); cut.createTask(1U, _task, _name, 12U, _stack, TaskContext::TaskFunctionType()); { // from task context @@ -162,14 +149,29 @@ TEST_F(TaskContextTest, testExecute) Mock::VerifyAndClearExpectations(&_freeRtosMock); Sequence seq; - EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) + EXPECT_CALL( + _freeRtosMock, + xTaskNotifyWait(0U, 7U, NotNull(), TestBindingMock::WAIT_EVENTS_TICK_COUNT)) .InSequence(seq) - .WillOnce(SetArgPointee<2>(eventMask)); - EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) + .WillOnce(DoAll(SetArgPointee<2>(eventMask), Return(true))); + EXPECT_CALL( + _freeRtosMock, + xTaskNotifyWait(0U, 7U, NotNull(), TestBindingMock::WAIT_EVENTS_TICK_COUNT)) .InSequence(seq) - .WillOnce(SetArgPointee<2>(0U)); + .WillOnce(DoAll(SetArgPointee<2>(0U), StopDispatch(&cut), Return(false))); EXPECT_CALL(_runnableMock1, execute()); - cut.dispatchWhileWork(); + // trigger shutdown on next iteration + EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) + .WillOnce(Return(static_cast(0L))); + EXPECT_CALL(_freeRtosMock, xTaskNotify(&_taskHandle, _, eSetBits)) + .InSequence(seq) + .WillOnce(SaveArg<1>(&eventMask)); + EXPECT_CALL( + _freeRtosMock, + xTaskNotifyWait(0U, 7U, NotNull(), TestBindingMock::WAIT_EVENTS_TICK_COUNT)) + .InSequence(seq) + .WillOnce(DoAll(CopyArgPointee2(&eventMask), Return(true))); + osTaskFunction(&cut); Mock::VerifyAndClearExpectations(&_runnableMock1); } { @@ -186,38 +188,30 @@ TEST_F(TaskContextTest, testExecute) Mock::VerifyAndClearExpectations(&_freeRtosMock); Sequence seq; - EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) + EXPECT_CALL( + _freeRtosMock, + xTaskNotifyWait(0U, 7U, NotNull(), TestBindingMock::WAIT_EVENTS_TICK_COUNT)) .InSequence(seq) - .WillOnce(SetArgPointee<2>(eventMask)); - EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) + .WillOnce(DoAll(SetArgPointee<2>(eventMask), Return(true))); + EXPECT_CALL( + _freeRtosMock, + xTaskNotifyWait(0U, 7U, NotNull(), TestBindingMock::WAIT_EVENTS_TICK_COUNT)) .InSequence(seq) - .WillOnce(SetArgPointee<2>(0U)); + .WillOnce(DoAll(SetArgPointee<2>(0U), StopDispatch(&cut), Return(false))); EXPECT_CALL(_runnableMock1, execute()); - cut.dispatchWhileWork(); - Mock::VerifyAndClearExpectations(&_runnableMock1); - } -} - -/** - * \refs: SMD_asyncFreeRtos_TaskContextAsyncApi - * \desc: To test timeout functionality - */ -TEST_F(TaskContextTest, testSetTimeout) -{ - TaskContext cut; - EXPECT_CALL( - _freeRtosMock, xTaskCreateStatic(NotNull(), _name, 100, NotNull(), 12U, _stack, &_task)) - .WillOnce(Return(&_taskHandle)); - cut.createTask(1U, _task, _name, 12U, _stack, TaskContext::TaskFunctionType()); - { + // trigger shutdown on next iteration EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) .WillOnce(Return(static_cast(0L))); - uint32_t eventMask = 0U; - // set timeout may be called with 0 value and should immediately set event EXPECT_CALL(_freeRtosMock, xTaskNotify(&_taskHandle, _, eSetBits)) + .InSequence(seq) .WillOnce(SaveArg<1>(&eventMask)); - cut.setTimeout(0U); - EXPECT_TRUE(eventMask != 0U); + EXPECT_CALL( + _freeRtosMock, + xTaskNotifyWait(0U, 7U, NotNull(), TestBindingMock::WAIT_EVENTS_TICK_COUNT)) + .InSequence(seq) + .WillOnce(DoAll(CopyArgPointee2(&eventMask), Return(true))); + osTaskFunction(&cut); + Mock::VerifyAndClearExpectations(&_runnableMock1); } } @@ -229,44 +223,16 @@ TEST_F(TaskContextTest, testSetTimeout) TEST_F(TaskContextTest, testSchedule) { TaskContext cut; + TaskFunction_t* osTaskFunction = 0L; EXPECT_CALL( _freeRtosMock, xTaskCreateStatic(NotNull(), _name, 100, NotNull(), 12U, _stack, &_task)) - .WillOnce(Return(&_taskHandle)); + .WillOnce(DoAll(SaveArg<0>(&osTaskFunction), Return(&_taskHandle))); cut.createTask(1U, _task, _name, 12U, _stack, TaskContext::TaskFunctionType()); - void* timerId = 0L; - TimerCallbackFunction_t callbackFunction = 0L; - EXPECT_CALL(_freeRtosMock, xTimerCreateStatic(_name, 1U, 0U, _, NotNull(), &_timer)) - .WillOnce( - DoAll(SaveArg<3>(&timerId), SaveArg<4>(&callbackFunction), Return(&_timerHandle))); - cut.createTimer(_timer, _name); - // now trigger timer the first time - EXPECT_CALL(_freeRtosMock, pvTimerGetTimerID(&_timerHandle)).WillRepeatedly(Return(timerId)); - { - // expect task notify - uint32_t eventMask = 0U; - EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) - .WillOnce(Return(static_cast(0L))); - EXPECT_CALL(_freeRtosMock, xTaskNotify(&_taskHandle, _, eSetBits)) - .WillOnce(SaveArg<1>(&eventMask)); - callbackFunction(&_timerHandle); - // set timer EXPECT_CALL(_systemTimerMock, getSystemTimeUs32Bit()).WillRepeatedly(Return(100000U)); - // dispatch and expect system time. Nothing should happen - Sequence seq; - EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) - .InSequence(seq) - .WillOnce(SetArgPointee<2>(eventMask)); - EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) - .InSequence(seq) - .WillOnce(SetArgPointee<2>(0U)); - cut.dispatchWhileWork(); - } - - { // Schedule first timer. Expect task notify uint32_t eventMask = 0U; EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) @@ -280,50 +246,60 @@ TEST_F(TaskContextTest, testSchedule) // Schedule second timer (to elapse laster). No task notify expected cut.schedule(_runnableMock2, _timeout2, 151U, TimeUnit::MILLISECONDS); + // Cancel the second timer, nothing should happen. + cut.cancel(_timeout2); { - // timer expires too early - EXPECT_CALL(_systemTimerMock, getSystemTimeUs32Bit()).WillRepeatedly(Return(249000U)); + // an event with an active timer will lead to a different timeout + Sequence seq; + EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 1500U)) + .InSequence(seq) + .WillOnce(DoAll(SetArgPointee<2>(eventMask), Return(true))); + EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 1500U)) + .InSequence(seq) + .WillOnce(DoAll(SetArgPointee<2>(0U), StopDispatch(&cut), Return(false))); + // trigger shutdown on next iteration EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) .WillOnce(Return(static_cast(0L))); EXPECT_CALL(_freeRtosMock, xTaskNotify(&_taskHandle, _, eSetBits)) + .InSequence(seq) .WillOnce(SaveArg<1>(&eventMask)); - callbackFunction(&_timerHandle); - - // Cancel the second timer, nothing should happen. - cut.cancel(_timeout2); + EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 1500U)) + .InSequence(seq) + .WillOnce(DoAll(CopyArgPointee2(&eventMask), Return(true))); + osTaskFunction(&cut); + Mock::VerifyAndClearExpectations(&_systemTimerMock); + } + { + // some time has elapsed and OS timer expires a bit too early + // which leads to a new setup of the timer. + // The timer then elapses after second iteration + EXPECT_CALL(_systemTimerMock, getSystemTimeUs32Bit()) + .WillOnce(Return(249000U)) + .WillRepeatedly(Return(250000U)); Sequence seq; - EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) + EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 10U)) .InSequence(seq) - .WillOnce(SetArgPointee<2>(eventMask)); - EXPECT_CALL(_freeRtosMock, xTimerChangePeriod(&_timerHandle, 10U, 0U)); - EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) + .WillOnce(DoAll(SetArgPointee<2>(0), Return(false))); + EXPECT_CALL(_runnableMock1, execute()).InSequence(seq); + EXPECT_CALL( + _freeRtosMock, + xTaskNotifyWait(0U, 7U, NotNull(), TestBindingMock::WAIT_EVENTS_TICK_COUNT)) .InSequence(seq) - .WillOnce(SetArgPointee<2>(0U)); - cut.dispatchWhileWork(); - } - - { - // timer expires at correct time + .WillOnce(DoAll(SetArgPointee<2>(0U), StopDispatch(&cut), Return(false))); + // trigger shutdown on next iteration EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) .WillOnce(Return(static_cast(0L))); EXPECT_CALL(_freeRtosMock, xTaskNotify(&_taskHandle, _, eSetBits)) - .WillOnce(SaveArg<1>(&eventMask)); - callbackFunction(&_timerHandle); - - // Expect expired - EXPECT_CALL(_systemTimerMock, getSystemTimeUs32Bit()).WillRepeatedly(Return(250000U)); - - Sequence seq; - EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) .InSequence(seq) - .WillOnce(SetArgPointee<2>(eventMask)); - EXPECT_CALL(_runnableMock1, execute()); - EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) + .WillOnce(SaveArg<1>(&eventMask)); + EXPECT_CALL( + _freeRtosMock, + xTaskNotifyWait(0U, 7U, NotNull(), TestBindingMock::WAIT_EVENTS_TICK_COUNT)) .InSequence(seq) - .WillOnce(SetArgPointee<2>(0U)); - cut.dispatchWhileWork(); + .WillOnce(DoAll(CopyArgPointee2(&eventMask), Return(true))); + osTaskFunction(&cut); } } } @@ -335,125 +311,207 @@ TEST_F(TaskContextTest, testSchedule) TEST_F(TaskContextTest, testScheduleAtFixedRate) { TaskContext cut; + TaskFunction_t* osTaskFunction = 0L; EXPECT_CALL( _freeRtosMock, xTaskCreateStatic(NotNull(), _name, 100, NotNull(), 12U, _stack, &_task)) - .WillOnce(Return(&_taskHandle)); + .WillOnce(DoAll(SaveArg<0>(&osTaskFunction), Return(&_taskHandle))); cut.createTask(1U, _task, _name, 12U, _stack, TaskContext::TaskFunctionType()); - void* timerId = 0L; - TimerCallbackFunction_t callbackFunction = 0L; - EXPECT_CALL(_freeRtosMock, xTimerCreateStatic(_name, 1U, 0U, _, NotNull(), &_timer)) - .WillOnce( - DoAll(SaveArg<3>(&timerId), SaveArg<4>(&callbackFunction), Return(&_timerHandle))); - cut.createTimer(_timer, _name); - // now trigger timer the first time - EXPECT_CALL(_freeRtosMock, pvTimerGetTimerID(&_timerHandle)).WillRepeatedly(Return(timerId)); - { - // expect task notify - uint32_t eventMask = 0U; - EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) - .WillOnce(Return(static_cast(0L))); - EXPECT_CALL(_freeRtosMock, xTaskNotify(&_taskHandle, _, eSetBits)) - .WillOnce(SaveArg<1>(&eventMask)); - callbackFunction(&_timerHandle); - // set timer EXPECT_CALL(_systemTimerMock, getSystemTimeUs32Bit()).WillRepeatedly(Return(100000U)); - // dispatch and expect system time. Nothing should happen - Sequence seq; - EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) - .InSequence(seq) - .WillOnce(SetArgPointee<2>(eventMask)); - EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) - .InSequence(seq) - .WillOnce(SetArgPointee<2>(0U)); - cut.dispatchWhileWork(); - } - - { // Schedule first timer at fixed rate. Expect task notify uint32_t eventMask = 0U; EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) .WillOnce(Return(static_cast(0L))); EXPECT_CALL(_freeRtosMock, xTaskNotify(&_taskHandle, _, eSetBits)) .WillOnce(SaveArg<1>(&eventMask)); - cut.scheduleAtFixedRate(_runnableMock1, _timeout1, 10U, TimeUnit::MILLISECONDS); + cut.scheduleAtFixedRate(_runnableMock1, _timeout1, 20U, TimeUnit::MILLISECONDS); + + // Schedule second timer (to elapse laster). No task notify expected + cut.scheduleAtFixedRate(_runnableMock2, _timeout2, 151U, TimeUnit::MILLISECONDS); + // Cancel the second timer, nothing should happen. + cut.cancel(_timeout2); + Mock::VerifyAndClearExpectations(&_freeRtosMock); { - EXPECT_CALL(_freeRtosMock, pvTimerGetTimerID(&_timerHandle)) - .WillRepeatedly(Return(timerId)); // expect nothing if scheduled again cut.scheduleAtFixedRate(_runnableMock1, _timeout1, 10U, TimeUnit::MILLISECONDS); Mock::VerifyAndClearExpectations(&_freeRtosMock); } { - EXPECT_CALL(_freeRtosMock, pvTimerGetTimerID(&_timerHandle)) - .WillRepeatedly(Return(timerId)); + // the event is received and nothing should happen while no time is elapsed Sequence seq; - EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) + EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 200U)) + .InSequence(seq) + .WillOnce(DoAll(SetArgPointee<2>(eventMask), Return(true))); + EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 200U)) + .InSequence(seq) + .WillOnce(DoAll(SetArgPointee<2>(0U), StopDispatch(&cut), Return(false))); + // trigger shutdown on next iteration + EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) + .WillOnce(Return(static_cast(0L))); + EXPECT_CALL(_freeRtosMock, xTaskNotify(&_taskHandle, _, eSetBits)) .InSequence(seq) - .WillOnce(SetArgPointee<2>(eventMask)); - EXPECT_CALL(_freeRtosMock, xTimerChangePeriod(&_timerHandle, 100U, 0U)); - EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) + .WillOnce(SaveArg<1>(&eventMask)); + EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 200U)) .InSequence(seq) - .WillOnce(SetArgPointee<2>(0U)); - cut.dispatchWhileWork(); + .WillOnce(DoAll(CopyArgPointee2(&eventMask), Return(true))); + osTaskFunction(&cut); Mock::VerifyAndClearExpectations(&_freeRtosMock); } - { - EXPECT_CALL(_freeRtosMock, pvTimerGetTimerID(&_timerHandle)) - .WillRepeatedly(Return(timerId)); - // timer expires at correct time + // time has elapsed and the timer should expire and lead to the next iteration + // with the same timeout + EXPECT_CALL(_systemTimerMock, getSystemTimeUs32Bit()) + .WillOnce(Return(105000U)) + .WillOnce(Return(120000U)) + .WillOnce(Return(120000U)) + .WillOnce(Return(120000U)) + .WillRepeatedly(Return(140000U)); + + Sequence seq; + EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 150U)) + .InSequence(seq) + .WillOnce(DoAll(SetArgPointee<2>(0), Return(false))); + EXPECT_CALL(_runnableMock1, execute()).InSequence(seq); + EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 200U)) + .InSequence(seq) + .WillOnce(DoAll(SetArgPointee<2>(0), Return(false))); + EXPECT_CALL(_runnableMock1, execute()).InSequence(seq); + EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 200U)) + .InSequence(seq) + .WillOnce(DoAll(SetArgPointee<2>(0U), StopDispatch(&cut), Return(false))); + // trigger shutdown on next iteration EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) .WillOnce(Return(static_cast(0L))); EXPECT_CALL(_freeRtosMock, xTaskNotify(&_taskHandle, _, eSetBits)) + .InSequence(seq) .WillOnce(SaveArg<1>(&eventMask)); - callbackFunction(&_timerHandle); + EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 200U)) + .InSequence(seq) + .WillOnce(DoAll(CopyArgPointee2(&eventMask), Return(true))); + osTaskFunction(&cut); + } + } +} + +/** + * \refs: SMD_asyncFreeRtos_TaskContextAsyncApi + * \desc: To test task schedule at fixedrate functionality with multiple timers + */ +TEST_F(TaskContextTest, testScheduleAtFixedRateMultipleTimers) +{ + TaskContext cut; + TaskFunction_t* osTaskFunction = 0L; + EXPECT_CALL( + _freeRtosMock, xTaskCreateStatic(NotNull(), _name, 100, NotNull(), 12U, _stack, &_task)) + .WillOnce(DoAll(SaveArg<0>(&osTaskFunction), Return(&_taskHandle))); + cut.createTask(1U, _task, _name, 12U, _stack, TaskContext::TaskFunctionType()); + + { + // set timer + EXPECT_CALL(_systemTimerMock, getSystemTimeUs32Bit()).WillRepeatedly(Return(100000U)); - // Expect expired - EXPECT_CALL(_systemTimerMock, getSystemTimeUs32Bit()).WillRepeatedly(Return(110000U)); + // Schedule first timer at fixed rate. Expect task notify + uint32_t eventMask = 0U; + EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) + .WillOnce(Return(static_cast(0L))); + EXPECT_CALL(_freeRtosMock, xTaskNotify(&_taskHandle, _, eSetBits)) + .WillOnce(SaveArg<1>(&eventMask)); + cut.scheduleAtFixedRate(_runnableMock1, _timeout1, 20U, TimeUnit::MILLISECONDS); + Mock::VerifyAndClearExpectations(&_freeRtosMock); + // Schedule second timer at fixed rate. Expect task notify again because it changes the next + // timeout + EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) + .WillOnce(Return(static_cast(0L))); + EXPECT_CALL(_freeRtosMock, xTaskNotify(&_taskHandle, _, eSetBits)) + .WillOnce(SaveArg<1>(&eventMask)); + cut.scheduleAtFixedRate(_runnableMock2, _timeout2, 12U, TimeUnit::MILLISECONDS); + Mock::VerifyAndClearExpectations(&_freeRtosMock); + { + // the second timer should lead to the right expected timeout Sequence seq; - EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) + EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 120U)) + .InSequence(seq) + .WillOnce(DoAll(SetArgPointee<2>(eventMask), Return(true))); + EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 120U)) + .InSequence(seq) + .WillOnce(DoAll(SetArgPointee<2>(0U), StopDispatch(&cut), Return(true))); + // trigger shutdown on next iteration + EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) + .WillOnce(Return(static_cast(0L))); + EXPECT_CALL(_freeRtosMock, xTaskNotify(&_taskHandle, _, eSetBits)) .InSequence(seq) - .WillOnce(SetArgPointee<2>(eventMask)); - EXPECT_CALL(_runnableMock1, execute()); - EXPECT_CALL(_freeRtosMock, xTimerChangePeriod(&_timerHandle, 100U, 0U)); - EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) + .WillOnce(SaveArg<1>(&eventMask)); + EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 120U)) .InSequence(seq) - .WillOnce(SetArgPointee<2>(0U)); - cut.dispatchWhileWork(); + .WillOnce(DoAll(CopyArgPointee2(&eventMask), Return(true))); + osTaskFunction(&cut); + Mock::VerifyAndClearExpectations(&_freeRtosMock); } } } /** + * \req: [BSW_ASFR_51], [BSW_ASFR_52], [BSW_ASFR_53] * \refs: SMD_asyncFreeRtos_TaskContextAsyncApi - * \desc: To test task schedule at fixedrate functionality with multiple timers + * \desc: To test dispatchWhileWork function to finish on work done */ -TEST_F(TaskContextTest, testScheduleAtFixedRateMultipleTimers) +TEST_F(TaskContextTest, testDispatchWhileWork) { TaskContext cut; - void* timerId = 0L; + TaskFunction_t* osTaskFunction = 0L; + EXPECT_CALL( + _freeRtosMock, xTaskCreateStatic(NotNull(), _name, 100, NotNull(), 12U, _stack, &_task)) + .WillOnce(DoAll(SaveArg<0>(&osTaskFunction), Return(&_taskHandle))); + cut.createTask(1U, _task, _name, 12U, _stack, TaskContext::TaskFunctionType()); - // set timer - EXPECT_CALL(_systemTimerMock, getSystemTimeUs32Bit()).WillRepeatedly(Return(100000U)); + { + // set timer + EXPECT_CALL(_systemTimerMock, getSystemTimeUs32Bit()).WillOnce(Return(100000U)); - EXPECT_CALL(_freeRtosMock, pvTimerGetTimerID(&_timerHandle)).WillRepeatedly(Return(timerId)); - EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) - .WillOnce(Return(static_cast(0L))); - EXPECT_CALL(_freeRtosMock, xTaskNotify(_, _, eSetBits)).Times(1); - cut.scheduleAtFixedRate(_runnableMock1, _timeout1, 10U, TimeUnit::MILLISECONDS); - Mock::VerifyAndClearExpectations(&_freeRtosMock); + // Schedule timer at fixed rate. Expect task notify + uint32_t eventMask1 = 0U; + EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) + .WillOnce(Return(static_cast(0L))); + EXPECT_CALL(_freeRtosMock, xTaskNotify(&_taskHandle, _, eSetBits)) + .WillOnce(SaveArg<1>(&eventMask1)); + cut.schedule(_runnableMock1, _timeout1, 20U, TimeUnit::MILLISECONDS); + Mock::VerifyAndClearExpectations(&_freeRtosMock); + Mock::VerifyAndClearExpectations(&_systemTimerMock); - // another task that expires later - cut.scheduleAtFixedRate(_runnableMock2, _timeout2, 20U, TimeUnit::MILLISECONDS); - Mock::VerifyAndClearExpectations(&_freeRtosMock); + // Execute a task + uint32_t eventMask2 = 0U; + EXPECT_CALL(_bindingMock, getHigherPriorityTaskWokenFunc()) + .WillOnce(Return(static_cast(0L))); + EXPECT_CALL(_freeRtosMock, xTaskNotify(&_taskHandle, _, eSetBits)) + .WillOnce(SaveArg<1>(&eventMask2)); + cut.execute(_runnableMock2); + Mock::VerifyAndClearExpectations(&_bindingMock); + Mock::VerifyAndClearExpectations(&_freeRtosMock); + + // time is running during dispatch + EXPECT_CALL(_systemTimerMock, getSystemTimeUs32Bit()) + .WillOnce(Return(110000U)) + .WillOnce(Return(120000U)) + .WillOnce(Return(120010U)) + .WillOnce(Return(120020U)); + Sequence seq; + EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) + .InSequence(seq) + .WillOnce(DoAll(SetArgPointee<2>((eventMask1 | eventMask2)), Return(true))); + EXPECT_CALL(_runnableMock2, execute()).InSequence(seq); + EXPECT_CALL(_runnableMock1, execute()).InSequence(seq); + EXPECT_CALL(_freeRtosMock, xTaskNotifyWait(0U, 7U, NotNull(), 0U)) + .InSequence(seq) + .WillOnce(Return(false)); + cut.dispatchWhileWork(); + } } /** diff --git a/libs/bsw/asyncFreeRtos/test/gtest/src/async/TaskInitializerTest.cpp b/libs/bsw/asyncFreeRtos/test/gtest/src/async/TaskInitializerTest.cpp index 12d2f091eb..bf90f3a04b 100644 --- a/libs/bsw/asyncFreeRtos/test/gtest/src/async/TaskInitializerTest.cpp +++ b/libs/bsw/asyncFreeRtos/test/gtest/src/async/TaskInitializerTest.cpp @@ -17,7 +17,6 @@ struct AdapterMock : public ::estd::singleton using StackSliceType = ::estd::slice; using TaskFunctionType = ::estd::function; using TaskObjectType = uint32_t*; - using TimerObjectType = uint32_t*; using TaskConfigType = uint32_t; AdapterMock() : ::estd::singleton(*this) {} @@ -39,11 +38,10 @@ struct TaskInitializerData { Cut::StackSliceType _stack; Cut::TaskFunctionType _taskFunction; - Cut::TaskObjectType* _task = nullptr; - Cut::TimerObjectType* _timer = nullptr; - char const* _name = nullptr; - ContextType _context = CONTEXT_INVALID; - Cut::TaskConfigType _config = 0U; + Cut::TaskObjectType* _task = nullptr; + char const* _name = nullptr; + ContextType _context = CONTEXT_INVALID; + Cut::TaskConfigType _config = 0U; }; struct TaskInitializerTest : public Test @@ -61,7 +59,6 @@ ACTION_P(CopyTaskInitializerData, dest) dest->_stack = arg0._stack; dest->_taskFunction = arg0._taskFunction; dest->_task = &arg0._task; - dest->_timer = &arg0._timer; dest->_name = arg0._name; dest->_context = arg0._context; dest->_config = arg0._config; @@ -85,7 +82,6 @@ TEST_F(TaskInitializerTest, testIdleTask) EXPECT_EQ(256, data._stack.size() * sizeof(StackType_t)); EXPECT_EQ(_taskFunction, data._taskFunction); EXPECT_TRUE(data._task != nullptr); - EXPECT_TRUE(data._timer != nullptr); EXPECT_EQ(ContextType(AdapterMock::TASK_IDLE), data._context); EXPECT_EQ(7U, data._config); Mock::VerifyAndClearExpectations(&_adapterMock); @@ -104,7 +100,6 @@ TEST_F(TaskInitializerTest, testIdleTask) EXPECT_EQ(sizeof(stack), data._stack.size() * sizeof(StackType_t)); EXPECT_EQ(_taskFunction, data._taskFunction); EXPECT_TRUE(data._task != nullptr); - EXPECT_TRUE(data._timer != nullptr); EXPECT_EQ(ContextType(AdapterMock::TASK_IDLE), data._context); EXPECT_EQ(7U, data._config); Mock::VerifyAndClearExpectations(&_adapterMock); @@ -129,7 +124,6 @@ TEST_F(TaskInitializerTest, testTimerTask) EXPECT_EQ(512, data._stack.size() * sizeof(StackType_t)); EXPECT_EQ(AdapterMock::TaskFunctionType(), data._taskFunction); EXPECT_TRUE(data._task != nullptr); - EXPECT_TRUE(data._timer != nullptr); EXPECT_EQ(ContextType(AdapterMock::TASK_TIMER), data._context); EXPECT_EQ(9U, data._config); Mock::VerifyAndClearExpectations(&_adapterMock); @@ -148,7 +142,6 @@ TEST_F(TaskInitializerTest, testTimerTask) EXPECT_EQ(sizeof(stack), data._stack.size() * sizeof(StackType_t)); EXPECT_EQ(AdapterMock::TaskFunctionType(), data._taskFunction); EXPECT_TRUE(data._task != nullptr); - EXPECT_TRUE(data._timer != nullptr); EXPECT_EQ(ContextType(AdapterMock::TASK_TIMER), data._context); EXPECT_EQ(8U, data._config); Mock::VerifyAndClearExpectations(&_adapterMock); @@ -173,7 +166,6 @@ TEST_F(TaskInitializerTest, testTask) EXPECT_EQ(512, data._stack.size() * sizeof(StackType_t)); EXPECT_EQ(AdapterMock::TaskFunctionType(), data._taskFunction); EXPECT_TRUE(data._task != nullptr); - EXPECT_TRUE(data._timer != nullptr); EXPECT_EQ(5U, data._context); EXPECT_EQ(9U, data._config); Mock::VerifyAndClearExpectations(&_adapterMock); @@ -192,7 +184,6 @@ TEST_F(TaskInitializerTest, testTask) EXPECT_EQ(sizeof(stack), data._stack.size() * sizeof(StackType_t)); EXPECT_EQ(AdapterMock::TaskFunctionType(), data._taskFunction); EXPECT_TRUE(data._task != nullptr); - EXPECT_TRUE(data._timer != nullptr); EXPECT_EQ(6U, data._context); EXPECT_EQ(8U, data._config); Mock::VerifyAndClearExpectations(&_adapterMock); @@ -209,7 +200,6 @@ TEST_F(TaskInitializerTest, testTask) EXPECT_EQ(512, data._stack.size() * sizeof(StackType_t)); EXPECT_EQ(_taskFunction, data._taskFunction); EXPECT_TRUE(data._task != nullptr); - EXPECT_TRUE(data._timer != nullptr); EXPECT_EQ(5U, data._context); EXPECT_EQ(9U, data._config); Mock::VerifyAndClearExpectations(&_adapterMock); @@ -228,7 +218,6 @@ TEST_F(TaskInitializerTest, testTask) EXPECT_EQ(sizeof(stack), data._stack.size() * sizeof(StackType_t)); EXPECT_EQ(_taskFunction, data._taskFunction); EXPECT_TRUE(data._task != nullptr); - EXPECT_TRUE(data._timer != nullptr); EXPECT_EQ(6U, data._context); EXPECT_EQ(8U, data._config); Mock::VerifyAndClearExpectations(&_adapterMock); diff --git a/libs/bsw/asyncImpl/include/async/EventPolicy.h b/libs/bsw/asyncImpl/include/async/EventPolicy.h index 16823eaabb..bc37837d37 100644 --- a/libs/bsw/asyncImpl/include/async/EventPolicy.h +++ b/libs/bsw/asyncImpl/include/async/EventPolicy.h @@ -24,6 +24,8 @@ class EventPolicy using EventDispatcherType = EventDispatcher; using HandlerFunctionType = typename EventDispatcher::HandlerFunctionType; + static EventMaskType const EVENT_MASK = static_cast(1U << Event); + explicit EventPolicy(EventDispatcher& eventDispatcher); void setEventHandler(HandlerFunctionType handlerFunction); @@ -32,8 +34,6 @@ class EventPolicy void setEvent(); private: - static EventMaskType const _eventMask = static_cast(1U << Event); - EventDispatcher& _eventDispatcher; }; @@ -61,7 +61,7 @@ inline void EventPolicy::removeEventHandler() template inline void EventPolicy::setEvent() { - _eventDispatcher.setEvents(_eventMask); + _eventDispatcher.setEvents(EVENT_MASK); } } // namespace async