Guest User

Untitled

a guest
Mar 23rd, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.09 KB | None | 0 0
  1. #![feature(integer_atomics, nll)]
  2.  
  3. extern crate num_traits;
  4. extern crate memmap;
  5.  
  6. use num_traits::{NumAssignOps, PrimInt, sign::Unsigned};
  7. use memmap::MmapMut;
  8. use std::error::Error as StdError;
  9. use std::fmt;
  10. use std::fs::{File, OpenOptions};
  11. use std::ops::{BitAndAssign, BitOrAssign, BitXorAssign};
  12. use std::mem::{align_of, size_of};
  13. use std::sync::atomic::{AtomicU32, Ordering};
  14.  
  15. #[derive(Debug)]
  16. enum Error {
  17. SomeErr,
  18. }
  19.  
  20. impl fmt::Display for Error {
  21. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  22. write!(f, "SomeErr")
  23. }
  24. }
  25.  
  26. impl StdError for Error {
  27. fn description(&self) -> &str {
  28. "SomeErr"
  29. }
  30. }
  31.  
  32. //////////////////////////////
  33. // Define AtomicUnsigned trait
  34.  
  35. trait AtomicUnsigned {
  36. type AtomicPrimitive;
  37. type Primitive: PrimInt + Unsigned + NumAssignOps + BitAndAssign + BitOrAssign + BitXorAssign;
  38.  
  39. // ... re-export atomic integer API for example:
  40. fn load(&self, order: Ordering) -> Self::Primitive;
  41. fn store(&self, val: Self::Primitive, order: Ordering);
  42. }
  43.  
  44. impl AtomicUnsigned for AtomicU32 {
  45. type AtomicPrimitive = AtomicU32;
  46. type Primitive = u32;
  47.  
  48. fn load(&self, order: Ordering) -> Self::Primitive {
  49. self.load(order)
  50. }
  51.  
  52. fn store(&self, val: Self::Primitive, order: Ordering) {
  53. self.store(val, order)
  54. }
  55. }
  56.  
  57. ///////////////////////////////////////
  58. // Define hardware register memory map structure
  59.  
  60. const GPIO_REGISTER_COUNT: usize = 41; // from BCM 2835 datasheet
  61.  
  62. trait GpioMmap {
  63. type Register: AtomicUnsigned;
  64. const DEVICE_ID: &'static str;
  65. const BASE_ADDR: usize;
  66. // ...
  67.  
  68. fn new() -> Result<Self, Box<std::error::Error>> where Self: std::marker::Sized;
  69. fn registers(&self) -> &[Self::Register; GPIO_REGISTER_COUNT];
  70.  
  71. }
  72.  
  73. /////////////////////////////////////////////////////////////
  74. // Specialize register memory map for Raspberry Pi 3 platform
  75.  
  76. struct Rpi3RaspbianGpioMmap {
  77. mmap: MmapMut,
  78. fd: File,
  79. }
  80.  
  81. impl GpioMmap for Rpi3RaspbianGpioMmap {
  82. type Register = AtomicU32;
  83. const DEVICE_ID: &'static str = "/tmp/foo";
  84. const BASE_ADDR: usize = 0x0000; // per BCM2835 datasheet (could not locate BCM2837 datasheet)
  85.  
  86. fn new() -> Result<Self, Box<std::error::Error>> where Self: std::marker::Sized {
  87. let fd = OpenOptions::new()
  88. .read(true)
  89. .write(true)
  90. .create(true)
  91. .open(&Self::DEVICE_ID)?;
  92. fd.set_len((GPIO_REGISTER_COUNT * size_of::<Self::Register>()) as u64)?;
  93.  
  94. let mmap = unsafe { MmapMut::map_mut(&fd)? };
  95.  
  96. let mmap_size = mmap.len() * size_of::<u8>();
  97. if mmap_size != GPIO_REGISTER_COUNT * size_of::<Self::Register>() {
  98. return Err(Box::new(Error::SomeErr));
  99. };
  100.  
  101. let mmap_addr = mmap.as_ptr() as usize;
  102. let register_align = align_of::<Self::Register>();
  103. if mmap_addr % register_align != 0 {
  104. return Err(Box::new(Error::SomeErr));
  105. }
  106.  
  107. Ok(Self {
  108. mmap,
  109. fd,
  110. })
  111. }
  112.  
  113. fn registers(&self) -> &[Self::Register; GPIO_REGISTER_COUNT] {
  114. unsafe {
  115. &*(self.mmap.as_ptr() as *const Self::Register as *const [Self::Register; GPIO_REGISTER_COUNT])
  116. }
  117. }
  118. }
  119.  
  120. ////////////////////////
  121. // Define HAL Components interface
  122.  
  123. trait Chal {
  124. type GpioMmap: GpioMmap;
  125.  
  126. fn new(gpio_mmap: Self::GpioMmap) -> Self;
  127. //...
  128. }
  129.  
  130. /////////////////////////////////////////////////////////
  131. // Specialize HAL Components interface for Raspberry Pi 3
  132.  
  133. struct GpioControlSet {
  134. pub fn_ctrl_reg_offset: usize,
  135. pub fn_ctrl_field_mask: u32,
  136. //...
  137. }
  138.  
  139. struct Rpi3Chal<G = Rpi3RaspbianGpioMmap> where G: GpioMmap,
  140. <G as GpioMmap>::Register: AtomicUnsigned<Primitive = u32> {
  141. gpio_mmap: <Rpi3Chal<G> as Chal>::GpioMmap,
  142. gpio_control_sets: [GpioControlSet; 1],
  143. //...
  144. }
  145.  
  146. impl<G> Chal for Rpi3Chal<G> where G: GpioMmap,
  147. // <<G as GpioMmap>::Register as AtomicUnsigned>::Primitive: From<u32> {
  148. <G as GpioMmap>::Register: AtomicUnsigned<Primitive = u32> {
  149. type GpioMmap = G;
  150.  
  151. fn new(gpio_mmap: Self::GpioMmap) -> Self {
  152. let gpio_control_set = GpioControlSet {
  153. fn_ctrl_reg_offset: 8, // made-up value
  154. fn_ctrl_field_mask: 0b111 << 16, //made-up value
  155. };
  156.  
  157. let chal = Self {
  158. gpio_mmap,
  159. gpio_control_sets: [gpio_control_set],
  160. };
  161. chal.init()
  162. }
  163. }
  164.  
  165. impl<G> Rpi3Chal<G> where G: GpioMmap,
  166. <G as GpioMmap>::Register: AtomicUnsigned<Primitive = u32> {
  167. fn init(self) -> Self {
  168. let led_gpio = &self.gpio_control_sets[0];
  169. let mut temp = self.gpio_mmap.registers()[led_gpio.fn_ctrl_reg_offset].load(Ordering::Relaxed); // <- returns AtomicUnsigned::Primitive
  170. temp &= !led_gpio.fn_ctrl_field_mask; // <- returns u32
  171. //...
  172. self.gpio_mmap.registers()[led_gpio.fn_ctrl_reg_offset].store(temp, Ordering::Relaxed);
  173. self
  174. }
  175. }
  176.  
  177. fn main() {}
Add Comment
Please, Sign In to add comment