Giter Site home page Giter Site logo

flipperzero's Introduction

Rust for Flipper Zero 🐬❤️🦀

crates.io Flipper Zero API docs.rs MIT license

This project allows writing Rust-based applications for the Flipper Zero.

It doesn't have any direct dependency on flipperzero-firmware or toolchain, so it can be used to build binaries with no external dependencies.

These crates only support the core and alloc crates.

The Rust thumbv7em-none-eabihf target currently only supports no_std development. This means it's not possible to use anything in the std crate.

SDK version

Currently supports SDK 62.3 ([email protected]).

The crate major version number will be updated after a bump in API version in the Flipper Zero firmware.

Crate version API version
Unreleased 62.3
0.11.x 35.0
0.10.x 28.2
0.9.x 23.0
0.8.x 20.0
0.7.x 14.0
0.6.x 11.2
0.5.x 10.1
0.4.x 7.5
0.3.x 2.2

Crates

Initial setup

  1. Install rustup by following the instructions on rustup.rs.
  2. Use rustup to install the thumbv7em-none-eabihf target:
    rustup target add thumbv7em-none-eabihf
    

Writing an application

The Flipper Zero supports installing externally built applications on the SD card.

See flipperzero-template🚀 to help you get started.

License

Licensed under the MIT License. See LICENSE for details.

flipperzero's People

Contributors

agarof avatar burnoo avatar dcoles avatar dependabot[bot] avatar georgikoemdzhiev avatar giacomoferretti avatar jarviscraft avatar kitterion avatar maybe-hello-world avatar mogenson avatar nereuxofficial avatar sitischu avatar ssoudan avatar str4d avatar strosel avatar tsarfox avatar zhaofengli avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flipperzero's Issues

Test harness

Currently all testing facilities are disabled for the crates in this repo. It makes sense because everything will only run on an actual Flipper Zero, but it does make verification of things tricky.

It would be useful to have a test harness, that runs the test binaries on a connected Flipper Zero. I'm imagining something like the integration tests for the yubikey crate, which require setting a YUBIKEY_SERIAL environment variable in order to run. The test-with crate might also be helpful here, specifically #[test_with::env(FLIPPER_ZERO_SERIAL_PORT)] or something, that can be used to enable at compilation time tests that require a connected Flipper Zero.

Where is the .fap?

First and foremost, I would just like to say you are my lord and savior. However, I am new to rust, and I have a question about where the .fap file is. My cargo workspace is called flipperapp, do I rename the flipperapp binary to flipperapp.fap? Thanks!

Failed to build hello-rust example

When trying to build the hello-rust example (cargo build --release), it fails and prints the following error:

error: the 'cargo' binary, normally provided by the 'cargo' component, is not applicable to the 'nightly-2022-11-03-aarch64-apple-darwin' toolchain

Steps to reproduce

  1. Download ZIP from GitHub
  2. Move hello-rust folder out (I moved it to my projects folder)
  3. Modify Cargo.toml so that dependencies don't specify paths
  4. In the hello-rust directory, run the following commands:
    1. rustup default nightly
    2. rustup target add thumbv7em-none-eabihf
    3. cargo build --release
  5. Build fails

Desktop

  • OS: macOS Ventura 13.2 (a) Beta (22D7750270d)
  • rustup: 1.25.1 (bb60b1e89 2022-07-12)
  • rustc: 1.67.0-nightly (edf018221 2022-11-02)
  • cargo: 1.67.0-nightly (7e484fc1a 2022-10-27)

Potential solution

In the rust-toolchain.toml file, changing channel to "nightly" seems to resolve this issue.

Astro Nvim no Intellisense in project.

Hi, I tried today to clone this project, try to build, upload my .fap apps, and I was successful but I noticed that there were no Intellisense suggestions at all. I do have rust_analyzer and it works on normal rust projects, can you tell me what I need to do for my Astro Nvim Intellisense/rust_analyzer to work properly with this project? Thank you.

Add support for FAP icons

Discussed in #20

Originally posted by GitCat3 December 7, 2022
So I notice that there seems to be no way to create an icon for the .fap in the flipper zero, is this planned or is there a way to do this and i'm just dumb?

build: automate bindings generation

Description

Introduction

Bindings are currently generated using tools/ based on bindgen. This works okay but have the following cons:

  • any updates to original flipper headers require manual regeneration of the sources:
    • this also requires some maintainer (i.e. @dcoles) aware of the right generation process (including correct file and environment setup);
  • this is hardly reproducible due to non-trivial build order;
  • this process is not transparent.

The suggestion

The idea is to replace this approach with a build.rs-based generation.

I expect this to be in a form of a cross-platform build.rs in crates/sys capable of running codegeneration by itself.

Unanswered questions

Original definitions location

It's hard for me to decide what is the best way to store files with original header-definitions. I guess that it is worth looking on other projects utilizing build.rs for FFI code generation.

One way may be using git submodules, although I look at this as not the best mechanism which is hard to maintain sometimes so looking at alternative approaches is something expected.

We may also be able to utilize api_symbols.csv provided in firmware repository as it seems to list available functions, but it seems to lack any struct definitions and type aliases which is a serious limitation.

Version updates

It is also worth discussing the mechanism for performing version updates.

I would suggest following dependabot's approach of performing scheduled update checks. We could theoretically configure GitHub Actions to run on schedule checking for fresh firmware releases and, in case of them being present, run automation to create a PR with header updates.

Better string formatting

As a developer, there are currently three main options for formatting strings in Flipper apps:

Safe Expressiveness Binary size overhead
std::fmt High High1
ufmt Low Low
sys::furi_string_printf High None2

Using std::fmt is the most flexible and familiar option for developers, but it can add 10+ KB to the overall binary size simply by formatting a single string. While this may be a reasonable trade-off made by an app developer, it's not something we can impose on all users of the flipperzero crates.

Enter ufmt which has substantially lower binary overhead, but comes at the expense of expressiveness (no padding/alignment/formatting options, no support for floats) and requires implementing the non-standard ufmt::uDisplay and ufmt::uWrite traits.

Finally there is the built-in sys::furi_string_printf C function, which has no binary-size overhead (it's provided by the Furi runtime), but is problematic to use in Rust because it has a variadic-based interface which is both unsafe and difficult to support in Rust (Rust currently only has limited support for C-variadic functions).

It would be nice to provide an option somewhere in the middle.

Footnotes

  1. See #48 and Formatting is Unreasonably Expensive for Embedded Rust

  2. Provided by Furi runtime

Question about non-core functionality

I'm looking into trying to build some additional IR functionality to a F0 (so it can send/receive via kermit). It's extremely possible it'll be a dead end due to hardware constraints, but if I were to get it working -- probably using bindgen around e-kermit -- would this be the kind of thing that you'd prefer live in its own separate library, or that might end up as a PR here as a separate crate? Nothing about this is mission-critical for the majority of flipper users, but I'm not sure if you'd like this repo to be a clearinghouse for various rust-related community efforts or if you'd like to keep it to the basics that apply to everyone once they get filled out?

Add ability to flash / launch a fap from Rust

It would be good to remove the remaining python/fbt tooling from the development toolchain/flow entirely. I had a quick looksies at how the official flipper zero tooling does file transfers and it looks like it might actually be very easy:

https://github.com/flipperdevices/flipperzero-firmware/blob/663eb6cd6d4a14d00caf93d402b71eadb9a4d63f/scripts/flipper/storage.py#L203

I'm getting back into Flipper stuff again (needless to say I need to rewrite all my trash onto your mature crates lol), so I might give this a go if you don't get around to it first.

`rt`: Add framework for creating heap statics

Normal Rust binaries will initialize heap statics on start, and then essentially leak the memory. This works fine because the memory is cleaned up during process exit. We can't assume the same with a FAP, so if we want to support "statics", we should provide a way in the runtime for initializing them before the user's app code runs, and freeing them after it exits.

Scene Management & Menu's example

Hi,

I'm currently working on a project using FZ sample apps as a reference, and I've encountered a challenge with scene management and creating menus. Despite studying the source code of these apps written in C, I'm having difficulty understanding how scenes are structured, how menus are implemented, and how to manage the flow between different scenes.

My goal is to develop an application with four distinct screens:

HomeScreen: Contains an "Ok" button that transitions to the next screen.
Menu Screen: Features two buttons, each leading to a separate scene.
Scene1: Displays the simple text "Scene1".
Scene2: Displays the simple text "Scene2".

I'm familiar with creating a single scene, but I'm unsure about how to expand this into full scene management to allow for seamless navigation through the app. Specifically, I want to enable users to move between screens using "OK" and "back" buttons, with the ability to exit the application only from the HomeScreen. Any other screen should return the user to the previous screen.

In the C examples I've reviewed, there's typically a scenes/ folder containing separate .c and .h files for each scene. I'd like to adopt a similar structure for my project, which is in Rust, something like:

src/
- scenes/
  -- home-screen.rs
  -- main-menu.rs 
  -- scene1.rs
  -- scene2.rs
  -- mod.rs
- main.rs

Although I've seen examples covering scene management and menus/submenus, they are often deeply intertwined with complex C code, making it hard for me to extract the parts relevant to my needs.

Could anyone provide a simplified example or guidance on how to handle scene management and menus for my project in Rust? Any help would be greatly appreciated as it would significantly aid my learning process.

Inconsistent use of `furi::time::Duration` and `core::time::Duration`

Currently we have some APIs that use core::time::Duration (e.g. flipperzero::furi::thread::sleep) and some that use flipperzero::furi::time::Duration (e.g. flipperzero::gpio::i2c). This isn't great since it leads to a rather confusing situation where you have two incompatible Duration implementations in scope.

My understanding that the main reason that flipperzero::furi::time exists is that there is no Instant implementation in core::time and to better align with the kernel's tick resolution.

A quick comparison:

core::time::Duration flipperzero::furi::time::Duration flipperzero::furi::time::Instant
Representation { secs: u64, nanos: u32 } { ticks: u32 } { ticks: u32 }
Size 12 bytes 4 bytes 4 bytes
Limits ~5.8¹¹ years ~49.7 days1 ± ~24.9 days1
Resolution 1 ns 1 ms1 1 ms1

Consumers:

Function Limits Resolution
furi_delay_us(u32) ~1.2 hours 1 μs
furi_delay_ms(u32) ~49.7 days 1 ms
furi_delay_tick(u32) ~49.7 days1 1 ms1
furi_hal_i2c_tx(..., u32) ~49.7 days 1 ms

Footnotes

  1. Assuming the default configTICK_RATE_HZ_RAW = 1000 2 3 4 5 6

tools: Migrate from text-based CLI to Protobuf RPC

Currently the binaries in tools/ use the text-based CLI over the serial port to communicate with a Flipper Zero and run FAPs. We should instead use the start_rpc_session CLI command to drop into the Protobuf RPC control mode, using e.g. the prost crate. This would remove most of the hand-written CLI parsing logic, and probably be more accurate and flexible.

In particular, I am curious about whether PB_App.StartRequest is specifically a request to Applications that enables us to provide arguments to FAPs (which the text CLI loader open Applications foo.fap does not), or whether it is a request to loader (and thus the same as the text CLI).

Notification_messages example?

Hi, can we get simple example how to use notification/notification_messages in rust? So far demo with DialogMessageButtons is only way we can interact with key presses. I am new to Rust and Flipper Zero and would really appropriate sample how to achieve this. Simple key input check and log message. Also GPIO would also be great to have some guides.
Thank you!

Allow running MIRI

Introduction

While some Flipper abstractions are easy to port to Rust, some have complicated lifecycles and are tricky to be wrapped in safe abstractions. Current work done in #29 is an illustration of this point.


The most common problems appearing are

Aliasing

Arguably, the most complicated and still volatile part of Unsafe Rust especially painful when ahving to work with APIs which originally provide shared access (first of all, callbacks).

This is also especially tricky artound Box-based allocations for which there are uniquness guarantees at some point.

Concurrency & mmulti-threading

When and where do we have to insert synchronizations for soundness?

This is specifically important for callback-based APIs.

Extern type trickery

See rust-lang/rfcs#1861 for what we may need ideally.

We may want to create formally unsized wrapper-types of form

#[repr(transparent)]
struct Foo {
    // this should be an extern (thus unsized) type
    // making this wrapper unsized
    raw: sys::Foo,
}

which would only be usable via pointers (and their derivatives, i.e. references) safely transmutable to/from raw pointers.


In order to facilitate the creation of such abstractions, more tools could be used.

Description

We should try allowing the usage of MIRI in the way similar to how the tests are run currently.

This would give us a chance to catch some errors inm wrapper implementations.

Please, add example with sys::furi_message_queue_get

I tried to reproduce this example https://github.com/flipperdevices/flipperzero-firmware/blob/dev/applications/examples/example_images/example_images.c , but can't get returned FuriStatusOk(or other value in bindings) in while loop

        let mut running = true;
        let mut event: sys::InputEvent = sys::InputEvent {
            sequence: 0,
            key: 0,
            type_: 0,
        };

        let event_ptr: *mut c_void = &mut event as *mut _ as *mut c_void;

        while running == true {
            if sys::furi_message_queue_get(event_queue, event_ptr, 100) == sys::FuriStatus_FuriStatusOk {
                println!("Event: {:?}", event);
                running = false;
                if (event.type_ == sys::InputType_InputTypePress) || (event.type_ == sys::InputType_InputTypeRepeat) {

                    println!("Event: {:?}", event);
                    match event.key {
                        sys::InputKey_InputKeyBack => {
                            running = false;
                            break;
                        }
                        _ => {
                            running = false;
                        }
                    }
                }
            }
        }

USB and Bluetooth Remote controller example

Hi, I would like to make simple USB/Bluetooth Remote controller (HID - Keyboard) with few screens (like elgato stream deck). Is there any example of how to make Rust version of Remote keyboard app from FlipperZero?
All I actually need is sample of how to use USB/Bluetooth to send keys like keyboard button press when user selects one option and clicks ok.

Document macro-ed binary invocation methods

Being a bit of a devils advocate here: main also, seems to be unsafe since the caller is again required to provide a valid pointer.

The same logic works here as with parse: since it is a generated function, it is accessible to nearby code which may, for example, call it with null.

Not to be too copy-pasty here, something like

# Safety

This should only be called by Flipperzero OS
and never manually.

would be enough.

Originally posted by @JarvisCraft in #95 (comment)

[Question] Creating FAP from scratch

Hello, I am trying to create a custom FAP using flipperzero-rs crate. I am new to Rust and not sure what I am doing wrong.
I created a new crate with following Cargo.toml

[package]
name = "pms"
version = "0.1.0"
edition = "2021"

[dependencies]
flipperzero = "0.7.2"
flipperzero-rt = "0.7.2"
flipperzero-sys = "0.7.2"

And when I run cargo build --release I get this:

ruslan@nba-153-01a-UZ ~/d/pms (master)> cargo build --release
   Compiling flipperzero-rt v0.7.2
   Compiling flipperzero-sys v0.7.2
   Compiling flipperzero v0.7.2
   Compiling pms v0.1.0 (/home/ruslan/dev/pms)
error: language item required, but not found: `eh_personality`
  |
  = note: this can occur when a binary crate with `#![no_std]` is compiled for a target where `eh_personality` is defined in the standard library
  = help: you may be able to compile for a target that doesn't need `eh_personality`, specify a target with `--target` or in `.cargo/config`

error: could not compile `pms` due to previous error

And if I use this command cargo build --target thumbv7em-none-eabihf I get really long error message which complains for rust-lld: error: undefined symbol: gpio_ext_pc0

How do I should modify Cargo.toml / command to build the app?

Tested fix for renaming build outputs with .fap extension.

HI, I've read on previous issue (#18 (comment)) about .fap files and location. I found a way to have build output renamed to .fap with Cargo.toml update.
Here is the original post about this topic --> rust-lang/cargo#1706 (comment)

Here is my Cargo.toml

cargo-features = ["different-binary-name"]    # <-- this 
[package]
name = "hello-rust"
version = "0.1.0"
edition = "2021"
rust-version = "1.64.0"
autobins = false
autoexamples = false
autotests = false
autobenches = false

[[bin]]
name = "hello-rust"
filename = "hello-rust.fap"  # <-- this
bench = false
test = false

[dependencies]
flipperzero = { version = "0.6.0", path = "../../crates/flipperzero" }
flipperzero-sys = { version = "0.6.0", path = "../../crates/sys" }
flipperzero-rt = { version = "0.6.0", path = "../../crates/rt" }

And that is pretty much it, I have created a build and upload it to Flipper and works like a charm.
Maybe you could update all other examples to include this.

Cargo releases compatible with API 46.0 (and 39.2)

The API 46.0 was released as part of 0.95.0, would you consider pushing that to cargo please?

Also, 0.93.0 OFW is the last version before the NFC refactor that has a few regressions. For that reason the Unleashed FW hasn't rebased yet and so it might be a good idea to actually release API 39.2 as well.

I created a patch for that MarSik@95ead55 but I can't post it as a PR, because your main branch has already moved to API 46.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.