diff --git a/firmware/acid-firmware/.cargo/config.toml b/firmware/acid-firmware/.cargo/config.toml index a15830b..e823237 100644 --- a/firmware/acid-firmware/.cargo/config.toml +++ b/firmware/acid-firmware/.cargo/config.toml @@ -38,3 +38,14 @@ ACID_COMPOSE_LOCALE = "cs_CZ.UTF-8" # This can be substituted with a `-Zbuild-std="core,alloc"` cargo flag. [unstable] build-std = ["alloc", "core"] + +[patch.crates-io] +esp-backtrace = { git = "https://github.com/Limeth/esp-hal.git", rev = "72e22e2de678297da65a185023309a76aef8a5ca" } +esp-hal = { git = "https://github.com/Limeth/esp-hal.git", rev = "72e22e2de678297da65a185023309a76aef8a5ca" } +esp-storage = { git = "https://github.com/Limeth/esp-hal.git", rev = "72e22e2de678297da65a185023309a76aef8a5ca" } +esp-alloc = { git = "https://github.com/Limeth/esp-hal.git", rev = "72e22e2de678297da65a185023309a76aef8a5ca" } +esp-println = { git = "https://github.com/Limeth/esp-hal.git", rev = "72e22e2de678297da65a185023309a76aef8a5ca" } +esp-radio = { git = "https://github.com/Limeth/esp-hal.git", rev = "72e22e2de678297da65a185023309a76aef8a5ca" } +esp-rtos = { git = "https://github.com/Limeth/esp-hal.git", rev = "72e22e2de678297da65a185023309a76aef8a5ca" } +esp-bootloader-esp-idf = { git = "https://github.com/Limeth/esp-hal.git", rev = "72e22e2de678297da65a185023309a76aef8a5ca" } +esp-sync = { git = "https://github.com/Limeth/esp-hal.git", rev = "72e22e2de678297da65a185023309a76aef8a5ca" } diff --git a/firmware/acid-firmware/src/main.rs b/firmware/acid-firmware/src/main.rs index b53c982..7a4dfa2 100644 --- a/firmware/acid-firmware/src/main.rs +++ b/firmware/acid-firmware/src/main.rs @@ -289,9 +289,7 @@ async fn main(_spawner: Spawner) { let timg0 = TimerGroup::new(peripherals.TIMG0); let software_interrupt = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT); - esp_rtos::start( - timg0.timer0, /*, software_interrupt.software_interrupt0 */ - ); + esp_rtos::start(timg0.timer0, software_interrupt.software_interrupt0); static EXECUTOR_CORE_0: StaticCell> = StaticCell::new(); let executor_core_0 = InterruptExecutor::new(software_interrupt.software_interrupt2); @@ -592,7 +590,7 @@ async fn main(_spawner: Spawner) { let second_core_stack = SECOND_CORE_STACK.init(Stack::new()); esp_rtos::start_second_core( peripherals.CPU_CTRL, - software_interrupt.software_interrupt0, + // software_interrupt.software_interrupt0, software_interrupt.software_interrupt1, second_core_stack, move || { diff --git a/firmware/acid-firmware/src/peripherals/st7701s/mod.rs b/firmware/acid-firmware/src/peripherals/st7701s/mod.rs index 35e9366..604e48b 100644 --- a/firmware/acid-firmware/src/peripherals/st7701s/mod.rs +++ b/firmware/acid-firmware/src/peripherals/st7701s/mod.rs @@ -1276,7 +1276,7 @@ where // // Adafruit would use 11 MHz. // I had lowered the frequency, so that `DmaBounce` could keep up. - .with_frequency(Rate::from_mhz(8)) // From Adafruit + .with_frequency(Rate::from_mhz(7)) // From Adafruit .with_clock_mode(ClockMode { polarity: Polarity::IdleLow, // From Adafruit phase: Phase::ShiftHigh, // From Adafruit diff --git a/firmware/acid-firmware/src/ui/dpi.rs b/firmware/acid-firmware/src/ui/dpi.rs index e7b3564..398b889 100644 --- a/firmware/acid-firmware/src/ui/dpi.rs +++ b/firmware/acid-firmware/src/ui/dpi.rs @@ -13,19 +13,19 @@ use embassy_sync::{ channel::{Channel, TrySendError}, signal::Signal, }; -use embassy_time::{Instant, Timer}; +use embassy_time::{Duration, Instant, Timer, WithTimeout}; use esp_alloc::MemoryCapability; use esp_hal::{ Blocking, dma::{ self, AnyGdmaChannel, BufView, BurstConfig, DmaChannel, DmaChannelConvert, DmaDescriptor, DmaDescriptorFlags, DmaEligible, DmaRxStreamBuf, DmaTxBuf, DmaTxBuffer, DmaTxInterrupt, - ExternalBurstConfig, Mem2Mem, + ExternalBurstConfig, Mem2Mem, SimpleMem2MemTransfer, }, dma_descriptors, handler, interrupt::{self, Priority}, lcd_cam::lcd::dpi::{Dpi, DpiTransfer}, - peripherals::{DMA, DMA_CH0, Peripherals, SPI2}, + peripherals::{DMA, DMA_CH0, Interrupt, Peripherals, SPI2}, ram, spi::master::AnySpi, }; @@ -74,6 +74,11 @@ pub unsafe fn cache_invalidate_addr(addr: u32, size: u32) { } } +// const DMA_CHANNEL_INBOUND: usize = 0; +// const INTERRUPT_INBOUND: Interrupt = Interrupt::DMA_IN_CH0; +const DMA_CHANNEL_OUTBOUND: usize = 2; +const INTERRUPT_OUTBOUND: Interrupt = Interrupt::DMA_OUT_CH2; + pub struct DmaBounce { // TODO: Make these generic. // They currently cannot be generic, because they lacks a `reborrow` method. @@ -344,21 +349,28 @@ impl DmaBounce { } fn enable_interrupts() { - // TODO: Get from self.channel - let channel_number = 2; - let interrupt = esp_hal::peripherals::Interrupt::DMA_OUT_CH2; - // Enable interrupts for the peripheral - interrupt::enable(interrupt, dma_interrupt_handler.priority()).unwrap(); + // interrupt::enable(INTERRUPT_INBOUND, dma_inbound_interrupt_handler.priority()).unwrap(); + interrupt::enable( + INTERRUPT_OUTBOUND, + dma_outbound_interrupt_handler.priority(), + ) + .unwrap(); // Bind the handler unsafe { - interrupt::bind_interrupt(interrupt, dma_interrupt_handler.handler()); + // interrupt::bind_interrupt(INTERRUPT_INBOUND, dma_inbound_interrupt_handler.handler()); + interrupt::bind_interrupt(INTERRUPT_OUTBOUND, dma_outbound_interrupt_handler.handler()); } // Enable interrupts in the peripheral. + // DMA::regs() + // .ch(DMA_CHANNEL_INBOUND) + // .in_int() + // .ena() + // .modify(|_, w| w.in_done().bit(true)); DMA::regs() - .ch(channel_number) + .ch(DMA_CHANNEL_OUTBOUND) .out_int() .ena() .modify(|_, w| w.out_eof().bit(true)); @@ -366,7 +378,7 @@ impl DmaBounce { /// Receive a window of bytes into the current dst bounce buffer. /// Finally, swaps the bounce buffers. - fn receive_window_blocking(&mut self) { + async fn receive_window(&mut self) { // Descriptors are initialized by `DmaTxBuf::new`. let buffer_src_window = &mut self.buffer_src[self.window_index_next * self.window_size..][..self.window_size]; @@ -392,13 +404,15 @@ impl DmaBounce { let bounce_dst_descs = unsafe { &mut *(self.bounce_dst_descs as *mut _) }; let src_descs = unsafe { &mut *(self.src_descs as *mut _) }; let mut mem2mem = Mem2Mem::new(self.channel.reborrow(), self.peripheral_src.reborrow()) + .into_async() .with_descriptors(bounce_dst_descs, src_descs, self.burst_config) .unwrap(); let transfer = mem2mem .start_transfer(&mut self.bounce_buffer_dst, buffer_src_window) .unwrap(); - transfer.wait().unwrap(); + // INBOUND_TRANSFER_FINISHED.wait().await; + transfer.wait_async().await.unwrap(); } self.increase_window_counter(1); @@ -409,7 +423,7 @@ impl DmaBounce { core::mem::swap(&mut self.bounce_buffer_dst, &mut self.bounce_buffer_src); } - self.window_index_next = self.window_index_next + windows; + self.window_index_next += windows; self.frame_index_next += self.window_index_next / self.windows_len; self.window_index_next = self.window_index_next % self.windows_len; } @@ -419,7 +433,7 @@ impl DmaBounce { Self::enable_interrupts(); // Receive the first window, so that the outbound transfer can read valid data. - self.receive_window_blocking(); + self.receive_window().await; let mut dma_tx_buffer = self.get_dma_tx_buffer(); let mut transfer = self @@ -434,8 +448,15 @@ impl DmaBounce { let mut windows_skipped_total = 0; loop { - self.receive_window_blocking(); - let windows_skipped = WINDOWS_SKIPPED.wait().await; + self.receive_window().await; + let windows_skipped = WINDOWS_SKIPPED + .wait() + // .with_timeout(Duration::from_secs(1)) + .await; + // .unwrap_or_else(|_| { + // error!("Timed out while waiting for skipped windows"); + // 0 + // }); if windows_skipped > 0 { self.increase_window_counter(windows_skipped); @@ -548,11 +569,12 @@ unsafe impl DmaTxBuffer for DmaTxBounceBuf { } static WINDOWS_SKIPPED: Signal = Signal::new(); +// static INBOUND_TRANSFER_FINISHED: Signal = Signal::new(); #[handler(priority = Priority::Priority3)] #[ram] // Improves performance. -fn dma_interrupt_handler() { - let interrupt = DMA::regs().ch(2).out_int(); +fn dma_outbound_interrupt_handler() { + let interrupt = DMA::regs().ch(DMA_CHANNEL_OUTBOUND).out_int(); let bounce_buffer_processed = interrupt.st().read().out_eof().bit_is_set(); if bounce_buffer_processed { // Clear the bit by writing 1 to the clear bits. @@ -566,6 +588,25 @@ fn dma_interrupt_handler() { } } +// #[handler(priority = Priority::Priority3)] +// #[ram] // Improves performance. +// fn dma_inbound_interrupt_handler() { +// warn!("Inbound"); + +// let interrupt = DMA::regs().ch(DMA_CHANNEL_INBOUND).in_int(); +// let bounce_buffer_processed = interrupt.st().read().in_done().bit_is_set(); +// if bounce_buffer_processed { +// // Clear the bit by writing 1 to the clear bits. +// interrupt.clr().write(|w| w.in_done().bit(true)); + +// assert!( +// !INBOUND_TRANSFER_FINISHED.signaled(), +// "inbound transfer already signalled" +// ); +// INBOUND_TRANSFER_FINISHED.signal(()); +// } +// } + pub async fn run_lcd( mut st7701s: St7701s<'static, Blocking>, framebuffer: &'static mut Framebuffer,