14 个版本 (3 个稳定版)

1.0.2 2021 年 1 月 1 日
1.0.1 2020 年 11 月 27 日
0.5.1 2020 年 5 月 31 日
0.5.0 2020 年 1 月 16 日
0.1.1 2018 年 7 月 16 日

#13 in #mmio

Download history · Rust 包仓库 57/week @ 2024-03-11 · Rust 包仓库 47/week @ 2024-03-18 · Rust 包仓库 18/week @ 2024-03-25 · Rust 包仓库 163/week @ 2024-04-01 · Rust 包仓库 24/week @ 2024-04-08 · Rust 包仓库 50/week @ 2024-04-15 · Rust 包仓库 44/week @ 2024-04-22 · Rust 包仓库 38/week @ 2024-04-29 · Rust 包仓库 29/week @ 2024-05-06 · Rust 包仓库 46/week @ 2024-05-13 · Rust 包仓库 70/week @ 2024-05-20 · Rust 包仓库 90/week @ 2024-05-27 · Rust 包仓库 25/week @ 2024-06-03 · Rust 包仓库 21/week @ 2024-06-10 · Rust 包仓库 22/week @ 2024-06-17 · Rust 包仓库 15/week @ 2024-06-24 · Rust 包仓库

每月 105 次下载
用于 2 crates

MIT/Apache

12KB
90

crates.io crates.io

register-rs

Rust 中类型安全的 MMIO 和 CPU 寄存器访问的统一接口。

概述

用法

此 crate 使用 tock-register-interface,请参阅他们的 README 了解完整的 API。请确保查看 register_structs! 的说明,特别是您必须 显式注释间隙 的实际情况。

定义 MMIO 寄存器

use register::{mmio::*, register_bitfields, register_structs};

register_bitfields! {
    u32,

    GPFSEL1 [
        FSEL14 OFFSET(12) NUMBITS(3) [
            Input = 0b000,
            Output = 0b001,
            TXD0 = 0b100
        ],

        FSEL15 OFFSET(15) NUMBITS(3) [
            Input = 0b000,
            Output = 0b001,
            RXD0 = 0b100
        ]
    ]
}

register_structs! {
    #[allow(non_snake_case)]
    pub RegisterBlock {
        (0x000 => GPFSEL1: ReadWrite<u32, GPFSEL1::Register>),
        (0x004 => SYSTMR_HI: ReadOnly<u32>),
        (0x008 => @END),
    }
}

fn main() {
    let regs = 0x1337_0000 as *const RegisterBlock;

    unsafe { (*regs).SYSTMR_HI.get() };
}

驱动程序的 Deref 模式

此 crate 的 MMIO 部分,通常用于实现设备驱动程序。在这种情况下,您可能会发现 Deref 模式 对于引用您的寄存器很有用。它让您不必在每次进行寄存器访问时手动解引用,同时也封装了 unsafe 关键字。

以下是一个示例(扩展上面的代码片段)

register_bitfields! {
    u32,

    // omitted
}

register_structs! {
    #[allow(non_snake_case)]
    pub RegisterBlock {
        // omitted
    }
}

pub struct DeviceDriver {
    base_addr: usize,
}

impl ops::Deref for DeviceDriver {
    type Target = RegisterBlock;

    fn deref(&self) -> &Self::Target {
        unsafe { &*self.ptr() }
    }
}

impl DeviceDriver {
    pub fn new(base_addr: usize) -> Self {
        DeviceDriver { base_addr }
    }

    /// Returns a pointer to the register block
    fn ptr(&self) -> *const RegisterBlock {
        self.base_addr as *const _
    }

    fn do_something(&self) -> u32 {
        self.GPFSEL1.set(0x1337);
        self.SYSTMR_HI.get()
    }
}

定义 CPU 寄存器

对于 CPU 寄存器,您只需实现相应的读写特质。所有其他方法默认提供。

#![feature(llvm_asm)]

use register::{cpu::RegisterReadWrite, register_bitfields};

register_bitfields! {u32,
    pub CNTP_CTL_EL0 [
        /// Enables the timer.
        ENABLE        OFFSET(0)  NUMBITS(1) [],

        /// Timer interrupt mask bit.
        IMASK         OFFSET(1)  NUMBITS(1) [],

        /// The status of the timer.
        ISTATUS       OFFSET(2)  NUMBITS(1) []
    ]
}

struct Reg;

impl RegisterReadWrite<u32, CNTP_CTL_EL0::Register> for Reg {
    /// Reads the raw bits of the CPU register.
    #[inline(always)]
    fn get(&self) -> u32 {
        let reg;
        unsafe {
            llvm_asm!("mrs $0, CNTP_CTL_EL0" : "=r"(reg) ::: "volatile");
        }
        reg
    }

    /// Writes raw bits to the CPU register.
    #[inline(always)]
    fn set(&self, value: u32) {
        unsafe {
            llvm_asm!("msr CNTP_CTL_EL0, $0" :: "r"(value) :: "volatile");
        }
    }
}

static CNTP_CTL_EL0: Reg = Reg {};

fn main() {
    CNTP_CTL_EL0.modify(CNTP_CTL_EL0::ENABLE::SET + CNTP_CTL_EL0::IMASK::SET);
}

测试

为了在 custom_test_frameworks 环境中使用此 crate,请在您的依赖部分设置 no_std_unit_tests 特性标志。

否则,您可能会遇到以下错误

error[E0463]: can't find crate for `test`
  --> src/bsp/driver/bcm/bcm2xxx_gpio.rs:52:1
   |
52 | / register_structs! {
53 | |     #[allow(non_snake_case)]
54 | |     RegisterBlock {
55 | |         (0x00 => GPFSEL0: ReadWrite<u32>),
...  |
66 | |     }
67 | | }
   | |_^ can't find crate
   |
   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: aborting due to previous error

许可

许可协议为以下之一

任选其一。

贡献

除非您明确声明,否则您有意提交的任何贡献,根据 Apache-2.0 许可协议定义,均应双许可,没有额外的条款或条件。

依赖项

~90KB