7 ms·
Writing embedded code with an async-aware programming language is wonderful (see Rust's embassy), but wonder how competitive this is when you need to push large
by tatjam 6mo ago
Writing embedded code with an async-aware programming language is wonderful (see Rust's embassy), but wonder how competitive this is when you need to push large quantities of data through a micro controller, I presume this is not suitable for real-time stuff?
- nasretdinov 6mo agoYou can disable GC in tinygo, so if you allocate all the necessary buffers beforehand it can have good performance with real-time characteristics. If you _need_ dynamic memory allocation then no, because you need GC it can't provide realtime guarantees.
- Groxx 6mo agoDoesn't seem like those should be mutually exclusive, though the habits involved are quite opposing and I can definitely believe they're uncommon. E.g. GC doesn't need to be precise. You could reserve CPU budget for GC, and only use that much at a time before yielding control. As long as you still free enough to not OOM, you're fine.
- carverauto 6mo agoWe're streaming RSTP camera feeds through WASM plugins and host-bridge adapters, no problem. I was surprised how well it worked TBH. https://code.carverauto.dev/carverauto/serviceradar/src/branch/staging/go/cmd/wasm-plugins/unifi-protect https://code.carverauto.dev/carverauto/serviceradar/src/bran...
- clktmr 6mo agoI've written a fair amount of code for EmbeddedGo. Garbage Collector is not an issue if you avoid heap allocations in your main loop. But if you're CPU bound a goroutine might block others from running for quite some time. If your platform supports async preemption, you might be able to patch the goroutine scheduler with realtime capabilities.
- randusername 6mo agoCan you elaborate on this and how it would be different from signaling on interrupts and DMA? Hardware-level async makes sense to me. I can scope it. I can read the data sheet. Software async in contrast seems difficult to characterize and reason about so I've been intimidated.
- jamesmunns 6mo agoIt's really not so different! In embassy, DMA transfers and interrupts become things that you can .await on, the process is basically: * The software starts a transaction, or triggers some event (like putting data in the fifo) * The software task yields * When the "fifo empty" interrupt or "dma transfer done interrupt" occurs, it wakes the task to resume * the software task checks if it is done, and either reloads/restarts if there's more to do, or returns "done" It's really not different than event driven state machines you would have written before, it's just "in-band" of the language now, and async/await gives you syntax to do it. Even if you don't know Rust, I'd suggest poking around at some of the examples here: https://github.com/embassy-rs/embassy/tree/main/examples https://github.com/embassy-rs/embassy/tree/main/examples And if you want, look into the code behind it.
- tatjam 6mo agoPrecisely, I would say embassy is a satisfying middle-point between "baremetal" firmware and running something like FreeRTOS / NuttX that hides the event loop from you.
- ted_dunning 5mo agoIn tinygo, the idiom is to catch an interrupt and put the info into a channel so that you can think about what is happening in go style. I use that capability, for instance, in go-wspr [1] to get very nice low-jitter timing for frequency corrections. [1] https://github.com/tdunning/go-wspr https://github.com/tdunning/go-wspr
- soypat 6mo agoIt is more performant than rust but less performant than Zig when not doing GC heavy stuff. https://github.com/tinygo-org/tinybench https://github.com/tinygo-org/tinybench