8.9 KiB
TACOS
This is the Trajectory Analysis Control OS (TACOS) that serves as a framework for flight computer development. TACOS offers a state machine, a CAN bus interface, a watchdog and other HAL features through it's submodules. It runs on cmsis-rtos2 FreeRTOS on STM32 microcontrollers with C++ (maybe future versions will offer external C interfaces to support a wide array of languages...).
To use TACOS one should implement threads, which fulfill the various roles of the module in the App directory. TACOS utilizes ALPAKA features, in particular requiring sta-core and rtos2-utils, as such it requires these to be in it's include path.
Setting up a TACOS project
Setting up the project
First one must create a new CubeIDE project with FreeRTOS. To avoid doing that however we recommend using the ioc-collection to get a preconfigured IOC for the STM microcontroller you are using. From here follow the following steps:
Import -> General -> Import an Existing STM32CubeMX Configuration File (.ioc)
- Select the .ioc file from the ioc-collection
- Enter the project name and location you want to save the project to
- Select C++ as the target language
- Click "Finish"
Setting up the folder structure
Now it is necessary to setup the dependencies and include paths for TACOS. For this first create a new folder in the project directory called Libs
. Then create another folder in the project directory called App
with the subfolders Inc
and Src
. Now also create a folder called sta
in the Inc
folder. Finally add the empty files App/Inc/sta/config.hpp
and App/Src/startup.cpp
.
Now your project should look like this:
...
App/
├── Inc/
│ ├── sta/
│ │ └── config.hpp
├── Src/
│ └── startup.cpp
Libs/
...
Setting up the dependencies
First it is recommended to initialize a git repository in the project folder with git init
. Then add the TACOS, sta-core and rtos2-utils repositories as submodules in the Libs
folder with the following commands:
cd Libs
git submodule add https://git.intern.spaceteamaachen.de/ALPAKA/TACOS.git
git submodule add https://git.intern.spaceteamaachen.de/ALPAKA/sta-core.git
git submodule add https://git.intern.spaceteamaachen.de/ALPAKA/rtos2-utils.git
Make sure that you add the include paths for TACOS, sta-core and rtos2-utils to the project with the following steps:
Properties -> C/C++ General -> Paths and Symbols -> Includes -> GNU C -> Add...
- Select
Add to all languages
andIs a workspace path
- Click on
Workspace
and select a folder from theYOUR_PROJECT_FOLDER/(Libs|App)
directory- Always select the
include
orInc
folder for the include paths - If the path you want to add is not in the list, refresh the project with
F5
in theProject Explorer
and try again
- Always select the
- Repeat for TACOS, sta-core, rtos2-utils and the App folder
Properties -> C/C++ General -> Paths and Symbols -> Source Location -> Add Folder...
- Add the
App
andLibs
folders
- Add the
Starting TACOS
Navigate to the Core/Src/freertos.c
file and add the following code to the StartDefaultTask
function:
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
extern void startTACOS(void *);
startTACOS(argument);
/* Infinite loop */
for(;;)
{
osDelay(1);
}
/* USER CODE END StartDefaultTask */
}
This will start the TACOS startup and initialize all TACOS threads (which will then initialize yours).
Configuring TACOS
In order to use TACOS, you need to provide a configuration file in the path sta/config.hpp
. The following code is an example for a TACOS-project using default configuration:
#ifndef INC_STA_CONFIG_HPP_
#define INC_STA_CONFIG_HPP_
// Using a board with an ASEAG module present.
#define STA_STM32_ASEAG
// Use the STM32F407 microprocessor.
#include <sta/devices/stm32/mcu/STM32F407xx.hpp>
// Doesn't really do too much right now. Has to be added for successful compilation.
#define STA_PRINTF_USE_STDLIB
// Enable debug serial output and assertions.
#define STA_ASSERT_FORCE
#define STA_DEBUGGING_ENABLED
// Enable Features
#define STA_RTOS_SYSTEM_EVENTS_ENABLE
// #define STA_RTOS_SYSTEM_WATCHDOG_ENABLE
// #define STA_RTOS_WATCHDOG_ENABLE
// #define STA_TACOS_WATCHDOG_FREQUENCY 10000
#define STA_CAN_BUS_ENABLE
// Statemachine settings.
#define STA_TACOS_NUM_STATES 3
// Uses the default configuration for TACOS.
#include<sta/tacos/configs/default.hpp>
#endif /* INC_STA_CONFIG_HPP_ */
PS: For not officially supported chips use this as the include:
#include <sta/devices/stm32/mcu/common.hpp>
#define STA_MCU_LITTLE_ENDIAN
#define STA_PLATFORM_STM32
Implementing your own threads
Let's create a simple thread that prints "Hello World" every second. First create a new file in the App/Inc/tasks
folder called spam_task.hpp
. Then add the following code:
#ifndef INC_TASKS_SPAM_TASK_HPP_
#define INC_TASKS_SPAM_TASK_HPP_
#include <sta/tacos.hpp>
namespace tasks
{
class SpamTask : public sta::tacos::TacosThread {
public:
SpamTask();
// One time function that is called when the thread is created.
void init() override;
// Repeatable function that is called every time the thread is executed.
void func() override;
};
} // namespace tasks
#endif /* INC_TASKS_SPAM_TASK_HPP_ */
This code defines a new thread that inherits from TacosThread
and implements the init
and func
functions. The init
function is called once when the thread is created and the func
function is called every time the thread is executed.
Now create a new file in the App/Src/tasks
folder called spam_task.cpp
and add the following code:
#include <tasks/spam_task.hpp>
namespace tasks {
SpamTask::SpamTask() :
TacosThread("SPAM", osPriorityNormal){}
void SpamTask::init() {
// Nothing to init...
}
void SpamTask::func() {
// Print "Hello World" every second.
STA_DEBUG_PRINTLN("Hello World");
this->periodicDelay(1); // Execute this function with 1 Hz.
}
} // namespace tasks
To start this thread, we first need to fill out the startup.cpp
file. This file may look like this:
#include <sta/tacos.hpp>
#include <tasks/spam_task.hpp>
#include <sta/debug/debug.hpp>
namespace sta
{
namespace tacos
{
void onStatemachineInit()
{
// ###### Register different threads for different states here. ######
// Register a "Spam Task" thread for all states except 1 and 2.
sta::tacos::addThread<tasks::SpamTask>(ALL_STATES - state_set{1,2});
STA_DEBUG_PRINTF("The answer to everything is %d", 42);
}
} // namespace tacos
} // namespace sta
And that's it! Now you have a thread that prints "Hello World" every second. Simply build the project and flash it to your microcontroller and be amazed by the Spam!
Setting up the CAN Bus
To enable the CAN Bus two things need to be done:
- Enable CAN in the IOC with the RX0 and RX1 Interrupts enabled.
- Add the following code to the
sta/config.hpp
file:
#define STA_TACOS_CAN_BUS_ENABLE
PS: For not officially supported chips add this:
#define STA_STM32_CAN_HANDLE {YOUR_HCAN_HANDLE}
There are two options for handling incoming CAN messages:
- If
#define STA_CAN_BUS_FWD_ENABLE
is set, the messages will be forwarded to the task with the ID of the message.
- Tasks set their ID with
setID(uint32_t id)
in their constructor. - From here they can handle the message by going through their
CAN_queue_
withCanSysMsg msg; CAN_queue_.get(&msg);
- All messages will trigger the weakly defined handleSysMessage callback.
- This could be implemented like this:
namespace sta
{
namespace tacos
{
bool handleSysMessage(CanMsgHeader &header, uint8_t *payload)
{
// Print the message ID and the first byte of the payload.
//(please don't do this in production, it will crash the system sooner or later)
STA_DEBUG_PRINTF("> ID: %d", header.sid);
switch (header.sid)
{
// State transition message
case STA_TACOS_CAN_BUS_SYS_MSG_ID:
// First byte of payload is the origin state, second byte is the destination state
tacos::setState(payload[0], payload[1], 0, true);
return true;
case MODULE_SW_RESET_CAN_ID:
HAL_NVIC_SystemReset();
return true; // :)
// ...
default:
return false;
}
return false; // I know, i know, this is not necessary, but it's good practice. And you know what they say about good practice: Do it!
}
}
}
Further information
To look into other function of TACOS please consult the READMEs in the include folder or the doxygen documentation. Also consult the sta-core and rtos2-utils READMEs for further information on the features that TACOS uses.