Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #![feature(integer_atomics, nll)]
- extern crate num_traits;
- extern crate memmap;
- use num_traits::{NumAssignOps, PrimInt, sign::Unsigned};
- use memmap::MmapMut;
- use std::error::Error as StdError;
- use std::fmt;
- use std::fs::OpenOptions;
- use std::ops::{BitAndAssign, BitOrAssign, BitXorAssign};
- use std::mem::{align_of, size_of};
- use std::sync::{Arc, atomic::{AtomicU32, Ordering}};
- use std::thread;
- type Result<T> = std::result::Result<T, Box<StdError>>;
- #[derive(Debug)]
- enum Error {
- SomeErr,
- }
- impl fmt::Display for Error {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "SomeErr")
- }
- }
- impl StdError for Error {
- fn description(&self) -> &str {
- "SomeErr"
- }
- }
- //////////////////////////////
- // Define AtomicUnsigned trait
- trait AtomicUnsigned {
- type AtomicPrimitive;
- type Primitive: PrimInt + Unsigned + NumAssignOps + BitAndAssign + BitOrAssign + BitXorAssign;
- // ... re-export atomic integer API for example:
- fn load(&self, order: Ordering) -> Self::Primitive;
- fn store(&self, val: Self::Primitive, order: Ordering);
- }
- impl AtomicUnsigned for AtomicU32 {
- type AtomicPrimitive = AtomicU32;
- type Primitive = u32;
- fn load(&self, order: Ordering) -> Self::Primitive {
- self.load(order)
- }
- fn store(&self, val: Self::Primitive, order: Ordering) {
- self.store(val, order)
- }
- }
- ///////////////////////////////////////
- // Define hardware register memory map structure
- const GPIO_REGISTER_COUNT: usize = 41; // from BCM 2835 datasheet
- trait GpioMmap: Send + Sync {
- type Register: AtomicUnsigned;
- const DEVICE_ID: &'static str;
- const BASE_ADDR: usize;
- // ...
- fn new() -> Result<Self> where Self: std::marker::Sized;
- fn registers(&self) -> &[Self::Register; GPIO_REGISTER_COUNT];
- }
- /////////////////////////////////////////////////////////////
- // Specialize register memory map for Raspberry Pi 3 platform
- struct Rpi3RaspbianGpioMmap {
- mmap: MmapMut,
- }
- impl GpioMmap for Rpi3RaspbianGpioMmap {
- type Register = AtomicU32;
- const DEVICE_ID: &'static str = "/tmp/foo";
- const BASE_ADDR: usize = 0x0000; // per BCM2835 datasheet (could not locate BCM2837 datasheet)
- fn new() -> Result<Self> where Self: std::marker::Sized {
- let fd = OpenOptions::new()
- .read(true)
- .write(true)
- .create(true)
- .open(&Self::DEVICE_ID)?;
- fd.set_len((GPIO_REGISTER_COUNT * size_of::<Self::Register>()) as u64)?;
- let mmap = unsafe { MmapMut::map_mut(&fd)? };
- let mmap_size = mmap.len() * size_of::<u8>();
- if mmap_size != GPIO_REGISTER_COUNT * size_of::<Self::Register>() {
- return Err(Box::new(Error::SomeErr));
- };
- let mmap_addr = mmap.as_ptr() as usize;
- let register_align = align_of::<Self::Register>();
- if mmap_addr % register_align != 0 {
- return Err(Box::new(Error::SomeErr));
- }
- Ok(Self {
- mmap,
- })
- }
- fn registers(&self) -> &[Self::Register; GPIO_REGISTER_COUNT] {
- unsafe {
- &*(self.mmap.as_ptr() as *const Self::Register as *const [Self::Register; GPIO_REGISTER_COUNT])
- }
- }
- }
- ////////////////////////
- // Define HAL Components interface
- trait Chal: Send + Sync {
- type GpioMmap: GpioMmap;
- fn new(gpio_mmap: Self::GpioMmap) -> Self;
- fn registers(&self) -> &[<<Self as Chal>::GpioMmap as GpioMmap>::Register; GPIO_REGISTER_COUNT];
- //...
- }
- /////////////////////////////////////////////////////////
- // Specialize HAL Components interface for Raspberry Pi 3
- struct GpioControlSet {
- pub fn_ctrl_reg_offset: usize,
- pub fn_ctrl_field_mask: u32,
- //...
- }
- struct Rpi3Chal<G = Rpi3RaspbianGpioMmap> where G: GpioMmap,
- <G as GpioMmap>::Register: AtomicUnsigned<Primitive = u32> {
- gpio_mmap: <Rpi3Chal<G> as Chal>::GpioMmap,
- gpio_control_sets: [GpioControlSet; 1],
- //...
- }
- impl<G> Chal for Rpi3Chal<G> where G: GpioMmap,
- // <<G as GpioMmap>::Register as AtomicUnsigned>::Primitive: From<u32> {
- <G as GpioMmap>::Register: AtomicUnsigned<Primitive = u32> {
- type GpioMmap = G;
- fn new(gpio_mmap: Self::GpioMmap) -> Self {
- let gpio_control_set = GpioControlSet {
- fn_ctrl_reg_offset: 8, // made-up value
- fn_ctrl_field_mask: 0b111 << 16, //made-up value
- };
- let chal = Self {
- gpio_mmap,
- gpio_control_sets: [gpio_control_set],
- };
- chal.init()
- }
- fn registers(&self) -> &[<<Self as Chal>::GpioMmap as GpioMmap>::Register; GPIO_REGISTER_COUNT] {
- self.gpio_mmap.registers()
- }
- }
- impl<G> Rpi3Chal<G> where G: GpioMmap,
- <G as GpioMmap>::Register: AtomicUnsigned<Primitive = u32> {
- fn init(self) -> Self {
- let led_gpio = &self.gpio_control_sets[0];
- let mut temp = self.gpio_mmap.registers()[led_gpio.fn_ctrl_reg_offset].load(Ordering::Relaxed); // <- returns AtomicUnsigned::Primitive
- temp &= !led_gpio.fn_ctrl_field_mask; // <- returns u32
- //...
- self.gpio_mmap.registers()[led_gpio.fn_ctrl_reg_offset].store(temp, Ordering::Relaxed);
- self
- }
- }
- fn main() {
- let _ = inner_main();
- }
- fn inner_main() -> Result<()> {
- let chal = Arc::new(Rpi3Chal::new(Rpi3RaspbianGpioMmap::new()?));
- let chal2 = Arc::clone(&chal);
- let th = thread::spawn(move || {
- chal2.registers()[0].store(42, Ordering::Relaxed);
- });
- th.join().unwrap();
- println!("{}", chal.registers()[0].load(Ordering::Relaxed));
- Ok(())
- }
Add Comment
Please, Sign In to add comment