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