#macro #enums #bit-fields #attributes #access #bitaccess

nightly macro bitaccess_macros

bitaccess宏实现(使用bitaccess代替此版本)

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

MIT/Apache

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_viawrite_via属性时,将创建全局寄存器。所有其他属性的行为与Inline register中一样。

Read_via | write_via

提供在字符串内的Rust指令。对于其他用途的示例,请检查测试。

依赖关系

~1.5MB
~37K SLoC