2017-06-12 63 views
0

在嵌入式编程中,可以通过放置在正确地址的结构来访问内存映射外设。我如何确保对外设的内存访问确实在Rust的总线上执行?在C中,这可以通过设置变量或字段volatile来完成。如何确保内存映射外设的内存访问是不稳定的?

考虑这个例子:

#[repr(C)] 
struct Periph { 
    sr: u32, /* Status */ 
    cr: u32, /* Control */ 
    dr: u32, /* Data */ 
} 

const PERIPH1: *mut Periph = 0x10001200 as *mut Periph; 
const PERIPH2: *mut Periph = 0x10001400 as *mut Periph; 

fn useperiph(p: &mut Periph) -> i32 { 
    p.cr = CR_CONSTANT; 
    if p.cr != CR_CONSTANT { 
     /* Peripheral was not enabled */ 
     return -1; 
    } 

    /* Loop a few micro seconds until ready */ 
    while p.sr != SR_CONSTANT {} 

    /* Write values to hardware FIFO */ 
    p.dr = DATA1; 
    p.dr = DATA2; 
    p.dr = DATA3; 
    0 
} 

我需要确保编译器不会删除支票上的控制寄存器,将离开状态寄存器的所有负载,而不会崩溃三个店到数据寄存器。我怎么做?

+0

也就是说https://stackoverflow.com/q/35009015/1233251的副本,但答案是过时的。我想我应该在那里做一个更新的答案,而不是在这里复制信息。 –

+0

请参阅我的回答[here](https://stackoverflow.com/a/44510388/1233251)。 –

回答

0

我所知道的最好的方法是使用类似于Zinc的volatile_cell库的东西。内存映射外设寄存器的结构具有VolatileCell<u32>型寄存器,而不是普通的u32VolatileCell包装一个值,具有相同的大小,并提供使用core::ptr::read_volatilecore::ptr::write_volatile的访问器。剥离下来到它的本质,VolatileCell看起来是这样的:

#[repr(C)] 
pub struct VolatileCell<T> { 
    value: T, 
} 

impl<T> VolatileCell<T> { 

    /// Get register value. 
    #[inline] 
    pub fn get(&self) -> T { 
     unsafe { 
      read_volatile(&self.value) 
     } 
    } 

    /// Set register value. 
    #[inline] 
    pub fn set(&self, value: T) { 
     unsafe { 
      write_volatile(&self.value as *const T as *mut T, value) 
     } 
    } 
} 

然后外设寄存器结构使用VolatileCell<u32>领域写着:

#[repr(C)] 
struct Periph { 
    sr: VolatileCell<u32>, /* Status */ 
    cr: VolatileCell<u32>, /* Control */ 
    dr: VolatileCell<u32>, /* Data */ 
} 

const PERIPH1: *mut Periph = 0x10001200 as *mut Periph; 
const PERIPH2: *mut Periph = 0x10001400 as *mut Periph; 

fn useperiph(p: &mut Periph) -> i32 { 
    p.cr.set(CR_CONSTANT); 
    if p.cr.get() != CR_CONSTANT { 
     /* Peripheral was not enabled */ 
     return -1; 
    } 

    /* Loop a few micro seconds until ready */ 
    while p.sr.get() != SR_CONSTANT {} 

    p.dr.set(DATA1); 
    p.dr.set(DATA2); 
    p.dr.set(DATA3); 
    0 
} 

生成的代码具有正确的语义,只是稍微详细比直接使用u32。明确表示可以说是一个好处。