Skip to content
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

Make Priority::get() public. #495

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Conversation

romixlab
Copy link

This will allow to safely get priority of a current task and implement various loggers with lockless queues for each priority level.

@korken89
Copy link
Collaborator

Hi, sorry for missing this PR.

Could you show a PoC for this? I'm not sure how making the get function public would help as this is not a part of the context.
Else you can extract the priority from the NVIC, which would not give you a dependency of RTIC.

@romixlab
Copy link
Author

Hi, I only investigated the possibility of implementing logging functionality through separate queues for each priority level. Didn't had time to implement it yet. There was some discussions in defmt, maybe it's already solved by now.
As for the NVIC, one advantage of Priority::get() is that it returns logical priority, not hardware one, or I'm mistaken here?

@korken89
Copy link
Collaborator

The hardware and logical priority is a simple conversion function, so in the end you'd get the same.
And it's the hardware priority that is important, so that you have one queue per hardware priority in use.

You can check out the conversion function here: https://github.com/rtic-rs/cortex-m-rtic/blob/master/src/export.rs#L190

@mattico
Copy link
Contributor

mattico commented Sep 28, 2021

I'm also using execution priority for lock-free queues for Defmt logging. I certainly would've appreciated RTIC providing a way to get the current priority easily.

Here's the code I use to get the current execution priority:

/// Returns the current execution priority
///
/// **NOTE:** This does not return hardware priority levels but converts them to an easier form.
/// Higher numbers represent higher priorities, starting at zero. The max regular priority is 15,
/// above that is HardFault(16) and NonMaskableInt(17).
pub fn current_priority() -> u8 {
    use cortex_m::peripheral::scb::{Exception, SystemHandler, VectActive};
    use cortex_m::peripheral::{NVIC, SCB};

    // IPSR should be slightly faster than SCB.ICSR
    let ipsr: u32;
    unsafe {
        asm!("mrs {}, IPSR", out(reg) ipsr);
    }
    let vect_active = VectActive::from(ipsr as u8).unwrap_or(VectActive::ThreadMode);

    match vect_active {
        VectActive::ThreadMode => 0,
        VectActive::Exception(ex) => {
            let sysh = match ex {
                Exception::MemoryManagement => SystemHandler::MemoryManagement,
                Exception::BusFault => SystemHandler::BusFault,
                Exception::UsageFault => SystemHandler::UsageFault,
                Exception::SVCall => SystemHandler::SVCall,
                Exception::DebugMonitor => SystemHandler::DebugMonitor,
                Exception::PendSV => SystemHandler::PendSV,
                Exception::SysTick => SystemHandler::SysTick,
                Exception::HardFault => return 16,
                Exception::NonMaskableInt => return 17,
            };
            16 - (SCB::get_priority(sysh) >> 4)
        }
        VectActive::Interrupt { irqn } => {
            16 - (NVIC::get_priority(InterruptNumber(irqn - 16)) >> 4)
        }
    }
}

If you can't use inline asm, you can instead read the active vector from SCB.ICSR. You may have to change the shifts based on how many interrupt priority bits your hardware has.

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

Successfully merging this pull request may close these issues.

3 participants