2016-01-26 105 views
10

我試圖做的「Blinky」爲在STM32F1xx之防鏽。 我知道有它的庫,但我想我自己的「LIB」學習的目的。如何寫入Rust中的內存映射地址?

我可以通過這樣的地址在C訪問STM32的「寄存器」:

*(uint32_t*)(0x40021000 + 0x018) |= 0x10; 
*(uint32_t*)(0x40011000 + 0x004) |= 0x33; 
*(uint32_t*)(0x40011000 + 0x004) &= ~0xCC; 
*(uint32_t*)(0x40011000 + 0x10) |= 0x300; 

while(1) {} 

這寫一些比特的RCC_APB2ENR寄存器使能端PC的時鐘,配置引腳,使我發現的LED。

我需要重新寫這一點,在防鏽,使consts,FNS並開始編寫好的代碼生鏽。在沒有FFI調用C代碼的Rust中可能嗎?我可以通過asm!宏實現嗎?

回答

8

在C語言中,你應該申報的指針作爲volatile當訪問硬件寄存器,以便編譯器完全按照您的編程進行訪問。否則,它可以對它們重新排序或消除對同一寄存器的重複訪問。

由於Rust 1.9(感謝RFC),您可以使用core::ptr::read_volatilecore::ptr::write_volatile來讀取和寫入此類內存。

如果你有一個老版本的Rust,這些可以用volatile_readvolatile_storecore::intrinsics中找到,但它們永久不穩定,因此需要夜間版本的Rust來訪問它們。

+0

對於C和Rust,編譯器對非易失性指針的行爲是否相同? – fevgenym

+0

是的,Rust編譯器可以執行相同的優化。這樣做的LLVM後端用於兩種語言。 – starblue

1

鏽具有在標準庫的std::ptr模塊。它提供的功能,如ptr::readptr::write這比非關聯更加明確。

所以,你的例子是

const A: *mut u32 = (0x40021000 + 0x018) as *mut u32; 
const B: *mut u32 = (0x40011000 + 0x004) as *mut u32; 
const C: *mut u32 = (0x40011000 + 0x10) as *mut u32; 
unsafe { 
    ptr::write(A, ptr::read(A) | 0x10); 
    ptr::write(B, ptr::read(B) | 0x33); 
    ptr::write(B, ptr::read(B) & !0xCC); 
    ptr::write(C, ptr::read(C) | 0x300); 
} 

更簡潔的版本是使用非關聯化,但只適用於Copy類型:

*A |= 0x10; 
*B |= 0x33; 
*B &= !0xCC; 
*C |= 0x300; 
3

功能read_volatilewrite_volatile是因爲1.9版本穩定,所以你應該使用這些。借款@ KER的示範樣本翻譯:

use std::ptr::{read_volatile, write_volatile}; 

const A: *mut u32 = (0x40021000 + 0x018) as *mut u32; 
const B: *mut u32 = (0x40011000 + 0x004) as *mut u32; 
const C: *mut u32 = (0x40011000 + 0x10) as *mut u32; 
unsafe { 
    write_volatile(A, read_volatile(A) | 0x10); 
    write_volatile(B, read_volatile(B) | 0x33); 
    write_volatile(B, read_volatile(B) & !0xCC); 
    write_volatile(C, read_volatile(C) | 0x300); 
} 

此外,volatile箱提供各地的揮發性訪問值包裝類型。

use volatile::Volatile; 

const A: *mut u32 = (0x40021000 + 0x018) as *mut u32; 
const B: *mut u32 = (0x40011000 + 0x004) as *mut u32; 
const C: *mut u32 = (0x40011000 + 0x10) as *mut u32; 

const volatile_A = A as *mut Volatile<u32>; 
const volatile_B = B as *mut Volatile<u32>; 
const volatile_C = C as *mut Volatile<u32>; 

unsafe { 
    (*volatile_A).update(|x| *x | 0x10); 
    (*volatile_B).update(|x| *x & !0xCC); 
    (*volatile_C).update(|x| *x | 0x300); 
} 
+0

好消息!謝謝 – fevgenym

相關問題