驱动程序

现在将新的 Registers 结构体用于我们的驱动程序。

  1. /// Driver for a PL011 UART.
  2. #[derive(Debug)]
  3. pub struct Uart {
  4. registers: *mut Registers,
  5. }
  6. impl Uart {
  7. /// Constructs a new instance of the UART driver for a PL011 device at the
  8. /// given base address.
  9. ///
  10. /// # Safety
  11. ///
  12. /// The given base address must point to the 8 MMIO control registers of a
  13. /// PL011 device, which must be mapped into the address space of the process
  14. /// as device memory and not have any other aliases.
  15. pub unsafe fn new(base_address: *mut u32) -> Self {
  16. Self { registers: base_address as *mut Registers }
  17. }
  18. /// Writes a single byte to the UART.
  19. pub fn write_byte(&self, byte: u8) {
  20. // Wait until there is room in the TX buffer.
  21. while self.read_flag_register().contains(Flags::TXFF) {}
  22. // SAFETY: We know that self.registers points to the control registers
  23. // of a PL011 device which is appropriately mapped.
  24. unsafe {
  25. // Write to the TX buffer.
  26. addr_of_mut!((*self.registers).dr).write_volatile(byte.into());
  27. }
  28. // Wait until the UART is no longer busy.
  29. while self.read_flag_register().contains(Flags::BUSY) {}
  30. }
  31. /// Reads and returns a pending byte, or `None` if nothing has been
  32. /// received.
  33. pub fn read_byte(&self) -> Option<u8> {
  34. if self.read_flag_register().contains(Flags::RXFE) {
  35. None
  36. } else {
  37. // SAFETY: We know that self.registers points to the control
  38. // registers of a PL011 device which is appropriately mapped.
  39. let data = unsafe { addr_of!((*self.registers).dr).read_volatile() };
  40. // TODO: Check for error conditions in bits 8-11.
  41. Some(data as u8)
  42. }
  43. }
  44. fn read_flag_register(&self) -> Flags {
  45. // SAFETY: We know that self.registers points to the control registers
  46. // of a PL011 device which is appropriately mapped.
  47. unsafe { addr_of!((*self.registers).fr).read_volatile() }
  48. }
  49. }
  • 请注意,只使用 addr_of! / addr_of_mut! 获取指向各个字段的指针,而不创建中间引用,这样很不安全。