4个版本 (破坏性更新)
| 0.4.0 | 2021年10月13日 | 
|---|---|
| 0.3.0 | 2021年9月26日 | 
| 0.2.0 | 2021年9月23日 | 
| 0.1.0 | 2021年9月23日 | 
#2024 in 数据结构
每月25次下载
12KB
186 行
Bitaccess
一个小型crate,用于在rust语言中替代缺少位字段访问器。
示例用法
#![feature(asm)]
use bitaccess::{bitaccess, FieldAccess};
#[derive(FieldAccess, Debug)]
#[field_access(u64)]
pub enum Mask {
    Unmasked = 0,
    Masked = 1,
}
#[bitaccess(
    base_type = u64,
    kind = read_write,
    read_via = r#"unsafe { asm!("mrs {}, daif", out(reg) value, options(nostack, nomem)); }"#,
    write_via = r#"unsafe { asm!("msr daif, {}", in(reg) value, options(nostack, nomem)); }"#
)]
pub enum Daif {
    #[bit(9)]
    #[variants(Mask)] D,
    #[bit(8)]
    #[variants(Mask)] A,
    #[bit(7)]
    #[variants(Mask)] I,
    #[bit(6)]
    #[variants(Mask)] F,
}
/// DAIF is an ARM register, so this example is not really suited for running on all machines.
/// It's here just to show power of the macro.
fn alter_daif() {
    println!("Daif IRQ: {:?}", Daif.read(Daif::I).variant());
    Daif.write(Daif::I, Mask::Unmasked);
    println!("Daif IRQ: {:?}", Daif.read(Daif::I).variant());
}
特性
内联寄存器
允许您创建一个存储在常规内存中的对象,无论是栈还是堆(可能通过某些解引用包装器)。
要创建此类结构,您必须创建一个枚举,如下所示
use bitaccess::{bitaccess, FieldAccess};
#[derive(FieldAccess)]
#[field_access(u64)]
enum VariantThird {
    Val1 = 0x1,
    Val2 = 0x3,
    Val3 = 0xf,
}
#[bitaccess(
    base_type = u64,
    kind = read_write
)]
#[repr(C)]
enum MyRegister {
    #[bits(0..=3)]
    FirstDescriptor,
    #[bit(4)]
    #[variants(On => 1, Off => 0)]
    SecondDescriptor,
    #[bitaccess(5..9)]
    #[variants(VariantThird)]
    ThirdDescriptor,
}
Base_type
任何整数类型。
放置除基本整数类型之外的任何类型是不稳定的,但可能有效
Kind
允许选项
- 只读
- 只写
- 读写 | 写读 | 默认
根据选择的选项,生成的代码可能提供ReadBits、WriteBits或两者的实现。字段可以省略,这将生成读写寄存器。
主枚举上的额外属性
bitaccess之后的所有属性都将复制到生成的结构体(是的,这个枚举在底层转换为结构体)
Bits / Bit / Bitaccess
字段属性,声明哪些位是给定字段的组成部分。
接受3种声明形式
显式
#[bits(偏移量 = N, 大小 = S)] 其中N和S都是可评估为base_type的表达式
范围
接受Range和RangeInclusive: 0..4 & 0..=3
单个
对于单个位访问器,允许 #[bit(N)]。
变体
字段可以以自动转换的变体形式出现(如上面的VariantThird)。Bitaccess支持两种声明此类访问的方式
内联
由逗号分隔的 标识符 => 值 对列表。变体将通过枚举访问,其中字段标识符用作名称,例如在上面示例中,我们会调用 SecondDescriptor::On。
外部
在 #[variants(Type)] 中仅指定类型将用于字段访问。类型必须继承 FieldAccess 特性并指定 #[field_access(N)] 属性,其中 N 必须与主枚举中的 base_type 匹配。
全局寄存器
#[derive(FieldAccess)]
#[field_access(u64)]
pub enum ExceptionLevel {
    EL0 = 0b00,
    EL1 = 0b01,
    EL2 = 0b10,
    EL3 = 0b11,
}
#[bitaccess(
    base_type = u64,
    kind = read_only,
    read_via = r#"unsafe { asm!("mrs {}, currentel", out(reg) value, options(nomem, nostack)) }"#
)]
pub enum CurrentEl {
    #[bits(2..4)]
    #[variants(ExceptionLevel)]
    Value,
}
全局寄存器在向位访问宏提供 read_via 或 write_via 属性时创建。所有其他属性的行为与 内联寄存器 相同。
Read_via | write_via
字符串中提供的 Rust 指令。有关其他使用示例,请查看测试。
依赖项
~1.5MB
~36K SLoC