Skip to content

cortex-r: _critical_section_1_0_acquire and _critical_section_1_0_release are undefined #19

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
xobs opened this issue Mar 28, 2025 · 6 comments

Comments

@xobs
Copy link

xobs commented Mar 28, 2025

I'm not sure why, but when I try building with cortex-ar = {version = "0.1.0", features = ["critical-section-single-core"]} I get errors such as "rust-lld: error: undefined symbol: _critical_section_1_0_acquire".

I can confirm that the critical section code is being built, but it's not present in the final binary.

I've managed to work around the issue by reimplementing it in my main, but from what I understand it should already work.

There's no LTO going on. I'm building for armebv7r-none-eabi with Rust 1.85.1.

Workaround:

#[no_mangle]
pub fn _critical_section_1_0_acquire() -> bool {
    use core::sync::atomic;
    // the i bit means "masked"
    let was_active = !cortex_ar::register::Cpsr::read().i();
    cortex_ar::interrupt::disable();
    atomic::compiler_fence(atomic::Ordering::SeqCst);
    was_active
}

#[no_mangle]
pub fn _critical_section_1_0_release(was_active: bool) {
    use core::sync::atomic;
    // Only re-enable interrupts if they were enabled before the critical section.
    if was_active {
        atomic::compiler_fence(atomic::Ordering::SeqCst);
        // Safety: This is OK because we're releasing a lock that was
        // entered with interrupts enabled
        unsafe {
            cortex_ar::interrupt::enable();
        }
    }
}
@xobs
Copy link
Author

xobs commented Mar 28, 2025

The project I'm working on, as it stands: xobs/tms570-flash-algorithm@5358a9a

@jonathanpallant
Copy link
Contributor

Huh

#20

@jonathanpallant
Copy link
Contributor

Try:

diff --git a/src/main.rs b/src/main.rs
index 8744df0..e9f367a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,32 +1,9 @@
 #![no_std]
 #![no_main]

-#[no_mangle]
-pub fn _critical_section_1_0_acquire() -> bool {
-    use core::sync::atomic;
-    // the i bit means "masked"
-    let was_active = !cortex_ar::register::Cpsr::read().i();
-    cortex_ar::interrupt::disable();
-    atomic::compiler_fence(atomic::Ordering::SeqCst);
-    was_active
-}
-
-#[no_mangle]
-pub fn _critical_section_1_0_release(was_active: bool) {
-    use core::sync::atomic;
-    // Only re-enable interrupts if they were enabled before the critical section.
-    if was_active {
-        atomic::compiler_fence(atomic::Ordering::SeqCst);
-        // Safety: This is OK because we're releasing a lock that was
-        // entered with interrupts enabled
-        unsafe {
-            cortex_ar::interrupt::enable();
-        }
-    }
-}
-
 use flash_algorithm::*;
 use rtt_target::{rprintln, rtt_init_print};
+use cortex_ar as _;

 struct Algorithm;

@xobs
Copy link
Author

xobs commented Mar 28, 2025

Huh indeed. Yes, that does solve the issue. I would never have thought to do that. I'm glad I posted here, because now there's at least a record of having to do that.

I'm trying to think of how the error could be improved, or how it could have more attention drawn to the solution. In my own implementation I'll add a big fat comment about that, and if nothing else there's a record here for the search engines to pick up.

I can understand why it's required -- otherwise I'm sure Rust prunes the crate because it doesn't see it being used at all. But it's still not very intuitive.

@xobs xobs closed this as completed Mar 28, 2025
@jonathanpallant
Copy link
Contributor

yeah, it's perhaps a failure of the critical-section design. I don't know how else to work around it, especially in a tiny crate like a flash algorithm that doesn't even bring in a cortex-foo-rt crate.

@adamgreig
Copy link
Member

This is the same problem that panic handlers and crates like defmt_rtt have, right? If a crate provides some symbol that's only used via a non-Rust call then rustc doesn't know how to see that it's required and omits the crate. It might be something that can be improved on the Rust side, either as a detection or some crate metadata to say "include me even if I'm not obviously being called".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants