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日 |
73 在 #bitfields
每月下载量:35
用于 bitaccess
42KB
1K SLoC
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之后的所有属性都将复制到生成的struct
中(是的,这个枚举在底层转换为struct)
Bits / Bit / Bitaccess
字段属性,声明哪些位是给定字段的组成部分。
接受3种声明形式
显式
#[bits(offset = N, size = S)]
其中N和S都是可评估为base_type的表达式
范围
接受Range和RangeInclusive: 0..4
& 0..=3
单个
对于单比特访问器,允许使用以下语法:#[bit(N)]
。
变体
字段可以自动转换为变体(如上面所示的VariantThird
)。位访问支持两种声明此类访问的方式
内联
逗号分隔的Identifier => Value
对列表。变体可以通过枚举的字段标识符来访问,例如,在上面的例子中,我们会调用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
属性时,将创建全局寄存器。所有其他属性的行为与Inline register
中一样。
Read_via | write_via
提供在字符串内的Rust指令。对于其他用途的示例,请检查测试。
依赖关系
~1.5MB
~37K SLoC