3 ms·
I could be wrong, but isn't every multi-task / RTOS essentially supporting this? Wake up, check flags, do work if required. Of course if you're bare-metal prog
by jvanderbot 3y ago
I could be wrong, but isn't every multi-task / RTOS essentially supporting this? Wake up, check flags, do work if required.
Of course if you're bare-metal programming, it might be nice to have a lightweight mechanism for this.
- Conscat 3y agoIf you're asking why do coroutines exist, it's because context switching in kernel space and synchronization have very high overhead by comparison. You use those features when you want parallelism, not concurrency. For parallelism, you also usually want a userspace task scheduler because simply spawning threads in kernelspace is much slower. Cilk and Go provide this built into their language runtime.
- kevin_thibedeau 3y agoContext switches on Cortex-M are relatively cheap with optimizations to limit the amount of data that has to be stacked.
- lmm 3y agoRelative to what? They might be cheaper than some architectures, but they're still a hell of a lot more expensive than not doing them.
- kragen 3y agowe seem to be talking about cooperative multitasking here correct me if i'm wrong, but i think that even with an almost standard abi it's five instructions and 27 cortex-m3 clock cycles; here we reserve r10 for the current task pointer (with the bonus that you can use it for a tls base register) and round-robin among the tasks in a circularly linked list: yield: push {r4-r9, r11, lr} @ save all callee-saved regs except r10 str sp, [r10], #4 @ save stack pointer in current task ldr r10, [r10] @ load pointer to next task ldr sp, [r10] @ switch to next task's stack pop {r4-r9, r11, pc} @ return into yielded context there i think in gcc that's more or less -mpic-register=r10 -msingle-pic-base, though that isn't what those options are meant for if you're willing and able to deform the abi a little by having less callee-saved registers, something you might want to do anyway for efficiency, you can cut r4-r9 down to r4-r5 and shave that down to i think 19 clocks? if you're willing to eliminate callee-saved registers entirely you can get to 15, but that seems like a heavy price to pay if you have to use the standard abi it's i think 37 clocks on a cortex-m3 or better: yield: push {r4-r12, lr} ldr r9, =current_task_pointer ldr r10, [r9] str sp, [r10], #4 ldr r10, [r10] str r10, [r9] ldr sp, [r10] pop {r4-r12, pc} i feel like something in the range of 20-40 clocks is really not that expensive? i mean an ldr or str is 3 or 4 clocks if it's not accessing tcm, right? and on cortex-m0 every taken branch is 3 clocks because you don't have branch prediction? i mean it's not going to compete with barrel processors on context switch time, but if it's really the cost of accessing seven fields of structs on the heap, it hardly seems like it's "a hell of a lot more expensive" than even zero if we're talking about preemptive context switching, that's a different ball of wax; you have to save all the registers that you use at all, not just callee-saved registers, and depending on your application maybe vfp registers as well as integer registers
- kragen 3y agoi should clarify that while i have tested both of these context-switching subroutines, and they do seem to work in simple programs, i haven't tested them on actual cortex-m hardware, much less measured their real-world performance
- tadfisher 3y agoThere's also the simplicity of bare embedded in Rust, because you can mostly[1] use Cargo, depend on the right embedded_hal crates for your target, and be up and running with a hardware-backed async runtime and everything. Zephyr, Tock, Mynewt, etc. all have bespoke build/deployment systems and driver ecosystems. That said, RTOS makes actually deploying working products much more realizable, so pick your poison. 1: I think you still need xargo/cargo-xbuild for no-std embedded sysroots, but there may have been some upstream development on that front since I last played in this sandbox.
- monocasa 3y ago> I think you still need xargo/cargo-xbuild for no-std embedded sysroots, but there may have been some upstream development on that front since I last played in this sandbox. Cargo's build-std flag is the bespoke way now. Unstable, but working it's way to stable. AFAIK cargo/build aren't getting any more development in lieu of build-std.
- vvanders 3y agoThat's good to hear, I've used that in the past to drive down codesize even on non embedded targets by compiling for size and rebuilding the stdlib.
- Archit3ch 3y ago> you can mostly[1] use Cargo, depend on the right embedded_hal crates for your target, and be up and running with a hardware-backed async runtime and everything Can one use Rust's embedded_hal from a different programming language?
- sophacles 3y agoIIUC you can make some api in rust that uses the HAL, which ties your code into board specific stuff. That api you write can be exposed via C abi so you can link C or languages that have an FFI to C to the rust code. https://docs.rust-embedded.org/book/interoperability/rust-with-c.html https://docs.rust-embedded.org/book/interoperability/rust-wi...
- azubinski 3y agoIt's different and very old story. Protothreads are classic now: https://dunkels.com/adam/pt/index.html https://dunkels.com/adam/pt/index.html Contiki OS is also a piece of embedded development classic: https://en.wikipedia.org/wiki/Contiki https://en.wikipedia.org/wiki/Contiki In general, it's more about syntax than semantics. Semantics is generally difficult and rarely changes.