From e73303a757f8ed7285a158a17579eb5c1ccd84fd Mon Sep 17 00:00:00 2001 From: Histausse Date: Mon, 21 Nov 2022 22:12:30 +0100 Subject: [PATCH] Start implementing LCD driver --- src/bsp/aarch64/time.rs | 6 +- src/bsp/generic_gpio_drivers/lcd.rs | 141 ++++++++++++++++++++++++++ src/bsp/generic_gpio_drivers/mod.rs | 3 + src/bsp/mod.rs | 5 +- src/bsp/rpi3/gpio.rs | 8 +- src/bsp/rpi3/memory_map.rs | 151 ++++++++++++++-------------- src/bsp/rpi3/uart.rs | 18 ++-- src/bsp/rpi4/memory_map.rs | 1 - src/main.rs | 24 +++-- src/panic.rs | 4 +- src/traits/console.rs | 2 - src/traits/mod.rs | 2 +- src/traits/time.rs | 3 +- src/utils/field.rs | 70 +++++-------- 14 files changed, 284 insertions(+), 154 deletions(-) create mode 100644 src/bsp/generic_gpio_drivers/lcd.rs create mode 100644 src/bsp/generic_gpio_drivers/mod.rs diff --git a/src/bsp/aarch64/time.rs b/src/bsp/aarch64/time.rs index 0843a19..3e41bb2 100644 --- a/src/bsp/aarch64/time.rs +++ b/src/bsp/aarch64/time.rs @@ -3,8 +3,8 @@ use core::arch::asm; use core::time::Duration; -use crate::traits::time::TimeManager; use crate::println; +use crate::traits::time::TimeManager; const NS_PER_S: u64 = 1_000_000_000; const CNTP_CTL_EL0_ENABLE_MASK: u64 = 0b001; @@ -40,7 +40,7 @@ impl TimeManager for Timer { asm!("ISB", options(nostack)); asm!("mrs {0:x}, CNTPCT_EL0", out(reg) ticks, options(nomem, nostack)); } - Duration::from_nanos((ticks*NS_PER_S)/self.frequency()) + Duration::from_nanos((ticks * NS_PER_S) / self.frequency()) } fn sleep(&self, duration: Duration) { @@ -66,7 +66,7 @@ impl TimeManager for Timer { return; } - // Enable the timer and mask (disable) the interrupt + // Enable the timer and mask (disable) the interrupt let mut ctl: u64 = CNTP_CTL_EL0_ENABLE_MASK + CNTP_CTL_EL0_IMASK_MASK; unsafe { // set the register values for the timer diff --git a/src/bsp/generic_gpio_drivers/lcd.rs b/src/bsp/generic_gpio_drivers/lcd.rs new file mode 100644 index 0000000..678b08f --- /dev/null +++ b/src/bsp/generic_gpio_drivers/lcd.rs @@ -0,0 +1,141 @@ +//! Driver for LiquidCrystal Displays plugs to the GPIO of the board. +//! The LCD need to be an Hitachi HD44780 chipset compatible. +//! +//! This driver inspired from the one from the arduino libriaries +//! (https://github.com/arduino-libraries/LiquidCrystal) and the +//! documentation from wikipedia (https://en.wikipedia.org/wiki/Hitachi_HD44780_LCD_controller) + +use crate::gpio; + +// TODO: change USIZE to a Pin struct (and implement the Pin struct :'( ) +/// The structure handling the LCD periferic +pub struct Lcd { + /// The Register Select pinout. + rs_pin: usize, + /// The Read/Write pinout. + /// + /// If set to None, assumes the rw pin of the lcd is connected to the ground (write state) + rw_pin: Option, + /// The Enable pinout. + /// + /// TODO: wiki says falling-edge triggered, arduino comment says activated by a HIGH pulse. + e_pin: usize, + /// First 4 data bits pins. + /// + /// Set to None if the lcd is in 4-bit mode. + first_data_bits_pins: Option<[usize; 4]>, + /// Last 4 data bits pins. + last_data_bits_pins: [usize; 4], + /// The number of line of the LCD. + nb_lines: usize, + /// The number of row of the LCD. + nb_rows: usize, + /// Weither or not the LCD has been initialized in the rigth state. + initialized: bool, +} + +impl Lcd { + /// Instanciate a [`Lcd`] object in 4 bits mode. + pub const fn new_4bits_mode( + rs_pin: usize, + rw_pin: Option, + e_pin: usize, + db4: usize, + db5: usize, + db6: usize, + db7: usize, + nb_lines: usize, + nb_rows: usize, + ) -> Self { + Self { + rs_pin, + rw_pin, + e_pin, + first_data_bits_pins: None, + last_data_bits_pins: [db4, db5, db6, db7], + nb_lines, + nb_rows, + initialized: false, + } + } + + /// Instanciate a [`Lcd`] object in 8 bits mode. + pub const fn new_8bits_mode( + rs_pin: usize, + rw_pin: Option, + e_pin: usize, + db0: usize, + db1: usize, + db2: usize, + db3: usize, + db4: usize, + db5: usize, + db6: usize, + db7: usize, + nb_lines: usize, + nb_rows: usize, + ) -> Self { + Self { + rs_pin, + rw_pin, + e_pin, + first_data_bits_pins: Some([db0, db1, db2, db3]), + last_data_bits_pins: [db4, db5, db6, db7], + nb_lines, + nb_rows, + initialized: false, + } + } + + /// Initialize the LCD. + pub fn init(&mut self) -> Result::<(), &str> { + gpio::set_pin_fonction(self.rs_pin, gpio::PinFunction::Output)?; + gpio::set_pin_output_state(self.rs_pin, gpio::PinOutputState::Low)?; + if let Some(rw_pin) = self.rw_pin { + gpio::set_pin_fonction(rw_pin, gpio::PinFunction::Output)?; + gpio::set_pin_output_state(rw_pin, gpio::PinOutputState::Low)?; + } + gpio::set_pin_fonction(self.e_pin, gpio::PinFunction::Output)?; + gpio::set_pin_output_state(self.e_pin, gpio::PinOutputState::Low)?; + if let Some(first_data_bits_pins) = self.first_data_bits_pins { + for pin in first_data_bits_pins.into_iter() { + gpio::set_pin_fonction(pin, gpio::PinFunction::Output)?; + } + } + for pin in self.last_data_bits_pins.into_iter() { + gpio::set_pin_fonction(pin, gpio::PinFunction::Output)?; + } + + // TODO: send 0b0011 3 times to make sure to be in 8bits mode 5x8 characters + // TODO: set the new mode with Function set (2 times if 4 bits modes, 1 to set DL=0, + // then the actual one) + self.initialized = true; + todo!(); + } + + /// Send an 'enable' signal. + fn enable(&self) { + todo!() + } + + /// Send a Function Set instruction. + fn function_set(&self) { + todo!() + } + + /// Send data to the lcd. + fn send_data(&self) { + todo!() + } + + /// Send 8 bits of data. + fn send_8bit(&self) { + todo!() + } + + /// Send 4 bits of data. + fn send_4bits(&self) { + // TODO: type? + todo!() + } +} diff --git a/src/bsp/generic_gpio_drivers/mod.rs b/src/bsp/generic_gpio_drivers/mod.rs new file mode 100644 index 0000000..be492c3 --- /dev/null +++ b/src/bsp/generic_gpio_drivers/mod.rs @@ -0,0 +1,3 @@ +//! Generic driver for perifierics to plug to the GPIO. + +pub mod lcd; diff --git a/src/bsp/mod.rs b/src/bsp/mod.rs index 0c1a74c..aee45c4 100644 --- a/src/bsp/mod.rs +++ b/src/bsp/mod.rs @@ -1,4 +1,4 @@ -//! Board Support Package: module containing implementation +//! Board Support Package: module containing implementation //! specific to a board. #[cfg(feature = "target_rpi3")] @@ -9,3 +9,6 @@ pub mod rpi4; #[cfg(target_arch = "aarch64")] pub mod aarch64; + +// TODO: only for bsp with support for GPIO +pub mod generic_gpio_drivers; diff --git a/src/bsp/rpi3/gpio.rs b/src/bsp/rpi3/gpio.rs index fac60e3..38029d7 100644 --- a/src/bsp/rpi3/gpio.rs +++ b/src/bsp/rpi3/gpio.rs @@ -71,7 +71,9 @@ pub fn set_pin_fonction(n: usize, function: PinFunction) -> Result<(), &'static let mut val = unsafe { core::ptr::read_volatile(address as *mut u32) }; val &= !field.get_mask(); val |= Into::::into(function) << field.get_offset(); - unsafe { core::ptr::write_volatile(address as *mut u32, val); } + unsafe { + core::ptr::write_volatile(address as *mut u32, val); + } Ok(()) } @@ -92,6 +94,8 @@ pub fn set_pin_output_state(n: usize, state: PinOutputState) -> Result<(), &'sta let val = field.get_mask(); let address = field.get_address(); // 0 has no effect on this field: no nead to read-modify-write - unsafe { core::ptr::write_volatile(address as *mut u32, val); } + unsafe { + core::ptr::write_volatile(address as *mut u32, val); + } Ok(()) } diff --git a/src/bsp/rpi3/memory_map.rs b/src/bsp/rpi3/memory_map.rs index 281a731..5ee6a8a 100644 --- a/src/bsp/rpi3/memory_map.rs +++ b/src/bsp/rpi3/memory_map.rs @@ -2,7 +2,6 @@ use crate::utils::field::Field; - pub const START_PHYSICAL_ADDRESS: usize = 0x3F00_0000; // ** GPIO addresses ** @@ -45,7 +44,7 @@ pub mod gpio { /// - 8-6: FSEL12 /// - 5-3: FSEL11 /// - 2-0: FSEL10 - pub const GPFSEL1:usize = GPIO_START + 0x04; + pub const GPFSEL1: usize = GPIO_START + 0x04; /// GPIO Function Select 2, R/W register. /// /// # Bits distribution: @@ -60,7 +59,7 @@ pub mod gpio { /// - 8-6: FSEL22 /// - 5-3: FSEL21 /// - 2-0: FSEL20 - pub const GPFSEL2:usize = GPIO_START + 0x08; + pub const GPFSEL2: usize = GPIO_START + 0x08; /// GPIO Function Select 3, R/W register. /// /// # Bits distribution: @@ -75,7 +74,7 @@ pub mod gpio { /// - 8-6: FSEL32 /// - 5-3: FSEL31 /// - 2-0: FSEL30 - pub const GPFSEL3:usize = GPIO_START + 0x0C; + pub const GPFSEL3: usize = GPIO_START + 0x0C; /// GPIO Function Select 4, R/W register. /// /// # Bits distribution: @@ -90,7 +89,7 @@ pub mod gpio { /// - 8-6: FSEL42 /// - 5-3: FSEL41 /// - 2-0: FSEL40 - pub const GPFSEL4:usize = GPIO_START + 0x10; + pub const GPFSEL4: usize = GPIO_START + 0x10; /// GPIO Function Select 5, R/W register. /// /// # Bits distribution: @@ -99,23 +98,23 @@ pub mod gpio { /// - 8-6: FSEL52 /// - 5-3: FSEL51 /// - 2-0: FSEL50 - pub const GPFSEL5:usize = GPIO_START + 0x14; - + pub const GPFSEL5: usize = GPIO_START + 0x14; + /// Return the field FSELn. - /// + /// /// # Panic - /// + /// /// Panic if the pin `n` does not exist. pub const fn get_fsel(n: usize) -> Field { if n > 53 { panic!("The PIN does not exist"); } - let address = [GPFSEL0, GPFSEL1, GPFSEL2, GPFSEL3, GPFSEL4, GPFSEL5][n/10]; - let offset = 3*(n%10); + let address = [GPFSEL0, GPFSEL1, GPFSEL2, GPFSEL3, GPFSEL4, GPFSEL5][n / 10]; + let offset = 3 * (n % 10); let size = 3; Field::new(address, offset, size) } - + // Pin Output Set /// Pin Output Set 0, W register. /// @@ -124,7 +123,7 @@ pub mod gpio { /// - 31: SET31 /// - ... /// - 0: SET0 - pub const GPSET0:usize = GPIO_START + 0x1C; + pub const GPSET0: usize = GPIO_START + 0x1C; /// Pin Output Set 1, W register. /// /// # Bits distribution: @@ -132,12 +131,12 @@ pub mod gpio { /// - 21: SET53 /// - ... /// - 0: SET32 - pub const GPSET1:usize = GPIO_START + 0x20; - + pub const GPSET1: usize = GPIO_START + 0x20; + /// Return the field SETn. - /// + /// /// # Panic - /// + /// /// Panic if the pin `n` does not exist. pub const fn get_set(n: usize) -> Field { if n > 53 { @@ -146,12 +145,12 @@ pub mod gpio { let (address, offset) = if n < 32 { (GPSET0, n) } else { - (GPSET1, n-32) + (GPSET1, n - 32) }; let size = 1; Field::new(address, offset, size) } - + // Pin Output Clear /// Pin Output Clear 0, W register. /// @@ -160,7 +159,7 @@ pub mod gpio { /// - 31: CLR31 /// - ... /// - 0: CLR0 - pub const GPCLR0:usize = GPIO_START + 0x28; + pub const GPCLR0: usize = GPIO_START + 0x28; /// Pin Output Clear 1, W register. /// /// # Bits distribution: @@ -168,12 +167,12 @@ pub mod gpio { /// - 21: CLR53 /// - ... /// - 0: CLR32 - pub const GPCLR1:usize = GPIO_START + 0x2C; - + pub const GPCLR1: usize = GPIO_START + 0x2C; + /// Return the field CLRn. - /// + /// /// # Panic - /// + /// /// Panic if the pin `n` does not exist. pub const fn get_clr(n: usize) -> Field { if n > 53 { @@ -182,73 +181,73 @@ pub mod gpio { let (address, offset) = if n < 32 { (GPCLR0, n) } else { - (GPCLR1, n-32) + (GPCLR1, n - 32) }; let size = 1; Field::new(address, offset, size) } - + // Pin Level /// Pin Level 0, R register. - pub const GPLEV0:usize = GPIO_START + 0x34; + pub const GPLEV0: usize = GPIO_START + 0x34; /// Pin Level 1, R register. - pub const GPLEV1:usize = GPIO_START + 0x38; - + pub const GPLEV1: usize = GPIO_START + 0x38; + // Pin Event Detect Status /// Pin Event Detect Status 0, R/W register. - pub const GPEDS0:usize = GPIO_START + 0x40; + pub const GPEDS0: usize = GPIO_START + 0x40; /// Pin Event Detect Status 1, R/W register. - pub const GPEDS1:usize = GPIO_START + 0x44; - + pub const GPEDS1: usize = GPIO_START + 0x44; + // Pin Rising Edge Detect Enable /// Pin Rising Edge Detect Enable 0, R/W register. - pub const GPREN0:usize = GPIO_START + 0x4C; + pub const GPREN0: usize = GPIO_START + 0x4C; /// Pin Rising Edge Detect Enable 1, R/W register. - pub const GPREN1:usize = GPIO_START + 0x50; - + pub const GPREN1: usize = GPIO_START + 0x50; + // Pin Falling Edge Detect Enable /// Pin Falling Edge Detect Enable 0, R/W register. - pub const GPFEN0:usize = GPIO_START + 0x58; + pub const GPFEN0: usize = GPIO_START + 0x58; /// Pin Falling Edge Detect Enable 1, R/W register. - pub const GPFEN1:usize = GPIO_START + 0x5C; - + pub const GPFEN1: usize = GPIO_START + 0x5C; + // Pin High Detect Enable /// Pin High Detect Enable 0, R/W register. - pub const GPHEN0:usize = GPIO_START + 0x64; + pub const GPHEN0: usize = GPIO_START + 0x64; /// Pin High Detect Enable 1, R/W register. - pub const GPHEN1:usize = GPIO_START + 0x68; - + pub const GPHEN1: usize = GPIO_START + 0x68; + // Pin Low Detect Enable /// Pin Low Detect Enable 0, R/W register. - pub const GPLEN0:usize = GPIO_START + 0x70; + pub const GPLEN0: usize = GPIO_START + 0x70; /// Pin Low Detect Enable 1, R/W register. - pub const GPLEN1:usize = GPIO_START + 0x74; - + pub const GPLEN1: usize = GPIO_START + 0x74; + // Pin Async, Rising Edge Detect /// Pin Async, Rising Edge Detect 0, R/W register. - pub const GPAREN0:usize = GPIO_START + 0x7C; + pub const GPAREN0: usize = GPIO_START + 0x7C; /// Pin Async, Rising Edge Detect 1, R/W register. - pub const GPAREN1:usize = GPIO_START + 0x80; - + pub const GPAREN1: usize = GPIO_START + 0x80; + // Pin Async, Falling Edge Detect /// Pin Async, Falling Edge Detect 0, R/W register. - pub const GPAFEN0:usize = GPIO_START + 0x88; + pub const GPAFEN0: usize = GPIO_START + 0x88; /// Pin Async, Falling Edge Detect1, R/W register. - pub const GPAFEN1:usize = GPIO_START + 0x8C; - + pub const GPAFEN1: usize = GPIO_START + 0x8C; + // Pin Pull-up/down Enable, R/W /// Pin Pull-up/down Enable, R/W register. - pub const GPPUD:usize = GPIO_START + 0x94; - + pub const GPPUD: usize = GPIO_START + 0x94; + // Pin Pull-up/down enable clock, R/W /// Pin Pull-up/down enable clock 0, R/W register. - pub const GPPUDCLK0:usize = GPIO_START + 0x98; + pub const GPPUDCLK0: usize = GPIO_START + 0x98; /// Pin Pull-up/down enable clock 1, R/W register. - pub const GPPUDCLK1:usize = GPIO_START + 0x9C; - + pub const GPPUDCLK1: usize = GPIO_START + 0x9C; + // Test ?, R/W, 4 bits /// Test register? only 4 bits long. - pub const GPIO_TEST:usize = GPIO_START + 0xB0; + pub const GPIO_TEST: usize = GPIO_START + 0xB0; } // ** GPIO addresses ** @@ -276,31 +275,30 @@ pub mod uart { pub dr: Field, /// OE, Overrun Error. Set to 1 if data received with FIFO full, R/W. - /// + /// /// Field located inside the Data Register [`dr`]. pub dr_oe: Field, /// BE, Break Error. Set to 1 if a break condition was detected, R/W. - /// + /// /// Field located inside the Data Register [`dr`]. pub dr_be: Field, /// PE, Parity Error. Set to 1 when the parity don't match data, R/W. - /// + /// /// Field located inside the Data Register [`dr`]. pub dr_pe: Field, /// FE, Framing Error. Set to 1 when character don't have valid stop bit, R/W. - /// + /// /// Field located inside the Data Register [`dr`]. pub dr_fe: Field, /// DATA, Data character. R/W. - /// + /// /// Field located inside the Data Register [`dr`]. pub dr_data: Field, - /// Receive Status Register/Error Clear Register, 32 bits long. /// /// # Bits distribution: @@ -313,22 +311,22 @@ pub mod uart { pub rsrecr: Field, /// OE, Overrun Error. Set to 1 if data received with FIFO full, R/W. - /// + /// /// Field located inside the Receive Status Register/Error Clear Register [`rsrecr`]. pub rsrecr_oe: Field, /// BE, Break Error. Set to 1 if a break condition was detected, R/W. - /// + /// /// Field located inside the Receive Status Register/Error Clear Register [`rsrecr`]. pub rsrecr_be: Field, /// PE, Parity Error. Set to 1 when the parity don't match data, R/W. - /// + /// /// Field located inside the Receive Status Register/Error Clear Register [`rsrecr`]. pub rsrecr_pe: Field, /// FE, Framing Error. Set to 1 when characteur don't have valid stop bit, R/W. - /// + /// /// Field located inside the Receive Status Register/Error Clear Register [`rsrecr`]. pub rsrecr_fe: Field, @@ -349,7 +347,7 @@ pub mod uart { /// - 3: BUSY. Is set, UART is busy transmitting data. R/W. /// - 2: DCD, unsuported. Write as 0, value read don't have meaning, R/W. /// - 1: DSR, unsuported. Write as 0, value read don't have meaning, R/W. - /// - 0: CTS, Clear To Send. + /// - 0: CTS, Clear To Send. pub fr: Field, /// RI, unsuported. Write as 0, value read don't have meaning, R/W. @@ -396,7 +394,7 @@ pub mod uart { /// Field located inside the Flag Register [`fr`]. pub fr_dsr: Field, - /// CTS, Clear To Send. + /// CTS, Clear To Send. /// /// Field located inside the Flag Register [`fr`]. pub fr_cts: Field, @@ -430,7 +428,7 @@ pub mod uart { /// - 6-5: WLEN: World lenght. Number of data bits transmitted by frame (0b00 -> 5b, 0b11 -> /// 8b), R/W. /// - 4: FEN, Enable FIFOs. 0: FIFOs disabled, 1: FIFO buffers are enables, R/W. - /// - 3: STP2, 2 Stop bit select. 1: 2 stop bits are transmitted at the end of the frame + /// - 3: STP2, 2 Stop bit select. 1: 2 stop bits are transmitted at the end of the frame /// (rx logic is not affected), R/W. /// - 2: EPS, Event Parity Select. 0: odd parity, check for odd number of 1 in data+parity /// bits, 1: event parity, check for even number of 1 in data+parity. No effect when @@ -457,7 +455,7 @@ pub mod uart { /// Field located inside the Line Constrol Register [`lcrh`]. pub lcrh_fen: Field, - /// STP2, 2 Stop bit select. 1: 2 stop bits are transmitted at the end of the frame + /// STP2, 2 Stop bit select. 1: 2 stop bits are transmitted at the end of the frame /// (rx logic is not affected), R/W. /// /// Field located inside the Line Constrol Register [`lcrh`]. @@ -486,7 +484,7 @@ pub mod uart { /// # Warning /// /// To program the CR: - /// + /// /// - 1) Disable UART /// - 2) Wait for the end of tx/rx of the current char /// - 3) Flush the transmit FIFO by setting `FEN` to 0 in [`LCRH`] @@ -510,7 +508,7 @@ pub mod uart { /// - 6-3: reserved. Write as 0, value read don't have meaning, R/W. /// - 2: SIRLP, unsuported, Write as 0, value read don't have meaning, R. /// - 1: SIREN, unsuported, Write as 0, value read don't have meaning, R. - /// - 0: UARTEN, UART enable. If set, the UART is enable, R/W. + /// - 0: UARTEN, UART enable. If set, the UART is enable, R/W. pub cr: Field, /// CTSEN, CTS hardware flow control enable. If set, data is only transmitted when @@ -639,7 +637,7 @@ pub mod uart { /// Field located inside the Control Register [`cr`]. pub cr_siren: Field, - /// UARTEN, UART enable. If set, the UART is enable, R/W. + /// UARTEN, UART enable. If set, the UART is enable, R/W. /// /// Field located inside the Control Register [`cr`]. /// @@ -658,7 +656,6 @@ pub mod uart { pub cr_uarten: Field, // TODO: Finish detailling the registers - /// Interrupt FIFO Level Select register, 32 bits long. /// /// # Bits distribution: @@ -666,7 +663,7 @@ pub mod uart { /// - 31-12: reserved. Write as 0, value read don't have meaning, R/W. /// - 11-9: RXIFPSEL, unsuported, Write as 0, value read don't have meaning, R. /// - 8-6: TXIFPSEL, unsuported, Write as 0, value read don't have meaning, R. - /// - 5-3: RXIFLSEL, Receive Interrupt FIFO Level Select. The level from which the + /// - 5-3: RXIFLSEL, Receive Interrupt FIFO Level Select. The level from which the /// reveive interrupt is send: /// - `0b000`: Send when FIFO becom 1/8 full /// - `0b001`: Send when FIFO becom 1/4 full @@ -675,7 +672,7 @@ pub mod uart { /// - `0b100`: Send when FIFO becom 7/7 full /// - Other values are reserved. /// R/W. - /// - 2-0: TXIFLSEL, Transmit Interrupt FIFO Level Select. The level from which the + /// - 2-0: TXIFLSEL, Transmit Interrupt FIFO Level Select. The level from which the /// transmit interrupt is send: /// - `0b000`: Send when FIFO becom 1/8 full /// - `0b001`: Send when FIFO becom 1/4 full @@ -809,7 +806,6 @@ pub mod uart { /// - 31-11: reserved. Write as 0, value read don't have meaning, R. /// - 10-0: TDR10_0. When ITCRI1 is set to 1, data read an write directly from the FIFOs, R/W. pub tdr: Field, - } impl UartMemoryMap { @@ -878,5 +874,4 @@ pub mod uart { } pub const UART: UartMemoryMap = UartMemoryMap::new(UART_START); - } diff --git a/src/bsp/rpi3/uart.rs b/src/bsp/rpi3/uart.rs index 153a3de..5cb6afd 100644 --- a/src/bsp/rpi3/uart.rs +++ b/src/bsp/rpi3/uart.rs @@ -20,15 +20,18 @@ pub struct UartInner<'a> { impl<'a> UartInner<'a> { /// Constructor for [`Uart`]. const fn new(memory_map: &'a mm::UartMemoryMap) -> Self { - Self { initialized: false, memory_map } + Self { + initialized: false, + memory_map, + } } /// Initialise the UART. fn init(&mut self) { // TODO: Recover from possible previous test. - + self.flush(); - + // Stop UART, see doc of CR register for the config process (P 185, doc BCM2835) self.memory_map.cr_uarten.read_and_write(0); @@ -54,10 +57,10 @@ impl<'a> UartInner<'a> { self.memory_map.lcrh.write_without_read(lcrh_val); let cr_val = self.memory_map.cr_txe.read_and_write_to_u32(1, 0); - let cr_val = self.memory_map.cr_rxe.read_and_write_to_u32(1, cr_val); + let cr_val = self.memory_map.cr_rxe.read_and_write_to_u32(1, cr_val); // Again, see doc of CR register for the config process (P 185, doc BCM2835) self.memory_map.cr.write_without_read(cr_val); - + // Start the UART self.memory_map.cr_uarten.read_and_write(1); self.initialized = true; @@ -153,14 +156,11 @@ impl Read for Uart<'_> { } impl<'a> Uart<'a> { - // TODO: not sure this should be public? public in bsp only? /// Create a new UART object const fn new(memory_map: &'a mm::UartMemoryMap) -> Self { Self { - inner: DummyMutex::new( - UartInner::new(memory_map) - ) + inner: DummyMutex::new(UartInner::new(memory_map)), } } diff --git a/src/bsp/rpi4/memory_map.rs b/src/bsp/rpi4/memory_map.rs index d4fe3fc..f4902bf 100644 --- a/src/bsp/rpi4/memory_map.rs +++ b/src/bsp/rpi4/memory_map.rs @@ -12,4 +12,3 @@ pub const UART2_START: usize = START_LOW_PERIPHERAL_MODE + 0x0020_1400; pub const UART3_START: usize = START_LOW_PERIPHERAL_MODE + 0x0020_1600; pub const UART4_START: usize = START_LOW_PERIPHERAL_MODE + 0x0020_1800; pub const UART5_START: usize = START_LOW_PERIPHERAL_MODE + 0x0020_1A00; - diff --git a/src/main.rs b/src/main.rs index b94c417..66963d7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,35 +9,35 @@ #![cfg_attr(not(test), no_std)] #![feature(format_args_nl)] #![feature(panic_info_message)] - #![allow(dead_code)] -mod traits; mod bsp; +mod traits; mod utils; +#[cfg(not(test))] +mod log; #[cfg(not(test))] mod panic; #[cfg(not(test))] mod print; -#[cfg(not(test))] -mod log; -#[cfg(not(test))] -use core::arch::global_asm; #[cfg(not(test))] use core::arch::asm; +#[cfg(not(test))] +use core::arch::global_asm; use core::time::Duration; // TODO: handle this with features #[cfg(not(test))] -use crate::bsp::rpi3::uart::console; +use crate::bsp::aarch64::time::time_manager; #[cfg(not(test))] use crate::bsp::rpi3::gpio; #[cfg(not(test))] -use crate::bsp::aarch64::time::time_manager; +use crate::bsp::rpi3::uart::console; +use crate::bsp::generic_gpio_drivers::lcd::Lcd; use crate::traits::time::TimeManager; // TODO: move this to BSP @@ -46,7 +46,9 @@ use crate::traits::time::TimeManager; #[inline(always)] pub fn wait_forever() -> ! { loop { - unsafe { asm!("wfe"); } + unsafe { + asm!("wfe"); + } } } @@ -58,7 +60,6 @@ global_asm!(include_str!("boot.s")); #[cfg(not(test))] #[no_mangle] pub unsafe fn _start_rust() -> ! { - // Set TX and RX function for pin 14 and 15 match gpio::set_pin_fonction(14, gpio::PinFunction::AltFunc0) { _ => (), @@ -82,6 +83,9 @@ pub unsafe fn _start_rust() -> ! { error!("error"); fatal!("fatal"); + let mut lcd = Lcd::new_8bits_mode(1, Some(2), 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, 80); + let _ = lcd.init(); + let mut buffer = ['X'; 200]; let mut i = 0; let mut c = console().read_char(); diff --git a/src/panic.rs b/src/panic.rs index ab496c8..3272822 100644 --- a/src/panic.rs +++ b/src/panic.rs @@ -36,7 +36,9 @@ fn panic(info: &PanicInfo) -> ! { "Kernel panic!\n\n\ Panic location:\n File: '{}', line {}, column {}\n\n\ {}", - location, line, column, + location, + line, + column, info.message().unwrap_or(&format_args!("")) ); wait_forever() diff --git a/src/traits/console.rs b/src/traits/console.rs index 9fe4660..16fee99 100644 --- a/src/traits/console.rs +++ b/src/traits/console.rs @@ -27,7 +27,6 @@ pub trait Read { fn flush_input(&self); } - /// A Dummy Console. /// /// The DummyConsole implement the [`Console`] trait, and do nothing. @@ -51,5 +50,4 @@ impl Read for DummyConsole { fn flush_input(&self) {} } - impl Console for DummyConsole {} diff --git a/src/traits/mod.rs b/src/traits/mod.rs index 0b45ab8..b1abd62 100644 --- a/src/traits/mod.rs +++ b/src/traits/mod.rs @@ -2,7 +2,7 @@ //! //! Most of those traits come with a dummy implementation. //! Actual implementations are either in generic modules or -//! in target specific modules. +//! in target specific modules. //! //! # TODO //! diff --git a/src/traits/time.rs b/src/traits/time.rs index 983a902..5c1f325 100644 --- a/src/traits/time.rs +++ b/src/traits/time.rs @@ -3,8 +3,7 @@ use core::time::Duration; pub trait TimeManager { - - /// Return the clock frequency, meaning the resolution of the + /// Return the clock frequency, meaning the resolution of the /// time mesurement. fn frequency(&self) -> u64; diff --git a/src/utils/field.rs b/src/utils/field.rs index bfa5ca8..8bf777b 100644 --- a/src/utils/field.rs +++ b/src/utils/field.rs @@ -7,10 +7,10 @@ use core::ptr::{read_volatile, write_volatile}; /// is only descriptif. /// /// Fields represent a continuous set of bits in an alligned -/// `u32`. This means that the address is a multiple of 4, +/// `u32`. This means that the address is a multiple of 4, /// the offset is < 32, and offset + size <= 32. /// -/// The constructor of the is class ensure that the field is +/// The constructor of the is class ensure that the field is /// always inside the `u32` at `address`, and that `address` /// is alligned. /// @@ -24,7 +24,7 @@ pub struct Field { /// The size of the field in bit. size: usize, /// The mask for the field in the `u32` at `address`. - mask: u32 + mask: u32, } impl Field { @@ -32,7 +32,7 @@ impl Field { /// The field is defined by the `size` bits at `offset` bits after /// `address`. (**`address` is in bytes, not bits**) pub const fn new(address: usize, offset: usize, size: usize) -> Self { - // align the address + // align the address let offset = offset + 8 * (address % 4); let address = address - (address % 4); // make sure the field is in the u32 at address @@ -45,7 +45,12 @@ impl Field { let mask = Self::compute_mask(offset, size); - Self { address, offset, size, mask } + Self { + address, + offset, + size, + mask, + } } /// Compute mask for the field. @@ -86,7 +91,11 @@ impl Field { /// Set the value of the field in the provided u32. #[inline] pub fn read_and_write_to_u32(&self, val: u32, register: u32) -> u32 { - assert_eq!(val & !(self.mask >> self.offset), 0, "Value greater than the field"); + assert_eq!( + val & !(self.mask >> self.offset), + 0, + "Value greater than the field" + ); register & !self.mask | (val << self.offset) } @@ -103,7 +112,7 @@ impl Field { unsafe { write_volatile(self.address as *mut u32, register) }; } - /// Write the value in memory but override every other value of the + /// Write the value in memory but override every other value of the /// u32 (replace them by 0s). pub fn write_without_read(&self, val: u32) { let register = self.read_and_write_to_u32(val, 0); @@ -124,26 +133,17 @@ mod test { #[test] fn test_get_address() { // Test when the address is alligned - assert_eq!( - Field::new(0x1234_5678, 0, 1).get_address(), - 0x1234_5678, - ); + assert_eq!(Field::new(0x1234_5678, 0, 1).get_address(), 0x1234_5678,); } #[test] fn test_get_offset() { - assert_eq!( - Field::new(0x1234_5678, 18, 1).get_offset(), - 18, - ); + assert_eq!(Field::new(0x1234_5678, 18, 1).get_offset(), 18,); } #[test] fn test_get_size() { - assert_eq!( - Field::new(0x1234_5678, 18, 1).get_size(), - 1, - ); + assert_eq!(Field::new(0x1234_5678, 18, 1).get_size(), 1,); } #[test] @@ -175,7 +175,7 @@ mod test { assert_eq!(field.get_address(), 0x1111_1114); assert_eq!(field.get_offset(), 8); - let field = Field::new(0x1111_1112, 32+16, 1); + let field = Field::new(0x1111_1112, 32 + 16, 1); assert_eq!(field.get_address(), 0x1111_1118); assert_eq!(field.get_offset(), 0); } @@ -188,32 +188,17 @@ mod test { #[test] fn test_get_mask() { - assert_eq!( - Field::new(0, 0, 1).get_mask(), - 0b0000_0001, - ); - assert_eq!( - Field::new(0, 0, 3).get_mask(), - 0b0000_0111, - ); - assert_eq!( - Field::new(0, 4, 1).get_mask(), - 0b0001_0000, - ); - assert_eq!( - Field::new(0, 4, 3).get_mask(), - 0b0111_0000, - ); + assert_eq!(Field::new(0, 0, 1).get_mask(), 0b0000_0001,); + assert_eq!(Field::new(0, 0, 3).get_mask(), 0b0000_0111,); + assert_eq!(Field::new(0, 4, 1).get_mask(), 0b0001_0000,); + assert_eq!(Field::new(0, 4, 3).get_mask(), 0b0111_0000,); } #[test] fn test_read_and_write_to_u32() { let field = Field::new(0, 3, 4); let val = 0b0101_0101; - assert_eq!( - field.read_and_write_to_u32(0b0101, val), - 0b0010_1101, - ); + assert_eq!(field.read_and_write_to_u32(0b0101, val), 0b0010_1101,); } #[test] @@ -227,9 +212,6 @@ mod test { fn test_read_from_u32() { let field = Field::new(0, 3, 4); let val = 0b1100_1111; - assert_eq!( - field.read_from_u32(val), - 0b1001, - ); + assert_eq!(field.read_from_u32(val), 0b1001,); } }