Драйвер
Тепер давайте використаємо нову структуру 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.
(&raw 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 { (&raw const (*self.registers).dr).read_volatile() };
// TODO: Перевірити на наявність помилок у бітах 8-11.
Some(data as u8)
}
}
fn read_flag_register(&self) -> Flags {
// БЕЗПЕКА: ми знаємо, що self.registers вказує на керуючі
// регістри пристрою PL011, який відповідним чином відображено.
unsafe { (&raw const (*self.registers).fr).read_volatile() }
}
}
- Зверніть увагу на використання
&raw const/&raw mutдля отримання вказівників на окремі поля без створення проміжного посилання, що було б нерозумним.