diff --git a/baremetal/src/boot_armv7a.s b/baremetal/src/boot_armv7a.s index 09f48d73..13917658 100644 --- a/baremetal/src/boot_armv7a.s +++ b/baremetal/src/boot_armv7a.s @@ -38,7 +38,6 @@ .section .text._start .global _start _start: - // TODO: add support for other CPU's other than the cortex a72 using the MIDR register mrc p15, 0, r0, c0, c0, 5 // read MPIDR, and r0, r0, #0b11 // on coretx a72 those bits are the CPU core id cmp r0, #0 // check for cpu 0 @@ -174,13 +173,13 @@ _start: mov r2, #0 .init_bss_loop: cmp r0, r1 - beq .start_rust + beq .finish_bss str r2, [r0], #4 // increment r0 by 4 (dword) b .init_bss_loop -.start_rust: +.finish_bss: // setting up the stack ldr sp, =__cpu0_stack_start - b _start_rust + b main // Corrupts r4, r1 = end index // r0 - L1 map ptr diff --git a/baremetal/src/drivers/ili9341/ili9341_spi.rs b/baremetal/src/drivers/ili9341/ili9341_spi.rs deleted file mode 100644 index f04d8257..00000000 --- a/baremetal/src/drivers/ili9341/ili9341_spi.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::peripherals::{Spi, PERIPHERALS}; - -use super::ili9341_gfx_device::Ili9341Commands; - -pub struct Ili9341Spi{ - spi:Spi, -} - -impl Ili9341Spi{ - pub fn new()->Self { - Self{spi:unsafe{PERIPHERALS.take_spi0()}} - } - - pub fn fast_mode(&mut self) { - self.spi.fast_mode(); - } - - pub fn write(&mut self, command:Ili9341Commands, data:&[u8;SIZE]) { - self.spi.write(command as u8, data); - } - - pub fn write_buffer(&mut self, command:Ili9341Commands, data:&[u8;super::ili9341_gfx_device::SPI_BUFFER_SIZE]) { - self.spi.write_dma(command as u8, data); - } -} \ No newline at end of file diff --git a/baremetal/src/drivers/ili9341/ili9341_gfx_device.rs b/baremetal/src/drivers/ili9341_gfx_device.rs similarity index 70% rename from baremetal/src/drivers/ili9341/ili9341_gfx_device.rs rename to baremetal/src/drivers/ili9341_gfx_device.rs index 2e9c0c5a..bfc8cfc7 100644 --- a/baremetal/src/drivers/ili9341/ili9341_gfx_device.rs +++ b/baremetal/src/drivers/ili9341_gfx_device.rs @@ -1,8 +1,6 @@ use lib_gb::ppu::{gb_ppu::{SCREEN_WIDTH, SCREEN_HEIGHT}, gfx_device::{GfxDevice, Pixel}}; -use crate::peripherals::{GpioPin, GpioManager, Mode, Timer}; - -use super::ili9341_spi::Ili9341Spi; +use crate::peripherals::{GpioPin, GpioManager, Mode, Timer, Spi, PERIPHERALS}; const ILI9341_SCREEN_WIDTH:usize = 320; const ILI9341_SCREEN_HEIGHT:usize = 240; @@ -14,7 +12,7 @@ const FRAME_BUFFER_X_OFFSET:usize = (ILI9341_SCREEN_WIDTH - TARGET_SCREEN_WIDTH) pub const SPI_BUFFER_SIZE:usize = TARGET_SCREEN_HEIGHT * TARGET_SCREEN_WIDTH * core::mem::size_of::(); #[repr(u8)] -pub enum Ili9341Commands{ +enum Ili9341Command{ SoftwareReset = 0x01, SleepOut = 0x11, GammaSet = 0x26, @@ -42,7 +40,7 @@ pub enum Ili9341Commands{ } struct Ili9341Contoller{ - spi:Ili9341Spi, + spi:Spi, timer: Timer, led_pin: GpioPin, reset_pin: GpioPin @@ -57,7 +55,7 @@ impl Ili9341Contoller{ let reset_pin = gpio.take_pin(reset_pin_bcm, Mode::Output); let led_pin = gpio.take_pin(led_pin_bcm, Mode::Output); - let spi = Ili9341Spi::new(); + let spi = unsafe{PERIPHERALS.take_spi0()}; let mut controller = Ili9341Contoller { spi, led_pin, reset_pin, timer}; @@ -81,37 +79,37 @@ impl Ili9341Contoller{ // fbcp-ili9341 inspired implementation: /*---------------------------------------------------------------------------------------------------------------------- */ // Reset the screen - controller.spi.write(Ili9341Commands::SoftwareReset,&[]); + controller.spi.write(Ili9341Command::SoftwareReset as u8,&[]); controller.sleep_ms(5); - controller.spi.write(Ili9341Commands::DisplayOff,&[]); + controller.spi.write(Ili9341Command::DisplayOff as u8,&[]); // Some power stuff, probably uneccessary but just for sure - controller.spi.write(Ili9341Commands::PowerControlA, &[0x39, 0x2C, 0x0, 0x34, 0x2]); - controller.spi.write(Ili9341Commands::PowerControlB, &[0x0, 0xC1, 0x30]); - controller.spi.write(Ili9341Commands::DriverTimingControlA, &[0x85, 0x0, 0x78]); - controller.spi.write(Ili9341Commands::DriverTimingControlB, &[0x0, 0x0]); - controller.spi.write(Ili9341Commands::PowerOnSequenceControl, &[0x64, 0x3, 0x12, 0x81]); - controller.spi.write(Ili9341Commands::PowerControl1, &[0x23]); - controller.spi.write(Ili9341Commands::PowerControl2,&[0x10]); - controller.spi.write(Ili9341Commands::VcomControl1, &[0xE3, 0x28]); - controller.spi.write(Ili9341Commands::VcomControl2, &[0x86]); + controller.spi.write(Ili9341Command::PowerControlA as u8, &[0x39, 0x2C, 0x0, 0x34, 0x2]); + controller.spi.write(Ili9341Command::PowerControlB as u8, &[0x0, 0xC1, 0x30]); + controller.spi.write(Ili9341Command::DriverTimingControlA as u8, &[0x85, 0x0, 0x78]); + controller.spi.write(Ili9341Command::DriverTimingControlB as u8, &[0x0, 0x0]); + controller.spi.write(Ili9341Command::PowerOnSequenceControl as u8, &[0x64, 0x3, 0x12, 0x81]); + controller.spi.write(Ili9341Command::PowerControl1 as u8, &[0x23]); + controller.spi.write(Ili9341Command::PowerControl2 as u8,&[0x10]); + controller.spi.write(Ili9341Command::VcomControl1 as u8, &[0xE3, 0x28]); + controller.spi.write(Ili9341Command::VcomControl2 as u8, &[0x86]); // Configuring the screen - controller.spi.write(Ili9341Commands::MemoryAccessControl, &[0x28]); // This command tlit the screen 90 degree and set pixel to BGR order - controller.spi.write(Ili9341Commands::PixelFormatSet, &[0x55]); // set pixel format to 16 bit per pixel; - controller.spi.write(Ili9341Commands::FrameRateControl, &[0x0, 0x10 /*According to the docs this is 119 hrz, setting this option in order to avoid screen tearing on rpi zero2 */]); - controller.spi.write(Ili9341Commands::DisplayFunctionControl, &[0x8, 0x82, 0x27]); + controller.spi.write(Ili9341Command::MemoryAccessControl as u8, &[0x28]); // This command tlit the screen 90 degree and set pixel to BGR order + controller.spi.write(Ili9341Command::PixelFormatSet as u8, &[0x55]); // set pixel format to 16 bit per pixel; + controller.spi.write(Ili9341Command::FrameRateControl as u8, &[0x0, 0x10 /*According to the docs this is 119 hrz, setting this option in order to avoid screen tearing on rpi zero2 */]); + controller.spi.write(Ili9341Command::DisplayFunctionControl as u8, &[0x8, 0x82, 0x27]); // Gamma values - pretty sure its redundant - controller.spi.write(Ili9341Commands::Enable3G, &[0x2]); - controller.spi.write(Ili9341Commands::GammaSet, &[0x1]); - controller.spi.write(Ili9341Commands::PossitiveGammaCorrection,&[0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00]); - controller.spi.write(Ili9341Commands::NegativeGammaCorrection, &[0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F]); + controller.spi.write(Ili9341Command::Enable3G as u8, &[0x2]); + controller.spi.write(Ili9341Command::GammaSet as u8, &[0x1]); + controller.spi.write(Ili9341Command::PossitiveGammaCorrection as u8,&[0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00]); + controller.spi.write(Ili9341Command::NegativeGammaCorrection as u8, &[0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F]); // Turn screen on - controller.spi.write(Ili9341Commands::SleepOut,&[]); + controller.spi.write(Ili9341Command::SleepOut as u8,&[]); controller.sleep_ms(120); - controller.spi.write(Ili9341Commands::DisplayOn,&[]); + controller.spi.write(Ili9341Command::DisplayOn as u8,&[]); /*---------------------------------------------------------------------------------------------------------------------- */ //End of fbcp-ili9341 inpired implementation @@ -121,10 +119,10 @@ impl Ili9341Contoller{ controller.led_pin.set_high(); // Clear screen - controller.spi.write(Ili9341Commands::ColumnAddressSet, &[0,0,((ILI9341_SCREEN_WIDTH -1) >> 8) as u8, ((ILI9341_SCREEN_WIDTH -1) & 0xFF) as u8]); - controller.spi.write(Ili9341Commands::PageAddressSet, &[0,0,((ILI9341_SCREEN_HEIGHT -1) >> 8) as u8, ((ILI9341_SCREEN_HEIGHT -1) & 0xFF) as u8]); + controller.spi.write(Ili9341Command::ColumnAddressSet as u8, &[0,0,((ILI9341_SCREEN_WIDTH -1) >> 8) as u8, ((ILI9341_SCREEN_WIDTH -1) & 0xFF) as u8]); + controller.spi.write(Ili9341Command::PageAddressSet as u8, &[0,0,((ILI9341_SCREEN_HEIGHT -1) >> 8) as u8, ((ILI9341_SCREEN_HEIGHT -1) & 0xFF) as u8]); // using write and not write buffer since this is not the correct size - controller.spi.write(Ili9341Commands::MemoryWrite, &Self::CLEAN_BUFFER); + controller.spi.write(Ili9341Command::MemoryWrite as u8, &Self::CLEAN_BUFFER); // need to sleep before changing the clock after transferring pixels to the lcd controller.sleep_ms(120); @@ -142,30 +140,30 @@ impl Ili9341Contoller{ unsafe{image_inter::scale_bilinear::(buffer.as_ptr(), scaled_buffer.as_mut_ptr())}; let end_x_index = TARGET_SCREEN_WIDTH + FRAME_BUFFER_X_OFFSET - 1; - self.spi.write(Ili9341Commands::ColumnAddressSet, &[ + self.spi.write(Ili9341Command::ColumnAddressSet as u8, &[ (FRAME_BUFFER_X_OFFSET >> 8) as u8, (FRAME_BUFFER_X_OFFSET & 0xFF) as u8, (end_x_index >> 8) as u8, (end_x_index & 0xFF) as u8 ]); - self.spi.write(Ili9341Commands::PageAddressSet, &[ + self.spi.write(Ili9341Command::PageAddressSet as u8, &[ 0x0, 0x0, ((TARGET_SCREEN_HEIGHT - 1) >> 8) as u8, ((TARGET_SCREEN_HEIGHT - 1) & 0xFF) as u8 ]); - self.spi.write_buffer(Ili9341Commands::MemoryWrite, &scaled_buffer); + self.spi.write_dma(Ili9341Command::MemoryWrite as u8, &scaled_buffer); } fn sleep_ms(&mut self, milliseconds_to_sleep:u64){ let target_wait_time = core::time::Duration::from_millis(milliseconds_to_sleep); - self.timer.sleep(target_wait_time); + self.timer.wait(target_wait_time); } } impl Drop for Ili9341Contoller{ fn drop(&mut self) { - self.spi.write(Ili9341Commands::DisplayOff, &[]); + self.spi.write(Ili9341Command::DisplayOff as u8, &[]); self.led_pin.set_low(); self.reset_pin.set_high(); self.sleep_ms(1); diff --git a/baremetal/src/drivers/mod.rs b/baremetal/src/drivers/mod.rs index bfc6af1b..8afcf7cb 100644 --- a/baremetal/src/drivers/mod.rs +++ b/baremetal/src/drivers/mod.rs @@ -1,8 +1,5 @@ mod gpio_joypad; -mod ili9341{ - pub mod ili9341_gfx_device; - pub mod ili9341_spi; -} +mod ili9341_gfx_device; pub use gpio_joypad::*; -pub use ili9341::ili9341_gfx_device::*; \ No newline at end of file +pub use ili9341_gfx_device::*; \ No newline at end of file diff --git a/baremetal/src/main.rs b/baremetal/src/main.rs index bc21246e..81b8f57f 100644 --- a/baremetal/src/main.rs +++ b/baremetal/src/main.rs @@ -23,8 +23,11 @@ const ROM:&'static [u8] = include_bytes!("../../Dependencies/TetrisDX.gbc"); const RESET_PIN_BCM:u8 = 13; const LED_PIN_BCM:u8 = 25; +// This function is no regular main. +// It will not return and will be jumped to from the _start proc in the boot code +// it is unmangled and exposed as a "C" function in order for the _start proc to call it #[no_mangle] -pub extern "C" fn _start_rust()->!{ +pub extern "C" fn main()->!{ unsafe{PERIPHERALS.set_core_clock()}; logging::UartLogger::init(log::LevelFilter::Debug); log::info!("Initialized logger"); diff --git a/baremetal/src/peripherals/timer.rs b/baremetal/src/peripherals/timer.rs index 56de2a63..e16b386f 100644 --- a/baremetal/src/peripherals/timer.rs +++ b/baremetal/src/peripherals/timer.rs @@ -37,7 +37,7 @@ impl Timer{ return Duration::from_micros(diff); } - pub fn sleep(&mut self, duration:Duration){ + pub fn wait(&mut self, duration:Duration){ let mut counter = core::time::Duration::ZERO; let _ = self.tick(); // reset the timer ticking and disard the result while counter < duration{ diff --git a/baremetal/src/peripherals/utils.rs b/baremetal/src/peripherals/utils.rs index d1102b28..f9e3eff0 100644 --- a/baremetal/src/peripherals/utils.rs +++ b/baremetal/src/peripherals/utils.rs @@ -24,27 +24,28 @@ pub(super) fn memory_barrier(){ core::sync::atomic::fence(core::sync::atomic::Ordering::SeqCst); } -pub(super) enum Peripheral{ +pub enum Peripheral{ Uninit, Init(T), Taken } impl Peripheral{ - pub(super) fn getT>(&mut self, init:F)->&mut T{ + pub(super) fn get(&mut self, init_callback: impl FnOnce()->T)->&mut T{ if let Self::Uninit = self { - *self = Self::Init(init()); + *self = Self::Init(init_callback()); } return match self{ Self::Init(t) => t, - _ => core::panic!("Peripheral is unavaliable, its either been taken or uninitialized"), + Self::Taken => core::panic!("Peripheral is unavaliable, its been taken "), + Self::Uninit => core::unreachable!("At this point the peripheral must be initialized"), }; } - pub(super) fn takeT>(&mut self, init:F)->T{ + pub(super) fn take(&mut self, init_callback: impl FnOnce()->T)->T{ let s = core::mem::replace(self, Self::Taken); return match s{ - Self::Uninit => init(), + Self::Uninit => init_callback(), Self::Init(t) => t, Self::Taken => core::panic!("Peripheral is unavaliable, its been taken"), }; diff --git a/baremetal/src/syncronization.rs b/baremetal/src/syncronization.rs index 50b7cdd8..72b6ef7e 100644 --- a/baremetal/src/syncronization.rs +++ b/baremetal/src/syncronization.rs @@ -13,11 +13,11 @@ impl Mutex{ Mutex { data:UnsafeCell::new(data), lock:AtomicBool::new(false) } } - pub fn lock<'a, TReturn>(&'a self, f: impl FnOnce(&'a mut TData)->TReturn)->TReturn{ + pub fn lock<'a, TReturn>(&'a self, callback: impl FnOnce(&'a mut TData)->TReturn)->TReturn{ // block untill given access to lock the mutex while self.lock.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst).is_ok(){} let data = unsafe{&mut *self.data.get()}; - let res = f(data); + let res = callback(data); // free the mutex self.lock.store(false, Ordering::SeqCst); diff --git a/image_inter/src/lib.rs b/image_inter/src/lib.rs index cfcf770c..bb4be381 100644 --- a/image_inter/src/lib.rs +++ b/image_inter/src/lib.rs @@ -65,8 +65,6 @@ pub unsafe fn scale_nearest (x + 0.5) as int let proj_x = round_f32(x as f32 / scale_x) as usize; let proj_y = round_f32(y as f32 / scale_y) as usize; let pixel = *input_buffer.add((proj_y * INPUT_WIDTH) + proj_x); @@ -78,6 +76,7 @@ pub unsafe fn scale_nearestu32{ f += 0.5; return f as u32; diff --git a/lib_gb/src/machine/mbc_initializer.rs b/lib_gb/src/machine/mbc_initializer.rs index ae00ced8..e4abe80a 100644 --- a/lib_gb/src/machine/mbc_initializer.rs +++ b/lib_gb/src/machine/mbc_initializer.rs @@ -1,4 +1,4 @@ -use crate::{mmu::carts::*, utils::global_static_alloctor::{static_alloc, static_alloc_array}}; +use crate::{mmu::carts::*, utils::global_static_alloctor::*}; use super::Mode; const CARTRIDGE_TYPE_ADDRESS:usize = 0x147; diff --git a/lib_gb/src/utils/global_static_alloctor.rs b/lib_gb/src/utils/global_static_alloctor.rs index 67a5bcd2..8aa0f778 100644 --- a/lib_gb/src/utils/global_static_alloctor.rs +++ b/lib_gb/src/utils/global_static_alloctor.rs @@ -4,7 +4,7 @@ use super::static_allocator::{StaticAllocator, Layout}; const STATIC_MEMORY_SIZE:usize = 0x100_0000; static mut MEMORY:[u8;STATIC_MEMORY_SIZE] = [0;STATIC_MEMORY_SIZE]; -static mut ALLOCATOR:StaticAllocator = unsafe{StaticAllocator::new(MEMORY.as_mut_ptr(), MEMORY.len())}; +static mut ALLOCATOR:StaticAllocator = unsafe{StaticAllocator::new(&mut MEMORY)}; pub fn static_alloc(t:T)->&'static mut T{ let layout = Layout::from_type::(); diff --git a/lib_gb/src/utils/static_allocator.rs b/lib_gb/src/utils/static_allocator.rs index b9080e3b..a64077fb 100644 --- a/lib_gb/src/utils/static_allocator.rs +++ b/lib_gb/src/utils/static_allocator.rs @@ -26,23 +26,22 @@ impl Layout{ } pub struct StaticAllocator{ - buffer_ptr:*mut u8, - buffer_size: usize, - allocation_offset:usize + buffer:&'static [u8], + allocation_size:usize } impl StaticAllocator{ - pub const unsafe fn new(buffer:*mut u8, buffer_size:usize)->Self{ - Self{ buffer_ptr: buffer, buffer_size, allocation_offset: 0 } + pub const fn new(buffer:&'static [u8])->Self{ + Self{ buffer, allocation_size: 0 } } pub unsafe fn alloc(&mut self, layout: Layout) -> NonNull { - let allocation_address = self.buffer_ptr.add(self.allocation_offset) as usize; + let allocation_address = self.buffer.as_ptr().add(self.allocation_size) as usize; let aligned_address = Self::align_address(allocation_address, layout.align); - self.allocation_offset += layout.size + (aligned_address - allocation_address); + self.allocation_size += layout.size + (aligned_address - allocation_address); - if self.allocation_offset > self.buffer_size{ - core::panic!("Allocation failed, allocator is out of static memory, pool size: {}, allocation req: {}", self.buffer_size, layout.size); + if self.allocation_size > self.buffer.len(){ + core::panic!("Allocation failed, allocator is out of static memory, pool size: {}, allocation req: {}", self.buffer.len(), layout.size); } return NonNull::new_unchecked(aligned_address as *mut u8); } @@ -61,7 +60,7 @@ mod tests{ fn test_alloc_alignment(){ unsafe{ static mut BUFFER:[u8;100] = [0;100]; - let mut allocator = StaticAllocator::new(BUFFER.as_mut_ptr(), 100); + let mut allocator = StaticAllocator::new(&mut BUFFER); let aligns = 5; for a in 1..aligns{ let align = 1 << a;