rtic icon indicating copy to clipboard operation
rtic copied to clipboard

Make Priority::get() public.

Open romixlab opened this issue 4 years ago • 4 comments

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

romixlab avatar Jul 13 '21 19:07 romixlab

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.

korken89 avatar Sep 28 '21 09:09 korken89

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?

romixlab avatar Sep 28 '21 10:09 romixlab

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

korken89 avatar Sep 28 '21 12:09 korken89

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.

mattico avatar Sep 28 '21 15:09 mattico