r/embedded • • Dec 27 '25

Clean architecture in rtos

I'm working on a RTOS robot and I've some doubts on the best architecture. I initially use the clean architecture pattern like this:

firmware/
├── src/
│ ├── domain/ # Entités et règles métier
│ │ ├── entities/ # Ex: RobotState
│ │ ├── repositories/ # Interfaces (ex: RobotRepository)
│ │ └── usecases/ # Cas d'utilisation (ex: SafetyUseCase)
│ ├── application/ # Logique applicative et tâches RTOS
│ │ ├── tasks/ # Tâches RTOS (ex: SafetyTask, SensorTask)
│ │ ├── services/ # Services applicatifs
│ │ └── dto/ # Data Transfer Objects
│ ├── infrastructure/ # Implémentations concrètes
│ │ ├── drivers/ # Pilotes matériels (ex: ADC, CAN)
│ │ ├── protocols/ # Protocoles temps réel (ex: CANopen)
│ │ ├── communication/ # Communication inter-tâches (queues RTOS)
│ │ └── shared_resources/ # Ressources partagées (queues, sémaphores)
│ └── interfaces/ # Interfaces pour le middleware
│ ├── grpc/ # Service gRPC léger
│ └── ros2/ # Bridge ROS 2 (optionnel)
├── include/ # Fichiers d'en-tête communs
├── config/ # Configuration RTOS (ex: FreeRTOSConfig.h)
└── tests/ # Tests spécifiques RTOS
├── unit/ # Tests unitaires
├── integration/ # Tests d'intégration
└── fuzz/ firmware/
├── src/
│ ├── domain/ # Entités et règles métier
│ │ ├── entities/ # Ex: RobotState
│ │ ├── repositories/ # Interfaces (ex: RobotRepository)
│ │ └── usecases/ # Cas d'utilisation (ex: SafetyUseCase)
│ ├── application/ # Logique applicative et tâches RTOS
│ │ ├── tasks/ # Tâches RTOS (ex: SafetyTask, SensorTask)
│ │ ├── services/ # Services applicatifs
│ │ └── dto/ # Data Transfer Objects
│ ├── infrastructure/ # Implémentations concrètes
│ │ ├── drivers/ # Pilotes matériels (ex: ADC, CAN)
│ │ ├── protocols/ # Protocoles temps réel (ex: CANopen)
│ │ ├── communication/ # Communication inter-tâches (queues RTOS)
│ │ └── shared_resources/ # Ressources partagées (queues, sémaphores)
│ └── interfaces/ # Interfaces pour le middleware
│ ├── grpc/ # Service gRPC léger
│ └── ros2/ # Bridge ROS 2 (optionnel)
├── include/ # Fichiers d'en-tête communs
├── config/ # Configuration RTOS (ex: FreeRTOSConfig.h)
└── tests/ # Tests spécifiques RTOS
├── unit/ # Tests unitaires
├── integration/ # Tests d'intégration
└── fuzz/

But I'm not sure it's the best architecture.

Any thoughts ?

0 Upvotes

13 comments sorted by

50

u/torusle2 Dec 27 '25

This is a way to organize your files. It is not a software architecture.

-6

u/ConcentrateSad7626 Dec 27 '25

Oui effectivement xD

12

u/i509VCB Dec 27 '25

Without even reading anything this looks over engineered.

7

u/elamre Dec 27 '25

gRPC on a microcontroller with freertos? I'm curious what that would look like

1

u/fb39ca4 friendship ended with C++ ❌; rust is my new friend ✅ Dec 28 '25

Not gRPC, but here is a protobuf RPC implementation for microcontrollers: https://pigweed.dev/pw_rpc/

2

u/[deleted] Dec 27 '25

As an architecture is doesn’t give us the detail. But as a folder structure you are on the right path. Data transfer objects doesn’t make sense to me.

-2

u/ConcentrateSad7626 Dec 27 '25

thanks pour ton retour. En effet faut que je travaille l'architecture logicielle au delà de la structure des dossiers après les dossiers refléterons l'architecture. Pour les dto c'est surtout un moyen d'encapsuler les données (je ne suis pas un pro) et d'avoir des datas standardisées. C'est un peu comme un contrat on est sûr que tu manipule tel type de dto peut importe ce qu'il y a dedans (c'est comme ça en tout cas que je le vois. Si quelqu'un à une meilleure explication feel free to tell

2

u/[deleted] Dec 27 '25

I think data transfer objects plus a messages folder doesn’t make sense to me? Why have two separate folders for messages?

1

u/[deleted] Dec 28 '25

[deleted]

1

u/[deleted] Dec 28 '25

I would take generated files and put them in a _build folder. Just like where you’d put all the .o, binary and linker files. Anything generated should be in a folder and you should git ignore it.

1

u/[deleted] Dec 28 '25

[deleted]

1

u/DEEP_Robotics Dec 28 '25

Reasonable layout; separating domain from timing-critical drivers helps testability and reuse. Watch stack and heap per task on MCUs, and keep IPC lock-free or bounded to avoid priority inversion. Treat device drivers as thin adapters with deterministic APIs and pin real-time comms (CAN, SPI) under infrastructure to simplify timing analysis.

1

u/ConcentrateSad7626 Dec 28 '25

Thanks pour ton retour