18 ms·
Moving to a RTOS on the RP2040
- GianFabien 2y agoGreat comparison of RTOS choices. Personally I find microPython to be an easier path. async/await based cooperative multi-tasking works well for me. Latest project driving 6 stepper motors and a variety of LEDS and scanning buttons - all in what appears to be real-time to the user.
- matt_trentini 2y agoAbsolutely, this would be a straightforward MicroPython project :)
- nick__m 2y agoFor a PTZ controller (No hard real-time requirements, minimal application memory usage) microPython look like productive choice. When I tried microPython (on the esp32 but i assume that the rp2040 is equally supported) I was pleased by it's pythonic supports of interrupts handlers !
- pjmlp 2y agoThese mini computers are much more powerful than the 8 and 16 bit home computers, microPython is more than capable to replace BASIC use cases from those early systems. It is still surprises me how many don't grasp how little we had available to us, and still managed to use high level languages.
- dekhn 2y agoI have to assume in this case the stepper motor signals are generated by a hardware peripheral (like RMT on the ESP32), rather than using python code to generate the stepper signal? In my microscope, I run a FluidNC board that's doing near real-time stepper motor control, and control it with a lightweight serial protocol, but I'm looking at https://pypi.org/project/micropython-stepper/ https://pypi.org/project/micropython-stepper/ which seems to be using python code with hardware timers.
- dragontamer 2y agoId have to imagine that Stepper Motor control is a job for RP2040 PIO? I can't say that I'm too familiar with PIO but a tiny bit of state (literally a few bits) and a few bytes of code should be enough to make a good driver and offload the whole task from the CPUs. I know RP2040 has dual CPU but motor control is often the job of a timer on other uCs.
- dekhn 2y agoHmm. Looking at https://github.com/redoxcode/micropython-stepper/blob/main/src/stepper/__init__.py#L101 https://github.com/redoxcode/micropython-stepper/blob/main/s... it looks like they basically run a fairly tight loop in Python using a Timer (which uses the hardware timer on ESP32 and RP2040, likely), poking the step pin in Python in the Timer callback. There is no specific timing for the step pulse, they just turn it on and then immediately off. I guess this works because the micropython implementation does fast attribute access and function calls. On a microcontroller, you could use PIO or I think the RMT peripheral or even just interrupt-driven pin poking. That's good for many use cases, although I strongly suspect it would fall over once you tried a very high step rate with microstepping (I run at 800-6400 step/sec) but I will try this out both for my lightweight test steppers (which use AccelStepper) as well as my microscope (which uses FluidNC). The scope will make it quite clear if we lose steps as I have a visual reference (the microscope slide has a calibrated fiducial marker).
- GianFabien 2y agoI was using 28BYJ-48 steppers driven using ULN2003A. Since the drive rate is 100-600 Hz, it was simple to use sub-ms timing to control signal edges. MicroControllers run 10-100s MHz, so microsecond timing is well within their capabilities. I haven't yet learnt to use PIOs. I'm old-school. Start by reading datasheets and then try out the simplest thing that could work and iterate from there. In general, I find third-party libraries more complex than my needs require. Took me a fair bit of reading microPython documentation and experimentation to fully grok the capabilities of the tasking model and event_loops. But once I got over that, it lead to clean, single responsibility class implementations.
- huppeldepup 2y agoNo mention of ChibiOS, unfortunately. I checked and the port still has problems installing on flash, so runs on RAM only. I’d also like to suggest uC/OS. It doesn’t take much more than setting a timer in asm to port that rtos but I haven’t had the time myself to try it.
- dTal 2y agoI've heard of uC/OS and always wondered - is it pronounced "mucous"?
- huppeldepup 2y agoThe author mentioned this somewhere in his book: competitors pronounced it mucous as a joke/jab. I believe it’s pronounced micro-cos as in microcosmos.
- stephen_g 2y agoI really like ChibiOS, it’s HAL and drivers are really nice. I used it in a project back when it was GPL with a linking exception (basically LGPL except you can’t really do shared libraries on microcontrollers).
- RossBencina 2y agoNo mention of ThreadX, which is open source these days https://github.com/eclipse-threadx/threadx/ https://github.com/eclipse-threadx/threadx/
- chrsw 2y agoI don't know why ThreadX isn't mentioned more frequently in these lists. It's relatively simple to use and understand.
- bangaladore 2y agoBy and far my favorite RTOS from a source code and API perspective. It's just elegant. And it has a POSIX API layer if you really need that.
- joezydeco 2y agoI'm looking to William Lamie's next project after ThreadX, the PX5 RTOS. The POSIX API won't be an afterthought. https://px5rtos.com/ https://px5rtos.com/
- bangaladore 2y agoYes, I have seen this. Looks interesting. Its certainly targeting a more enterprise audience (much like ThreadX was originally) You have to pay to use it, price unknown other than maybe >= 5k$ per year?, and it looks like it will be prohibitively expensive (for my usecases at least) to have source access. To me, those make it nonstarters.
- pantalaimon 2y agoRIOT would be another alternative https://github.com/RIOT-OS/RIOT https://github.com/RIOT-OS/RIOT
- drrotmos 2y agoPersonally, I've begun switching over my RP2040 projects to Rust using Embassy. Rust did take some getting used to, but I quite like it. Not an RTOS, but it satisfies a lot of the same requirements that'd lead you to an RTOS.
- johnsea 2y agoWow that looks cool. Thanks for the mention!
- lloydatkinson 2y agoI believe this has come up before but what are some of the differences between RTIC and Embassy?
- Katzenmann 2y agoRTIC is really simple and doesn't use it's own HALs. Also it's macro system makes it hard to modularize your code since all tasks need to be in one module. I've played around with it a bit and it seems like it could be great in the future, but currently not really. Embassy has it's own HALs which makes it better at async and has also nicer ergonomic IMO
- liamkinne 2y agoImportantly for RP2040 users, RTIC 2.0.0 is currently single-core only. I’m using RTIC for the firmware on my STM32H7 based product (https://umi.engineering https://umi.engineering) and it has been a joy.
- jamesmunns 2y ago> Embassy has it's own HALs which makes it better at async and has also nicer ergonomic IMO Worth noting, you don't HAVE to use the embassy HALs with the embassy executor. However, AFAIK, the only mainstream non-embassy HALs that supports async is the ESP32 HALs. There's no technical lock in, it's just that everyone I've seen implementing async support (outside ESP32) tends to do it within the Embassy project today. That may change over time.
- 5ADBEEF 2y agothe pi pico is 100% supported in Zephyr. https://github.com/zephyrproject-rtos/zephyr/tree/main/boards/raspberrypi/rpi_pico https://github.com/zephyrproject-rtos/zephyr/tree/main/board... Did the author not check the docs? https://docs.zephyrproject.org/latest/boards/raspberrypi/rpi_pico/doc/index.html https://docs.zephyrproject.org/latest/boards/raspberrypi/rpi... Additionally, you aren't intended (for many situations) to use a single "main" Zephyr install, but to include what external modules you need in your project's west.yml. If you have a number of projects sharing the same Zephyr install that's a separate discussion but installing every possible toolchain/HAL is not the only way to do things.
- introiboad 2y agoAlso it should be trivial to build using the GNU Arm Embedded toolchain if the author did not want to install the Zephyr SDK, not sure why this did not work for them.
- snvzz 2y agoAIUI seL4 runs on that chip. It would likely not be a bad option.
- rmu09 2y agoDo you have more information? seL4 seems to run on raspberry pi 3/4, but I didn't find any mention of cortex-m class CPUs being supported.
- snvzz 2y agoNevermind, I did not realize rp2040 is M0+ thus ARMv6. ARMv7 is the minimum, and MMU is required. RISC-V is recommended.
- TickleSteve 2y agoThis is a microcontroller (Cortex-M) not an application processor (Cortex-A).
- taunus 2y agoIf you want to look into Rust RTIC https://rtic.rs/2/book/en/ https://rtic.rs/2/book/en/ has rp2040 support and is very lightweight
- sgt 2y agoCan't go wrong with FreeRTOS. It's basically an industry standard at this point.
- alextingle 2y agoWhat's the solution to his problem getting printf() to work? That does sound like a PIA.
- constantcrying 2y agoUnlikely to be a software problem. If I had to guess the serial communication bus is misconfigured.
- TickleSteve 2y agoFreeRTOS has nothing to do with printf, thats a toolchain/standard library thing for his particular board.
- rcxdude 2y agoYou will need your printf to be written with FreeRTOS in mind: it's often not re-entrant at all, let alone actually blocking on IO instead of busy-waiting.
- TickleSteve 2y agotrue, my point being that "printf not working" is nothing to do with FreeRTOS.
- retSava 2y agoIf I understood it correctly, it was that the compiler suite shipped with newlib, which have or can have printf supporting re-entrant use (several threads can call printf in async manner), or not supporting that case (typically sync usage, blocking across I/O). The re-entrant ones use malloc/free for, iiuc, a per-thread buffer. In many cases when you have smaller systems, you actually don't want your OS to do dynamic memory allocation, since it opens up for all kinds of bugs related to eg double-free, or use-after-free, or running out of heap, or too defragmented heap. It's also easier to calculate memory usage (and thus be fairly certain it will be enough) if you allocate as much of the memory as possible as static memory. Hence why some coding standards such as MISRA-C disallows use of dynamic memory allocation. Exactly what caused the lock-up here isn't delved deeper into, but it might be that there was not enough heap, or not a working malloc-implementation linked into the compiled binary (could be a stub), or could be that a non-re-entrant printf was linked in while they tried printf from several threads.
- a-dub 2y agohm. haven't seen camelCase hard real-time task definitions since the vxworks days!
- DannyBee 2y agoThis author seems like they are expecting an RTOS to be the same as Arduino environment, or at least, susceptible to just hacking around and hoping it works. Most are not. Given a lot of Arduino these days have mbed or freertos under the covers, with some way to expose it, that may have been a better route for the author's style. Zephyr is easy to use (Clion also has good support for it), but like, you can't just choose not to install the toolchain and expect it to all work. It also definitely supports the Pi Pico - i've used it on it before, no issues. A simpler rundown of these RTOSen would be: 1. FreeRTOS - supported by roughly everything, but drivers and such are mostly per-SOC/device, which is a pain in the ass. The APIs are not very user friendly, but you get used to it. To give a sense of level - if you wanted to use bluetooth with FreeRTOS, you get to find your own stack. 2. Zephyr - supports real hardware abstractions and supports most SOC. You may have to do a little board work. If you wanted to use bluetooth with Zephyr, it has a bluetooth stack you can use, you may have to add a little support for your HCI. 3. NuttX - not great support, but very cool if you can get it working - not really highly supported by industry yet. I never got far enough into NuttX to try bluetooth in NuttX. There is also mbed, but we'll skip it. In practice, people in the RTOS world will usually go with what the SOC vendor supports. So if you are using Nordic stuff, you are probably on Zephyr. If you are using NXP stuff, probably FreeRTOS, etc. That is how they get good support.
- anymouse123456 2y ago"Zephyr is easy to use" That has not been my experience. From where I sit, Zephyr has very pretty marketing material. Behind all that snazz, Zephyr is outrageously bloated, extremely slow to compile and wildly difficult to get up and running.
- DannyBee 2y agoI dunno, maybe i got lucky. It takes me maybe 10 minutes to get clion + zephyr started and working for a new project. If there is board work, at that point i'm playing with making the board work. I started with platformio's zephyr support and then moved to clion as platformio kind of died. I have never, and would never, try to use west as the main build system of my project directly. As for bloat/compilation speed, i guess it all depends on what you are trying to use it for. As per the other thread - if you are trying to use it as "an RTOS that is a less hacky version of arduino stuff", i think it works great. If you are trying to use it for "i have meaningful hardware constraints and need to keep track of every byte", i doubt it would work well compared to FreeRTOS. I think the limit is probably "i am using nordic boards to develop bluetooth stuff". I do agree they try to sell it for a lot of things.
- bborud 2y agoHaving toolchains installed system-wide in the traditional UNIX way is painful, and dare I say it, not the smartest of approaches. If it works for you: great, but if you work on a project with multiple developers, sometimes working on multiple projects that have different targets, you will spend a lot of time trying to figure out build and configuration problems. It also doesn't help that people keep using Python for tooling. Why would you want to insist on using a language that brings its own versioning problems and which will behave differently on each developer's computer? I've done embedded development for about a decade now (both as a hobby and professionally) and it is puzzling that people think it is okay to spend a week trying to make everyone's setup do the same thing on a project and then not see how this is a problem. It is a problem. It is annoying. It does waste time. It is unnecessary. Tools should be statically linked binaries. I don't care what language people use to write tools, be it Rust, Go, C, C++. I just wish people would stop prioritizing ad-hoc development and start to make robust tools that can be trusted to work the same way regardless of what's installed on your computer. Python doesn't do that. And it doesn't help that people get angry and defensive instead of taking this a bit more seriously. That being said, things like PlatformIO are a step in the right direction. I know it is a Python project (and occasionally that turns out to be a problem, but less often that for other tools), but they have the right idea: toolchains have to be managed, SDKs have to be managed, libraries have to be managed, project configuration has to be simple, builds have to be reproducible and they have to be reproducible anywhere and anytime. I wish more of the embedded industry would realize that it would be better to have some common efforts to structure things and not always invent their own stuff. I know a lot of people who work for some of the major MCU manufacturers and I am always disheartened when I talk to them because they tend to be very near-sighted: they are mostly busy trying to solve their own immediate problems and tend to not have a great deal of focus on developers' needs.
- anymouse123456 2y agoJust want to second this entire post. It feels like I wrote it myself.
- LtdJorge 2y agoWouldn't Docker (or other container tools) be a good candidate? Instead of installing the toolchains locally, do the build on a container based on an image with the exact toolchain you need.
- boffinAudio 2y agoAlways, always, always start your new embedded project in a Virtual Machine. NEVER MIX TOOLS ON THE SAME SYSTEM. This has been the #1 cause of quality issues for my (commercial) projects. If you start a project with a new chipset, with a new vendor - build a new VM, install the vendors tools (and only the vendors tools) in that VM, and do your builds from there. Do your hacking on your own (non-VM) machine, sure. That's perfectly fine. But ALWAYS use the VM to do your releases. And, for the love of FNORD, KEEP YOUR VM IN SYNC WITH YOUR DEV WORKSTATION. Disclaimer: currently going through the immense pains of dealing with a firmware build that absolutely has to be fixed while the original dev is on vacation - nobody can get into their workstation, the VM prepared for the task is 6 months out of date, and the customer is wondering why they should pay for the whole team to do something that one very special programmer is the only one on the planet can do .. grr ..
- ptman 2y agoDoes nix and flakes help with a reproducible build environment?
- matt_trentini 2y agoOr, better still, use containers. Haven't used virtual machines in years - and I don't miss them one bit!
- jononor 2y agoI feel your pain. Releases should be built by CI system, imo. Tag a release in git, and binaries plop out (after tests have passed).
- anymouse123456 2y agoI've had similar experiences to the OP. I went ahead and rolled a simple green thread timer. It doesn't support actual process management like a real kernel, and doesn't make any guarantees about anything, but it has gotten me further than bare metal scheduling and helped me avoid the shit show that is RTOSes. Think JavaScript timer callbacks with an optional context struct (in C) It has allowed me to interrogate a variety of sensors, process inbound signals, make control decisions and emit commands, all at various frequencies. I highly recommend folks try something like this before ruining your life with these slow, abstract architectures.
- mordae 2y agoRolling your own swapcontext() is not that hard on Cortex-M0 and Pico SDK let's you override couple macros to hook into its locking code.
- demondemidi 2y agoGave up on freertos because printf doesn’t work? someone didn’t have the patience to read the documentation.
- roland35 2y agoZypher is indeed a pain in the neck to learn. I have lots of experience with freertos, setting up tool chains, etc, but just getting a basic project with zephyr is confusing.
- rkangel 2y agoI really want to get ve Hubris a try on a proper project (https://hubris.oxide.computer/reference/ https://hubris.oxide.computer/reference/). As an architectural approach it aligns closely with what I am going for in embedded land, but in C with more pain. And is not dissimilar to what you do in Erlang/Elixir in hosted land. Embassy looks to be a good choice in more memory constrained situations where you can't afford multiple stacks.
- bangaladore 2y agoI think Eclipse ThreadX is a great option (https://github.com/eclipse-threadx/threadx https://github.com/eclipse-threadx/threadx) Its might be the most used ThreadX on the market in the professional space (due to its history), but its quite frankly stupid simple to use. It was initially developed by Express Logic, then partnered tightly with Renesas, Then sold to Microsoft, and then transferred to the Eclipse foundation for good. They also provide NetX(duo), FileX, LevelX, UsbX and GuiX with full source and the same licensing afaik. Personally I don't care for UsbX or GuiX.