Драйвер
Тепер давайте використаємо нову структуру Registers
у нашому драйвері.
/// Драйвер для PL011 UART. #[derive(Debug)] pub struct Uart { registers: *mut Registers, } impl Uart { /// Створює новий екземпляр драйвера UART для пристрою PL011 /// за заданою базовою адресою. /// /// # Безпека /// /// Задана базова адреса повинна вказувати на 8 керуючих регістрів MMIO пристрою /// PL011, які повинні бути відображені в адресному просторі процесу /// як пам'ять пристрою і не мати ніяких інших псевдонімів. pub unsafe fn new(base_address: *mut u32) -> Self { Self { registers: base_address as *mut Registers } } /// Записує один байт до UART. pub fn write_byte(&self, byte: u8) { // Чекаємо, поки не звільниться місце в буфері TX. while self.read_flag_register().contains(Flags::TXFF) {} // БЕЗПЕКА: ми знаємо, що self.registers вказує на керуючі // регістри пристрою PL011, який відповідним чином відображено. unsafe { // Записуємо в буфер TX. addr_of_mut!((*self.registers).dr).write_volatile(byte.into()); } // Чекаємо, поки UART більше не буде зайнято. while self.read_flag_register().contains(Flags::BUSY) {} } /// Читає і повертає байт очікування, або `None`, якщо нічого не було /// отримано. pub fn read_byte(&self) -> Option<u8> { if self.read_flag_register().contains(Flags::RXFE) { None } else { // БЕЗПЕКА: ми знаємо, що self.registers вказує на керуючі // регістри пристрою PL011, який відповідним чином відображено. let data = unsafe { addr_of!((*self.registers).dr).read_volatile() }; // TODO: Перевірити на наявність помилок у бітах 8-11. Some(data as u8) } } fn read_flag_register(&self) -> Flags { // БЕЗПЕКА: ми знаємо, що self.registers вказує на керуючі // регістри пристрою PL011, який відповідним чином відображено. unsafe { addr_of!((*self.registers).fr).read_volatile() } } }
- Зверніть увагу на використання
addr_of!
/addr_of_mut!
для отримання вказівників на окремі поля без створення проміжного посилання, що було б нерозумним.