Driver
Agora vamos usar o novo struct Registers
em nosso driver.
/// Driver para um UART PL011. #[derive(Debug)] pub struct Uart { registers: *mut Registers, } impl Uart { /// ConstrĂłi uma nova instĂąncia do driver UART para um dispositivo PL011 no endereço /// base fornecido. /// /// # Segurança /// /// O endereço base fornecido deve apontar para os 8 registradores de controle MMIO de um /// dispositivo PL011, que deve ser mapeado no espaço de endereços do processo /// como memĂłria de dispositivo e nĂŁo ter nenhum outro alias. pub unsafe fn new(base_address: *mut u32) -> Self { Self { registers: base_address as *mut Registers } } /// Grava um Ășnico byte no UART. pub fn write_byte(&self, byte: u8) { // Aguarde atĂ© que haja espaço no buffer TX. while self.read_flag_register().contains(Flags::TXFF) {} // SEGURANĂA: Sabemos que self.registers aponta para os registradores // de controle de um dispositivo PL011 que estĂĄ mapeado adequadamente. unsafe { // Escreva no buffer TX. addr_of_mut!((*self.registers).dr).write_volatile(byte.into()); } // Aguarde atĂ© que o UART nĂŁo esteja mais ocupado. while self.read_flag_register().contains(Flags::BUSY) {} } /// LĂȘ e retorna um byte pendente ou `None` se nada foi /// recebido. pub fn read_byte(&self) -> Option<u8> { if self.read_flag_register().contains(Flags::RXFE) { None } else { // SEGURANĂA: Sabemos que self.registers aponta para os registradores // de controle de um dispositivo PL011 que estĂĄ mapeado adequadamente. let data = unsafe { addr_of!((*self.registers).dr).read_volatile() }; // TODO: Verifique as condiçÔes de erro nos bits 8-11. Some(data as u8) } } fn read_flag_register(&self) -> Flags { // SEGURANĂA: Sabemos que self.registers aponta para os registradores // de controle de um dispositivo PL011 que estĂĄ mapeado adequadamente. unsafe { addr_of!((*self.registers).fr).read_volatile() } } }
- Observe o uso de
addr_of!
/addr_of_mut!
para obter ponteiros para campos individuais sem criar uma referĂȘncia intermediĂĄria, o que seria incorreto.