Guest User

Untitled

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