Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nickshl/DevCore.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Framework/AppTask.cpp')
-rw-r--r--Framework/AppTask.cpp274
1 files changed, 274 insertions, 0 deletions
diff --git a/Framework/AppTask.cpp b/Framework/AppTask.cpp
new file mode 100644
index 0000000..aeedc1f
--- /dev/null
+++ b/Framework/AppTask.cpp
@@ -0,0 +1,274 @@
+//******************************************************************************
+// @file AppTask.cpp
+// @author Nicolai Shlapunov
+//
+// @details DevCore: Application Task Base Class, implementation
+//
+// @copyright Copyright (c) 2016, Devtronic & Nicolai Shlapunov
+// All rights reserved.
+//
+// @section SUPPORT
+//
+// Devtronic invests time and resources providing this open source code,
+// please support Devtronic and open-source hardware/software by
+// donations and/or purchasing products from Devtronic.
+//
+//******************************************************************************
+
+// *****************************************************************************
+// *** Includes ************************************************************
+// *****************************************************************************
+#include "AppTask.h"
+#include "RtosMutex.h"
+
+// *****************************************************************************
+// *** Static variables ****************************************************
+// *****************************************************************************
+static RtosMutex startup_mutex;
+static uint32_t startup_cnt = 0U;
+
+// *****************************************************************************
+// *** Create task function ************************************************
+// *****************************************************************************
+void AppTask::CreateTask()
+{
+ Result result = Result::RESULT_OK;
+
+ // If interval timer period isn't zero or task queue present
+ if((timer.GetTimerPeriod() != 0U) || (task_queue.GetQueueLen() != 0U))
+ {
+ // Set Control Queue name
+ ctrl_queue.SetName(task_name, "Ctrl");
+ // Create control queue
+ result = ctrl_queue.Create();
+ }
+ // If task queue present
+ if(task_queue.GetQueueLen() != 0U)
+ {
+ // Set Task Queue name
+ task_queue.SetName(task_name, "Task");
+ // Create task queue
+ result |= task_queue.Create();
+ }
+ // If interval timer period isn't zero
+ if(timer.GetTimerPeriod() != 0U)
+ {
+ // Create timer
+ result |= timer.Create();
+ }
+ // Create task: function - TaskFunctionCallback(), parameter - pointer to "this"
+ result |= Rtos::TaskCreate(TaskFunctionCallback, task_name, stack_size, this, task_priority);
+
+ // Check result
+ if(result.IsBad())
+ {
+ // TODO: implement error handling
+ Break();
+ }
+}
+
+// *****************************************************************************
+// *** SendTaskMessage function ********************************************
+// *****************************************************************************
+Result AppTask::SendTaskMessage(const void* task_msg, bool is_priority)
+{
+ Result result = Result::RESULT_OK;
+
+ // Send task message to front or back of task queue
+ if(is_priority == true)
+ {
+ result = task_queue.SendToFront(task_msg);
+ }
+ else
+ {
+ result = task_queue.SendToBack(task_msg);
+ }
+
+ // If successful - send message to the control queue
+ if(result.IsGood())
+ {
+ CtrlQueueMsg ctrl_msg;
+ ctrl_msg.type = CTRL_TASK_QUEUE_MSG;
+ result = SendControlMessage(ctrl_msg, is_priority);
+ }
+
+ return result;
+}
+
+// *****************************************************************************
+// *** IntLoop function ****************************************************
+// *****************************************************************************
+Result AppTask::IntLoop()
+{
+ Result result = Result::RESULT_OK;
+
+ while(result.IsGood())
+ {
+ // Buffer for control message
+ CtrlQueueMsg ctrl_msg;
+ // Read on the control queue
+ result = ctrl_queue.Receive(&ctrl_msg, timer.GetTimerPeriod() * 2U);
+ // If successful
+ if(result.IsGood())
+ {
+ // Check message type
+ switch(ctrl_msg.type)
+ {
+ case CTRL_TIMER_MSG:
+ result = TimerExpired();
+ break;
+
+ case CTRL_TASK_QUEUE_MSG:
+ {
+ // Non blocking read from the task queue
+ result = task_queue.Receive(task_msg_ptr, 0U);
+ // If successful
+ if(result.IsGood())
+ {
+ // Process it!
+ result = ProcessMessage();
+ }
+ break;
+ }
+
+ default:
+ result = Result::ERR_INVALID_ITEM;
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
+// *****************************************************************************
+// *** TaskFunctionCallback ************************************************
+// *****************************************************************************
+void AppTask::TaskFunctionCallback(void* ptr)
+{
+ Result result = Result::ERR_NULL_PTR;
+
+ if(ptr != nullptr)
+ {
+ // Set good result
+ result = Result::RESULT_OK;
+ // Get reference to the task object
+ AppTask& app_task = *(static_cast<AppTask*>(ptr));
+
+ // Increment counter before call Setup()
+ ChangeCnt(true);
+ // Call virtual Setup() function from AppTask class
+ app_task.Setup();
+ // Decrement counter after call Setup()
+ ChangeCnt(false);
+ // Pause for give other tasks run Setup()
+ RtosTick::DelayTicks(1U);
+ // Pause while other tasks run Setup() before executing any Loop()
+ while(startup_cnt) RtosTick::DelayTicks(1U);
+
+ // If no timer or queue - just call Loop() function
+ if((app_task.timer.GetTimerPeriod() == 0U) && (app_task.task_queue.GetQueueLen() == 0U))
+ {
+ // Call virtual Loop() function from AppTask class
+ while(app_task.Loop() == Result::RESULT_OK);
+ }
+ else
+ {
+ // Start task timer if needed
+ if(app_task.timer.GetTimerPeriod() != 0U)
+ {
+ result = app_task.timer.Start();
+ }
+ // Check result
+ if(result.IsGood())
+ {
+ // Call internal AppTask function
+ result = app_task.IntLoop();
+ }
+ // Stop task timer if needed
+ if(app_task.timer.GetTimerPeriod() != 0U)
+ {
+ result |= app_task.timer.Stop();
+ }
+ }
+ }
+
+ // Check result
+ if(result.IsBad())
+ {
+ // TODO: implement error handling
+ Break();
+ }
+
+ // Delete task after exit
+ Rtos::TaskDelete();
+}
+
+// *****************************************************************************
+// *** TimerCallback function **********************************************
+// *****************************************************************************
+void AppTask::TimerCallback(void* ptr)
+{
+ Result result = Result::ERR_NULL_PTR;
+
+ if(ptr != nullptr)
+ {
+ // Get reference to the task object
+ AppTask& task = *((AppTask*)ptr);
+
+ // Create control timer message
+ CtrlQueueMsg timer_msg;
+ timer_msg.type = CTRL_TIMER_MSG;
+
+ // Send message to the control queue
+ result = task.SendControlMessage(timer_msg);
+ }
+
+ // Check result
+ if(result.IsBad())
+ {
+ // TODO: implement error handling
+ Break();
+ }
+}
+
+// *****************************************************************************
+// *** SendControlMessage function *****************************************
+// *****************************************************************************
+Result AppTask::SendControlMessage(const CtrlQueueMsg& ctrl_msg, bool is_priority)
+{
+ Result result;
+
+ if(is_priority == true)
+ {
+ result = ctrl_queue.SendToFront(&ctrl_msg);
+ }
+ else
+ {
+ result = ctrl_queue.SendToBack(&ctrl_msg);
+ }
+
+ return result;
+}
+
+// *****************************************************************************
+// *** Change counter ******************************************************
+// *****************************************************************************
+void AppTask::ChangeCnt(bool is_up)
+{
+ // Take semaphore before change counter
+ startup_mutex.Lock();
+ // Check direction
+ if(is_up == true)
+ {
+ // Increment counter
+ startup_cnt++;
+ }
+ else
+ {
+ // Decrement counter
+ startup_cnt--;
+ }
+ // Give semaphore after changes
+ startup_mutex.Release();
+}