4 ms·
any chance that code is up somewhere? Sounds interesting
by sgillen 7y ago
any chance that code is up somewhere? Sounds interesting
- baybal2 7y agoMy guess is following: some people will put in doubt the rationale of using threads for embedded development as such. See, MCUs are much more interrupt driven than today's PCs, when it comes to I/O, and don't have to run interface logic as it's usually done in hardware. You can make a widget feel quite snappy and interactive even with very simple linear code. For the few tasks genuinely requiring real parallelism, or programming fancy multicore MCUs, it will likely be that you will need more than just thread separation, and it is better to do it properly than use hacks — in other world, use process separation and let complexities be handled by the OS.
- adrianratnapala 7y agoYou can think of it as the reactor pattern. You only have one physical CPU so all you are doing is churning through callback-based event handlers. The callbacks in this case might be the literal interrupt handlers (in which case your dispatcher "loop" is actually the hardware). Or else you make your interrupt write a little bit of state that then gets dispatched by your actual event loop. Either way, you write responsive software by doing everything in short-running callbacks. I find it amusing that (some) sophisticated GUI and server framework for big computers re-invent this.
- photojosh 7y ago> doing everything in short-running callbacks We call them "interrupt handlers." :)
- adrianratnapala 7y agoIt's amusing how you and alexhutcheson both corrected me in opposite directions. For reasons Alex explains, interrupt handlers have to be really minimal. So you often use them to set state that makes the main loop branch off into the "real" handler. But even then, you often don't want to wait a long time in that handler either. That too becomes a short-running event handler (though not necessarily a callback). Just not as extremely short running as it would have to be if did it in the interrupt handler.
- alexhutcheson 7y agoOne important difference is that in the MCU world interrupt handlers need to be really short and fast, because often various classes of interrupts are blocked from occurring while an interrupt handler is running. A common pattern is for the interrupt handler to just set some bits to say “this occurred” and return. The bits are then checked and handled in the main loop.
- huhtenberg 7y ago> using threads for embedded development Reminds me of something - I used to work for an embedded shop where they used exception-like error handling that was implemented through some basic C macro fuckery. It made the code markedly more succinct, had next to zero overhead and it was just a fantastic piece of work in general. 20 years later and I still remember it fondly.
- jwr 7y ago> My guess is following: some people will put in doubt the rationale of using threads for embedded development as such. I'm reading through the comments here and it is difficult to even address some of them, because there is apparent confusion as to the meaning of the word "thread". In embedded you often do not need or even want threads. What you need is a way to deal with events (mostly interrupts) without losing your sanity. A reasonable approach is to have a state machine that reacts to events, and all interrupt handlers only inject events into the state machine. The state machine is the only "thread" that runs: the CPU runs it until its done processing the current event, and then goes to sleep. Interrupt handlers do as little as possible, basically just drop events into a queue (or even a single slot) for the state machine to process. This works fine for simple state machines, but quickly gets tedious and complex, especially if you have tasks that involve several sequential events (initialize peripherals, setup ADC, read from ADC, calculate parameters, setup an output device based on parameters computed from ADC reads). A very good way to hide the state machine is to use CSP (you might have seen it in the Go language or in Clojure as core.async). This lets you write the same thing using certain primitives (channels, blocking and non-blocking reads and writes). Note that until this point this has nothing to do with threads! Clojure's core.async works just as well in Clojurescript, which compiles down to JavaScript and runs in a single thread!
- photojosh 7y agoI never cleaned it up for release, but if you email me I could send through some interesting bits of it. I2C and the peripheral we were dealing with is quite stateful, and writing the access code in a synchronous fashion wasn't possible due to overrunning other constraints. It seemed like a good idea at the time. The sibling comment has it pretty right... it would probably have been quicker in the end to go to an RTOS. That said, I'm still fairly proud of the I2C state machine that runs in the interrupt handler– it was completely separate from the protothread code that layered over the top. It's in a few microcontrollers in products we do, the funkiest is the smallest standard AVR package you can get, which imitated an obsolete tiny I/O expander chip we had to replace on a 6mm wide PCB. That was using I2C slave mode, but we could then run the entire sensor interfacing on that board rather than using a separate micro.