嵌入式 Rust- 如何防止为 ISR 生成 'extra' 代码

Embedded Rust- How to prevent generation of 'extra' code for ISR

我正在尝试编写简单的 RTOS,但我正在努力处理编译器生成的额外 asm 代码。代码目标是 cortex-m4 cpu,我正在为其使用 cortex-m 和 cortex-m-rt crate。 我可以使用 #[no_mangle] 属性删除蹦床,但我不知道如何 remove/prevent 生成 push {r7, lr}pop {r7, pc}说明。

这是我的 PendSV 代码:

#[allow(non_snake_case)]
#[no_mangle]
pub fn PendSV() {
    unsafe{
        asm!("nop")
    }
}

这里是生成的代码:

push    {r7, lr}
mov     r7, sp
nop                                                                                                                                      
pop     {r7, pc}

我正在寻找某种属性或编译器选项,这样我就可以 nop 作为 PendSV 函数的一部分生成。可能吗?

您需要将 PendSV 设为 naked function。 “裸”表示不为该函数生成前奏和return代码。

所以,天真地,像这样:

#![feature(asm)]
#![feature(naked_functions)]

#[allow(non_snake_case)]
#[no_mangle]
#[naked]
pub fn PendSV() {
    unsafe {
        asm!("nop")
    }
}

使用以下代码会收到两个警告:

warning: Rust ABI is unsupported in naked functions

warning: asm in naked functions must use noreturn option

要补救,请使用 C ABI 和 noreturn 选项:

#[allow(non_snake_case)]
#[no_mangle]
#[naked]
pub extern "C" fn PendSV() {
    unsafe {
        asm!(
            "nop",
            options(noreturn)
        )
    }
}

在 x86 下,编译为(通过 Compiler Explorer):

PendSV:
        nop
        ud2

ud2 可能仍然不是您想要的。生成它是因为到现在为止,您已经指出该函数没有 return,但是,在执行单个 nop 之后,执行流程将到达函数的末尾(它 return,如果不是因为你使用的是裸函数...)

因此,您有责任决定在 PendSV 之后执行什么。您可能想要无限循环、跳转或“return 来自中断”指令(iret 用 x86 术语来说,我对 ARM 不太熟悉)。