Guest User

Untitled

a guest
Mar 23rd, 2018
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.19 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::atomic::{AtomicU32, Ordering};
  14.  
  15. type Result<T> = std::result::Result<T, Box<StdError>>;
  16.  
  17. #[derive(Debug)]
  18. enum Error {
  19. SomeErr,
  20. }
  21.  
  22. impl fmt::Display for Error {
  23. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  24. write!(f, "SomeErr")
  25. }
  26. }
  27.  
  28. impl StdError for Error {
  29. fn description(&self) -> &str {
  30. "SomeErr"
  31. }
  32. }
  33.  
  34. //////////////////////////////
  35. // Define AtomicUnsigned trait
  36.  
  37. trait AtomicUnsigned {
  38. type AtomicPrimitive;
  39. type Primitive: PrimInt + Unsigned + NumAssignOps + BitAndAssign + BitOrAssign + BitXorAssign;
  40.  
  41. // ... re-export atomic integer API for example:
  42. fn load(&self, order: Ordering) -> Self::Primitive;
  43. fn store(&self, val: Self::Primitive, order: Ordering);
  44. }
  45.  
  46. impl AtomicUnsigned for AtomicU32 {
  47. type AtomicPrimitive = AtomicU32;
  48. type Primitive = u32;
  49.  
  50. fn load(&self, order: Ordering) -> Self::Primitive {
  51. self.load(order)
  52. }
  53.  
  54. fn store(&self, val: Self::Primitive, order: Ordering) {
  55. self.store(val, order)
  56. }
  57. }
  58.  
  59. ///////////////////////////////////////
  60. // Define hardware register memory map structure
  61.  
  62. const GPIO_REGISTER_COUNT: usize = 41; // from BCM 2835 datasheet
  63.  
  64. trait GpioMmap {
  65. type Register: AtomicUnsigned;
  66. const DEVICE_ID: &'static str;
  67. const BASE_ADDR: usize;
  68. // ...
  69.  
  70. fn new() -> Result<Self> where Self: std::marker::Sized;
  71. fn registers(&self) -> &[Self::Register; GPIO_REGISTER_COUNT];
  72.  
  73. }
  74.  
  75. /////////////////////////////////////////////////////////////
  76. // Specialize register memory map for Raspberry Pi 3 platform
  77.  
  78. struct Rpi3RaspbianGpioMmap {
  79. mmap: MmapMut,
  80. }
  81.  
  82. impl GpioMmap for Rpi3RaspbianGpioMmap {
  83. type Register = AtomicU32;
  84. const DEVICE_ID: &'static str = "/tmp/foo";
  85. const BASE_ADDR: usize = 0x0000; // per BCM2835 datasheet (could not locate BCM2837 datasheet)
  86.  
  87. fn new() -> Result<Self> where Self: std::marker::Sized {
  88. let fd = OpenOptions::new()
  89. .read(true)
  90. .write(true)
  91. .create(true)
  92. .open(&Self::DEVICE_ID)?;
  93. fd.set_len((GPIO_REGISTER_COUNT * size_of::<Self::Register>()) as u64)?;
  94.  
  95. let mmap = unsafe { MmapMut::map_mut(&fd)? };
  96.  
  97. let mmap_size = mmap.len() * size_of::<u8>();
  98. if mmap_size != GPIO_REGISTER_COUNT * size_of::<Self::Register>() {
  99. return Err(Box::new(Error::SomeErr));
  100. };
  101.  
  102. let mmap_addr = mmap.as_ptr() as usize;
  103. let register_align = align_of::<Self::Register>();
  104. if mmap_addr % register_align != 0 {
  105. return Err(Box::new(Error::SomeErr));
  106. }
  107.  
  108. Ok(Self {
  109. mmap,
  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() {
  178. let _ = inner_main();
  179. }
  180.  
  181. fn inner_main() -> Result<()> {
  182. let chal = Rpi3Chal::new(Rpi3RaspbianGpioMmap::new()?);
  183.  
  184. Ok(())
  185. }
Add Comment
Please, Sign In to add comment