Amanieu / corosensei

A fast and safe implementation of stackful coroutines in Rust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Using on RP2040 - armv6 with partial Thumb7

kpishere opened this issue · comments

In attempting to build for RP2040 target="thumbv6m-none-eabi", I get the errors shown below.

Inspecting some build files, out/probe1|2|3, I see errors in :

probe0 - r11_available is false? Due to error below.
probe1 - r7_available is false due to return values not being equal? "!0 = !{i32 63}"
probe2 - r9_available is false due to return values not being equal? "!0 = !{i32 63}"

If the above were true, I'd see --cfg r9_reserved and there would be a build panic but I don't see any of that. All I see is --cfg is_thumb

I'm a little confused by what is happening here.

stderr:

error[E0463]: can't find crate for `std`
  |
  = note: the `thumbv6m-none-eabi` target may not support the standard library
  = note: `std` is required by `probe0` because it does not declare `#![no_std]`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0463`.
error: cannot use register `r11`: the frame pointer (r11) cannot be used as an operand for inline asm
 --> <anon>:2:56
  |
2 | pub fn probe() { let _ = unsafe { core::arch::asm!("", out("r11") _) }; }
  |                                                        ^^^^^^^^^^^^

error: aborting due to previous error

    Running `rustc --crate-name corosensei --edition=2021 /Users/kevinpeck/.cargo/git/checkouts/corosensei-fbd4e5d7357ec9c8/0985c39/src/lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts,future-incompat --crate-type lib --emit=dep-info,metadata,link -C opt-level=3 -C embed-bitcode=no -C codegen-units=1 -C debuginfo=2 -C debug-assertions=on -C metadata=5a185a71dee15bf6 -C extra-filename=-5a185a71dee15bf6 --out-dir /Users/kevinpeck/Desktop/RepRap-RatRigVCore3/rp2040-project-template/target/thumbv6m-none-eabi/debug/deps --target thumbv6m-none-eabi -L dependency=/Users/kevinpeck/Desktop/RepRap-RatRigVCore3/rp2040-project-template/target/thumbv6m-none-eabi/debug/deps -L dependency=/Users/kevinpeck/Desktop/RepRap-RatRigVCore3/rp2040-project-template/target/debug/deps --extern cfg_if=/Users/kevinpeck/Desktop/RepRap-RatRigVCore3/rp2040-project-template/target/thumbv6m-none-eabi/debug/deps/libcfg_if-98ec3ee8113dde9b.rmeta --extern scopeguard=/Users/kevinpeck/Desktop/RepRap-RatRigVCore3/rp2040-project-template/target/thumbv6m-none-eabi/debug/deps/libscopeguard-4bc87324e88bd5c9.rmeta --cap-lints allow -C linker=flip-link -C link-arg=--nmagic -C link-arg=-Tlink.x -C link-arg=-Tdefmt.x -C inline-threshold=5 -C no-vectorize-loops --cfg is_thumb`

error: registers must be in range r0-r7 or lr
   |
note: instantiated into assembly here
  --> <inline asm>:13:6
   |
13 | push {r11, lr}
   |      ^

error: registers must be in range r0-r7 or pc
   |
note: instantiated into assembly here
  --> <inline asm>:23:5
   |
23 | pop {r11, pc}
   |     ^

error: registers must be in range r0-r7 or lr
   |
note: instantiated into assembly here
  --> <inline asm>:39:6
   |
39 | push {r11, lr}
   |      ^

error: instruction requires: thumb2
   |
note: instantiated into assembly here
  --> <inline asm>:40:1
   |
40 | str sp, [r1, #-8]!
   | ^

error: instruction requires: thumb2
   |
note: instantiated into assembly here
  --> <inline asm>:52:1
   |
52 | adr lr, stack_init_trampoline_return + 1
   | ^

error: invalid instruction, any one of the following would fix this:
   |
note: instantiated into assembly here
  --> <inline asm>:53:1
   |
53 | ldr pc, [r1, #4]
   | ^

note: instruction requires: thumb2
   |
note: instantiated into assembly here
  --> <inline asm>:53:1
   |
53 | ldr pc, [r1, #4]
   | ^

note: operand must be a register in range [r0, r7]
   |
note: instantiated into assembly here
  --> <inline asm>:53:5
   |
53 | ldr pc, [r1, #4]
   |     ^

error: could not compile `corosensei` due to 6 previous errors

Caused by:
  process didn't exit successfully: `... (exit status: 1)```

It looks like autocfg::new() fails with this target as it requires stdlib to work. If I comment out all lines and set flags literally, it behaves as expected. Looks like can't use that class.

autocfg automatically detects whether a target requires #![no_std] and should insert it automatically. It works fine when I tested locally for the thumbv6m-none-eabi target.

Some changes to the assembly code were still required to support Thumb1, see #4.

@Amanieu Omg, fantastic! Looked over your changes, was just working on it. Would have taken me for ever with having to learn the constructs of Rust.

Still though, I'm getting the error about std not supported on target. I'm just building the rp2040-project-template and here is the first bit of my main.rs (below).

In that project I've added the following dependancy: corosensei = { path = "../corosensei", default-features = false }

where my change log for your crate look like :

commit e296893cc205702855b377839cda87b7fca91fce (HEAD -> dev)
Author: Amanieu d'Antras <amanieu@gmail.com>
Date:   Thu Jun 30 17:36:57 2022 +0100

    Add support for thumbv6m-none-eabi

commit 078aa0e25f7c5ef52c4528fb51a72f627e6e66d8
Author: Amanieu d'Antras <amanieu@gmail.com>
Date:   Thu Jun 30 17:48:15 2022 +0100

    Update CI to use cross v0.2.2

commit 0985c390846865e33b6ac51d7646b9966ce5f58d (upstream/master, origin/master, origin/HEAD, master)`
``


Main.rs file for project rp2040-project-template:

#![no_std]
#![no_main]

use bsp::entry;
use defmt::*;
use defmt_rtt as _;
use embedded_hal::digital::v2::OutputPin;
use embedded_time::fixed_point::FixedPoint;
use panic_probe as _;
use corosensei::{Coroutine, CoroutineResult};
use rp_pico as bsp;
use bsp::hal::{
clocks::{init_clocks_and_plls, Clock},
pac,
sio::Sio,
watchdog::Watchdog,
};

#[entry]
\....



Also, I'm not using nightly.  Do I need to use that?

Well, by doing this ..

diff --git a/build.rs b/build.rs
index ce7f542..b7d539c 100644
--- a/build.rs
+++ b/build.rs
@@ -19,10 +19,10 @@ fn main() {
     }
 
     // Probe some registers using asm! to see if they are reserved.
-    let cfg = autocfg::new();
-    let r7_available = cfg.probe_expression("unsafe { core::arch::asm!(\"\", out(\"r7\") _) }");
-    let r9_available = cfg.probe_expression("unsafe { core::arch::asm!(\"\", out(\"r9\") _) }");
-    let r11_available = cfg.probe_expression("unsafe { core::arch::asm!(\"\", out(\"r11\") _) }");
+//    let cfg = autocfg::new();
+    let r7_available = false; //cfg.probe_expression("unsafe { core::arch::asm!(\"\", out(\"r7\") _) }");
+    let r9_available = false; //cfg.probe_expression("unsafe { core::arch::asm!(\"\", out(\"r9\") _) }");
+    let r11_available = true; //cfg.probe_expression("unsafe { core::arch::asm!(\"\", out(\"r11\") _) }");

I'm able to build the package directly with cargo build --verbose --target=thumbv6m-none-eabi --no-default-features

But I still get the following error :

error: cannot use register `r11`: the frame pointer (r11) cannot be used as an operand for inline asm
   --> src/arch/arm.rs:85:21
    |
85  |                       lateout("r11") _,
    |                       ^^^^^^^^^^^^^^^^
...
442 | /     asm_may_unwind!(
443 | |         // R6 is pushed separately because we want the FP/LR pair to be together
444 | |         // at the top of the stack so that it acts a frame record.
445 | |         "push {{r6}}",
...   |
470 | |         in("r2") sp.get(),
471 | |     );
    | |_____- in this macro invocation
    |
    = note: this error originates in the macro `asm_clobbers` (in Nightly builds, run with -Z macro-backtrace for more info)

If I change that value to r7 with :

diff --git a/src/arch/arm.rs b/src/arch/arm.rs
index e5fe33a..3f5ebe3 100644
--- a/src/arch/arm.rs
+++ b/src/arch/arm.rs
@@ -82,7 +82,7 @@ cfg_if::cfg_if! {
             (options($($opt:ident),*), $($asm:tt)*) => {
                 asm!(
                     $($asm)*
-                    lateout("r11") _,
+                    lateout("r7") _,
                     lateout("r4") _, lateout("r5") _, lateout("r8") _, lateout("r10") _,
                     lateout("q4") _, lateout("q5") _, lateout("q6") _, lateout("q7") _,
                     clobber_abi("C"),

It builds. Work? I dunno, the tests don't build.

Can you try using the latest nightly compiler to see if this fixes the problem?

@Amanieu Sure. So, I ran this ..

rustup override set nightly
info: using existing install for 'nightly-x86_64-apple-darwin'
info: override toolchain for '/Users/kevinpeck/Desktop/RepRap-RatRigVCore3/corosensei' set to 'nightly-x86_64-apple-darwin'

  nightly-x86_64-apple-darwin unchanged - rustc 1.64.0-nightly (7425fb293 2022-06-30)

Got an error suggesting this, so ran this ... rustup target add thumbv6m-none-eabi

It installed these ..

info: downloading component 'rust-std' for 'thumbv6m-none-eabi'
info: installing component 'rust-std' for 'thumbv6m-none-eabi'

And now it builds with cargo build --verbose --target=thumbv6m-none-eabi --no-default-features

Thank-you! It builds without changes! Tests don't work so .. we'll do some basic stuff and see.

Looks like I have to provide my own stack implementation so got to figure out that.

I think this was just a case of inline assembly still having some bugs in older rustc versions.