Author Topic: Rust Tools and Resources for Embedded  (Read 3384 times)

0 Members and 1 Guest are viewing this topic.

Offline ulianoTopic starter

  • Regular Contributor
  • *
  • Posts: 172
  • Country: it
Rust Tools and Resources for Embedded
« on: March 30, 2023, 10:04:55 am »
PLEASE, PLEASE, PLEASE try not to pollute this thread with ad hominem, strawman, funky and flawed edge cases... we already have the other thread  for that.
It would be nice to collect here only constructive discussion and useful information.

FLASHING/RUNNING/LOGGING/DEBUGGING
Two somewhat overlapping tool-sets competing for sponsors, the first one
probe-rs
is the rusty implementation that replaces gdb (includes a gdb stub for seamless integration)
On windows if you want to use J-Link you need to replace its USB drivers with zadig  thus preventing the regular Segger tools to connect to it (how can possibly those people think that you ever wanna do that???)
beside the debugger itself, two command line tools and a vscode extension are provided:
cargo-flash: downloads the code to the MCU,  starts it, and returns
cargo-embed: downloads the code to the MCU,  starts it, open RTT terminal (s) and starts the debugger server (you need to connect to it manually)
can save logs -AFTER- you kill the communication, saving does not support defmt (see below)
probe-rs-debugger: a vscode extension that allows seamless debugging experience by configuring launch.json, logs are directed to a vscode terminal (I don't know if and how the can be automatically saved). This extension + probe-res functionally replace cortex-debug + openocd which is also a viable alternative, even if I perceive the older (and possibly going to be dismissed) one.
To my understanding these are the "original" tools on which the second toolset
knurling tools
is built upon. They provide different resources:
probe-run: is a cargo-embed replacement which adds stack back-traces (albeit a false positive warning "(HOST) WARN  call stack was corrupted; unwinding could not be completed still appears notwithstanding the fact that its issue has been closed since long time) and integrates with vscode extension rust-analyzer by enabling the run|debug button (this doesn't work for me, initially I believed that it was due to the funky macros of RTIC (see below) but then I downloaded an official template which doesn't use RTIC macros, here run|debug appears -only- over #[test] functions. Fun fact: if you delete the target directory and perform a developer-reload-window in vscode the run|debug button appears momentarily). Probe run sends the logs to stdout allowing redirection to an online, host side, application (e.g. for plotting, oh I'm gonna love this so much!). To facilitate writing such applications probe-run can format the defmt (see below) logs in json format.
defmt: logging framework optimized for efficiency through compile time encoding of the log format that are decoded host side. This, combined with RTT, allows for the highest logging speed. Inside a vscode defmt messages are clickable leading to the source log statement.
flip-link: zero-cost stack overflow protection. (nice and easy)
app-template: showcase for defmt logging, flip-link protection and run time panic.
defmt-test: didn't have time for this

REAL TIME AND CONCURRENCY
Using plain rust in a MCU where ISR are essential for most projects is kinda pain in the ass as the usual pattern (is there any alternative??) is to initialize ISR resources in the main thread and the borrow checker makes this simple thing difficult. Following this pattern there are no "security" issues as when initalizing interrupts are disabled. The
RTIC
framework was devised to facilitate this process, it organizes the code in tasks of four kinds:
two running at the "main" level one after the other
init: here you set up all the hardware resources and divides them in local (meant to be used by one and only one task) and shared with different strategies to prevent data races
idle: useful if you want to implement sleep between interrupts or if you are a superloop nostalgic
and two interrupt driven
hardware: old style ISR
software: these can be scheduled _at or _after some time or duration by exploiting unused interrupt vectors
All this "magic" takes care for you of the tedious chore of fighting the borrow checker when you don't need it and is based on macros that aggressively rewrite the source code before sending it to the compiler (nothing to do with the dumb cpp #define(s) )
Its API are under fast development so stability does not live here, but the major bummer is that (for the moment?) is cortex-m only, however this seems to fit quite well in the ISR driven MCU paradigm for REAL TIME applications. Here is an application template using defmt.
Another option which seem to have a lot of hype (more than RTIC) is
Embassy
which approaches concurrency through coroutines exploiting rust's async/await mechanism which is, you know, a form of multithreading not really REAL TIME. Yes you can spawn different executors each with its own priority (and its own stack!!) but these are no ISR. This and the fact that it comes with loads of communication resources (USB, Bluetooth, LoRa, Ethernet,...) seems to suggest that its major application is on the IoT side of embedded. (This is a very superficial glimpse on Embassy which I didn't have yet the time to investigate in some detail)

MISSING
- levels of abstractions (many)
- useful crates (libraries, drivers,... )
- ...

INTERIM CONSIDERATIONS.
Before convincing others of the superior safety of RUST based solely on its borrow checker, enthusiasts should take the time to guide those who are interested in approaching this language in the field of embedded systems. These individuals may wish to continue working with their hardware and using the paradigm for which it was designed, namely, responding to events through interrupts and creating drivers that take advantage of DMA. Furthermore, enthusiasts should provide information on the tools to use, some of which may not have undergone recent development, and they should strive to ensure that these tools are as bug-free as possible (meaning that at least the features advertised in one page websites should work! and, sadly no, some don't!).


« Last Edit: March 30, 2023, 10:42:51 am by uliano »
 
The following users thanked this post: nctnico, JPortici

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 19470
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: Rust Tools and Resources for Embedded
« Reply #1 on: March 30, 2023, 10:29:09 am »
PLEASE, PLEASE, PLEASE try not to pollute this thread with ad hominem, strawman, funky and flawed edge cases... we already have the other thread  for that.
It would be nice to collect here only constructive discussion and useful information.

Seconded!

Thanks for starting this thread and collating some information. Let us all hope it remains a source of information.
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Offline ulianoTopic starter

  • Regular Contributor
  • *
  • Posts: 172
  • Country: it
Re: Rust Tools and Resources for Embedded
« Reply #2 on: March 31, 2023, 08:01:29 am »
I'm afraid to have removed the lid of the Pandora's jar, and I don't like at all what I found.

Lets start from some silly code, just a few lines more than rtic template, task 1 panics after 100 seconds while task 2 logs the tick count every second.

Code: [Select]
#![no_main]
#![no_std]

use rtic411 as _; // global logger + panicking-behavior + memory layout

#[rtic::app(
    device = stm32f4xx_hal::pac, // TODO: Replace `some_hal::pac` with the path to the PAC
    dispatchers = [SPI1,SPI2] // TODO: Replace the `FreeInterrupt1, ...` with free interrupt vectors if software tasks are used
)]
mod app {
    use dwt_systick_monotonic::DwtSystick;
    use rtic411::exit;
    use stm32f4xx_hal::{
        prelude::*,
    };
    // TODO: Add a monotonic if scheduling will be used
    #[monotonic(binds = SysTick, default = true)]
    type DwtMono = DwtSystick<96_000_000>;

    // Shared resources go here
    #[shared]
    struct Shared {
        // TODO: Add resources
    }

    // Local resources go here
    #[local]
    struct Local {
        // TODO: Add resources
    }

    #[init]
    fn init(cx: init::Context) -> (Shared, Local, init::Monotonics) {

        defmt::info!("init");

        // setup clocks
        let rcc = cx.device.RCC.constrain();       
        let mut dcb = cx.core.DCB;       
        let dwt = cx.core.DWT;       
        let systick = cx.core.SYST;       
        let clocks = rcc
        .cfgr
        .use_hse(25.MHz())
        .sysclk(96.MHz())
        .freeze();

        // Setup the monotonic timer
        let mono = DwtSystick::new(&mut dcb, dwt, systick, clocks.sysclk().to_Hz());

        task1::spawn_after(100.secs()).ok();
        task2::spawn_after(1.secs()).ok();
        //timer.start(1.secs()).unwrap();
        (
            Shared {
                // Initialization of shared resources go here
            },
            Local {
                //timer
                // Initialization of local resources go here
            },
            init::Monotonics(mono
                // Initialization of optional monotonic timers go here
            ),
        )
    }

    // Optional idle, can be removed if not needed.
    #[idle]
    fn idle(_: idle::Context) -> ! {
        defmt::info!("idle");

        loop {
            continue;
        }
    }

    // TODO: Add tasks
    #[task]
    fn task1(_cx: task1::Context) {
        defmt::info!("Hello from task1!");
        exit();
    }

    #[task]
    fn task2(_cx: task2::Context) {
        defmt::info!("Hello from task2!");
        defmt::trace!("time: {}",monotonics::now());
        task2::spawn_after(1.secs()).ok();
    }
}

here dwt_systick_monotonic is used to measure time, according to rtic book it's
Quote
a more efficient (tickless) implementation - requires both SysTick and DWT, supports both high resolution and large time spans
then  lookin' into its source you learn that you can configure it in your cargo.toml file activating the "extend" feature to allow for longer durations/interval using 64bits  like so

Code: [Select]
dwt-systick-monotonic = {version = "1.1.0", feature = "extend"}
then you run your the silly example and, surprise it panics!

Code: [Select]
> cargo run --bin minimal
warning: D:\stuff\rustbedded\rtic411\Cargo.toml: unused manifest key: dependencies.dwt-systick-monotonic.feature
   Compiling rtic411 v0.1.0 (D:\stuff\rustbedded\rtic411)
    Finished dev [optimized + debuginfo] target(s) in 0.68s
     Running `probe-run --chip STM32F411CEUx target\thumbv7em-none-eabihf\debug\minimal`
(HOST) INFO  flashing program (16 pages / 16.00 KiB)
(HOST) INFO  success!
────────────────────────────────────────────────────────────────────────────────
0 INFO  init
└─ minimal::app::init @ src\bin\minimal.rs:35
1 ERROR panicked at 'attempt to multiply with overflow', C:\Users\uliano\.cargo\registry\src\github.com-1ecc6299db9ec823\fugit-0.3.6\src\duration.rs:597:1
└─ panic_probe::print_defmt::print @ C:\Users\uliano\.cargo\registry\src\github.com-1ecc6299db9ec823\panic-probe-0.3.0\src\lib.rs:91
────────────────────────────────────────────────────────────────────────────────
stack backtrace:
   0: HardFaultTrampoline
      <exception entry>
   1: lib::inline::__udf
        at ./asm/inline.rs:181:5
   2: __udf
        at ./asm/lib.rs:51:17
   3: cortex_m::asm::udf
        at C:\Users\uliano\.cargo\registry\src\github.com-1ecc6299db9ec823\cortex-m-0.7.7\src\asm.rs:43:5
   4: rust_begin_unwind
        at C:\Users\uliano\.cargo\registry\src\github.com-1ecc6299db9ec823\panic-probe-0.3.0\src\lib.rs:72:9
   5: core::panicking::panic_fmt
        at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/core/src/panicking.rs:64:14
   6: core::panicking::panic
        at /rustc/8460ca823e8367a30dda430efda790588b8c84d3/library/core/src/panicking.rs:114:5
   7: minimal::app::init
   8: minimal::app::rtic_ext::main::{{closure}}
        at src\bin\minimal.rs:6:1
   9: minimal::app::rtic_ext::main::__rtic_init_resources
        at src\bin\minimal.rs:6:1
  10: rtic::export::Priority::new
  11: main
        at src\bin\minimal.rs:6:1
  12: Reset
(HOST) WARN  call stack was corrupted; unwinding could not be completed
(HOST) ERROR the program panicked
error: process didn't exit successfully: `probe-run --chip STM32F411CEUx target\thumbv7em-none-eabihf\debug\minimal` (exit code: 22)
D:\stuff\rustbedded\rtic411
>

knowing that integer are checked for overflow when not building in release mode... I can observe that 100 seconds get wrapped

Code: [Select]
> cargo run --bin minimal --release
warning: D:\stuff\rustbedded\rtic411\Cargo.toml: unused manifest key: dependencies.dwt-systick-monotonic.feature
    Finished release [optimized + debuginfo] target(s) in 0.09s
     Running `probe-run --chip STM32F411CEUx target\thumbv7em-none-eabihf\release\minimal`
(HOST) INFO  flashing program (10 pages / 10.00 KiB)
(HOST) INFO  success!
────────────────────────────────────────────────────────────────────────────────
0 INFO  init
└─ minimal::app::init @ src\bin\minimal.rs:35
1 INFO  idle
└─ minimal::app::idle @ src\bin\minimal.rs:71
2 INFO  Hello from task2!
└─ minimal::app::task2 @ src\bin\minimal.rs:87
3 TRACE time: 96001360 ticks @ (1/96000000)
└─ minimal::app::task2 @ src\bin\minimal.rs:88
4 INFO  Hello from task2!
└─ minimal::app::task2 @ src\bin\minimal.rs:87
5 TRACE time: 192007175 ticks @ (1/96000000)
└─ minimal::app::task2 @ src\bin\minimal.rs:88
6 INFO  Hello from task2!
└─ minimal::app::task2 @ src\bin\minimal.rs:87
7 TRACE time: 288012990 ticks @ (1/96000000)
└─ minimal::app::task2 @ src\bin\minimal.rs:88
8 INFO  Hello from task2!
└─ minimal::app::task2 @ src\bin\minimal.rs:87
9 TRACE time: 384018805 ticks @ (1/96000000)
└─ minimal::app::task2 @ src\bin\minimal.rs:88
10 INFO  Hello from task2!
└─ minimal::app::task2 @ src\bin\minimal.rs:87
11 TRACE time: 480024620 ticks @ (1/96000000)
└─ minimal::app::task2 @ src\bin\minimal.rs:88
12 INFO  Hello from task2!
└─ minimal::app::task2 @ src\bin\minimal.rs:87
13 TRACE time: 576030435 ticks @ (1/96000000)
└─ minimal::app::task2 @ src\bin\minimal.rs:88
14 INFO  Hello from task2!
└─ minimal::app::task2 @ src\bin\minimal.rs:87
15 TRACE time: 672036250 ticks @ (1/96000000)
└─ minimal::app::task2 @ src\bin\minimal.rs:88
16 INFO  Hello from task2!
└─ minimal::app::task2 @ src\bin\minimal.rs:87
17 TRACE time: 768042065 ticks @ (1/96000000)
└─ minimal::app::task2 @ src\bin\minimal.rs:88
18 INFO  Hello from task2!
└─ minimal::app::task2 @ src\bin\minimal.rs:87
19 TRACE time: 864047880 ticks @ (1/96000000)
└─ minimal::app::task2 @ src\bin\minimal.rs:88
20 INFO  Hello from task2!
└─ minimal::app::task2 @ src\bin\minimal.rs:87
21 TRACE time: 960053695 ticks @ (1/96000000)
└─ minimal::app::task2 @ src\bin\minimal.rs:88
22 INFO  Hello from task1!
└─ minimal::app::task1 @ src\bin\minimal.rs:81
────────────────────────────────────────────────────────────────────────────────
stack backtrace:
   0: lib::inline::__bkpt
        at ./asm/inline.rs:14:5
   1: __bkpt
        at ./asm/lib.rs:51:17
   2: rtic411::exit
        at src\lib.rs:30:5
   3: minimal::app::task1
        at src\bin\minimal.rs:82:9
   4: minimal::app::SPI1::{{closure}}
        at src\bin\minimal.rs:6:1
   5: rtic::export::run
        at C:\Users\uliano\.cargo\registry\src\github.com-1ecc6299db9ec823\cortex-m-rtic-1.1.4\src\export.rs:68:9
   6: SPI1
        at src\bin\minimal.rs:6:1
      <exception entry>
   7: minimal::app::idl
        at src\bin\minimal.rs:73:9
   8: main
        at src\bin\minimal.rs:6:1
   9: Reset
(HOST) WARN  call stack was corrupted; unwinding could not be completed
(HOST) INFO  device halted without error
D:\stuff\rustbedded\rtic411
>

leading me to think that, nevermind the "extend" feature, here times are specified by 32bit structure.

So I turned my attention to fugit, the crate that actually implements interval and durations, where i read:

Quote
Support for both u32 and u64 backing storage ... Selection of base happens at compile time

the hell? didn't I selected the u64 by specifying "extend" in dwt-systick-monotonic? Who brought in fugit with u32 backing store? I didn't knew I was on the edge of the abyss and I looked for a tool to print the building crate dependencies:


Code: [Select]
> cargo tree
rtic411 v0.1.0 (D:\stuff\rustbedded\rtic411)
├── cortex-m v0.7.7
│   ├── bare-metal v0.2.5
│   │   [build-dependencies]
│   │   └── rustc_version v0.2.3
│   │       └── semver v0.9.0
│   │           └── semver-parser v0.7.0
│   ├── bitfield v0.13.2
│   ├── critical-section v1.1.1
│   ├── embedded-hal v0.2.7
│   │   ├── nb v0.1.3
│   │   │   └── nb v1.1.0
│   │   │       └── defmt v0.3.2
│   │   │           ├── bitflags v1.3.2
│   │   │           └── defmt-macros v0.3.3 (proc-macro)
│   │   │               ├── defmt-parser v0.3.1
│   │   │               ├── proc-macro-error v1.0.4
│   │   │               │   ├── proc-macro-error-attr v1.0.4 (proc-macro)
│   │   │               │   │   ├── proc-macro2 v1.0.54
│   │   │               │   │   │   └── unicode-ident v1.0.8
│   │   │               │   │   └── quote v1.0.26
│   │   │               │   │       └── proc-macro2 v1.0.54 (*)
│   │   │               │   │   [build-dependencies]
│   │   │               │   │   └── version_check v0.9.4
│   │   │               │   ├── proc-macro2 v1.0.54 (*)
│   │   │               │   ├── quote v1.0.26 (*)
│   │   │               │   └── syn v1.0.109
│   │   │               │       ├── proc-macro2 v1.0.54 (*)
│   │   │               │       ├── quote v1.0.26 (*)
│   │   │               │       └── unicode-ident v1.0.8
│   │   │               │   [build-dependencies]
│   │   │               │   └── version_check v0.9.4
│   │   │               ├── proc-macro2 v1.0.54 (*)
│   │   │               ├── quote v1.0.26 (*)
│   │   │               └── syn v1.0.109 (*)
│   │   └── void v1.0.2
│   └── volatile-register v0.2.1
│       └── vcell v0.1.3
├── cortex-m-rtic v1.1.4
│   ├── bare-metal v1.0.0
│   ├── cortex-m v0.7.7 (*)
│   ├── cortex-m-rtic-macros v1.1.6 (proc-macro)
│   │   ├── proc-macro-error v1.0.4 (*)
│   │   ├── proc-macro2 v1.0.54 (*)
│   │   ├── quote v1.0.26 (*)
│   │   ├── rtic-syntax v1.0.3
│   │   │   ├── indexmap v1.9.3
│   │   │   │   └── hashbrown v0.12.3
│   │   │   │   [build-dependencies]
│   │   │   │   └── autocfg v1.1.0
│   │   │   ├── proc-macro2 v1.0.54 (*)
│   │   │   ├── quote v1.0.26 (*)
│   │   │   └── syn v1.0.109 (*)
│   │   └── syn v1.0.109 (*)
│   ├── heapless v0.7.16
│   │   ├── hash32 v0.2.1
│   │   │   └── byteorder v1.4.3
│   │   └── stable_deref_trait v1.2.0
│   │   [build-dependencies]
│   │   └── rustc_version v0.4.0
│   │       └── semver v1.0.17
│   ├── rtic-core v1.0.0
│   └── rtic-monotonic v1.0.0
│   [build-dependencies]
│   └── version_check v0.9.4
├── defmt v0.3.2 (*)
├── defmt-rtt v0.3.2
│   ├── critical-section v0.2.8
│   │   ├── bare-metal v1.0.0
│   │   └── critical-section v1.1.1
│   └── defmt v0.3.2 (*)
├── dwt-systick-monotonic v1.1.0
│   ├── cfg-if v1.0.0
│   ├── cortex-m v0.7.7 (*)
│   ├── fugit v0.3.6
│   │   ├── defmt v0.3.2 (*)
│   │   └── gcd v2.3.0
│   └── rtic-monotonic v1.0.0
├── panic-probe v0.3.0
│   ├── cortex-m v0.7.7 (*)
│   └── defmt v0.3.2 (*)
└── stm32f4xx-hal v0.15.0
    ├── bare-metal v1.0.0
    ├── bitflags v1.3.2
    ├── cortex-m v0.7.7 (*)
    ├── cortex-m-rt v0.7.3
    │   └── cortex-m-rt-macros v0.7.0 (proc-macro)
    │       ├── proc-macro2 v1.0.54 (*)
    │       ├── quote v1.0.26 (*)
    │       └── syn v1.0.109 (*)
    ├── defmt v0.3.2 (*)
    ├── embedded-dma v0.2.0
    │   └── stable_deref_trait v1.2.0
    ├── embedded-hal v0.2.7 (*)
    ├── embedded-hal v1.0.0-alpha.8
    │   └── nb v1.1.0 (*)
    ├── embedded-storage v0.2.0
    ├── fugit v0.3.6 (*)
    ├── fugit-timer v0.1.3
    │   ├── fugit v0.3.6 (*)
    │   └── nb v1.1.0 (*)
    ├── nb v1.1.0 (*)
    ├── rand_core v0.6.4
    ├── rtic-monotonic v1.0.0
    ├── stm32f4 v0.15.1
    │   ├── bare-metal v1.0.0
    │   ├── cortex-m v0.7.7 (*)
    │   ├── cortex-m-rt v0.7.3 (*)
    │   └── vcell v0.1.3
    ├── systick-monotonic v1.0.1
    │   ├── cortex-m v0.7.7 (*)
    │   ├── fugit v0.3.6 (*)
    │   └── rtic-monotonic v1.0.0
    ├── time v0.3.20
    │   └── time-core v0.1.0
    └── void v1.0.2
D:\stuff\rustbedded\rtic411
>

It's just me freaking out for the multiple usages of many different crates OVER WHICH I CAN'T HAVE ANY CONTROL, or can I?, worse the version may be different in each usage and even worst the same crate has a newer version of itself as a dependency?



Sorry, here it is where I call myself out. Even if I had time (my week of forced vacation is turning to an end) and will, I don't even know how and to whom report this gigantic issue.

/rant alert

How can people using this stuff not be aware of this mess?

Maybe now I understand why there is so much focus on safety, could it be a gigantic diversion?

/end rant
« Last Edit: March 31, 2023, 08:14:36 am by uliano »
 

Offline gekkio

  • Newbie
  • Posts: 3
  • Country: fi
Re: Rust Tools and Resources for Embedded
« Reply #3 on: March 31, 2023, 11:55:54 am »
Looks like the extend feature didn't get enabled because there was a typo: in Cargo.toml, you should list it under features, not feature:

Code: [Select]
dwt-systick-monotonic = { version = "1.1.0", features = ["extend"] }
If you look closely, you even got a warning about it, which is unfortunately easy to miss, especially if you get a lot of output lines when building your project:

Code: [Select]
> cargo run --bin minimal --release
warning: D:\stuff\rustbedded\rtic411\Cargo.toml: unused manifest key: dependencies.dwt-systick-monotonic.feature

It's not quite the same thing, but imagine you typoed some very important #define in some C code and the program instead used a default value leading to problems. It would be lovely to get a better error message and/or catch these at compile time, but it's unfortunately not always easy.  :'(

I've used both RTIC and Embassy and recently had a slightly similar timer overflow issue with the latter, which turned out to be a configuration error caused by my own code. At first I felt annoyed, but in retrospect I think it was great to get a panic in debug mode instead of having the entire timekeeping of the system messed up silently. The main challenge was understanding the real cause of the problem based on the error message, which was a fairly generic overflow panic in some timer code.

One useful tip: you can get a fairly verbose but useful explanation of actually enabled features of dependencies by running cargo tree -e features
 

Offline ulianoTopic starter

  • Regular Contributor
  • *
  • Posts: 172
  • Country: it
Re: Rust Tools and Resources for Embedded
« Reply #4 on: March 31, 2023, 12:16:07 pm »
OMG!!  |O

Funny thing is that Rust-analyzer wasn't complaining at all.

However now I Have a new problem: the feature is enabled but I cant use anymore 1.secs() as I get:

Code: [Select]
error: could not compile `rtic411` due to 4 previous errors
error[E0308]: mismatched types
  --> src\bin\minimal.rs:51:28
   |
51 |         task1::spawn_after(100.secs()).ok();
   |         ------------------ ^^^^^^^^^^ expected `u64`, found `u32`
   |         |
   |         arguments to this function are incorrect
   |
   = note: expected struct `dwt_systick_monotonic::fugit::Duration<u64, 1, 96000000>`
              found struct `dwt_systick_monotonic::fugit::Duration<u32, _, _>`
note: function defined here
 

Offline gekkio

  • Newbie
  • Posts: 3
  • Country: fi
Re: Rust Tools and Resources for Embedded
« Reply #5 on: March 31, 2023, 12:36:45 pm »
My guess is that you have imported fugit::ExtU32 in that file, which should be replaced by fugit::ExtU64. One way to think about the error is that the .secs() function currently only exists for the u32 type, so Rust infers the type of the literal 100 to be u32 instead of u64.

In general Rust is much stricter about integer types than C (no implicit int conversions!), but also can infer the intended type of literals correctly as long as there's enough information available for the compiler.

In this case you could also use a more explicit literal 100_u64 to force the type, but this would just lead to a different error since the secs function would simply not exist for the type at all.
 

Offline ulianoTopic starter

  • Regular Contributor
  • *
  • Posts: 172
  • Country: it
Re: Rust Tools and Resources for Embedded
« Reply #6 on: March 31, 2023, 12:54:39 pm »

However now I Have a new problem: the feature is enabled but I cant use anymore 1.secs()

got away with dwt_systick_monotonic::fugit::Duration::<u64,1, 96_000_000>::from_ticks(96_000_000)

it seems that there are 2 different implementation of fugit, one based on u32, brought in by

Code: [Select]
    use stm32f4xx_hal::{
        prelude::*,
    };

and used everywhere, for example here for rate units:

Code: [Select]
        let clocks = rcc
        .cfgr
        .use_hse(25.MHz())
        .sysclk(96.MHz())
        .freeze();

the other based on u64 used by fugit.

even if I could express a duration in terms of the latter I wasn't able to use shortcut methods (like .secs() )for human readable units.

This design with compile time option for the types is very much convoluted.



« Last Edit: March 31, 2023, 01:02:24 pm by uliano »
 

Offline ulianoTopic starter

  • Regular Contributor
  • *
  • Posts: 172
  • Country: it
Re: Rust Tools and Resources for Embedded
« Reply #7 on: March 31, 2023, 01:01:52 pm »
My guess is that you have imported fugit::ExtU32 in that file, which should be replaced by fugit::ExtU64. One way to think about the error is that the .secs() function currently only exists for the u32 type, so Rust infers the type of the literal 100 to be u32 instead of u64.

In general Rust is much stricter about integer types than C (no implicit int conversions!), but also can infer the intended type of literals correctly as long as there's enough information available for the compiler.

In this case you could also use a more explicit literal 100_u64 to force the type, but this would just lead to a different error since the secs function would simply not exist for the type at all.

I didn't it was stm32f4xx_hal to import it, and for the good reason that it is using it in u32 version.

as for the 1_u64.secs I get

no method named `secs` found for type `u64` in the current scope
items from traits can only be used if the trait is in scope

sure, the current scope has u32 version brought in by hal's prelude.
 

Offline ulianoTopic starter

  • Regular Contributor
  • *
  • Posts: 172
  • Country: it
Re: Rust Tools and Resources for Embedded
« Reply #8 on: March 31, 2023, 01:20:54 pm »
this is solved by specifying both u32 and u64 before .secs() & co:

Code: [Select]
    use dwt_systick_monotonic::fugit::*;
    use stm32f4xx_hal::{
        prelude::*,
    };

...

        let clocks = rcc
        .cfgr
        .use_hse(25_u32.MHz())
        .sysclk(96_u32.MHz())
        .freeze();

...

        task2::spawn_after(1_u64.secs()).ok();
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 14445
  • Country: fr
Re: Rust Tools and Resources for Embedded
« Reply #9 on: March 31, 2023, 08:40:03 pm »
What does a 'panic' on some MCU lead to? ::)
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26892
  • Country: nl
    • NCT Developments
Re: Rust Tools and Resources for Embedded
« Reply #10 on: March 31, 2023, 08:48:12 pm »
What does a 'panic' on some MCU lead to? ::)
(Watchdog) reset ofcourse...
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf