Open dbrgn opened 8 years ago
I actually took a stab at this the other day. I am really close but ran into an issue. I am happy to dig into it more tonight and this weekend.
Here's my progress so far: https://github.com/tjpeden/firmware/commit/38529b100cc9c6e2866968d3c6e6ae1bb2162c71
There are some formatting changes in application.rs
that aren't really important, but what is important is that I changed the delay
parameters down to 100ms but my photon is still blinking as if it were 500ms (from when I flashed the original code). The DFU shows successful in the output of make PLATFORM=photon all program-dfu
in main/
So, that is what I will figure out next.
Let me know if you want/need me to change anything I've done. I'm compiling a few other libraries from rust but I'm not 100% sure if we need/want them?
I'm now sure how to tell Cargo to let the makefiles dictate the target dirs. Thoughts?
@tjpeden Did you forget to commit the Cargo.toml file? AFAIK, you can't call cargo
without a Cargo.toml file and a project directory. See http://doc.crates.io/guide.html
I'm compiling a few other libraries from rust but I'm not 100% sure if we need/want them?
We only need the core crate in this case.
I'm now sure how to tell Cargo to let the makefiles dictate the target dirs. Thoughts?
If you mean telling cargo to use a custom target directory, then you can use a configuration file with the following key:
# .cargo/config
[build]
target-dir = "custom/target/directory"
Then cargo will output the binary/docs to "custom/target/directory" instead of the default "target" directory.
Other thoughts:
With cargo support we wouldn't need the build_core.sh script. There is cargo crate: rust-libcore that builds the core crate when used as a dependency.
Ideally, I'd like to only use cargo to build particle applications. I'm envisioning something like this:
$ cargo new --bin app
$ cd app
# depend on particle libraries
$ vim Cargo.toml
$ cat Cargo.toml
[package]
name = "app"
version = "0.1.0"
authors = ["me"]
[dependencies]
particle = "0.1.0"
# write app
$ vim src/main.rs
# builds the core crate, particle's C dependencies, and the app
$ cargo build --target=photon
# This installs the cargo-flash and cargo-debug binaries used below
$ cargo install particle-tools
# Custom cargo subcommand that flashes the application
# This subcommand can just shell out to `particle flash ...`
$ cargo flash
# Or, start a remote gdb session
$ cargo debug
I'm sure this is feasible because I have done the cargo build
part here. Check the "apps" and the travis output, specially the *-size
and *-objdump
calls. But, I'm not sure how to expand this to produce a binary or ELF file that's usable by particle's bootloader because I'm not familiar with bootloaders in general as I always flash programs directly at the start of the flash memory (0x08000000).
Can anyone point me to information about particle's bootloader or bootloaders in general. Does the bootloader expect an ELF file that starts at some specific address, other than 0x08000000? Does the particle's bootloader expect the ELF file to contain some specific symbols?
@japaric woah, that would be pretty awesome :)
@japaric, you're right, I did. Fixed. Also just committed my attempt at using .cargo/config
. The problem is I think that the path is based on a couple make variables (if I understand the make spaghetti correctly lol). Either way, it doesn't place the output files where make expects them, even if I specify the directory that the .o
is normally placed, cargo will still use it's own directory structure from there. Not to mention I currently have it outputting a .a
file.
All of that aside, everything I've seen online has cautioned against using that crate, but maybe that's wrong? I like the idea of using only cargo for building and programming the rust code.
What crate should we use to test being able to use extern crate
to make sure it works?
Unfortunately, my fiance won't let me work on it anymore today. lol
@japaric, I really like that project you linked. I think that would be an awesome way to model the Particle Rust support
@japaric This is looking great. Thank you!
Photon firmware consists of several dynamically linked modules. If you run make
in the modules folder 3 of the modules will be built if you want to see some examples.
0x08000000
Bootloader0x08020000
System part 10x08060000
System part 20x080a0000
User applicationThe addresses and number of modules may be different on different platforms. I often reference this file in the CLI: https://github.com/spark/particle-cli/blob/master/lib/deviceSpecs/specifications.js
Additionally, there are several pieces of data prepended and appended to our modules using linker scripts. Here's a tool for reading them: https://github.com/spark/binary-version-reader
Hope that helps!
@tjpeden
@japaric, you're right, I did. Fixed. Also just committed my attempt at using .cargo/config. The problem is I think that the path is based on a couple make variables (if I understand the make spaghetti correctly lol). Either way, it doesn't place the output files where make expects them, even if I specify the directory that the .o is normally placed, cargo will still use it's own directory structure from there. Not to mention I currently have it outputting a .a file.
I guess you can let cargo
output its files in the default target directory, and add some cp commands to the Makefile to move the files when the rest of the build system expects them.
About the .a file, you should be able to use something like cargo rustc -- --emit=obj
to make cargo output .o files.
All of that aside, everything I've seen online has cautioned against using that crate, but maybe that's wrong? I like the idea of using only cargo for building and programming the rust code.
You mean the rust-libcore crate? What's the argument against it? The zinc project also uses that crate to build the core crate.
What crate should we use to test being able to use extern crate to make sure it works?
You can test with the spin
crate, that crate works with just the core
crate.
@towynlin That's pretty helpful. I took a quick look and I'm starting to understand how the pieces fall together. Looks like the setup
and loop
symbols are mandatory, right? During the weekend, I'll take a closer look to the linker scripts and see if I can hack my copper
cargo project to generate an ELF file that matches the layout of the user-part example you pointed out. I don't have hardware yet so that's as far I can go right now.
Added the spin crate and got the following error running make PLATFORM=photon all program-dfu
from main/
:
...
cargo rustc --target thumbv7m-none-eabi -- -O -Z no-landing-pads -g -L ../build/arm/rust
Updating registry `https://github.com/rust-lang/crates.io-index`
Compiling spin v0.3.5
/home/tjp/.multirust/toolchains/nightly/cargo/registry/src/github.com-88ac128001ac3a9a/spin-0.3.5/src/lib.rs:1:1: 1:1 error: can't find crate for `core` [E0463]
This is how I have the Cargo.toml
configured:
[package]
name = "application"
version = "0.1.0"
authors = ["TJ Peden <tj@tjcoding.com>"]
[lib]
crate-type = ["staticlib"]
[dependencies]
rust-libcore = "0.0.3"
spin = "0.3.5"
I'm not sure how to fix that.
@tjpeden Ah right, spin
can't be cross compiled like this because it (spin
) would need to depend on rust-libcore
but it doesn't. One "solution" would be install the libcore.rlib that cargo build --target=
generated in your rust installation directory. But I don't like this solution because it pollutes your Rust install. Let me discuss this with other Rust devs to see if there's a cleaner solution.
IRC?
IRC?
Yeah, I asked one of the core devs that's working on Rust cross compilation story. Cargo doesn't support this use case out the box, but there's an RFC with a possible solution for this but requires adding new features to cargo.
I also received an idea on how to support this use case without needing new cargo features but hasn't been explored/implemented yet. The idea is that you create a "sysroot" (a directory tree) that contains the cross compiled core crate, and then configure cargo to use rustc --sysroot ...
instead of just rustc
, that way cargo looks for "standard" dependencies (like libcore) in the sysroot you created rather than in the rust installation directory. I'm going to explore this idea and report back my findings.
Awesome! Thanks @japaric
@japaric love your goal of a cargo build process, would love to see the build process work like that.
I created a cargo sysroot subcommand that implements the solution I mentioned above. More details in the README. This subcommand depends on this cargo PR, which hasn't landed yet, so it's not currently usable with the latest cargo nightly.
@tjpeden You may want to test that ^. You'll need to compile cargo checked out at that PR though.
I will indeed
@japaric I am having trouble building Cargo on that branch. Is there something special one has to do other than the instructions in the readme?
@japaric I am having trouble building Cargo on that branch. Is there something special one has to do other than the instructions in the readme?
Cargo is a Cargo project, so I just did cd cargo && cargo build
. The new cargo binary will be in target/debug/cargo
. I haven't use the make
instructions in the readme in a long time.
That works a lot better, thanks!
This is what I got:
$ ~/code/cargo/target/debug/cargo sysroot --target ../build/arm/rust/thumbv7m-none-eabi.json target/sysroot
INFO: source up to date
INFO: symlinking host crates
INFO: building the core crate
An unknown error occurred
To learn more, run the command again with --verbose.
thread '<main>' panicked at 'assertion failed: try!(Command:: new ( "cargo" ) . args ( & [ "build" , "--target" ] ) . arg (
ctx . target ) . arg ( if ctx . release { "--release" } else { "--lib" }
) . current_dir ( src_dir ) . env ( "CARGO_TARGET_DIR" , temp_dir ) .
status ( )).success()', /home/tjp/.cargo/git/checkouts/cargo-sysroot-c5462c8bc31a2590/master/src/main.rs:204
An unknown error occurred
To learn more, run the command again with --verbose.
@tjpeden Ah, yes. cargo-sysroot
doesn't support taking a file path as target right now (I'll fix that later). For now, you'll need to have the json file in the same directory where cargo sysroot
is called, and you'll have to call cargo sysroot --target thumbv7m-none-eabi
(without the json extension).
I'm getting the same thing :-/
Could you add --verbose and pass it along?
Could you add --verbose and pass it along?
done
Okay, I think I have this setup wrong.
$ ~/code/cargo/target/debug/cargo sysroot --target thumb7m-none-eabi target/sysroot --verbose
INFO: source up to date
INFO: symlinking host crates
INFO: building the core crate
Process didn't exit successfully: `rustc - --crate-name _ --crate-type dylib --crate-type staticlib --crate-type bin --print=file-names --target thumb7m-none-eabi` (exit code: 101)
--- stderr
error: Error loading target specification: Could not find specification for target "thumb7m-none-eabi"
thread '<main>' panicked at 'assertion failed: try!(cmd . current_dir ( src_dir ) . env ( "CARGO_TARGET_DIR" , temp_dir ) .
status ( )).success()', .cargo/git/checkouts/cargo-sysroot-c5462c8bc31a2590/master/src/main.rs:238
An unknown error occurred
To learn more, run the command again with --verbose.
$ ll
total 48K
drwxrwxr-x 11 tjp tjp 4.0K Jan 19 23:45 applications/
-rw-rw-r-- 1 tjp tjp 1.6K Jan 19 23:46 build.mk
-rw-r--r-- 1 tjp tjp 3.6K Feb 3 23:14 Cargo.lock
-rw-rw-r-- 1 tjp tjp 163 Feb 4 08:14 Cargo.toml
-rw-rw-r-- 1 tjp tjp 839 Jan 19 23:29 import.mk
drwxrwxr-x 2 tjp tjp 4.0K Jan 19 23:45 inc/
drwxrwxr-x 7 tjp tjp 4.0K Jan 19 23:29 libraries/
-rw-rw-r-- 1 tjp tjp 701 Jan 19 23:45 makefile
drwxrwxr-x 3 tjp tjp 4.0K Jan 29 17:43 src/
drwxrwxr-x 3 tjp tjp 4.0K Feb 3 10:31 target/
drwxrwxr-x 8 tjp tjp 4.0K Jan 19 23:45 tests/
-rw-r--r-- 1 tjp tjp 381 Feb 3 12:02 thumbv7m-none-eabi.json
Do I have thumb7m-none-eabi.json
in the right place? Also, thanks for adding that verbose flag, worked like a charm!
@tjpeden
There's a typo in this command
$ ~/code/cargo/target/debug/cargo sysroot --target thumb7m-none-eabi target/sysroot --verbose
The target is missing a "v": thumbv7m-none-eabi, because that's the name of the spec file: thumbv7m-none-eabi.json.
Once you fix the typo you should see this line in the log:
INFO: copy target specification file
This could have been detected and the tool could have informed you about this, but I haven't implemented nice error reporting (yet).
P.S. If you are using zinc's target specification files then delete the "data-layout" field from the file or you'll hit this issue.
I apologize, I should have caught that. I'm using the target file from build/arm/rust
so I don't think it's an issue?
However, the fs::copy
line failed:
~/code/cargo/target/debug/cargo sysroot --target thumbv7m-none-eabi target/sysroot --verbose
INFO: source up to date
INFO: symlinking host crates
INFO: building the core crate
Fresh core v0.0.0 (<redacted>)
INFO: copy the core crate to the sysroot
thread '<main>' panicked at 'fs::copy(src, dst)', .cargo/git/checkouts/cargo-sysroot-c5462c8bc31a2590/master/src/main.rs:257
An unknown error occurred
To learn more, run the command again with --verbose.
It's not an access issue (I'm on Ubuntu) so I'm not sure what would cause it to fail. Thoughts?
I'm using the target file from build/arm/rust so I don't think it's an issue?
If you get a LLVM assertion while building the core crate, remove the "data-layout" field from the json file should fix. It's problem that appeared in recent nightlies.
It's not an access issue (I'm on Ubuntu) so I'm not sure what would cause it to fail. Thoughts?
No idea with just that information. But I pushed a debug branch to cargo-sysroot, it'll print the src and dst arguments of the failing fs::copy and will also preserve the temporary directory so you can inspect it. You can install that branch with cargo install --git https://github.com/japaric/cargo-sysroot/ --branch debug
.
Also, could we take this discussion somewhere else? Either the cargo-sysroot bug tracker or to IRC (I'm japaric on freenode, I'm on #rust, #cargo, #particle, etc)
What's the status here? I'm waiting for advances in Cargo support in order to continue working on library features :)
Any news, @tjpeden?
I received my Photon this past Monday and got a LED blinking using the particle-cli
tool. So, I'm going to look into this soon. I'm going to try two approaches: (a) have the Makefile build system use Cargo and (b) have Cargo call the Makefile system. I'll report back as soon as I get any of them working.
P.S. I was hoping to use the particle-cli
tool as a reference on how the binaries are assembled but the particle compile
command uses a web service to compile the program. Is the backend code published somewhere?
@japaric Instructions on how to compile the firmware locally can be found here. All the firmware and a ton of information can be found in that repo. There's also this write up which contains more details about the build setup.
Thanks for helping out, I'm looking forward to using Cargo with the Photon!
I took the route (b) I mentioned before and I got a working Cargo project that builds photon apps. Check https://github.com/japaric/photon for details. We can use it as a starting point to prototype rustic bindings around the HAL. I'll look into that next; getting bindgen to emit low level bindings to the HAL would be a great start. I'd also like to build a cargo subcommand that flashes the ELF generated by Cargo into the photon because it requires computing a CRC.
@japaric that's awesome, could you contribute that as a PR?
actually, now that I'm looking at your repo, I suppose that doesn't make a ton of sense, since it's a rebuild and not a fork
Awesome! This week I'm quite busy but I'll take a closer look next week.
Cargo is the Rust package manager. It handles metadata, compilation and dependencies.
If we want to properly integrate with the Rust library ecosystem, we should support Cargo.
This would replace #7 and #8.