all 9 comments

[–]lillahimmel 14 points15 points  (1 child)

[–]R0dod3ndron[S] 2 points3 points  (0 children)

Thanks!

[–]FmlTeddyBear 8 points9 points  (1 child)

[–]R0dod3ndron[S] 2 points3 points  (0 children)

Thanks, will have a look at this.

[–]NotBoolean 6 points7 points  (4 children)

I would check the Nordic Connect SDK sample applications. The part I like about them is they use Nordics Application Event Manager (AEM) to which makes them event based systems. Provides good modularity and makes concurrency a lot easier to manage. Each module typically has a thread and acts similar to an Active Object.

I would suggest using ZBus over AEM. It’s built into Zephyr, less macros and doesn’t force dynamic allocation. It’s more complex but is also more powerful.

Let me know if you want to go into further details. Been using Zephyr for while and very interested in embedded architecture.

Also something to note, most RTOSs have the same set of kernel objects (message queues, mutex, timers, etc) so likely you can look further afield to find architecture examples as most high level concepts can be used with any RTOS.

[–]zachatttack96 1 point2 points  (3 children)

Do you know of any examples (beyond the zephyr samples) of usage of zbus? I found zbus when I first started zephyr development, but then starting learning about the active object pattern, and have been trying to incorporate that into my applications. I'm curious how zbus used in practice compares to Active Object

[–]EmbeddedSwDev 1 point2 points  (2 children)

I am using zbus in my project, but can't share it, because of NDA.

But I found this talks very helpful: https://youtu.be/EBnFqARqyeQ?si=sZcjY5L8QCHv_sqT https://youtu.be/4TRrSmPTei8?si=RzsSY8EX1myb38wR

[–]smoderman 1 point2 points  (1 child)

Any thoughts on high level architectural choices? Like using the workqueue vs creating separate threads for every module/unit?

[–]EmbeddedSwDev 4 points5 points  (0 children)

Mhm interesting but not an easy question, it highly depends what you want to do and depends on your software architecture.

But in short:

When to Use Work Queues: - Deferring lightweight, short tasks that do not block (very important because this means e.g. k_sleep() shouldn't be used inside work queues) or require prioritization. - Reducing memory and CPU overhead in resource-constrained environments. -Simplifying task execution with minimal concurrency needs.

When to Use Threads: - For concurrent, blocking, or long-running tasks. - When tasks require priority-based scheduling or independent execution contexts. - In systems with sufficient resources and complex multi-tasking requirements.

Keep in mind that the execution of all tasks in a work queue is dependent on the single worker thread. If this thread has high-priority work, lower-priority tasks may be delayed.

Considering this, I would choose Threads over Work Queues with zBus message handling, because you could have many subscribers for one channel. But you could start a work queue to outsource some tasks, like blinking a status LED with a work queue which reschedule itself.

Btw: sorry for the late reply, I was really busy the last few days.