rust-embedded / cortex-m

Low level access to Cortex-M processors
Apache License 2.0
834 stars 152 forks source link

enable_icache gives linker error #245

Closed diondokter closed 4 years ago

diondokter commented 4 years ago

Hey all,

when enabling the ICache, I now get this linker error: image

It seems it's got to do with the change in #234. The __enable_icache symbol that's defined in the assembly can't be found.

I'm compiling for the stm32h743 on the latest nightly (rustc 1.46.0-nightly (346aec9b0 2020-07-11)).

My .cargo/config (it's just the default I believe):

[target.thumbv7em-none-eabihf]
runner = 'arm-none-eabi-gdb -x debug.gdb'
rustflags = [
  # LLD (shipped with the Rust toolchain) is used as the default linker
  "-C", "link-arg=-Tlink.x",

  # if you run into problems with LLD switch to the GNU linker by commenting out
  # this line
  #"-C", "linker=arm-none-eabi-ld",

  # if you need to link to pre-compiled C libraries provided by a C toolchain
  # use GCC as the linker by commenting out both lines above and then
  # uncommenting the three lines below
  # "-C", "linker=arm-none-eabi-gcc",
  # "-C", "link-arg=-Wl,-Tlink.x",
  # "-C", "link-arg=-nostartfiles",
]

[build]
target = "thumbv7em-none-eabihf"

I've tried the commented options as well, but that didn't help.

adamgreig commented 4 years ago

Huh, the same .cargo/config works for me on both stable and nightly Rust with scb.enable_icache(), and I'm seeing the __enable_icache symbol present in the output executable (and it's definitely in bin/thumbv7em-none-eabihf.a too).

Could you try cargo clean and then cargo build --target thumbv7em-none-eabihf --release and then find the libcortex-m.a file in your target/thumbv7em-none-eabihf/release directory and run arm-none-eabi-nm against it, to check you're linking to an up-to-date version of libcortex-m.a (which should be a copy of cortex-m/bin/thumbv7em-none-eabihf.a)?

On a random test build I just did from clean against cortex-m master, I see:

arm-none-eabi-nm target/thumbv7em-none-eabihf/release/build/cortex-m-c697a65722ec350b/out/libcortex-m.a

cortex-m.o:
00000000 T __bkpt
<snip>
00000000 T __wfi

cortex-m-v7.o:
00000000 T __basepri_max
00000000 T __basepri_r
00000000 T __basepri_w
00000000 T __enable_dcache
00000000 T __enable_icache
00000000 T __faultmask
<snip>
diondokter commented 4 years ago

I've tried it on both Windows 10 and Ubuntu 18.04 now. Same result.

Both had cargo clean and cargo build --target thumbv7em-none-eabihf --release. My linux compile was on a fresh rustup install.

My target folder does contain a libcortex-m-rt.a, but not a libcortex-m.a. This is the same as when I go back to an older commit that works, though.

adamgreig commented 4 years ago

Something's definitely wrong if you're not getting a libcortex-m.a anywhere in target/, you'll need that for any cortex-m assembly routines. If you run cargo with -v do you see a line about the cortex-m build script, like this?

Running `target/release/build/cortex-m-d899f986a1a35fe7/build-script-build`

The build script is responsible for copying the relevant target binary archive into libcortex-m.a in the target folder and for telling Cargo to link against it. You should also see the output folder included in the linker search path in the final step, like

-L target/thumbv7em-none-eabihf/release/build/cortex-m-b6b455b6792cab16/out

How are you depending on cortex-m? If you're using a git path, maybe it would be worth checking out the repository and trying a [patch.crates-io] cortex-m = { path = "../cortex-m" } instead, just to help troubleshoot.

diondokter commented 4 years ago

This is my verbose output:

cargo -v build --target thumbv7em-none-eabihf --release
<snip>
Compiling cortex-m v0.6.2 (https://github.com/rust-embedded/cortex-m#ec2e1783)
<snip>
Running `rustc --crate-name build_script_build --edition=2018 C:\Users\diond\.cargo\git\checkouts\cortex-m-6c400ec63ab46e19\ec2e178\build.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -C opt-level=3 -Cembed-bitcode=no -C debuginfo=2 --cfg "feature=\"inline-asm\"" -C metadata=e0c6265c96799c88 -C extra-filename=-e0c6265c96799c88 --out-dir C:\Repos\work\project\target\release\build\cortex-m-e0c6265c96799c88 -L dependency=C:\Repos\work\project\target\release\deps --cap-lints allow`
<snip>
Running `C:\Repos\work\project\target\release\build\cortex-m-e0c6265c96799c88\build-script-build`
<snip>
Running `rustc --crate-name cortex_m --edition=2018 C:\Users\diond\.cargo\git\checkouts\cortex-m-6c400ec63ab46e19\ec2e178\src\lib.rs --error-format=json --json=diagnostic-rendered-ansi,artifacts --crate-type lib --emit=dep-info,metadata,link -C opt-level=3 -Cembed-bitcode=no -C debuginfo=2 --cfg "feature=\"inline-asm\"" -C metadata=63c85c03c39ce01c -C extra-filename=-63c85c03c39ce01c --out-dir C:\Repos\work\project\target\thumbv7em-none-eabihf\release\deps --target thumbv7em-none-eabihf -L dependency=C:\Repos\work\project\target\thumbv7em-none-eabihf\release\deps -L dependency=C:\Repos\work\project\target\release\deps --extern bare_metal=C:\Repos\work\project\target\thumbv7em-none-eabihf\release\deps\libbare_metal-fc9c47509f7a523b.rmeta --extern bitfield=C:\Repos\work\project\target\thumbv7em-none-eabihf\release\deps\libbitfield-1cb9757b1dd6ad57.rmeta --extern volatile_register=C:\Repos\work\project\target\thumbv7em-none-eabihf\release\deps\libvolatile_register-2942452464761746.rmeta --cap-lints allow -C link-arg=-Tlink.x --cfg cortex_m --cfg armv7m --cfg armv7em --cfg has_fpu`
<snip>
<linker error>

I don't see the out folder mentioned with a -L option. Again, cortex-m-rt does have that.

So the build script is built and it is executed. Also tried checking out the repo and use a path to it, but the result is the same.

adamgreig commented 4 years ago

Oh, right, nuts, I think I've worked out what the issue is. If you disable the inline-asm feature does the build work? Our build.rs script only links against the pre-built object if inline-asm is not enabled, but we now require it in all builds for the cache management.

diondokter commented 4 years ago

Ah I see! I turned off the inline-assembly feature and now it works.

I took a look at the build script and saw this if statement:

    if target.starts_with("thumb") && env::var_os("CARGO_FEATURE_INLINE_ASM").is_none() {
        fs::copy(
            format!("bin/{}.a", target),
            out_dir.join(format!("lib{}.a", name)),
        ).unwrap();

        println!("cargo:rustc-link-lib=static={}", name);
        println!("cargo:rustc-link-search={}", out_dir.display());
    }

It only copies the libcortex-m.a if inline asm is turned off.

adamgreig commented 4 years ago

Looks like we both realised at the same time. I've opened the PR above which should fix this, though I'm not sure if there's any disadvantage of always linking the prebuilt object.