[HN Gopher] Oxide on My Wrist: Hubris on PineTime was the best w...
       ___________________________________________________________________
        
       Oxide on My Wrist: Hubris on PineTime was the best worst idea
        
       Author : todsacerdoti
       Score  : 255 points
       Date   : 2022-03-28 09:51 UTC (13 hours ago)
        
 (HTM) web link (artemis.sh)
 (TXT) w3m dump (artemis.sh)
        
       | dcow wrote:
       | Thank you for the LoFi tunes. I dig that stuff!
        
       | protoman3000 wrote:
       | The github repo of hubris [0] is very nice, as they immediately
       | tell you where what is, e.g.                  drv/ contains
       | drivers, a mix of simple driver lib crates and fully-fledged
       | server bin crates. Current convention is that drv/SYSTEM-DEVICE
       | is the driver for DEVICE on SYSTEM (where SYSTEM is usually an
       | SoC name), whereas drv/SYSTEM-DEVICE-server is the server bin
       | crate.
       | 
       | Why does nobody do this in their readmes normally? They just let
       | you look into their code and tell you "now figure it all out
       | yourself".
       | 
       | [0] https://github.com/faithanalog/hubris/tree/pinetime
        
         | Jerrrry wrote:
        
         | steveklabnik wrote:
         | In Rust, it's because most projects follow the default layout,
         | and so is less needed.
         | 
         | We have a custom build system on top of Cargo, and so things
         | are a bit weird for a normal Rust project, and so it's extra
         | important.
        
         | JadeNB wrote:
         | > Why does nobody do this in their readmes normally? They just
         | let you look into their code and tell you "now figure it all
         | out yourself".
         | 
         | I think it's worth praising this repo without knocking others.
         | Open source authors have no obligation to their users; if they
         | don't have the time to, or just don't care to, so organise
         | their READMEs, then they need not. In fact, if it's
         | sufficiently important, for much open-source software anyone
         | _else_ can do it, and submit a patch.
        
           | nerdponx wrote:
           | This isn't just about open source. Developers on internal
           | projects should do this too, but don't.
        
             | bluGill wrote:
             | Have you ever tried to write useful documentation? As a
             | programmer you are far to close to the code. You assume
             | things are obvious that are not, while going into great
             | detail describing things that are obvious (or maybe not
             | obvious, but only rarely interesting and so should be
             | documented in a deeper link not the main documentation). Or
             | worse because you have to document it you document the code
             | lines (++i; // increment i by one).
             | 
             | This is a hard problem. I try to make an effort, but too
             | often I get it wrong.
        
         | hemogloben wrote:
         | I've never understood why github shows the first line of the
         | most recent commit for files / folders next to their name
         | instead of the first line of any README.md file inside the
         | folder.
         | 
         | Even on projects that I'm actively working on, the most recent
         | commit of a folder gives me no useful information, whereas if I
         | could edit the README.md I could atleast add a description of
         | each folder so that new users could understand the directory
         | structure better.
        
           | athenot wrote:
           | Same thought; I would _love_ if there were a way to toggle
           | between  "latest commit message" and "first line of
           | documentation for the file", depending on whether it's a
           | familiar project or a new one I'm browsing.
        
       | a9h74j wrote:
       | > Compare these two videos of writing a solid block of color to
       | the screen, first through the SPI task, and second with direct
       | SPI hardware access:
       | 
       | I wonder if the performance difference could, in some
       | applications, create a preference for processors with enough SPI
       | ports to dedicate one per peripheral (no chip select required).
       | Not only no shared bus (as in I2C), but no shared SPI-task.
        
       | RantyDave wrote:
       | Zephyr can do MPU
       | https://docs.zephyrproject.org/latest/reference/usermode/mem...
        
       | ComputerGuru wrote:
       | Can anyone clue me in on the status of async/await in hubris? I
       | have some HAL code that both really needs and uses async (or
       | callbacks) to work and currently just use my own homebrew WFE/WFI
       | wakers (with a fixed, known _a priori_ number of tasks) but it
       | would be nice to switch to something more elegant and less
       | brittle.
       | 
       | (Context: async/await-based per-task loop to facilitate
       | background LoRa send/receive while other tasks can continue to
       | operate (DMA, SPI, etc) independently, with the overall loop
       | shutting the primary Cortex core down when processing is
       | completed/while waiting for events/updates.)
       | 
       | The last I checked, hubris was strictly synchronous and I didn't
       | get the sense that the interaction between tasks was
       | architectured in such a way that would facilitate low-power
       | designs for battery-powered devices.
        
         | iudqnolq wrote:
         | For others, embassy.dev are the main people working on embedded
         | async.
        
         | steveklabnik wrote:
         | We don't use async in hubris, so there is no async/await.
         | Hubris is 99.99999% synchronous.
         | 
         | For more:
         | https://hubris.oxide.computer/reference/#_why_synchronous
         | 
         | (Basically, this probably hasn't changed since you looked at
         | it, but for anyone else who hasn't seen it yet...)
         | 
         | > shutting the primary Cortex core down
         | 
         | We don't have mainline support for multicore systems, and
         | there's a big ? in there, design-wise. So yes, you are right to
         | recognize that that is the current state of things.
        
           | ComputerGuru wrote:
           | Hi Steve. Thanks for the confirmation - obviously a
           | synchronous design doesn't automatically/necessarily preclude
           | most high-level use cases that async can support - it just
           | requires an alternative approach and some careful
           | consideration. In fact, it could make it easier to do many
           | things like power management.
           | 
           | Can you comment on this: others have asked here on HN before
           | but didn't seem to get an answer - does power
           | management/consumption factor in at all in the architectural
           | design (even if it's "this makes it possible to add power
           | management later") or is it strictly a non-goal? (I know your
           | _current_ particular application domains aren 't constrained
           | by battery capacity.)
           | 
           | It would be easy enough to hack the kernel to always WFI/WFE
           | if all tasks are exited/completed, but I'm thinking about
           | cases where task(s) are still running but the supervisor
           | process is aware that they're all currently in a busy-waiting
           | state. But that wouldn't be sufficient (on its own) if the OS
           | requires certain peripherals to always remain powered up,
           | uses a high-frequency tick interrupt that will constantly
           | wake the device anyway, etc, etc.
        
       | wlkjlkeleg wrote:
        
       | gnicholas wrote:
       | Can anyone provide a comparison of PineTime and Pebble? My Time
       | Steel is aging and I'm trying to figure out if the PineTime would
       | be a workable replacement.
        
         | wanderer_ wrote:
         | The pinetime can basically do anything you want it to, as long
         | as you're willing to make it so. I'm wearing it on my wrist
         | right now, but I have an iPhone and the support for it is not
         | great. In terms of build quality, it's quite good, and the
         | battery lasts for about a week. It's slimmer than an apple
         | watch, which is a major plus for me. But if you have an iphone,
         | step tracking and limited music control is all you'll get in
         | terms of accessory use. You can always contribute, however, and
         | there is a very active community working on the firmware in the
         | github repo (https://github.com/InfiniTimeOrg/InfiniTime).
         | 
         | The thing that the PineTime does really well, however, is beat
         | the price tag of basically every other smartwatch out there
         | ($30). I'm not sure how chip-shortage prices might be affecting
         | this though...
        
       | visy wrote:
       | Thanks for the shoutout on the twister :)
        
       | f0e4c2f7 wrote:
       | I love projects like this. I've considered getting a smartwatch.
       | Something like this makes the idea more appealing. Whats the most
       | hackable watch? Is there a pinephone of smartwatches?
        
         | nickspacek wrote:
         | It's not the most hackable, but there are some dedicated folks
         | hacking at the Amazfit watches. I have the original Bip, which
         | has a ridiculous battery life (30+ days easily) and GPS. The
         | GPS will run your battery down with extensive use, but if I'm
         | running a few times a week it'll still go 2 weeks.
         | 
         | It isn't that powerful, and I wish it had a second physical
         | button. I haven't explored the mods very much because it does
         | what I need it to do, but the scene has the feel of the early
         | Xbox hacking scene, to me at least.
         | 
         | There's this watch which appears to be heavily inspired from
         | the Amazfit Bip:
         | https://www.kickstarter.com/projects/gfw/banglejs-2-the-open...
        
         | ushakov wrote:
         | PineTime with wasp-os!
        
         | nsb1 wrote:
         | There is! And it's even featured in this article!
        
         | bitdivision wrote:
         | The article is about running Hubris on the PineTime. Quite
         | literally the Pinephone of watches.
         | 
         | https://www.pine64.org/pinetime/
        
       | zozbot234 wrote:
       | See Tock OS https://www.tockos.org/ for another Rust-based
       | embedded OS with a fairly comparable design to Hubris. The
       | debugging capabilities of Humility make an interesting comparison
       | to what's provided by cargo-embed
       | https://probe.rs/docs/tools/cargo-embed/ and the Knurling Tools
       | https://knurling.ferrous-systems.com/tools/ by Ferrous Systems.
       | 
       | Ultimately, the embedded space (including all sorts of low-level,
       | retro, "bare-metal", remote etc. programming) has common needs
       | and it would be convenient to see more widespread cooperation
       | among these projects, improving reliability and avoiding wasteful
       | duplication of work. More resources at https://github.com/rust-
       | embedded/awesome-embedded-rust
        
         | randomskk wrote:
         | Under the hood, cargo-embed, knurling's probe-run, and Humility
         | are all built atop probe-rs (https://probe.rs/) to provide
         | debugging - I think in this case it's actually a great example
         | of cooperation between projects! Probe-rs has received PRs from
         | both Knurling and Oxide devs; it provides the common interface
         | to use various types of debug hardware and talk to various
         | types of microcontroller cores, essentially replacing OpenOCD.
        
         | panick21_ wrote:
         | People often have good reason to not adopt existing systems.
         | Oxide started with TockOS and have written and talked about why
         | they didn't end up using it.
         | 
         | This twitter space goes into a lot of detail:
         | https://www.youtube.com/watch?v=cypmufnPfLw
         | 
         | But at the end of the day, no_std will allow a bigger ecosystem
         | and sharing between many of these projects.
        
           | zozbot234 wrote:
           | Thing is, it's not even clear that their added elements are
           | all that sensible. If you're always running trusted tasks on
           | your embedded hardware, what do you need the MPU for? Even in
           | principle, it can only save you a bounds check. And if you
           | start running outside code, then the clear privilege
           | separation in Tock between trusted "Capsules" and other
           | "Tasks" starts looking plenty attractive. Even OP notes that
           | this MPU business introduces severe overhead.
        
             | panick21_ wrote:
             | That is just one of many reasons and not the main one.
             | Again, actually watch and listen to the associated
             | talks/blogs/docs and so on.
        
             | TickleSteve wrote:
             | Data-execution exploits mean that you may accidentally run
             | code you weren't expecting to. If you have any kind of
             | message parser taking input from an external system and
             | examining it, you may be vulnerable to these types of
             | exploits without realising it.
             | 
             | Having the ability to mark (for example) your stack as non-
             | executable is a simple change that can remove a whole class
             | of problems.
             | 
             | That is only the skimming the surface tho.
        
               | zozbot234 wrote:
               | Yes, this is a concern in memory-unsafe languages like C.
               | But Rust can build memory-safe primitives with only a
               | modest amount of runtime checking wrt. inherently unsafe
               | operations.
               | 
               | (Of course, having better formal models of how 'unsafe'
               | code behaves might allow us to be a lot more rigorous in
               | building safe primitives, such as by endowing some
               | 'unsafe' calls with proof objects that might reify the
               | outcome of a bounds check.)
        
               | TickleSteve wrote:
               | Rust helps, but isnt immune (e.g. stack overflows).
               | 
               | Also, when you're dealing with embedded code, you're very
               | likely going to be using unsafe code (e.g. driver level).
               | With no other protection, incorrectly programming a DMA
               | transfer to trample over code-space is not unknown... and
               | Rust cannot protect you from that.
               | 
               | (Having said that... an MPU window will also not
               | necessarilly catch a bad DMA transfer either).
        
               | zozbot234 wrote:
               | > Rust helps, but isnt immune (e.g. stack overflows).
               | 
               | This is a good point but isn't Hubris designed to use
               | statically bounded amounts of memory anyway, like much
               | embedded software? AIUI, this was a key reason for
               | keeping their design focused on synchronized requests,
               | avoiding the hard-to-predict buffering that's needed for
               | supporting 'async' models.
        
               | steveklabnik wrote:
               | Defense in depth matters. The blog post shows an example
               | of Hubris correctly killing a task that's touching memory
               | it's not supposed to. That "supposed to" was due to a
               | configuration error, but configuration errors can and do
               | happen, and maybe would not be as benign as this one was.
        
               | rcxdude wrote:
               | Defence in depth. Rust isn't completely immune to memory
               | safety bugs, due to the need for unsafe code underlying
               | many primitives in the language as well as soundness bugs
               | in the compiler, it just makes them much rarer. It's well
               | worth designing the system so it doesn't fall apart as
               | soon as one such bug appears.
        
             | bcantrill wrote:
             | Other folks have mentioned this, but it's important to
             | understand the limitations of Rust with respect to safety.
             | In particular: every stack operation is -- at some level --
             | an unsafe operation as it operates without a bounds check.
             | This isn't Rust's fault per se; non-segmented architectures
             | don't have an architecturally defined way to know the stack
             | base. As a result, even an entirely safe Rust program can
             | make an illegal access to memory that results in fatal
             | program failure. That, of course, assumes memory
             | protection; if you don't have memory protection (or, like
             | many embedded operating systems, you don't make use of it),
             | stack overflows will plow into adjacent memory.
             | 
             | But wait, it gets worse: stack overflows are often _not_
             | due to infinite stack consumption (e.g., recursion) but
             | rather simply going deep on an unusual code path. If stack
             | consumption just goes slightly beyond the base of the stack
             | and there is no memory protection, this is corrupt-and-run
             | -- and you are left debugging a problem that looks every
             | bit like a gnarly data race in an unsafe programming
             | language. And this problem becomes especially acute when
             | memory is scarce: you really don 't want a tiny embedded
             | system to be dedicating a bunch of its memory to stack
             | space that will never ("never") be used, so you make the
             | stacks as tight as possible -- making stack overflows in
             | fact much more likely.
             | 
             | Indeed, even _with_ the MPU, these problems were acute in
             | the development of Hubris: we originally put the stack at
             | the top of a task 's data space, and its data at the bottom
             | -- and we found that tasks that only slightly exceeded
             | their stack (rather than running all of the way through its
             | data and into the protection boundary) were corrupting
             | themselves with difficult-to-debug failures. We flipped the
             | order to assure that every stack overflow hit the
             | protection boundary[0], which required us to be much more
             | intentional about the stack versus data split -- but had
             | the added benefit of allowing us to add debugging support
             | for it.[1]
             | 
             | Stack overflows are still pesky (and still a leading cause
             | of task death!), but without the MPU, each one of these
             | stack overflows would be data corruption -- answering for
             | us viscerally what we "need the MPU for."
             | 
             | [0] https://github.com/oxidecomputer/hubris/commit/d75e8329
             | 31f67...
             | 
             | [1] https://github.com/oxidecomputer/humility#humility-
             | stackmarg...
        
               | ctz wrote:
               | > non-segmented architectures don't have an
               | architecturally defined way to know the stack base
               | 
               | ARMv8-M does have stack limit registers, which do
               | precisely this. Being a much simpler mechanism than the
               | MPU, they are quicker to switch than the entire MPU state
               | when switching tasks.
        
               | bcantrill wrote:
               | Yes, true -- it's more accurate to say "architectures
               | traditionally don't have a way to know the stack base."
               | Certainly, having an architecturally-defined way to know
               | the base of the stack is/would be really really helpful,
               | and would allow stack overflow to be at once less
               | dangerous and much more debuggable!
        
               | zozbot234 wrote:
               | > This isn't Rust's fault per se; non-segmented
               | architectures don't have an architecturally defined way
               | to know the stack base.
               | 
               | Bounding stack usage is of course a whole-program
               | concern, but that ought to be feasible when building for
               | embedded, where external "plugin" components are unlikely
               | and there's no inherent need for true separate
               | compilation. (Arguably, in such cases even the need for
               | an actual "stack" structure is actually quite limited; a
               | smarter compiler might well replace many uses of the
               | activation stack with references to static data,
               | reserving it for cases where e.g. reentrancy is actively
               | needed. AIUI, there has been some work along those lines
               | for LLVM.)
        
               | bcantrill wrote:
               | But to get back to your original question: you can see
               | why the state of things today necessitates the use of the
               | MPU, even for Rust?
        
             | bluGill wrote:
             | The real question is what is the correct risk tolerance,
             | there are many degrees in here with trade offs. If I mostly
             | trust the other programmers then I'm just concerned about
             | mistakes. If I'm running code that might have been written
             | by some evil cracker trying to do some evil then I need
             | more protection.
        
       | smbv wrote:
       | https://archive.ph/E8rQv
        
       | mkesper wrote:
       | Cool, almost the same chip is used in the microbit v2.
       | https://support.microbit.org/support/solutions/articles/1900...
        
       ___________________________________________________________________
       (page generated 2022-03-28 23:01 UTC)