diff --git a/.cproject b/.cproject
index 97a996a..528a81e 100644
--- a/.cproject
+++ b/.cproject
@@ -54,6 +54,7 @@
+
@@ -77,6 +78,7 @@
+
@@ -100,10 +102,11 @@
-
-
+
+
+
@@ -197,10 +200,10 @@
-
-
+
+
@@ -228,4 +231,5 @@
+
\ No newline at end of file
diff --git a/App/Inc/sta/config.hpp b/App/Inc/sta/config.hpp
index 9db0927..f132634 100644
--- a/App/Inc/sta/config.hpp
+++ b/App/Inc/sta/config.hpp
@@ -27,4 +27,9 @@
#define STA_RTOS_SYSTEM_WATCHDOG_ENABLE
#define STA_RTOS_WATCHDOG_ENABLE
+
+// Settings for TACOS
+#define STA_TACOS_MANAGER_PRIORITY osPriorityNormal
+#define STA_TACOS_NUM_STATES 4
+
#endif /* INC_STA_CONFIG_HPP_ */
diff --git a/App/Inc/tasks/statemachine.hpp b/App/Inc/tasks/statemachine.hpp
index e045353..0adc089 100644
--- a/App/Inc/tasks/statemachine.hpp
+++ b/App/Inc/tasks/statemachine.hpp
@@ -29,4 +29,17 @@ enum tacos_states_t
};
+namespace tacos
+{
+ class StateMachine
+ {
+ public:
+
+
+ private:
+
+ };
+}
+
+
#endif /* INC_TASKS_STATEMACHINE_HPP_ */
diff --git a/App/Src/tasks/manager.cpp b/App/Src/tasks/manager.cpp
index 868f51b..8a286b0 100644
--- a/App/Src/tasks/manager.cpp
+++ b/App/Src/tasks/manager.cpp
@@ -6,42 +6,70 @@
*/
+#include
+#include
+
#include
#include
#include
#include
-#include
-#include
+
#include
+#include
-#define STATE_CHANGED_MSK 0x01
-#define STATE_CHANGED_TIMOUT_MSK 0x02
-// The state changed event defined somewhere else.
-extern osEventFlagsId_t stateChangeEvent_id;
+namespace tacos
+{
+
+ // The data structure representing a TACOS task.
+ struct tacos_task_t
+ {
+ // The code to be executed for this task.
+ osThreadFunc_t func;
+
+ // The attributes for the task.
+ osThreadAttr_t attribs;
+
+ // A list of currently running instances of this task.
+ std::list running;
+
+ // A list of states for which this task should be running.
+ std::list states;
+ };
+
+
+} // namespace tacos
+
// The current state defined somewhere else.
extern tacos_states_t currentState;
-// The data structure representing a TACOS task.
-struct tacos_task_t
+extern "C"
{
- // The code to be executed for this task.
- osThreadFunc_t func;
+ void managerTask(void *)
+ {
+ STA_DEBUG_PRINTLN("INITIALIZED MANAGER TASK");
+
+ while (true)
+ {
+ // Wait until the state machine triggers an event signaling a state-change.
+ uint32_t flags = osEventFlagsWait(stateChangeEvent_id, STATE_CHANGED_MSK, osFlagsWaitAll, osWaitForever);
+
+
+ }
+ }
+}
+
+
+
+
- // The attributes for the task.
- osThreadAttr_t attribs;
- // A list of currently running instances of this task.
- std::list running;
- // A list of states for which this task should be running.
- std::list states;
-};
std::list tasks;
@@ -111,12 +139,12 @@ extern "C" void startManagerTask(void *)
{
if (!task.running.empty())
{
- osThreadCreate(thread_def, argument);
+ osThreadDef (task.attribs.name, task.attribs.priority, 1, 0);
+
+ osThreadCreate(osTh, argument);
}
}
}
-
- STA_DEBUG_PRINTLN("STARTING NEW TASKS DUE TO STATE CHANGE!");
}
osThreadExit();
diff --git a/App/Src/tasks/statemachine.cpp b/App/Src/tasks/statemachine.cpp
index e3326bb..e06e9c4 100644
--- a/App/Src/tasks/statemachine.cpp
+++ b/App/Src/tasks/statemachine.cpp
@@ -46,8 +46,8 @@ void changeState(uint8_t flag)
osEventFlagsSet(stateChangeEvent_id, flag);
osEventFlagsClear(stateChangeEvent_id, TACOS_STATE_CHG_ALL);
- uint8_t lockoutCycles = 0;
- uint8_t failsafeCycles = 0;
+ uint32_t lockoutCycles = 0;
+ uint32_t failsafeCycles = 0;
switch (currentState) {
case tacos_states_t::init:
diff --git a/Tacos/include/sta/tacos/manager.hpp b/Tacos/include/sta/tacos/manager.hpp
new file mode 100644
index 0000000..3de94c7
--- /dev/null
+++ b/Tacos/include/sta/tacos/manager.hpp
@@ -0,0 +1,86 @@
+/*
+ * manager.hpp
+ *
+ * Created on: Sep 19, 2023
+ * Author: Dario
+ */
+
+#ifndef INCLUDE_STA_TACOS_MANAGER_HPP_
+#define INCLUDE_STA_TACOS_MANAGER_HPP_
+
+
+#include
+
+#ifndef STA_TACOS_MANAGER_PRIORITY
+# error "Manger task priority not specified in config.hpp"
+#else
+
+#include
+#include
+#include
+
+namespace sta
+{
+ namespace tacos
+ {
+ class Manager : public TacosThread
+ {
+ public:
+ static Manager* instance()
+ {
+ static CGuard g;
+
+ if (!_instance)
+ {
+ // Create a the manager singleton instance.
+ Manager::_instance = new Manager();
+
+ // Start the manager task as a tacos task.
+ Manager::_instance->start();
+ }
+
+ return _instance;
+ }
+
+ void registerThread(TacosThread thread, std::list states);
+
+ void init() override;
+
+ void func() override;
+
+ private:
+ class CGuard
+ {
+ public:
+ ~CGuard()
+ {
+ if( NULL != Manager::_instance )
+ {
+ delete Manager::_instance;
+ Manager::_instance = NULL;
+ }
+ }
+ };
+
+ static Manager* _instance;
+
+ Manager();
+
+ Manager(const Manager&);
+
+ ~Manager() {}
+
+ void updateThreads();
+
+ void startThreads(uint16_t state);
+
+ void stopThreads(uint16_t state);
+
+ std::set threads_[STA_TACOS_NUM_STATES];
+ };
+ } // namespace tacos
+} // namespace sta
+
+#endif // STA_TACOS_MANAGER_PRIORITY
+
+#endif /* INCLUDE_STA_TACOS_MANAGER_HPP_ */
diff --git a/Tacos/include/sta/tacos/startup.hpp b/Tacos/include/sta/tacos/startup.hpp
new file mode 100644
index 0000000..f108f85
--- /dev/null
+++ b/Tacos/include/sta/tacos/startup.hpp
@@ -0,0 +1,31 @@
+/*
+ * startup.hpp
+ *
+ * Created on: 22 Sep 2023
+ * Author: Dario
+ */
+
+#ifndef INCLUDE_STA_TACOS_STARTUP_HPP_
+#define INCLUDE_STA_TACOS_STARTUP_HPP_
+
+namespace sta
+{
+ namespace tacos
+ {
+ /**
+ * @brief Function that is called before the statemachine task is started.
+ * Override it to adjust the statemachine to your specifications.
+ */
+ void onStatemachineInit();
+
+ /**
+ * @brief Function that is called before the manager task is started.
+ * Override it to adjust the manager to your specifications.
+ */
+ void onManagerInit();
+ } // namespace tacos
+} // namespace sta
+
+
+
+#endif /* INCLUDE_STA_TACOS_STARTUP_HPP_ */
diff --git a/Tacos/include/sta/tacos/statemachine.hpp b/Tacos/include/sta/tacos/statemachine.hpp
new file mode 100644
index 0000000..363776b
--- /dev/null
+++ b/Tacos/include/sta/tacos/statemachine.hpp
@@ -0,0 +1,73 @@
+/*
+ * statemachine.hpp
+ *
+ * Created on: Sep 14, 2023
+ * Author: Dario
+ */
+
+#ifndef INCLUDE_TACOS_STATEMACHINE_HPP_
+#define INCLUDE_TACOS_STATEMACHINE_HPP_
+
+#include
+
+#include
+
+namespace sta
+{
+ namespace tacos
+ {
+ class Statemachine : public TacosThread
+ {
+ public:
+ static Statemachine* instance()
+ {
+ static CGuard g;
+
+ if (!_instance)
+ {
+ // Create a the manager singleton instance.
+ Statemachine::_instance = new Statemachine();
+
+ // Start the manager task as a tacos task.
+ Statemachine::_instance->start();
+ }
+
+ return _instance;
+ }
+
+ void init() override;
+
+ void func() override;
+
+ uint16_t getCurrentState();
+
+ private:
+ class CGuard
+ {
+ public:
+ ~CGuard()
+ {
+ if( NULL != Statemachine::_instance )
+ {
+ delete Statemachine::_instance;
+ Statemachine::_instance = NULL;
+ }
+ }
+ };
+
+ Statemachine();
+
+ Statemachine(const Statemachine&);
+
+ ~Statemachine() {}
+
+ static Statemachine * _instance;
+
+ uint16_t currentState_;
+ };
+ } // namespace tacos
+} // namespace sta
+
+
+
+#endif /* INCLUDE_TACOS_STATEMACHINE_HPP_ */
diff --git a/Tacos/include/sta/tacos/thread.hpp b/Tacos/include/sta/tacos/thread.hpp
new file mode 100644
index 0000000..94d1a1a
--- /dev/null
+++ b/Tacos/include/sta/tacos/thread.hpp
@@ -0,0 +1,78 @@
+/*
+ * task.hpp
+ *
+ * Created on: Sep 14, 2023
+ * Author: Dario
+ */
+
+#ifndef INCLUDE_TACOS_TASK_HPP_
+#define INCLUDE_TACOS_TASK_HPP_
+
+#include
+
+#include
+
+
+namespace sta
+{
+ namespace tacos
+ {
+ class TacosThread : public RtosThread
+ {
+ public:
+ /**
+ *
+ */
+ TacosThread(const char* name, osPriority_t prio);
+
+ virtual ~TacosThread();
+
+ /**
+ * @brief Start the execution of this thread.
+ */
+ void start();
+
+ /**
+ * @brief Checks if this thread is currently running.
+ */
+ bool isRunning();
+
+ /**
+ * @brief Get the currently running instance.
+ */
+ osThreadId_t getInstance();
+
+ /**
+ *
+ */
+ const char* getName() const;
+
+ bool operator==(const TacosThread& other) const;
+ bool operator<(const TacosThread& other) const;
+
+ /**
+ * @brief A function that wraps this task's functionality in a loop. This loop will run until
+ * termination is requested.
+ */
+ void loop();
+
+ virtual void init();
+
+ /**
+ * @brief The body of the thread's loop. Has to be implemented by the user.
+ */
+ virtual void func();
+ private:
+ /**
+ * @brief Static function to pass to RTOS to run as a thread. Calls the loop function implemented here.
+ */
+ static void entry_point(void* arg);
+
+ osThreadId_t instance_;
+ osThreadAttr_t attribs_;
+ };
+ }
+}
+
+
+#endif /* INCLUDE_TACOS_TASK_HPP_ */
diff --git a/Tacos/src/manager.cpp b/Tacos/src/manager.cpp
new file mode 100644
index 0000000..f95054f
--- /dev/null
+++ b/Tacos/src/manager.cpp
@@ -0,0 +1,99 @@
+/*
+ * manager.cpp
+ *
+ * Created on: Sep 19, 2023
+ * Author: Dario
+ */
+
+#include
+#include
+
+
+namespace sta
+{
+ namespace tacos
+ {
+ void Manager::registerThread(TacosThread thread, std::list states)
+ {
+ for (uint16_t state : states)
+ {
+ STA_ASSERT(state < STA_TACOS_NUM_STATES);
+
+ threads_[state].emplace(thread);
+ }
+ }
+
+ void Manager::startThreads(uint16_t state)
+ {
+ STA_ASSERT(state < STA_TACOS_NUM_STATES);
+
+ for (TacosThread thread : threads_[state])
+ {
+ if (!thread.isRunning())
+ {
+ thread.start();
+ }
+ }
+ }
+
+ void Manager::stopThreads(uint16_t state)
+ {
+ uint16_t currentState = Statemachine::instance()->getCurrentState();
+
+ for (uint16_t state = 0; state < STA_TACOS_NUM_STATES; ++state)
+ {
+ if (state == currentState)
+ {
+ continue;
+ }
+
+ for (TacosThread thread : threads_[state])
+ {
+ // If the thread is currently running but not part of the set of threads that should be running...
+ if (thread.isRunning() && threads_[currentState].count(thread) == 0)
+ {
+ // ...politely request termination.
+ thread.requestTermination();
+ }
+ }
+ }
+ }
+
+ void Manager::updateThreads()
+ {
+ uint16_t state = Statemachine::instance()->getCurrentState();
+
+ startThreads(state);
+ stopThreads(state);
+ }
+
+ void Manager::init()
+ {
+ startThreads(Statemachine::instance()->getCurrentState());
+ }
+
+ void Manager::func()
+ {
+ // Wait for either the termination request or the state change flag.
+ uint32_t flags = osEventFlagsWait(getInstance(), STA_RTOS_THREAD_FLAG_TERMINATE, osFlagsWaitAny, osWaitForever);
+
+ if ((flags & STA_RTOS_THREAD_FLAG_TERMINATE) != 0)
+ {
+ // The loop implemented by the TacosThread class should handle termination.
+ return;
+ }
+
+ // Start all new tasks and stop all the tasks that aren't supposed to be running.
+ updateThreads();
+ }
+
+ Manager::Manager()
+ : TacosThread{"Manager", STA_TACOS_MANAGER_PRIORITY}
+ {
+
+ }
+
+ } // namespace tacos
+} // namespace sta
+
+
diff --git a/Tacos/src/startup.cpp b/Tacos/src/startup.cpp
new file mode 100644
index 0000000..51e7670
--- /dev/null
+++ b/Tacos/src/startup.cpp
@@ -0,0 +1,91 @@
+/*
+ * startup.cpp
+ *
+ * Created on: 22 Sep 2023
+ * Author: Dario
+ */
+
+
+#include
+#include
+#include
+
+// sta-core-specific imports.
+#include
+#include
+#include
+#include
+
+// Tacos-specific includes.
+#include
+#include
+#include
+
+
+// The UART mutex defined in freertos.c
+extern osMutexId_t uartMutexHandle;
+
+
+namespace sta
+{
+ // Here the printable used for debugging is defined.
+ Printable * Debug;
+
+ namespace tacos
+ {
+ void initPrintable()
+ {
+ // Initialize the mutex for UART communication.
+ RtosMutex * mutex = new RtosMutex(&uartMutexHandle);
+
+ // Initialize the UART interface and printable object.
+ UARTSettings settings = { .mode = UARTMode::RX_TX };
+ STM32UART * intf_ptr = new STM32UART(&huart2, settings, mutex);
+ Debug = new PrintableUART(intf_ptr);
+
+ STA_DEBUG_PRINTLN("UART SUCCESSFULLY INITIALIZED");
+ }
+
+
+ STA_WEAK
+ void onStatemachineInit()
+ {}
+
+
+ void initStatemachine()
+ {
+ onStatemachineInit();
+
+ Statemachine::instance()->start();
+ }
+
+
+ STA_WEAK
+ void onManagerInit()
+ {}
+
+
+ void initManager()
+ {
+ onManagerInit();
+
+ Statemachine::instance()->start();
+ }
+ } // namespace tacos
+
+
+ namespace rtos
+ {
+ // Override the weak implementation of startupExtras provided in rtos2-utils.
+ void startupExtras(void * argument)
+ {
+ tacos::initPrintable();
+
+ tacos::initStatemachine();
+
+ tacos::initManager();
+ }
+ } // namespace rtos
+} // namespace sta
+
+
diff --git a/Tacos/src/statemachine.cpp b/Tacos/src/statemachine.cpp
new file mode 100644
index 0000000..9388863
--- /dev/null
+++ b/Tacos/src/statemachine.cpp
@@ -0,0 +1,32 @@
+/*
+ * statemachine.cpp
+ *
+ * Created on: 21 Sep 2023
+ * Author: Dario
+ */
+
+#include
+
+namespace sta
+{
+ namespace tacos
+ {
+ void Statemachine::init()
+ {
+
+ }
+
+ void Statemachine::func()
+ {
+
+ }
+
+ uint16_t Statemachine::getCurrentState()
+ {
+ return currentState_;
+ }
+ } // namespace tacos
+} // namespace sta
+
+
+
diff --git a/Tacos/src/thread.cpp b/Tacos/src/thread.cpp
new file mode 100644
index 0000000..4a8e94b
--- /dev/null
+++ b/Tacos/src/thread.cpp
@@ -0,0 +1,86 @@
+/*
+ * thread.cpp
+ *
+ * Created on: Sep 14, 2023
+ * Author: Dario
+ */
+
+
+#include
+#include
+
+#include
+#include
+
+
+namespace sta
+{
+ namespace tacos
+ {
+ TacosThread::TacosThread(const char* name, osPriority_t prio)
+ : RtosThread(RtosHandle(Handle::Deferred(&instance_))),
+ attribs_{ .name = name, .priority = prio }
+ {
+
+ }
+
+ static void entry_point(void* arg)
+ {
+ STA_ASSERT(arg != nullptr);
+
+ TacosThread* instance = reinterpret_cast(arg) ;
+ instance->loop();
+ }
+
+ void TacosThread::start()
+ {
+ STA_ASSERT(!isRunning());
+
+ instance_ = osThreadNew(entry_point, this, &attribs_);
+
+ STA_ASSERT(instance_ != NULL);
+ }
+
+ bool TacosThread::isRunning()
+ {
+ return instance_ != NULL;
+ }
+
+ osThreadId_t TacosThread::getInstance()
+ {
+ STA_ASSERT(isRunning());
+
+ return instance_;
+ }
+
+ const char* TacosThread::getName() const
+ {
+ return attribs_.name;
+ }
+
+ void TacosThread::loop()
+ {
+ init();
+
+ while ((osEventFlagsGet(instance_) & STA_RTOS_THREAD_FLAG_TERMINATE) == 0)
+ {
+ func();
+ }
+
+ instance_ = NULL;
+
+ osThreadExit();
+ }
+
+ bool TacosThread::operator==(const TacosThread& other) const
+ {
+ return std::strcmp(this->getName(), other.getName()) == 0;
+ }
+
+ bool TacosThread::operator<(const TacosThread& other) const
+ {
+ return std::strcmp(this->getName(), other.getName()) < 0;
+ }
+ } // namespace tacos
+} // namespace sta
+