Embedded ARM OS options? - Page 1
Forum section: electronics / general

author: bd139
author_rank: Super Contributor
timestamp: February 14, 2018, 10:14:39 am
content: Currently working on a prototype for a medium complexity mixed mode analogue and digital device. This is based around the PSoC 6 / Cortex M4. I have considerably underestimated the complexity of trying to build something with an event loop on a single thread as I have several peripherals and subsystems to control at the same time. Three of these are isolated. I hit a wall trying to add a serial port to it so I can control the device from a host machine. How do I talk to all the functions? Architectural fail. Start again.This brings me into the world of operating systems. Are there any "easy to roll", "very light weight" and "license free" tiny operating systems for ARM Cortex M4? All I need to do is run about 10-12 "tasks" which have static memory allocation and are event based (interrupt or timer driven). These will communicate via shared memory or FIFO if the OS allows that abstraction. Ergo I really need a preemptable scheduler with safe communication primitives. Real time guarantees aren't required for this; it's noddy user interface functions. I can possibly build something using setjmp in C and manual preemption wrapped in a header library (I have done this in the distant past) but I'd like to avoid that mess and go for a clean abstraction.Before anyone suggests it, Linux is way too heavy. There is no budget to import something commercial.Edit: just a note, kicking it back down to another core is a possibility. It's all hanging off a PSoC 4 board at the moment. I'm actually doing most of the work in C on a Linux VM at the moment just to see how it fits together. There is no actual target device yet

author: chickenHeadKnob
author_rank: Super Contributor
timestamp: February 14, 2018, 10:48:52 am
content: I'm not a PSOC person but I believe FreeRtos has been ported to the psoc5. It will do everything you need (and more but only is you need it)

author: andersm
author_rank: Super Contributor
timestamp: February 14, 2018, 10:49:25 am
content: There's more RTOSes for ARM than stars in the sky. ARM have their own CMSIS-RTX (based on Keil's RTX, Apache license). FreeRTOS is popular (modified GPL), though its API is butt-ugly IMO.

author: bd139
author_rank: Super Contributor
timestamp: February 14, 2018, 10:51:59 am
content: Thanks will have a look at these. I've looked at FreeRTOS already and it's a possibility but I agree the API is ugly.PSoC to me here is just a standard ARM core with some funky shit around the edges that make me not have to add a few opamps to the BOM on this

author: jeremy
author_rank: Super Contributor
timestamp: February 14, 2018, 10:58:11 am
content: The good thing about freertos is that it is ridiculously battle tested and stable (IMO), and can also be 100% statically allocated if need be. It also doesn’t force you to use a whole bunch of libraries you don’t need, and doesn’t force you to use a specific build tool (I’m looking at you, mbed...)You can also run it on a PC for testing.I’ve seen better APIs, but I’m not sure I’d go so far as saying the freertos one is “ugly”.Edit: also interesting you are using the PSoC 6, I wasn’t aware they were really on the market yet other than dev kits.

author: bd139
author_rank: Super Contributor
timestamp: February 14, 2018, 11:02:26 am
content: Not using yet. Awaiting dev kit availability. The target design will likely be PSoC 6 but I'm using a PSoC 4 kit at the moment hooked up into the rig. All the software is running on a desktop machine poking it. I'm really awaiting the final pricing of PSoC 6 ICs before I commit to it.

author: Berni
author_rank: Super Contributor
timestamp: February 14, 2018, 11:17:22 am
content: Yep freeRTOS is the way to go. Its free, very well tested and doesn't bring a bunch of crap you probably don't need.As for the API being ugly that's likely due to one of these high reliability coding standards it tries to conform to. Somehow things like this are supposed to prevent programmers from making silly bug or at least make it less often. In reality it probably just makes code harder to read.

author: bd139
author_rank: Super Contributor
timestamp: February 14, 2018, 11:19:55 am
content: Fair points. Thanks all. Will look at FreeRTOS in depth.I'll do a hello world on Linux then I will attempt to get it to target my PSoC dev board and see where I get to. I have an encoder and Si570 synthesizer hooked up so if I can get it to set that by end of March and read/set it via serial port / SCPI i'll be happy

author: enz
author_rank: Regular Contributor
timestamp: February 14, 2018, 11:38:06 am
content: If you are looking for a simple, but stable, RTOS and don't mind C++, than scmRTOS (https://github.com/scmrtos) could be an attractive alternative. Comes with an MIT license.I have used it in a couple of projects with a Cortex-M0 and it did work very well and was easy to use.It doesn't come with a lot of features, nor with a HAL. But this is an advantage in my opinion.Best regards,Martin

author: andersm
author_rank: Super Contributor
timestamp: February 14, 2018, 01:25:49 pm
content: Correction to what I wrote above: after Amazon bought FreeRTOS, its license was changed to MIT from the previous GPL with linking exception.

author: mac.6
author_rank: Regular Contributor
timestamp: February 14, 2018, 01:26:51 pm
content: freeRTOS, as it's basically ported everywhere, works quite fine (minus some quirks between ports), and is not anymore encumbered with GPL as v10 is now MIT.

author: bd139
author_rank: Super Contributor
timestamp: February 14, 2018, 02:07:38 pm
content: Thanks for the further replies everyone - much appreciated.

author: mikerj
author_rank: Super Contributor
timestamp: February 14, 2018, 05:23:16 pm
content: Another vote for FreeRTOS here. It might not be the perfect RTOS but it's mature and reliable and so widely used that any issues you come across are likely to have been solved before.Setting the appropriate interrupt priority threshold for RTOS and non-RTOS calling interrupts made my head hurt a bit the first time I used it due to the upside down Cortex priority levels, but once you understand how that works it's pretty straight forward.

author: Howardlong
author_rank: Super Contributor
timestamp: February 14, 2018, 05:41:47 pm
content: Quote from: andersm on February 14, 2018, 01:25:49 pmAmazon buying FreeRTOS, how did I miss that? I sincerely hope Richard Barry has made a good few quid out of that deal, he deserves it for the quality engineering and dedication he’s put into it over the years, and particularly because it’s been, well, free for most of us. I often wondered what his business model was, ie, were there enough companies buying the paid-for options, for example.At least Amazon is hardware agnostic in this space, or at least I’d imagine they are. It would’ve been frustrating had one of the microcontroller manufacturers bought it, and the innevitable loss of ongoing support that would go with that.I agree that the API is a bit of a mindset thing: it’s not that it’s messy, it’s just a bit of a hill to climb.

author: bd139
author_rank: Super Contributor
timestamp: February 14, 2018, 05:56:04 pm
content: Climbing hard nowI picked another target to play with that I have already floating around that works out of box (pic24+mplab)

author: andyturk
author_rank: Frequent Contributor
timestamp: February 14, 2018, 06:16:21 pm
content: Quote from: andersm on February 14, 2018, 10:49:25 amAnother vote for CMSIS-RTX. It's actively being maintained by ARM and has a generous license.The downside is that you'll have to "port" it to your platform, as it's a generic RTOS. That's not especially difficult (IMO), but it is a speed bump.

author: krho
author_rank: Regular Contributor
timestamp: February 14, 2018, 06:37:24 pm
content: I just foundµOS++ IIIetoday it's also generous MIT license.

author: ShowKemp
author_rank: Contributor
timestamp: February 15, 2018, 02:13:52 am
content: Hi,I'm assuming you were using PSoC Creator to develop the application (for the PSoC), for PSoC6 you can add FreeRTOS very easily , but it's the FreeRTOS version 9 (i haven't seen if they updated to v10 tho). You can see more projects for the PSoC6 on the same blog, here .I did a port of FreRTOS 9 and 10 for the PSoC4200 devices, you can see it here .Hope it helps.https://iotexpert.com/2017/05/30/psoc-6-freertos-first-example/https://iotexpert.com/category/devices/psoc-6/https://github.com/C47D/FreeRTOS9_49-42xx

author: bd139
author_rank: Super Contributor
timestamp: February 15, 2018, 12:22:47 pm
content: Thanks for that - appreciated. Will have a look through.Big failure though; I just blew up my PSoC, kitprog and the USB port it was attached to- forgot the power supply I had wired up wasn't floating.

author: Berni
author_rank: Super Contributor
timestamp: February 15, 2018, 02:04:03 pm
content: Quote from: bd139 on February 14, 2018, 05:56:04 pmBy the way 16bit PICs have a bit of a gotcha when it comes to memory and OSes. There normal addressing modes can only access up to a certain amount of RAM. The memory above that magic number needs a special addressing mode that is only used for this extended memory(Yeah oldschool x86 all over again) so only this lower part of RAM is easily usable by freeRTOS, the upper part is best statically allocated. But the limit is reasonably high so most PICs don't have enough RAM to run into it.

author: bd139
author_rank: Super Contributor
timestamp: February 15, 2018, 02:10:42 pm
content: Yeah that's not a problem for this. It doesn't need dynamic allocation or any heap really. There's one command buffer and a bunch of configuration and state variables that are global and that's it. In the current incarnation it's all in a big for loop with one procedure for each task and the task when it gets called checks for state change in the globals it knows about and then reacts, or changes the variable based on panel controls etc. Interrupts only mutate the global state at the moment. Makes serial handling difficult to add so adding FreeRTOS here makes stuff easier with queues so I can deliver events instead of watching state.Inputs for this are: rotary encoder, 5 buttons, 5 ADC inputs (multiplexed), serial port, 2 GP digital lines.Outputs are: serial port, 3 DAC outputs, one synthesizer IC (I2C), one 44780 LCD, 6 GP digital lines.uC just controls state or listens to it via serial port and reports it on the display. No intelligence going on.

author: NorthGuy
author_rank: Super Contributor
timestamp: February 15, 2018, 03:20:28 pm
content: Quote from: bd139 on February 15, 2018, 02:10:42 pmWhat is the exact problem with the serial? You can use DMA or interrupts, which are much less imposing than RTOS.

author: bd139
author_rank: Super Contributor
timestamp: February 15, 2018, 03:42:56 pm
content: It's more a matter of scale and management. This thing is starting to have to handle a lot of interrupts.

author: NorthGuy
author_rank: Super Contributor
timestamp: February 15, 2018, 04:15:04 pm
content: Quote from: bd139 on February 15, 2018, 03:42:56 pmRTOS will only add more interruptsRTOS takes resources and gives you back convenience. So, if the problem is in your inability to organize things, RTOS may help. But if it's too tight without RTOS, RTOS will only make things worse.

author: bd139
author_rank: Super Contributor
timestamp: February 15, 2018, 05:06:27 pm
content: Definitely agree. RTOS gives me the abstractions and the ability to scale this design up if I want, which is what I'm after. If I had to rewrite it later on, I'd be burning a lot of time which I don't have.

author: Berni
author_rank: Super Contributor
timestamp: February 15, 2018, 05:43:29 pm
content: Well a RTOS can also help you utilize resources more efficiently and reduce CPU load.When the waiting chain for a resource is short and tightly controlled then you can handle it with interrupts and/or DMA. Its a lot of low level messing about to make everything work nicely and be reliable in non ideal situations but can be very efficient.But then you get to something like reading from a SD card from multiple parts of your program. All access to your card likely goes trough a FAT32 library to manage your filesystem. So your main code calls the filesystem that calls the storage media abstraction layer that calls the sd card driver that initiates a sector read to the card. Now the card has to go find your data and start transferring it over the bus to you. Okay you might have a DMA handling that so that the whole transfer happens in the background and you get a interrupt when the sectors data is ready to go inside a RAM location, but what do you do in the mean time. The storage media abstraction layer can't do anythyng until it has the sectors contents so the FAT library has to wait and the main code has to wait. So all you can reasonably do in the meantime is service interrupts while the sd card driver waits in a empty while loop until the data is here.Bring a RTOS in the mix and things look diferently. The moment that sd card driver starts the sector read it goes and tells the OS to switch context so it sends it off running other tasks in the mean time. Once the DMA is done and fires a interrupt that tells the OS to switch context back and unblock that thread and we are back executing where we left off now that we have the data we need and can go on to do things with it. No CPU time was wasted for the cost of a bit of context switching overhead. And in case another thread needs the SD card too it will simply block magicaly since the OS will realise the SD card is not free yet and just stall that thread until its free.

author: mikerj
author_rank: Super Contributor
timestamp: February 15, 2018, 05:46:40 pm
content: Quote from: Berni on February 15, 2018, 05:43:29 pmYou use state machines to carry on running other "tasks", just the same as any reasonably well written embedded code running without an RTOS. It tends to start getting a bit messy and more difficult to maintain as the size and functionality of the code grows, which is where an RTOS starts making sense.

author: nctnico
author_rank: Super Contributor
timestamp: February 15, 2018, 05:57:53 pm
content: Quote from: mikerj on February 15, 2018, 05:46:40 pmBut you have to realise that this only works if you setup the OS to do time slicing and really run tasks in parallel. This means that you'll need mutexes for shared data and that each task will need to have it's own stack. Many OSses do round robin scheduling by default which is pretty similar to having one big main loop.IMHO an RTOS only makes sense if you need to interrupt a task (=time slicing) which is taking a long time to complete and thus blocks other tasks. The cost will be high though because time slicing will make the system as a whole less deterministic.

author: Berni
author_rank: Super Contributor
timestamp: February 15, 2018, 06:31:40 pm
content: Well yes you can do a lot of multitasking like things with a giant loop of state machines, but it can get messy in some cases.Taking the SD card example again. Once you issue the call into the FAT32 library you are essentially giving it control of your time sharing since the library was likely something you taken from someone else (If you didin't then you have way too much time on your hands). It won't return until its done with what you asked it to do. And a FAT32 library can become quite busy sometimes. A single call into it could send it looking for the allocation table, realising it doesn't have it ready, then realising it has dirty data in its sector buffer since you can't afford lots of RAM dedicated to that so it has to first flush that, get the allocation table data, realize it needs another part of it from somewhere else, modifies the table and its other copy because its FAT32, flushes all that out and then finally places the piece of data in the location you asked to write upon finally returning back out. In the process making a heap of random read and write accesses to a old crappy SD card that has abysmal random access performance so by the time you get back out of there a lot of time has passed. You could have the sd card driver call some functions to do usefull work while its waiting for data but then those function get time assigned to them very eraticaly and if they set off something that ends up talking to the FAT32 library or the code that started the FAT32 call you could have mangled some data or got into a call loop that eats up the whole stack and crashes. It even does it in that nice random non reproducible way that is a nightmare to troubleshoot.Not saying that RTOS is a magical wand that fixes all this. If a RTOS is used wrong it can cause huge slowdowns and resource usage and you shouldn't be running like 100 threads in it. But when well thought out to keep the number of threads and context switches down it can make things run very efficiently while providing great and reliable millisecond accurate timing for the semi time critical things. The really time critical things you simply do in oldschool high priority interrupts to take control away from the RTOS and get your nanosecond timing for where you really need it. That way you get the best of both worlds.

author: obiwanjacobi
author_rank: Super Contributor
timestamp: February 16, 2018, 07:26:44 am
content: Just wanna throw this in here, for when you need a bit more structure but (perhaps) not a full-blown RTOS.There is a way to setup a cooperative multitasking scheme that does not have much overhead.It uses macros to do the magic.You can put one task in a file (C) or a class (C++) because it requires a singe var to maintain its state-machine.You can write code like this (main loop / C++)Code:task1.Execute();task2.Execute();task3.Execute();task4.Execute();The task methods itself(using the macros):Code:Task_Begin(Execute){// no - this will not hang the program ...while(true){// ... because we yield from this method (that is the magic!)Task_YieldUntil(IncrementCount());/* Execution will exit (yield) and enter (next call to Execute) exactly here (Task_YieldUntil).* So make sure you perform the action required by the task (for this part) in one method.*/// execution falls through when IncrementCount returned true._counter = 0;Serial.print("Counted to ");Serial.println(_maxCount);}}Task_EndNote that this is cooperative multi tasking, so play nice.I have used this in several occasions and it has worked well.

author: nctnico
author_rank: Super Contributor
timestamp: February 16, 2018, 08:36:08 am
content: Yuk! Another kind of protothreads!

author: mikerj
author_rank: Super Contributor
timestamp: February 16, 2018, 11:15:02 am
content: Quote from: obiwanjacobi on February 16, 2018, 07:26:44 amIt's not really cooperative multitasking, it's a bunch of state machines hidden beneath some syntactic sugar, just like protothreads.

author: obiwanjacobi
author_rank: Super Contributor
timestamp: February 16, 2018, 02:18:15 pm
content: I take it you guys are not big fans of protothreads.(had to look it up)I do not see why this would not be cooperative? It breaks if you do not play nice - that pretty much makes it cooperative in my book.Anyway, whatever you call this, it works for simple scenario's without much overhead (low on resources - not everybody runs on an ARM cortex with a more memory than you can count) and the ugliness is pretty well hidden in the macros.You have to follow the pattern -or it may not work- but if you do, it's simple and sweet.If you have room to spare and you already know an RTOS' API, then by all means, go with that.

author: Vic20
author_rank: Contributor
timestamp: February 17, 2018, 12:32:37 pm
content: I personally use ChibiOS/RTIt's quite easy to set-up, it can use only static memory allocation, and is complemented with a good HAL.In my case it is a very good option because of the number of ST32 demos available using this RTOS.Don't know the work that could be needed to port it to PSOC.

author: nctnico
author_rank: Super Contributor
timestamp: February 17, 2018, 12:49:02 pm
content: Quote from: obiwanjacobi on February 16, 2018, 02:18:15 pmThe problem is that protothreads (or whatever you call you own reincarnation of it) hides functionality/actual flow in macros which makes the code less obvious and thus harder to maintain.

author: rhb
author_rank: Super Contributor
timestamp: February 17, 2018, 02:14:34 pm
content: Minix 3 runs on ARM. I'm not sure the status of it, but it's got a good pedigree and the project focus is reliability. I would have suggested it earlier, but it's probably overkill for the OP's work.

author: andersm
author_rank: Super Contributor
timestamp: February 17, 2018, 05:43:24 pm
content: Quote from: rhb on February 17, 2018, 02:14:34 pmAIUI, modern Minix requires an MMU, while the OP asked about something running on a Cortex-M4. I also believe the ARM version so far only runs on the BeagleBoard and BeagleBone, though that may be outdated information. Probably also a more complex setup than what OP was looking for (same goes for eg. RTEMS and Zephyr).

author: rhb
author_rank: Super Contributor
timestamp: February 17, 2018, 06:47:12 pm
content: I just included it for the benefit of someone else reading the thread later.I'm not sure why Minix would need an MMU. I'm pretty sure that it does not implement virtual memory. The entire reason that Linux came into being was Andy Tanenbaum refused to put in virtual memory and Fred van Kempen got in trouble with Prentice-Hall for copyright violations and had to take down his patches to Minix.The only reason I can think of that Minix3 would use an MMU is so that an addressing error would generate a page fault and kill the process without doing other damage.

author: bd139
author_rank: Super Contributor
timestamp: February 17, 2018, 08:05:57 pm
content: You need an MMU for page protection as well.

author: andersm
author_rank: Super Contributor
timestamp: February 17, 2018, 08:19:48 pm
content: Quote from: rhb on February 17, 2018, 06:47:12 pmAccording to the release notes, virtual memory was added in Minix 3.1.4, released in 2009.

author: Vic20
author_rank: Contributor
timestamp: February 17, 2018, 10:51:53 pm
content: Quote from: bd139 on February 17, 2018, 08:05:57 pmMemory protection can be obtained using a MPU (Memory Protection Unit)Cortex M4 processors have MPU but not MMUYou can protect memory pages but you don't get virtual memoryIn an RTOS used in firmware development it is usual to trust all the tasks so the MPU, if present, is not always used.For high security applications a MPU can come handy.In a Cortex-M4 application I think that a MMU would be overkill.

author: mikerj
author_rank: Super Contributor
timestamp: February 19, 2018, 12:38:30 pm
content: Quote from: obiwanjacobi on February 16, 2018, 02:18:15 pmIt's cooperative purely in the sense that it's up to the programmer to ensure each "task" doesn't consume too much time, but it's not a cooperative RTOS.