Rust on Particle: development discussion

Hey there, you've heard that we're looking for help developing Rust on Particle?

Let's use this thread to discuss development of Rust on Particle! Excite! :smiley_cat:

2 Likes

Letā€™s get going! :slight_smile: Hereā€™s a summary of our discussion so far from the PR conversation:

  • The user-facing API will be idiomatic rust, making effective use of traits. Traits will allow the capabilities of the system resources to be described and checked at compile time. For example, not all pins support PWM - traits will capture this information so attempts to use PWM on a pin that doesnā€™t support it would result in a compiler error.

  • weā€™ll consider using parts of zinc.rs that allow bare metal interaction with the MCU, to provide an equivalent of the CMSIS API that C++ developers have access to on our platform.

  • for discussion: will the user API be object-oriented (OO), functional, procedural? Wiring++ and original Wiring are examples of OO and procedural API paradigms.

Iā€™m not a Rust expert but Iā€™ve played with it a bit, and am reading up on Rust idioms while I type some thoughts here.

  • I think we should keep the fn main() {} standard basic Rust application format rather than replicating the whole setup() and loop() thing from Arduino. I see that Rust has a loop keyword so perhaps a template Rust app looks like this:
fn main() {
  // setup-y things
  loop {
    // loop-y things
  }
}
  • Iā€™m really excited to use Cargo and have a real package management system. We should lean on Cargo heavily, which will hopefully give us some nice modularity. That also suggests that an empty template app should begin with importing the Particle crate, and then maybe the board definitions are modules? Something like this:
extern crate particle;

use particle::photon as board;

fn main() {
  board::pin_mode(D7, OUTPUT);

  particle::publish("Photon is initialized!");

  loop {
    board::digital_write(D7, HIGH);
    delay(1000);
    board::digital_write(D7, HIGH);
    delay(1000);
  }
}
  • Regarding OO vs. functional, my gut says functional, but at the same time Iā€™m struggling to imagine what the syntax for each would look like, and in particular what an easy-to-use functional programming API would look like, since functional programming can often be scary for n00bs.
2 Likes

Another thought - since Rust is all about safety, itā€™d be great to utilize that safety to ensure that boards and their peripherals are properly initialized. for instance, if you try to digital_write a pin that has not been initialized as an OUTPUT, it should fail on compile (with beautiful, easy-to-understand compile errors). similarly, if you try to initialize two peripherals that utilize the same pins, it should also fail on compile, perhaps unless you de-initialize the first peripheral before initializing the second?

1 Like

Also, hereā€™s somebody elseā€™s attempt at mashing up Rust and Arduino:

Not my favorite, as it uses Arduinoā€™s camelCase syntax, but there might be some interesting learnings in there regardless

Rust just announced 1.6, which is an important milestone for using Rust on embedded systems because libcore is now stable:

2 Likes

Is that possible? How would the system firmware support that? I'm sure this is among the things you're discussing internally. I would imagine that main is already an unmangled symbol in system firmware, but perhaps another symbol could be used? I'm really eager to help this move forward. :smiley:

Itā€™s possible to have main as the main entrypoint. With dynamic linking of the application code, ultimately itā€™s boils down to a function address in a table - the name isnā€™t significant. This would replace what we normally use for setup(), and loop() could be a call to System.reset() , an infinite loop or some other appropriate action.

1 Like

I left some comments on Github: https://github.com/zsup/firmware-rust/issues/2

Until we have a maintainer who will be organizing the effort? I would be more than happy to jump in today but not sure who is doing what and the priorities should be. Not to over manage something like this but I would participate in a Trello board to keep focus on priorities and who is working on what.

Iā€™ll do my best to keep it organized, but the best place to dig in is on Github Issues, and we can use that to manage and prioritize efforts:

1 Like

Does Rustā€™s use of the GCC ARM toolchain mean no runtime-type-inference (RTTI) on ARM, just like C++ on ARM?

Rust only uses arm-none-eabi-gcc for linking, whereas the LLVM backend is used for code generation. Also, there is no 1 to 1 equivalent to C++ RTTI in Rust. But, depending on what you want to do, generics, traits and/or enums may cover your use. There is also the Any trait and the TypeId struct for dynamic typing and downcasting.

Disclaimer: I have limited experience with dynamic typing in Rust, but Iā€™m sure the folks in Mozillaā€™s IRC channels like #rust can answer any questions you have about dynamic typing idioms in Rust.

1 Like

If rust needs RTTI for dynamic typing, we can enable that for the application firmware. Itā€™s been disabled by default simply because of the increased size of the binaries produced. If thereā€™s a way to only add this to the build conditionally upon the use of dynamic typing operators that would be ideal.

Is there anything that can be done on this project without actually having a board on hand?

Yes, lots! :smile: We can discuss the design of the api, implementation choices, build systems. Thereā€™s much that can be done without having the hardware.

Perfect!

Although, impatience kicked in, and I ordered a couple of kits yesterday, which will hopefully be here in a few days.

Iā€™m still relatively new to rust (only started looking at it just before Christmas, and didnā€™t have much time in there), so Iā€™m still a bit wobbly on some of the higher level constructs. That being said, Iā€™d like it if we could keep things as close to idiomatic-rust as possible; Iā€™ve a feeling that doing so will keep us from having to fight with the language as we go, and what Iā€™ve learned so far is that rust fights you back when you fight itā€¦ hard. Also, the more idiomatic it is, the easier itā€™ll be for those with rust experience to pick up and use the api.

I donā€™t believe itā€™ll need RTTI, as thereā€™s no dynamic typing in rustā€¦ at all. Even a single generic function (generics are rustā€™s way of handling polymorphism) which is called by multiple different types, is turned into a separate ā€œmonomorphicā€ function for each of those types at compile time. My understanding is that only those types that actually call that generic function will have a monomorphic function created for them at compile time ā€¦ so the binary wonā€™t bloat more than it absolutely has to.

2 Likes

That seems to be the consensus among those who want to participate, we all seem to want to maintain idiomacy for all the reasons you mentioned. @Tycheon, have you checked out the issues on @zachā€™s repo? Thereā€™s been some discussion there as well.

@tjp I did take a peak, yeah. Being relatively new to rust, and completely new to Particle (as well as not having anything to test on), I figured Iā€™d come here to ask the newbie questions, rather than cluttering up an issue thread.

Also, I wasnā€™t entirely sure that that was the consensus; There were a number of people in favour, but no ā€œPerfect! Letā€™s do it this way!ā€, so I figured Iā€™d add another voice to the consensus, just in case. :smile:

Either Iā€™m looking in the wrong spot (incredibly likely), or itā€™s all still very very nascent. So Iā€™m left not really knowing where best to try and help out; Completely as a result of my own inexperience, without question.

Just saw /zsup/firmware-rust/issues/2 on GitHub (this portal wonā€™t let me link it, as more than 4 links show up in the preview pane)

ā€¦ Clearly I need more coffee >_<

Sorry for tanking the S:N ratio