2016-01-26 34 views
10

私はRustのSTM32F1xxに対して "Blinky"を作ろうとしています。 私はlibsがあることを知っていますが、私は学習目的のために自分の "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) {} 

これは、ポートCのクロッキングを可能にするためにRCC_APB2ENRレジスタにいくつかのビットを書き込み、ピンを設定し、私のディスカバリー上のLEDを可能にします。

これをRustで書き直して、const、fnsを作成し、素敵なRustyコードを書き始める必要があります。 FFIがCコードを呼び出すことなくRustで可能ですか? asm!マクロでこれを達成できますか?

答えて

8

あなたはvolatileときのように、あなたのポインタを宣言する必要がありますハードウェア・レジスタにアクセスするため、コンパイラはプログラムのプログラミングとまったく同じようにアクセスします。さもなければ、それらはそれらを並べ替えるか、同じレジスタへの重複したアクセスを排除するかもしれません。

錆1.9(これはRFCのおかげで)core::ptr::read_volatilecore::ptr::write_volatileを使用すると、このようなメモリに読み書きすることができます。あなたが錆の古いバージョンをお持ちの場合は

は、これらは、しかし、永続的に不安定でvolatile_readvolatile_storecore::intrinsicsで、として利用可能であり、したがって、それらにアクセスするために錆の夜間のバージョンが必要です。

+0

不揮発性ポインタのコンパイラの動作はCとRustで同じですか? – fevgenym

+0

はい、Rustコンパイラは同じ最適化を実行できます。これを行うLLVMバックエンドは両方の言語で使用されます。 – starblue

1

rustは標準ライブラリに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タイプの作品:Cで

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

機能read_volatileおよびwrite_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

関連する問題