doc: Added READMEs for TACOS usage

This commit is contained in:
CarlWachter 2024-11-03 15:09:58 +01:00
parent 80ae4502b6
commit f6952ccd32
4 changed files with 296 additions and 13 deletions

190
README.md
View File

@ -1,18 +1,63 @@
# TACOS
This is the Trajectory Analysis Control OS (TACOS) that serves as a starting point for developing TACOS-based projects, by implementing threads in the App directory. TACOS is a subset of the features provided by ALPAKA. In particular, TACOS consists of the STM32-specific components of sta-core, rtos-2 and rtos2-utils.
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...).
## Setting Up TACOS
To use TACOS one should implement threads, which fulfill the various roles of the module in the App directory. TACOS utilizes [ALPAKA](https://git.intern.spaceteamaachen.de/ALPAKA) features, in particular requiring [sta-core](https://git.intern.spaceteamaachen.de/ALPAKA/sta-core) and [rtos2-utils](https://git.intern.spaceteamaachen.de/ALPAKA/rtos2-utils), as such it requires these to be in it's include path.
Add this as a library an existing CubeIDE project using FreeRTOS. Generally, we advise you to add it as a submodule. Make sure that you add the include paths for Tacos, i.e. sta-core and rtos2-utils, to the project with the following steps:
```
Properties -> C/C++ General -> Paths and Symbols -> Includes -> GNU C -> Add...
Properties -> C/C++ General -> Paths and Symbols -> Includes -> GNU C++ -> Add...
Properties -> C/C++ General -> Paths and Symbols -> Source Location -> Add Folder...
## 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](https://git.intern.spaceteamaachen.de/ALPAKA/ioc-collection) to get a preconfigured IOC for the STM microcontroller you are using. From here follow the following steps:
1. ```Import -> General -> Import an Existing STM32CubeMX Configuration File (.ioc)```
2. Select the .ioc file from the ioc-collection
3. Enter the project name and location you want to save the project to
4. Select C++ as the target language
5. 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/
...
```
Create a new thread via the project's IOC and call `startTACOS()` from this thread. If your thread is called `defaultTask`, the corresponding function `StartDefaultTask` generated in `Core/Src/freertos.c` should look like this:
### 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:
```bash
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:
1. `Properties -> C/C++ General -> Paths and Symbols -> Includes -> GNU C -> Add...`
2. Select `Add to all languages` and `Is a workspace path`
3. Click on `Workspace` and select a folder from the `YOUR_PROJECT_FOLDER/(Libs|App)` directory
- Always select the `include` or `Inc` folder for the include paths
- If the path you want to add is not in the list, refresh the project with `F5` in the `Project Explorer` and try again
4. Repeat for TACOS, sta-core, rtos2-utils and the App folder
5. `Properties -> C/C++ General -> Paths and Symbols -> Source Location -> Add Folder...`
- Add the `App` and `Libs` folders
### Starting TACOS
Navigate to the `Core/Src/freertos.c` file and add the following code to the `StartDefaultTask` function:
```cpp
void StartDefaultTask(void *argument)
{
/* USER CODE BEGIN StartDefaultTask */
@ -28,9 +73,11 @@ void StartDefaultTask(void *argument)
}
```
## Configuring TACOS
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:
```
```cpp
#ifndef INC_STA_CONFIG_HPP_
#define INC_STA_CONFIG_HPP_
@ -50,6 +97,7 @@ In order to use TACOS, you need to provide a configuration file in the path `sta
#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.
@ -61,12 +109,85 @@ In order to use TACOS, you need to provide a configuration file in the path `sta
#endif /* INC_STA_CONFIG_HPP_ */
```
PS: For not officially supported chips use this as the include:
```
```cpp
#include <sta/devices/stm32/mcu/common.hpp>
#define STA_MCU_LITTLE_ENDIAN
#define STA_PLATFORM_STM32
```
## Setting up the CAN Bus
### 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:
```cpp
#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:
```cpp
#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:
```cpp
#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:
1. Enable CAN in the IOC with the RX0 and RX1 Interrupts enabled.
@ -79,4 +200,47 @@ PS: For not officially supported chips add this:
#define STA_STM32_CAN_HANDLE {YOUR_HCAN_HANDLE}
```
After this messages will automatically be forwarded to the task with it's ID. To send messages use the interface defined in `tacos.hpp`.
There are two options for handling incoming CAN messages:
1. 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_` with `CanSysMsg msg; CAN_queue_.get(&msg);`
2. All messages will trigger the weakly defined handleSysMessage callback.
- This could be implemented like this:
```cpp
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.

93
include/sta/README.md Normal file
View File

@ -0,0 +1,93 @@
# TACOS.hpp
The TACOS API is defined in the tacos.hpp, in normal use cases you should only need to include this file.
## Functions
```cpp
uint16_t getState()
```
Retrieves the current state of the TACOS state machine.
---
```cpp
void requestState(uint32_t from, uint32_t to, uint32_t lockout = 0, bool publish = true)
```
Requests a state transition. Invalid state transitions will be dismissed. First come, first serve.
- **Parameters**:
- `from`: The starting state for the transition.
- `to`: The target state to transition to.
- `lockout`: (Optional) A timer to block further transitions.
- `publish`: (Optional) Whether to publish the state transition to the CAN bus.
```cpp
void forceState(uint32_t from, uint32_t to, uint32_t lockout = 0, bool publish = true)
```
Forces a state transition. Will be ignored if already in the given state. Triggers instantly.
- **Parameters**:
- `from`: The starting state for the transition.
- `to`: The target state to transition to.
- `lockout`: (Optional) A timer to block further transitions.
- `publish`: (Optional) Whether to publish the state transition to the CAN bus.
---
```cpp
void setStateTimed(uint32_t from, uint32_t to, uint32_t millis, uint32_t lockout = 0, bool publish = false)
```
Requests a state transition after a specified time.
- **Parameters**:
- `from`: The starting state.
- `to`: The target state.
- `millis`: The wait time in milliseconds before requesting the transition.
- `lockout`: (Optional) A timer for blocking subsequent transitions.
---
```cpp
template<typename T, typename ... Args> std::shared_ptr<T> addThread(std::set<uint16_t> states, Args ... args)
```
Registers a new thread to be run by TACOS.
- **Template Parameters**:
- `T`: The class type of the thread, which should inherit from `TacosThread`.
- **Parameters**:
- `states`: A set of states in which the thread should be active.
- `args`: The constructor arguments for the thread class.
---
### CAN Bus Functions (Conditional)
The following functions are available only if `STA_TACOS_CAN_BUS_ENABLED` is defined:
```cpp
bool queueCanBusMsg(CanSysMsg & msg, uint32_t timeout)
```
Queues a message to be sent over the CAN bus.
- **Parameters**:
- `msg`: The message to be sent.
- `timeout`: The maximum time to wait for sending the message.
---
```cpp
bool publishState(uint32_t from, uint32_t to, uint32_t timeout = 0)
```
Publishes a state transition message to the CAN bus.
- **Parameters**:
- `from`: The starting state for the transition.
- `to`: The target state.
- `timeout`: (Optional) A timeout for CAN communication.

View File

@ -0,0 +1,23 @@
# TACOS tasks and prototypes
## Statemachine
The statemachine is the core of TACOS. It is responsible for managing the state of the system and executing the threads that are registered to it. The statemachine is a singleton and can be accessed via `sta::tacos::Statemachine::instance()`.
For further info check the file or the doxygen documentation.
## Watchdog
The watchdog checks if all threads are setting a flag after every func call. If a thread does not set the flag in the given interval the thread is restarted.
The watchdog is enabled and configured with the following defines:
```cpp
#define STA_RTOS_WATCHDOG_ENABLE
#define STA_TACOS_WATCHDOG_FREQUENCY 10000
```
## CAN Bus
The CAN bus is used to communicate between different devices. The CAN bus task is triggered by IRQ from the transceiver or if something is inserted into it's output queue.
This thing is a huge steaming (but functioning) pile of shit. Further documentation is on hold until rework.
## Thread.hpp
Here the TacosThread is defined. Very straight forward. Just take a look inside.

View File

@ -0,0 +1,3 @@
# TACOS C API
Currently the only C API is the entry point for starting up TACOS. This will be extended to provide full functionality via C calling conventions.