implement verry basic unsafe UART
This commit is contained in:
parent
0c7793fe1f
commit
037c48fba0
6 changed files with 686 additions and 218 deletions
|
@ -1,8 +1,6 @@
|
||||||
//! GPIO module.
|
//! GPIO module.
|
||||||
|
|
||||||
use super::memory_map;
|
use super::memory_map::gpio::*;
|
||||||
use crate::println;
|
|
||||||
|
|
||||||
|
|
||||||
/// The number of pin for the raspberry 3.
|
/// The number of pin for the raspberry 3.
|
||||||
const NUMBER_PIN: usize = 54;
|
const NUMBER_PIN: usize = 54;
|
||||||
|
@ -67,13 +65,12 @@ pub fn set_pin_fonction(n: usize, function: PinFunction) -> Result<(), &'static
|
||||||
if n >= NUMBER_PIN {
|
if n >= NUMBER_PIN {
|
||||||
return Err("The pin does not exist.");
|
return Err("The pin does not exist.");
|
||||||
}
|
}
|
||||||
let field = memory_map::get_fsel(n);
|
let field = get_fsel(n);
|
||||||
// TODO: SYNC
|
// TODO: SYNC
|
||||||
let mut val = unsafe { core::ptr::read_volatile(field.get_address() as *mut u32) };
|
let address = field.get_address();
|
||||||
|
let mut val = unsafe { core::ptr::read_volatile(address as *mut u32) };
|
||||||
val &= !field.get_mask();
|
val &= !field.get_mask();
|
||||||
val |= Into::<u32>::into(function) << field.get_offset();
|
val |= Into::<u32>::into(function) << field.get_offset();
|
||||||
let address = field.get_address();
|
|
||||||
println!("Set {val:b} at 0x{address:x}");
|
|
||||||
unsafe { core::ptr::write_volatile(address as *mut u32, val); }
|
unsafe { core::ptr::write_volatile(address as *mut u32, val); }
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -89,12 +86,11 @@ pub fn set_pin_output_state(n: usize, state: PinOutputState) -> Result<(), &'sta
|
||||||
return Err("The pin does not exist.");
|
return Err("The pin does not exist.");
|
||||||
}
|
}
|
||||||
let field = match state {
|
let field = match state {
|
||||||
PinOutputState::High => memory_map::get_set(n),
|
PinOutputState::High => get_set(n),
|
||||||
PinOutputState::Low => memory_map::get_clr(n),
|
PinOutputState::Low => get_clr(n),
|
||||||
};
|
};
|
||||||
let val = field.get_mask();
|
let val = field.get_mask();
|
||||||
let address = field.get_address();
|
let address = field.get_address();
|
||||||
println!("Set {val:b} at 0x{address:x}");
|
|
||||||
// 0 has no effect on this field: no nead to read-modify-write
|
// 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(())
|
Ok(())
|
||||||
|
|
|
@ -2,219 +2,520 @@
|
||||||
|
|
||||||
use crate::utils::field::Field;
|
use crate::utils::field::Field;
|
||||||
|
|
||||||
pub const GPIO_OFFSET: usize = 0x0020_0000;
|
|
||||||
pub const UART0_OFFSET: usize = 0x0020_1000;
|
|
||||||
|
|
||||||
pub const START_PHYSICAL_ADDRESS: usize = 0x3F00_0000;
|
pub const START_PHYSICAL_ADDRESS: usize = 0x3F00_0000;
|
||||||
|
|
||||||
pub const UART0_START: usize = START_PHYSICAL_ADDRESS + UART0_OFFSET;
|
|
||||||
|
|
||||||
// ** GPIO addresses **
|
// ** GPIO addresses **
|
||||||
|
/// Offset between the GPIO addresses and the beginning of the physical addresses
|
||||||
|
pub const GPIO_OFFSET: usize = 0x0020_0000;
|
||||||
/// Beginning of the GPIO adresses
|
/// Beginning of the GPIO adresses
|
||||||
pub const GPIO_START: usize = START_PHYSICAL_ADDRESS + GPIO_OFFSET;
|
pub const GPIO_START: usize = START_PHYSICAL_ADDRESS + GPIO_OFFSET;
|
||||||
|
|
||||||
// Function Select
|
/// GPIO memory map.
|
||||||
/// GPIO Function Select 0, R/W register.
|
pub mod gpio {
|
||||||
/// bits 29-27: FSEL9
|
use super::*;
|
||||||
/// bits 26-24: FSEL8
|
|
||||||
/// bits 23-21: FSEL7
|
|
||||||
/// bits 20-18: FSEL6
|
|
||||||
/// bits 17-15: FSEL5
|
|
||||||
/// bits 14-12: FSEL4
|
|
||||||
/// bits 11-9: FSEL3
|
|
||||||
/// bits 8-6: FSEL2
|
|
||||||
/// bits 5-3: FSEL1
|
|
||||||
/// bits 2-0: FSEL0
|
|
||||||
pub const GPFSEL0: usize = GPIO_START + 0x00;
|
|
||||||
/// GPIO Function Select 1, R/W register.
|
|
||||||
/// bits 29-27: FSEL19
|
|
||||||
/// bits 26-24: FSEL18
|
|
||||||
/// bits 23-21: FSEL17
|
|
||||||
/// bits 20-18: FSEL16
|
|
||||||
/// bits 17-15: FSEL15
|
|
||||||
/// bits 14-12: FSEL14
|
|
||||||
/// bits 11-9: FSEL13
|
|
||||||
/// bits 8-6: FSEL12
|
|
||||||
/// bits 5-3: FSEL11
|
|
||||||
/// bits 2-0: FSEL10
|
|
||||||
pub const GPFSEL1:usize = GPIO_START + 0x04;
|
|
||||||
/// GPIO Function Select 2, R/W register.
|
|
||||||
/// bits 29-27: FSEL29
|
|
||||||
/// bits 26-24: FSEL28
|
|
||||||
/// bits 23-21: FSEL27
|
|
||||||
/// bits 20-18: FSEL26
|
|
||||||
/// bits 17-15: FSEL25
|
|
||||||
/// bits 14-12: FSEL24
|
|
||||||
/// bits 11-9: FSEL23
|
|
||||||
/// bits 8-6: FSEL22
|
|
||||||
/// bits 5-3: FSEL21
|
|
||||||
/// bits 2-0: FSEL20
|
|
||||||
pub const GPFSEL2:usize = GPIO_START + 0x08;
|
|
||||||
/// GPIO Function Select 3, R/W register.
|
|
||||||
/// bits 29-27: FSEL39
|
|
||||||
/// bits 26-24: FSEL38
|
|
||||||
/// bits 23-21: FSEL37
|
|
||||||
/// bits 20-18: FSEL36
|
|
||||||
/// bits 17-15: FSEL35
|
|
||||||
/// bits 14-12: FSEL34
|
|
||||||
/// bits 11-9: FSEL33
|
|
||||||
/// bits 8-6: FSEL32
|
|
||||||
/// bits 5-3: FSEL31
|
|
||||||
/// bits 2-0: FSEL30
|
|
||||||
pub const GPFSEL3:usize = GPIO_START + 0x0C;
|
|
||||||
/// GPIO Function Select 4, R/W register.
|
|
||||||
/// bits 29-27: FSEL49
|
|
||||||
/// bits 26-24: FSEL48
|
|
||||||
/// bits 23-21: FSEL47
|
|
||||||
/// bits 20-18: FSEL46
|
|
||||||
/// bits 17-15: FSEL45
|
|
||||||
/// bits 14-12: FSEL44
|
|
||||||
/// bits 11-9: FSEL43
|
|
||||||
/// bits 8-6: FSEL42
|
|
||||||
/// bits 5-3: FSEL41
|
|
||||||
/// bits 2-0: FSEL40
|
|
||||||
pub const GPFSEL4:usize = GPIO_START + 0x10;
|
|
||||||
/// GPIO Function Select 5, R/W register.
|
|
||||||
/// bits 11-9: FSEL53
|
|
||||||
/// bits 8-6: FSEL52
|
|
||||||
/// bits 5-3: FSEL51
|
|
||||||
/// bits 2-0: FSEL50
|
|
||||||
pub const GPFSEL5:usize = GPIO_START + 0x14;
|
|
||||||
|
|
||||||
/// Return the field FSELn.
|
// Function Select
|
||||||
///
|
/// GPIO Function Select 0, R/W register.
|
||||||
/// # Panic
|
///
|
||||||
///
|
/// # Bits distribution:
|
||||||
/// Panic if the pin `n` does not exist.
|
///
|
||||||
pub const fn get_fsel(n: usize) -> Field {
|
/// - 29-27: FSEL9
|
||||||
if n > 53 {
|
/// - 26-24: FSEL8
|
||||||
panic!("The PIN does not exist");
|
/// - 23-21: FSEL7
|
||||||
|
/// - 20-18: FSEL6
|
||||||
|
/// - 17-15: FSEL5
|
||||||
|
/// - 14-12: FSEL4
|
||||||
|
/// - 11-9: FSEL3
|
||||||
|
/// - 8-6: FSEL2
|
||||||
|
/// - 5-3: FSEL1
|
||||||
|
/// - 2-0: FSEL0
|
||||||
|
pub const GPFSEL0: usize = GPIO_START + 0x00;
|
||||||
|
/// GPIO Function Select 1, R/W register.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 29-27: FSEL19
|
||||||
|
/// - 26-24: FSEL18
|
||||||
|
/// - 23-21: FSEL17
|
||||||
|
/// - 20-18: FSEL16
|
||||||
|
/// - 17-15: FSEL15
|
||||||
|
/// - 14-12: FSEL14
|
||||||
|
/// - 11-9: FSEL13
|
||||||
|
/// - 8-6: FSEL12
|
||||||
|
/// - 5-3: FSEL11
|
||||||
|
/// - 2-0: FSEL10
|
||||||
|
pub const GPFSEL1:usize = GPIO_START + 0x04;
|
||||||
|
/// GPIO Function Select 2, R/W register.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 29-27: FSEL29
|
||||||
|
/// - 26-24: FSEL28
|
||||||
|
/// - 23-21: FSEL27
|
||||||
|
/// - 20-18: FSEL26
|
||||||
|
/// - 17-15: FSEL25
|
||||||
|
/// - 14-12: FSEL24
|
||||||
|
/// - 11-9: FSEL23
|
||||||
|
/// - 8-6: FSEL22
|
||||||
|
/// - 5-3: FSEL21
|
||||||
|
/// - 2-0: FSEL20
|
||||||
|
pub const GPFSEL2:usize = GPIO_START + 0x08;
|
||||||
|
/// GPIO Function Select 3, R/W register.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 29-27: FSEL39
|
||||||
|
/// - 26-24: FSEL38
|
||||||
|
/// - 23-21: FSEL37
|
||||||
|
/// - 20-18: FSEL36
|
||||||
|
/// - 17-15: FSEL35
|
||||||
|
/// - 14-12: FSEL34
|
||||||
|
/// - 11-9: FSEL33
|
||||||
|
/// - 8-6: FSEL32
|
||||||
|
/// - 5-3: FSEL31
|
||||||
|
/// - 2-0: FSEL30
|
||||||
|
pub const GPFSEL3:usize = GPIO_START + 0x0C;
|
||||||
|
/// GPIO Function Select 4, R/W register.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 29-27: FSEL49
|
||||||
|
/// - 26-24: FSEL48
|
||||||
|
/// - 23-21: FSEL47
|
||||||
|
/// - 20-18: FSEL46
|
||||||
|
/// - 17-15: FSEL45
|
||||||
|
/// - 14-12: FSEL44
|
||||||
|
/// - 11-9: FSEL43
|
||||||
|
/// - 8-6: FSEL42
|
||||||
|
/// - 5-3: FSEL41
|
||||||
|
/// - 2-0: FSEL40
|
||||||
|
pub const GPFSEL4:usize = GPIO_START + 0x10;
|
||||||
|
/// GPIO Function Select 5, R/W register.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 11-9: FSEL53
|
||||||
|
/// - 8-6: FSEL52
|
||||||
|
/// - 5-3: FSEL51
|
||||||
|
/// - 2-0: FSEL50
|
||||||
|
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 size = 3;
|
||||||
|
Field::new(address, offset, size)
|
||||||
}
|
}
|
||||||
let address = [GPFSEL0, GPFSEL1, GPFSEL2, GPFSEL3, GPFSEL4, GPFSEL5][n/10];
|
|
||||||
let offset = 3*(n%10);
|
// Pin Output Set
|
||||||
let size = 3;
|
/// Pin Output Set 0, W register.
|
||||||
Field::new(address, offset, size)
|
///
|
||||||
}
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
// Pin Output Set
|
/// - 31: SET31
|
||||||
/// Pin Output Set 0, W register.
|
/// - ...
|
||||||
/// bit 31: SET31
|
/// - 0: SET0
|
||||||
/// ...
|
pub const GPSET0:usize = GPIO_START + 0x1C;
|
||||||
/// bit 0: SET0
|
/// Pin Output Set 1, W register.
|
||||||
pub const GPSET0:usize = GPIO_START + 0x1C;
|
///
|
||||||
/// Pin Output Set 1, W register.
|
/// # Bits distribution:
|
||||||
/// bit 21: SET53
|
///
|
||||||
/// ...
|
/// - 21: SET53
|
||||||
/// bit 0: SET32
|
/// - ...
|
||||||
pub const GPSET1:usize = GPIO_START + 0x20;
|
/// - 0: SET32
|
||||||
|
pub const GPSET1:usize = GPIO_START + 0x20;
|
||||||
/// Return the field SETn.
|
|
||||||
///
|
/// Return the field SETn.
|
||||||
/// # Panic
|
///
|
||||||
///
|
/// # Panic
|
||||||
/// Panic if the pin `n` does not exist.
|
///
|
||||||
pub const fn get_set(n: usize) -> Field {
|
/// Panic if the pin `n` does not exist.
|
||||||
if n > 53 {
|
pub const fn get_set(n: usize) -> Field {
|
||||||
panic!("The PIN does not exist");
|
if n > 53 {
|
||||||
|
panic!("The PIN does not exist");
|
||||||
|
}
|
||||||
|
let (address, offset) = if n < 32 {
|
||||||
|
(GPSET0, n)
|
||||||
|
} else {
|
||||||
|
(GPSET1, n-32)
|
||||||
|
};
|
||||||
|
let size = 1;
|
||||||
|
Field::new(address, offset, size)
|
||||||
}
|
}
|
||||||
let (address, offset) = if n < 32 {
|
|
||||||
(GPSET0, n)
|
// Pin Output Clear
|
||||||
} else {
|
/// Pin Output Clear 0, W register.
|
||||||
(GPSET1, n-32)
|
///
|
||||||
};
|
/// # Bits distribution:
|
||||||
let size = 1;
|
///
|
||||||
Field::new(address, offset, size)
|
/// - 31: CLR31
|
||||||
}
|
/// - ...
|
||||||
|
/// - 0: CLR0
|
||||||
// Pin Output Clear
|
pub const GPCLR0:usize = GPIO_START + 0x28;
|
||||||
/// Pin Output Clear 0, W register.
|
/// Pin Output Clear 1, W register.
|
||||||
/// bit 31: CLR31
|
///
|
||||||
/// ...
|
/// # Bits distribution:
|
||||||
/// bit 0: CLR0
|
///
|
||||||
pub const GPCLR0:usize = GPIO_START + 0x28;
|
/// - 21: CLR53
|
||||||
/// Pin Output Clear 1, W register.
|
/// - ...
|
||||||
/// bit 21: CLR53
|
/// - 0: CLR32
|
||||||
/// ...
|
pub const GPCLR1:usize = GPIO_START + 0x2C;
|
||||||
/// bit 0: CLR32
|
|
||||||
pub const GPCLR1:usize = GPIO_START + 0x2C;
|
/// Return the field CLRn.
|
||||||
|
///
|
||||||
/// Return the field CLRn.
|
/// # Panic
|
||||||
///
|
///
|
||||||
/// # Panic
|
/// Panic if the pin `n` does not exist.
|
||||||
///
|
pub const fn get_clr(n: usize) -> Field {
|
||||||
/// Panic if the pin `n` does not exist.
|
if n > 53 {
|
||||||
pub const fn get_clr(n: usize) -> Field {
|
panic!("The PIN does not exist");
|
||||||
if n > 53 {
|
}
|
||||||
panic!("The PIN does not exist");
|
let (address, offset) = if n < 32 {
|
||||||
|
(GPCLR0, n)
|
||||||
|
} else {
|
||||||
|
(GPCLR1, n-32)
|
||||||
|
};
|
||||||
|
let size = 1;
|
||||||
|
Field::new(address, offset, size)
|
||||||
}
|
}
|
||||||
let (address, offset) = if n < 32 {
|
|
||||||
(GPCLR0, n)
|
// Pin Level
|
||||||
} else {
|
/// Pin Level 0, R register.
|
||||||
(GPCLR1, n-32)
|
pub const GPLEV0:usize = GPIO_START + 0x34;
|
||||||
};
|
/// Pin Level 1, R register.
|
||||||
let size = 1;
|
pub const GPLEV1:usize = GPIO_START + 0x38;
|
||||||
Field::new(address, offset, size)
|
|
||||||
|
// Pin Event Detect Status
|
||||||
|
/// Pin Event Detect Status 0, R/W register.
|
||||||
|
pub const GPEDS0:usize = GPIO_START + 0x40;
|
||||||
|
/// Pin Event Detect Status 1, R/W register.
|
||||||
|
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;
|
||||||
|
/// Pin Rising Edge Detect Enable 1, R/W register.
|
||||||
|
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;
|
||||||
|
/// Pin Falling Edge Detect Enable 1, R/W register.
|
||||||
|
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;
|
||||||
|
/// Pin High Detect Enable 1, R/W register.
|
||||||
|
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;
|
||||||
|
/// Pin Low Detect Enable 1, R/W register.
|
||||||
|
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;
|
||||||
|
/// Pin Async, Rising Edge Detect 1, R/W register.
|
||||||
|
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;
|
||||||
|
/// Pin Async, Falling Edge Detect1, R/W register.
|
||||||
|
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;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
/// Pin Pull-up/down enable clock 1, R/W register.
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pin Level
|
|
||||||
/// Pin Level 0, R register.
|
|
||||||
pub const GPLEV0:usize = GPIO_START + 0x34;
|
|
||||||
/// Pin Level 1, R register.
|
|
||||||
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;
|
|
||||||
/// Pin Event Detect Status 1, R/W register.
|
|
||||||
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;
|
|
||||||
/// Pin Rising Edge Detect Enable 1, R/W register.
|
|
||||||
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;
|
|
||||||
/// Pin Falling Edge Detect Enable 1, R/W register.
|
|
||||||
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;
|
|
||||||
/// Pin High Detect Enable 1, R/W register.
|
|
||||||
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;
|
|
||||||
/// Pin Low Detect Enable 1, R/W register.
|
|
||||||
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;
|
|
||||||
/// Pin Async, Rising Edge Detect 1, R/W register.
|
|
||||||
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;
|
|
||||||
/// Pin Async, Falling Edge Detect1, R/W register.
|
|
||||||
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;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
/// Pin Pull-up/down enable clock 1, R/W register.
|
|
||||||
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;
|
|
||||||
// ** GPIO addresses **
|
// ** GPIO addresses **
|
||||||
|
|
||||||
|
// ** UART addresses **
|
||||||
|
/// Offset between the UART addresses and the beginning of the physical addresses
|
||||||
|
pub const UART_OFFSET: usize = 0x0020_1000;
|
||||||
|
/// Begeinning of the UART addresses.
|
||||||
|
pub const UART_START: usize = START_PHYSICAL_ADDRESS + UART_OFFSET;
|
||||||
|
|
||||||
|
/// UART memory map.
|
||||||
|
pub mod uart {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
/// Data Register, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 31-12: reserved. Write as 0, value read don't have meaning, R/W.
|
||||||
|
/// - 11: OE, Overrun Error. Set to 1 if data received with FIFO full, R/W.
|
||||||
|
/// - 10: BE, Break Error. Set to 1 if a break condition was detected, R/W.
|
||||||
|
/// - 9: PE, Parity Error. Set to 1 when the parity don't match data, R/W.
|
||||||
|
/// - 8: FE, Framing Error. Set to 1 when character don't have valid stop bit, R/W.
|
||||||
|
/// - 7-0: DATA, Data character. R/W.
|
||||||
|
pub const DR: usize = UART_START + 0x00;
|
||||||
|
/// Receive Status Register/Error Clear Register, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 31-12: reserved. Write as 0, value read don't have meaning, R/W.
|
||||||
|
/// - 3: OE, Overrun Error. Set to 1 if data received with FIFO full, R/W.
|
||||||
|
/// - 2: BE, Break Error. Set to 1 if a break condition was detected, R/W.
|
||||||
|
/// - 1: PE, Parity Error. Set to 1 when the parity don't match data, R/W.
|
||||||
|
/// - 0: FE, Framing Error. Set to 1 when characteur don't have valid stop bit, R/W.
|
||||||
|
pub const RSRECR: usize = UART_START + 0x04;
|
||||||
|
/// Flag register, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 31-9: reserved. Write as 0, value read don't have meaning, R/W.
|
||||||
|
/// - 8: RI, unsuported. Write as 0, value read don't have meaning, R/W.
|
||||||
|
/// - 7: TXFE, Transmit FIFO Empty. If FIFO disabled, set when tx holding register empty.
|
||||||
|
/// If FIFO enabled, set when tx FIFP is empty. R/W.
|
||||||
|
/// - 6: RXFF, Receive FIFO Full. If FIFO disabled, set when rx holding register is full.
|
||||||
|
/// If FIFO enabled, set when rx FIFO is full. R/W.
|
||||||
|
/// - 5: TXFF, Transmit FIFO Full. If FIFO disabled, set when tx holding register full.
|
||||||
|
/// If FIFO enabled, set when tx FIFP is full. R/W.
|
||||||
|
/// - 4: RXFE, Receive FIFO Empty. If FIFO disabled, set when rx holding register is empty.
|
||||||
|
/// If FIFO enabled, set when rx FIFO is empty. R/W.
|
||||||
|
/// - 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.
|
||||||
|
pub const FR: usize = UART_START + 0x18;
|
||||||
|
/// Not in use. 32 bits long.
|
||||||
|
pub const ILPR: usize = UART_START + 0x20;
|
||||||
|
/// Integer Baud rate divisor, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 31-16: reserved. Write as 0, value read don't have meaning, R/W.
|
||||||
|
/// - 15-0: IBRD. The integer baud rate divisor, R/W.
|
||||||
|
pub const IBRD: usize = UART_START + 0x24;
|
||||||
|
/// Fractional Baud rate divisor, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 31-6: reserved. Write as 0, value read don't have meaning, R/W.
|
||||||
|
/// - 5-0: FBRD. The fractional baud rate divisor, R/W.
|
||||||
|
pub const FBRD: usize = UART_START + 0x28;
|
||||||
|
/// Line Constrol register, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 31-8: reserved. Write as 0, value read don't have meaning, R/W.
|
||||||
|
/// - 7: SPS, Stick Parity Select. 0: the stick parity is disabled, 1: either
|
||||||
|
/// depending on EPS (Event Parity Select), R/W.
|
||||||
|
/// - 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
|
||||||
|
/// (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
|
||||||
|
/// PEN disable parity check. R/W.
|
||||||
|
/// - 1: PEN, Parity Enable. 0: Don't add parity bit and don't check parity, 1: add parity bit
|
||||||
|
/// and check for parity, R/W.
|
||||||
|
/// - 0: BRK: Send break. If set, send continuous low level to TXD after the current char, R/W.
|
||||||
|
pub const LCRH: usize = UART_START + 0x2C;
|
||||||
|
/// Control register, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # 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`]
|
||||||
|
/// - 4) Reprogram `CR`.
|
||||||
|
/// - 5) Enable UART
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 31-16: reserved. Write as 0, value read don't have meaning, R/W.
|
||||||
|
/// - 15: CTSEN, CTS hardware flow control enable. If set, data is only transmitted when
|
||||||
|
/// nUARTCTS is asserted, R/W.
|
||||||
|
/// - 14: RTSEN, RST hardware flow control enable. If set, data is only requested when there
|
||||||
|
/// is space in the receive FIFO, R/W.
|
||||||
|
/// - 13: OUT2, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 12: OUT1, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 11: RTS, Request To Send. When set to 1, nUARTRTS is low, R/W.
|
||||||
|
/// - 10: DTR, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 9: RXE, Receive enable. If set, (and if UARTEN is set), the uart can read data, R/W.
|
||||||
|
/// - 8: TXE, Transmit enable. If set, (and if UARTEN is set), the uart can send data, R/W.
|
||||||
|
/// - 7: LBE, LoopBack Enable. If set, UARTTXD is fed through to the UARTRXD path, R/W.
|
||||||
|
/// - 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.
|
||||||
|
pub const CR: usize = UART_START + 0x30;
|
||||||
|
/// Interrupt FIFO level Select register, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 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
|
||||||
|
/// reveive interrupt is send:
|
||||||
|
/// - `0b000`: Send when FIFO becom 1/8 full
|
||||||
|
/// - `0b001`: Send when FIFO becom 1/4 full
|
||||||
|
/// - `0b010`: Send when FIFO becom 1/2 full
|
||||||
|
/// - `0b011`: Send when FIFO becom 3/4 full
|
||||||
|
/// - `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
|
||||||
|
/// transmit interrupt is send:
|
||||||
|
/// - `0b000`: Send when FIFO becom 1/8 full
|
||||||
|
/// - `0b001`: Send when FIFO becom 1/4 full
|
||||||
|
/// - `0b010`: Send when FIFO becom 1/2 full
|
||||||
|
/// - `0b011`: Send when FIFO becom 3/4 full
|
||||||
|
/// - `0b100`: Send when FIFO becom 7/7 full
|
||||||
|
/// - Other values are reserved.
|
||||||
|
/// R/W.
|
||||||
|
pub const IFLS: usize = UART_START + 0x34;
|
||||||
|
/// Interupt Mask Set Clear register, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 31-11: reserved. Write as 0, value read don't have meaning, R/W.
|
||||||
|
/// - 10: OEIM, Overrun Error Interrupt Mask. Value of the mask for OE Interrupt, R/W.
|
||||||
|
/// - 9: BEIM, Break Error Interrupt Mask. Value of the mask for BE Interrupt, R/W.
|
||||||
|
/// - 8: PEIM, Parity Error Interrupt Mask. Value of the mask for PE Interrupt, R/W.
|
||||||
|
/// - 7: FEIM, Framing Error Interrupt Mask. Value of the mask for FE Interrupt, R/W.
|
||||||
|
/// - 6: RT Interrupt, Receive Timeout Interrupt Mask. Value of the mask for RTIM, R/W.
|
||||||
|
/// - 5: TXIM, Transmit Interrupt Mask. Value of the mask for TX Interrupt, R/W.
|
||||||
|
/// - 4: RXIM, Receive Interrupt Mask. Value of the mask for RX Interrupt, R/W.
|
||||||
|
/// - 3: DSRMIM, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 2: DCDMIM, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 1: CTSMIM, nUARTCTS Modem Interrupt Mask. Value of the mask for CTS Interrupt, R/W.
|
||||||
|
/// - 0: RIMIM, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
pub const IMSC: usize = UART_START + 0x38;
|
||||||
|
/// Raw Interupt Status register, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 31-11: reserved. Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 10: OERIS, Overrun Error Raw Interrupt Status. Raw interrupt state of the OE Interrupt, R.
|
||||||
|
/// - 9: BERIS, Break Error Raw Interrupt Status. Raw interrupt state of the BE Interrupt, R.
|
||||||
|
/// - 8: PERIS, Parity Error Raw Interrupt Status. Raw interrupt state of the PE Interrupt, R.
|
||||||
|
/// - 7: FERIS, Framing Error Raw Interrupt Status. Raw interrupt state of the FE Interrupt, R.
|
||||||
|
/// - 6: RT Interrupt, Receive Timeout Raw Interrupt Status. Raw interrupt state of the RTRIS, R.
|
||||||
|
/// - 5: TXRIS, Transmit Raw Interrupt Status. Raw interrupt state of the TX Interrupt, R.
|
||||||
|
/// - 4: RXRIS, Receive Raw Interrupt Status. Raw interrupt state of the RX Interrupt, R.
|
||||||
|
/// - 3: DSRMRIS, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 2: DCDMRIS, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 1: CTSMRIS, nUARTCTS Modem Raw Interrupt Status. Raw interrupt state of the CTS Interrupt, R.
|
||||||
|
/// - 0: RRISIM, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
pub const RIS: usize = UART_START + 0x3C;
|
||||||
|
/// Masked Interupt Status register, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 31-11: reserved. Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 10: OEMIS, Overrun Error Masked Interrupt Status. Masked interrupt state of the OE Interrupt, R.
|
||||||
|
/// - 9: BEMIS, Break Error Masked Interrupt Status. Masked interrupt state of the BE Interrupt, R.
|
||||||
|
/// - 8: PEMIS, Parity Error Masked Interrupt Status. Masked interrupt state of the PE Interrupt, R.
|
||||||
|
/// - 7: FEMIS, Framing Error Masked Interrupt Status. Masked interrupt state of the FE Interrupt, R.
|
||||||
|
/// - 6: RT Interrupt, Receive Timeout Masked Interrupt Status. Masked interrupt state of the RTMIS, R.
|
||||||
|
/// - 5: TXMIS, Transmit Masked Interrupt Status. Masked interrupt state of the TX Interrupt, R.
|
||||||
|
/// - 4: RXMIS, Receive Masked Interrupt Status. Masked interrupt state of the RX Interrupt, R.
|
||||||
|
/// - 3: DSRMMIS, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 2: DCDMMIS, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 1: CTSMMIS, nUARTCTS Modem Masked Interrupt Status. Masked interrupt state of the CTS Interrupt, R.
|
||||||
|
/// - 0: RMISIM, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
pub const MIS: usize = UART_START + 0x40;
|
||||||
|
/// Interupt Clear Register, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 31-11: reserved. Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 10: OEIC, Overrun Error Interrupt Clear. Clear the OE Interrupt, R.
|
||||||
|
/// - 9: BEIC, Break Error Interrupt Clear. Clear the BE Interrupt, R.
|
||||||
|
/// - 8: PEIC, Parity Error Interrupt Clear. Clear the PE Interrupt, R.
|
||||||
|
/// - 7: FEIC, Framing Error Interrupt Clear. Clear the FE Interrupt, R.
|
||||||
|
/// - 6: RT Interrupt, Receive Timeout Interrupt Clear. Clear the RTIC, R.
|
||||||
|
/// - 5: TXIC, Transmit Interrupt Clear. Clear the TX Interrupt, R.
|
||||||
|
/// - 4: RXIC, Receive Interrupt Clear. Clear the RX Interrupt, R.
|
||||||
|
/// - 3: DSRMIC, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 2: DCDMIC, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 1: CTSMIC, nUARTCTS Modem Interrupt Clear. Clear the CTS Interrupt, R.
|
||||||
|
/// - 0: RICIM, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
pub const ICR: usize = UART_START + 0x44;
|
||||||
|
/// DMA Control Register, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 31-3: reserved. Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 2: DMAONERR, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 1: TXDMAE, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 0: RXDMAE, unsuported, Write as 0, value read don't have meaning, R.
|
||||||
|
pub const DMACR: usize = UART_START + 0x48;
|
||||||
|
/// Test Control register, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 31-2: reserved. Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 1: ITCR1, Test FIFO enable. If set, read/write directly to the FIFOs with TDR10_0, R/W.
|
||||||
|
/// - 0: ITCR0, Integration Test Enable. If set, the UART is placed in intergration test mode,
|
||||||
|
/// R/W.
|
||||||
|
pub const ITCR: usize = UART_START + 0x80;
|
||||||
|
/// Integration Test Input register, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 31-4: reserved. Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 3: ITIP3. Reads returns the value of nUARTCTS, R/W.
|
||||||
|
/// - 2-1: reserved. Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 0: ITIP0. Reads the value of UARTRXD, R/W.
|
||||||
|
pub const ITIP: usize = UART_START + 0x84;
|
||||||
|
/// Integration Test Output register, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 31-12: reserved. Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 11: ITOP11, Intra-chip Output. Writes set the value to be driven on UARTLSINTR, Reads
|
||||||
|
/// returns the value of UARTLSINTR at the output of the test multiplexor, R/W.
|
||||||
|
/// - 10: ITOP10, Intra-chip Output. Writes set the value to be driven on UARTRXINTR, Reads
|
||||||
|
/// returns the value of UARTRXINTR at the output of the test multiplexor, R/W.
|
||||||
|
/// - 9: ITOP9, Intra-chip Output. Writes set the value to be driven on UARTTXINTR, Reads
|
||||||
|
/// returns the value of UARTTXINTR at the output of the test multiplexor, R/W.
|
||||||
|
/// - 8: ITOP8, Intra-chip Output. Writes set the value to be driven on UARTRTINTR, Reads
|
||||||
|
/// returns the value of UARTRTINTR at the output of the test multiplexor, R/W.
|
||||||
|
/// - 7: ITOP7, Intra-chip Output. Writes set the value to be driven on UARTEINTR, Reads
|
||||||
|
/// returns the value of UARTEINTR at the output of the test multiplexor, R/W.
|
||||||
|
/// - 6: ITOP6, Intra-chip Output. Writes set the value to be driven on UARTINTR, Reads
|
||||||
|
/// returns the value of UARTINTR at the output of the test multiplexor, R/W.
|
||||||
|
/// - 5-4: reserved. Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 3: ITIP3: Primary Output. Writes specify the value on nUARTRTS, R/W.
|
||||||
|
/// - 2-1: reserved. Write as 0, value read don't have meaning, R.
|
||||||
|
/// - 0: ITIP0, Primary Output. Writes specify the value to be driven on UARTTXD, R/W.
|
||||||
|
pub const ITOP: usize = UART_START + 0x88;
|
||||||
|
/// Test Data register, 32 bits long.
|
||||||
|
///
|
||||||
|
/// # Bits distribution:
|
||||||
|
///
|
||||||
|
/// - 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 const TDR: usize = UART_START + 0x8C;
|
||||||
|
}
|
||||||
|
|
|
@ -4,3 +4,5 @@
|
||||||
pub(self) mod memory_map;
|
pub(self) mod memory_map;
|
||||||
|
|
||||||
pub mod gpio;
|
pub mod gpio;
|
||||||
|
|
||||||
|
pub mod uart;
|
||||||
|
|
146
src/bsp/rpi3/uart.rs
Normal file
146
src/bsp/rpi3/uart.rs
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
//! Driver for the UART.
|
||||||
|
|
||||||
|
use core::arch::asm;
|
||||||
|
use core::fmt;
|
||||||
|
use core::ptr::{read_volatile, write_volatile};
|
||||||
|
|
||||||
|
use crate::utils::field::Field;
|
||||||
|
use crate::traits::console::{Write, Console};
|
||||||
|
|
||||||
|
use super::memory_map::uart::*;
|
||||||
|
|
||||||
|
|
||||||
|
pub struct Uart {
|
||||||
|
initialized: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
const TMP_UARTEN: Field = Field::new(CR, 0, 1);
|
||||||
|
const TMP_TXE: Field = Field::new(CR, 8, 1);
|
||||||
|
const TMP_BUSY: Field = Field::new(FR, 3, 1);
|
||||||
|
const TMP_TXFF: Field = Field::new(FR, 5, 1);
|
||||||
|
const TMP_FEN: Field = Field::new(LCRH, 4, 1);
|
||||||
|
const TMP_WLEN: Field = Field::new(LCRH, 5, 2);
|
||||||
|
const TMP_IBRD: Field = Field::new(IBRD, 0, 16);
|
||||||
|
const TMP_FBRD: Field = Field::new(FBRD, 0, 6);
|
||||||
|
const TMP_DATA: Field = Field::new(DR, 0, 8);
|
||||||
|
|
||||||
|
impl Uart {
|
||||||
|
// TODO: not sure this should be public outside of bsp.
|
||||||
|
/// Constructor for [`Uart`].
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Uart { initialized: false }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Initialise the UART.
|
||||||
|
pub fn init(&mut self) {
|
||||||
|
// TODO: Recover from possible previous test.
|
||||||
|
|
||||||
|
self.flush();
|
||||||
|
|
||||||
|
// Stop UART
|
||||||
|
let mut cr_val = unsafe { read_volatile(TMP_UARTEN.get_address() as *mut u32) };
|
||||||
|
cr_val &= !TMP_UARTEN.get_mask();
|
||||||
|
unsafe { write_volatile(TMP_UARTEN.get_address() as *mut u32, cr_val); }
|
||||||
|
|
||||||
|
// Flush the FIFOs
|
||||||
|
let mut lcrh_val = unsafe { read_volatile(TMP_FEN.get_address() as *mut u32) };
|
||||||
|
lcrh_val &= !TMP_FEN.get_mask();
|
||||||
|
unsafe { write_volatile(TMP_FEN.get_address() as *mut u32, lcrh_val); }
|
||||||
|
|
||||||
|
// Clear all interrupt
|
||||||
|
unsafe { write_volatile(ICR as *mut u32, 0); }
|
||||||
|
|
||||||
|
// Config UART
|
||||||
|
// 8N1 115_200 bauds.
|
||||||
|
|
||||||
|
// divbaud = freq/16/baudrate = 48_000_000 / 16 / 115_200 = 26.041666666666668
|
||||||
|
// => IBRD = 26
|
||||||
|
// => FBRD = round(0.041666666666668 * 64) = 3 // TODO: why 64?
|
||||||
|
unsafe { write_volatile(TMP_IBRD.get_address() as *mut u32, 26 & TMP_IBRD.get_mask()); }
|
||||||
|
unsafe { write_volatile(TMP_FBRD.get_address() as *mut u32, 3 & TMP_FBRD.get_mask()); }
|
||||||
|
|
||||||
|
lcrh_val = 0;
|
||||||
|
// Set word len to 8
|
||||||
|
lcrh_val |= 0b11 << TMP_WLEN.get_offset();
|
||||||
|
// Reenable the FIFOs
|
||||||
|
lcrh_val |= TMP_FEN.get_mask();
|
||||||
|
unsafe { write_volatile(LCRH as *mut u32, lcrh_val); }
|
||||||
|
|
||||||
|
let mut cr_val = 0;
|
||||||
|
cr_val |= TMP_TXE.get_mask(); // enable TX
|
||||||
|
unsafe { write_volatile(TMP_TXE.get_address() as *mut u32, cr_val); }
|
||||||
|
|
||||||
|
// Start the UART
|
||||||
|
cr_val |= TMP_UARTEN.get_mask();
|
||||||
|
unsafe { write_volatile(TMP_UARTEN.get_address() as *mut u32, cr_val); }
|
||||||
|
|
||||||
|
self.initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test if the UART is busy.
|
||||||
|
fn is_busy(&self) -> bool {
|
||||||
|
let fr_val = unsafe { read_volatile(TMP_BUSY.get_address() as *mut u32) };
|
||||||
|
(fr_val & TMP_BUSY.get_mask()) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Test if the the TX FIFO is full.
|
||||||
|
fn is_tx_full(&self) -> bool {
|
||||||
|
let fr_val = unsafe { read_volatile(TMP_TXFF.get_address() as *mut u32) };
|
||||||
|
(fr_val & TMP_TXFF.get_mask()) != 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow the use of uart for fmt::Write::write_fmt.
|
||||||
|
impl fmt::Write for Uart {
|
||||||
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
|
for c in s.chars() {
|
||||||
|
if c == '\n' {
|
||||||
|
Write::write_char(self, '\r');
|
||||||
|
}
|
||||||
|
Write::write_char(self, c);
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add sync
|
||||||
|
impl Write for Uart {
|
||||||
|
fn write_char(&self, c: char) {
|
||||||
|
if !self.initialized {
|
||||||
|
//panic!("Cannot write to a non initialized UART");
|
||||||
|
}
|
||||||
|
while self.is_tx_full() {
|
||||||
|
use super::gpio;
|
||||||
|
let _ = gpio::set_pin_output_state(20, gpio::PinOutputState::High);
|
||||||
|
unsafe { asm!("nop") };
|
||||||
|
}
|
||||||
|
unsafe { write_volatile(TMP_DATA.get_address() as *mut u32, c as u32) };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_fmt(&self, args: fmt::Arguments) -> fmt::Result {
|
||||||
|
// TODO: use syncronisation here
|
||||||
|
let mut new_uart = Uart { initialized: self.initialized };
|
||||||
|
fmt::Write::write_fmt(&mut new_uart, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&self) {
|
||||||
|
while self.is_busy() {
|
||||||
|
unsafe { asm!("nop") };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Console for Uart {}
|
||||||
|
|
||||||
|
static UART: Uart = Uart { initialized: true }; // TODO: use sync
|
||||||
|
|
||||||
|
pub fn init() {
|
||||||
|
let mut uart = Uart::new();
|
||||||
|
uart.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: move?
|
||||||
|
/// Return a reference to the Uart Output.
|
||||||
|
pub fn console() -> &'static dyn Console {
|
||||||
|
&UART
|
||||||
|
}
|
31
src/main.rs
31
src/main.rs
|
@ -10,6 +10,8 @@
|
||||||
#![feature(format_args_nl)]
|
#![feature(format_args_nl)]
|
||||||
#![feature(panic_info_message)]
|
#![feature(panic_info_message)]
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
mod traits;
|
mod traits;
|
||||||
mod bsp;
|
mod bsp;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
@ -21,7 +23,8 @@ use core::arch::global_asm;
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
|
|
||||||
// TODO: handle this with features
|
// TODO: handle this with features
|
||||||
use crate::bsp::qemu::console::console;
|
//use crate::bsp::qemu::console::console;
|
||||||
|
use crate::bsp::rpi3::uart::console;
|
||||||
use crate::bsp::rpi3::gpio;
|
use crate::bsp::rpi3::gpio;
|
||||||
|
|
||||||
// TODO: move this to BSP
|
// TODO: move this to BSP
|
||||||
|
@ -39,21 +42,39 @@ global_asm!(include_str!("boot.s"));
|
||||||
/// Start the rust part of the kernel
|
/// Start the rust part of the kernel
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn _start_rust() -> ! {
|
pub unsafe fn _start_rust() -> ! {
|
||||||
|
|
||||||
|
// Set TX and RX function for pin 14 and 15
|
||||||
|
match gpio::set_pin_fonction(14, gpio::PinFunction::AltFunc0) {
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
match gpio::set_pin_fonction(15, gpio::PinFunction::AltFunc0) {
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
// Debut led
|
||||||
|
match gpio::set_pin_fonction(20, gpio::PinFunction::Output) {
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
match gpio::set_pin_output_state(20, gpio::PinOutputState::Low) {
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
bsp::rpi3::uart::init();
|
||||||
|
println!("Hello there");
|
||||||
|
|
||||||
match gpio::set_pin_fonction(21, gpio::PinFunction::Output) {
|
match gpio::set_pin_fonction(21, gpio::PinFunction::Output) {
|
||||||
Ok(()) => println!("Successfully set pin to output"),
|
Ok(()) => println!("Successfully set pin to output"),
|
||||||
Err(err) => println!("Failled to set pin: {err}"),
|
Err(err) => println!("Failled to set pin: {err}"),
|
||||||
}
|
}
|
||||||
loop {
|
loop {
|
||||||
match gpio::set_pin_output_state(21, gpio::PinOutputState::High) {
|
match gpio::set_pin_output_state(21, gpio::PinOutputState::High) {
|
||||||
Ok(()) => println!("Successfully set pin to HIGH"),
|
Ok(()) => (),
|
||||||
Err(err) => println!("Failled to set pin: {err}"),
|
Err(_err) => println!("Failled to set pin 21 to High"),
|
||||||
}
|
}
|
||||||
for _ in 0..5000000 {
|
for _ in 0..5000000 {
|
||||||
asm!("nop");
|
asm!("nop");
|
||||||
}
|
}
|
||||||
match gpio::set_pin_output_state(21, gpio::PinOutputState::Low) {
|
match gpio::set_pin_output_state(21, gpio::PinOutputState::Low) {
|
||||||
Ok(()) => println!("Successfully set pin to HIGH"),
|
Ok(()) => (),
|
||||||
Err(err) => println!("Failled to set pin: {err}"),
|
Err(_err) => println!("Failled to set pin 21 to Low"),
|
||||||
}
|
}
|
||||||
for _ in 0..5000000 {
|
for _ in 0..5000000 {
|
||||||
asm!("nop");
|
asm!("nop");
|
||||||
|
|
|
@ -31,3 +31,5 @@ impl Write for DummyConsole {
|
||||||
|
|
||||||
fn flush(&self) {}
|
fn flush(&self) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Console for DummyConsole {}
|
||||||
|
|
Loading…
Reference in a new issue