国产电影一区二区三区,,欧美大片免费观看,伊人久久大香线蕉av,国产日韩成人内射视频

嵌入式 Rust 中斷向量表詳解

前言

在ARM Cortex-M 微控制器編寫 Rust 代碼時,通常使用 cortex-m-rt  cortex-m crate。cortex-m-rt提供了 Cortex-M 內核的基本寄存器存取接口,啟動代碼,內核標準向量表、代碼段、數據段的定義,cortex-m提供對所有基于 Cortex-M 的微控制器標準的內核中的外設(例如 NVIC和 SysTick)以及一些外設操作的標準接口代碼。cortex-m-rt 還確保復位、中斷和異常向量表的定位,確保應用程序定義的中斷入口函數填充到指定的位置。 按照 cortex-m-rt 中使用定義,向量表由以下部分組成:

如果為cortex-m-rt crate啟用device功能,則它不會填充設備特定中斷的向量表。相反,這是留給外設訪問箱(PAC),用于特定的設備。.text  _stack_start 部分也可以通過配置移動或修改,但異常向量表則必須與芯片硬件定義的規則一致。 異常向量表由 ARM 制定,因此在任何基于 Cortex-M 的微控制器上都應該是相同的。當然也有一些芯片廠商沒有完全按照 ARM 的規則設計芯片,例如,某些微控制器將啟動配置、標記或校驗和存儲在異常向量表的“保留”字段中,或者需要在向量表或應用程序之間添加額外的標頭,在這種情況下,我們需要修改表以便我們的代碼能夠自動運行,而不至于跑飛。

建立一個基本的項目

讓我們設置一個典型的、最小的 Cortex-M0 項目作為示例。我們將省略 PAC 部分的代碼,因為本示例不需要它。

$ cargo new cmexample --bin
    Created binary (application) `cmexample` package
$ cd cmexample/
$ cargo add cortex-m-rt
    Adding cortex-m-rt v0.7.2 to dependencies.
           Features:
            - device
            - set-sp
            - set-vtor
$ cargo add -F critical-section-single-core cortex-m
    Adding cortex-m v0.7.7 to dependencies.
           Features:
           + critical-section-single-core
           - cm7
           - cm7-r0p1
           - critical-section
           - inline-asm
           - linker-plugin-lto
           - serde
           - std
$ cargo add panic-halt
    Adding panic-halt v0.2.0 to dependencies.

新建一個簡單的 main 文件

#![no_std]
#![no_main]

use panic_halt as _;
use cortex_m_rt::entry;

#[entry]
fn main() -> ! {
    loop {}
}

添加鏈接文件memory.x

MEMORY
{
    FLASH : ORIGIN = 0x00000000, LENGTH = 64K
    RAM : ORIGIN = 0x20000000, LENGTH = 20K
}

配置 Cargo 使用thumbv6目標并添加以下內容到.cargo/config.toml來獲取cortex-m-rt提供的鏈接器腳本:

[target.'cfg(all(target_arch = "arm", target_os = "none"))']
rustflags = [
    "-C", "link-arg=-Tlink.x",
]

[build]
target = "thumbv6m-none-eabi"

查看可執行文件的中斷向量表

如果一切順利,構建后,將有一個針對 ARM 目標的 ELF 可執行文件,其中包含向量表和代碼段、數據段等部分:

$ file target/thumbv6m-none-eabi/release/cmexample
target/thumbv6m-none-eabi/release/cmexample: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, with debug_info, not stripped
$ arm-none-eabi-size -Ax target/thumbv6m-none-eabi/release/cmexample
target/thumbv6m-none-eabi/release/cmexample  :
section              size         addr
.vector_table        0xc0          0x0
.text                0x64         0xc0
.rodata               0x0        0x124
.data                 0x0   0x20000000
.gnu.sgstubs          0x0        0x140
.bss                  0x0   0x20000000
.uninit               0x0   0x20000000
.ARM.attributes      0x32          0x0
.debug_frame       0x6528          0x0
.debug_abbrev      0x1139          0x0
.debug_info       0x26271          0x0
.debug_aranges     0x1e00          0x0
.debug_ranges     0x153f0          0x0
.debug_str        0x3e653          0x0
.debug_pubnames   0x16152          0x0
.debug_pubtypes     0x252          0x0
.debug_line       0x25015          0x0
.debug_loc           0x74          0x0
.comment             0x6d          0x0
Total             0xbe705

使用 objdump 我們可以檢查向量表的內容:

$ arm-none-eabi-objdump -s --section .vector_table target/thumbv6m-none-eabi/release/cmexample
target/thumbv6m-none-eabi/release/cmexample:     file format elf32-littlearm

Contents of section .vector_table:
 0000 00500020 c1000000 0b010000 0f010000  .P. ............
 0010 00000000 00000000 00000000 00000000  ................
 0020 00000000 00000000 00000000 0b010000  ................
 0030 00000000 00000000 0b010000 0b010000  ................
 0040 0b010000 0b010000 0b010000 0b010000  ................
 0050 0b010000 0b010000 0b010000 0b010000  ................
 0060 0b010000 0b010000 0b010000 0b010000  ................
 0070 0b010000 0b010000 0b010000 0b010000  ................
 0080 0b010000 0b010000 0b010000 0b010000  ................
 0090 0b010000 0b010000 0b010000 0b010000  ................
 00a0 0b010000 0b010000 0b010000 0b010000  ................
 00b0 0b010000 0b010000 0b010000 0b010000  ................

所有向量都指向默認處理程序。讓我們為 SysTick 中斷定義一個新的處理程序,例如:

#[exception]
fn SysTick() {
 todo!();
}

現在我們可以看到 0x3c 處的 SysTick 向量已更新:

$ arm-none-eabi-objdump -s --section .vector_table target/thumbv6m-none-eabi/release/cmexample
target/thumbv6m-none-eabi/release/cmexample:     file format elf32-littlearm

Contents of section .vector_table:
 0000 00500020 c1000000 23010000 91010000  .P. ....#.......
 0010 00000000 00000000 00000000 00000000  ................
 0020 00000000 00000000 00000000 23010000  ............#...
 0030 00000000 00000000 23010000 09010000  ........#.......
 0040 23010000 23010000 23010000 23010000  #...#...#...#...
 0050 23010000 23010000 23010000 23010000  #...#...#...#...
 0060 23010000 23010000 23010000 23010000  #...#...#...#...
 0070 23010000 23010000 23010000 23010000  #...#...#...#...
 0080 23010000 23010000 23010000 23010000  #...#...#...#...
 0090 23010000 23010000 23010000 23010000  #...#...#...#...
 00a0 23010000 23010000 23010000 23010000  #...#...#...#...
 00b0 23010000 23010000 23010000 23010000  #...#...#...#...

定義廠商芯片的向量表

注意:通常不需要我們這樣做, 當在應用程序中定義異常處理程序時,cortex-m-rt  PAC 將自動填充該表。僅對于具有 cortex-m-rt 無法滿足的特殊要求的控制器時才需要執行此操作。以某廠商的CortexM33芯片為例。

#[cfg(feature = "rt")]
extern "C" {
    fn UART0();
    fn UART1();
    fn TIMR0();
    fn TIMR1();
    fn DMA();
    fn SPI0();
    fn PWM_CH0();
    fn WDT();
    fn UART2();
    fn PWM_CH1();
    fn SARADC0();
    fn BTIMER0();
    fn HALL0();
    fn PWM_CH2();
    fn PWM_HALT();
    fn I2C0();
    fn CAN0();
    fn SPI1();
    fn RTC_BASE();
    fn PWM_CH3();
    fn TIMER2();
    fn UART3();
    fn TIMER3();
    fn SARADC1();
    fn BOD();
    fn CORDIC();
    fn BTIMER1();
    fn PWM_CH4();
    fn HALL1();
}
#[doc(hidden)]
pub union Vector {
    _handler: unsafe extern "C" fn(),
    _reserved: u32,
}
#[cfg(feature = "rt")]
#[doc(hidden)]
#[link_section = ".vector_table.interrupts"]
#[no_mangle]
pub static __INTERRUPTS: [Vector; 29] = [
    Vector { _handler: UART0 },
    Vector { _handler: UART1 },
    Vector { _handler: TIMR0 },
    Vector { _handler: TIMR1 },
    Vector { _handler: DMA },
    Vector { _handler: SPI0 },
    Vector { _handler: PWM_CH0 },
    Vector { _handler: WDT },
    Vector { _handler: UART2 },
    Vector { _handler: PWM_CH1 },
    Vector { _handler: SARADC0 },
    Vector { _handler: BTIMER0 },
    Vector { _handler: HALL0 },
    Vector { _handler: PWM_CH2 },
    Vector { _handler: PWM_HALT },
    Vector { _handler: I2C0 },
    Vector { _handler: CAN0 },
    Vector { _handler: SPI1 },
    Vector { _handler: RTC_BASE },
    Vector { _handler: PWM_CH3 },
    Vector { _handler: TIMER2 },
    Vector { _handler: UART3 },
    Vector { _handler: TIMER3 },
    Vector { _handler: SARADC1 },
    Vector { _handler: BOD },
    Vector { _handler: CORDIC },
    Vector { _handler: BTIMER1 },
    Vector { _handler: PWM_CH4 },
    Vector { _handler: HALL1 },
];
#[doc = r"Enumeration of all the interrupts."]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u16)]
pub enum Interrupt {
    #[doc = "0 - UART0 global interrupt"]
    UART0 = 0,
    #[doc = "1 - UART1 global interrupt"]
    UART1 = 1,
    #[doc = "2 - TIMR0 global interrupt"]
    TIMR0 = 2,
    #[doc = "3 - TIMR1 global interrupt"]
    TIMR1 = 3,
    #[doc = "4 - DMA global interrupt"]
    DMA = 4,
    #[doc = "5 - SPI0 global interrupt"]
    SPI0 = 5,
    #[doc = "6 - PWM_CH0 global interrupt"]
    PWM_CH0 = 6,
    #[doc = "7 - WDT global interrupt"]
    WDT = 7,
    #[doc = "8 - UART2 global interrupt"]
    UART2 = 8,
    #[doc = "9 - PWM_CH1 global interrupt"]
    PWM_CH1 = 9,
    #[doc = "10 - SARADC0 global interrupt"]
    SARADC0 = 10,
    #[doc = "11 - BTIMER0 global interrupt"]
    BTIMER0 = 11,
    #[doc = "12 - HALL0 global interrupt"]
    HALL0 = 12,
    #[doc = "13 - PWM_CH2 global interrupt"]
    PWM_CH2 = 13,
    #[doc = "14 - PWM_HALT global interrupt"]
    PWM_HALT = 14,
    #[doc = "15 - I2C0 global interrupt"]
    I2C0 = 15,
    #[doc = "16 - CAN0 global interrupt"]
    CAN0 = 16,
    #[doc = "17 - SPI1 global interrupt"]
    SPI1 = 17,
    #[doc = "18 - RTC_BASE global interrupt"]
    RTC_BASE = 18,
    #[doc = "19 - PWM_CH3 global interrupt"]
    PWM_CH3 = 19,
    #[doc = "20 - TIMER2 global interrupt"]
    TIMER2 = 20,
    #[doc = "21 - UART3 global interrupt"]
    UART3 = 21,
    #[doc = "22 - TIMER3 global interrupt"]
    TIMER3 = 22,
    #[doc = "23 - SARADC1 global interrupt"]
    SARADC1 = 23,
    #[doc = "24 - BOD global interrupt"]
    BOD = 24,
    #[doc = "25 - CORDIC global interrupt"]
    CORDIC = 25,
    #[doc = "26 - BTIMER1 global interrupt"]
    BTIMER1 = 26,
    #[doc = "27 - PWM_CH4 global interrupt"]
    PWM_CH4 = 27,
    #[doc = "28 - HALL1 global interrupt"]
    HALL1 = 28,
}
unsafe impl cortex_m::interrupt::InterruptNumber for Interrupt {
    #[inline(always)]
    fn number(self) -> u16 {
        self as u16
    }
}

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 3
收藏 4
關注 15
成為作者 賺取收益
全部留言
0/200
成為第一個和作者交流的人吧