diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 9d8ce33327..1492e8c633 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -47,7 +47,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed an issue that caused LCD_CAM drivers to turn off their clocks unexpectedly (#3007) - Fixed an issue where DMA-driver peripherals started transferring before the data was ready (#3003) - Fixed an issue on ESP32 and S2 where short asynchronous Timer delays would never resolve (#3093) - +- Fixed an issue setting higher UART baud rates (#3104) - ESP32-S2: Fixed linker script (#3096) ### Removed diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index b1df6962a2..1fca7c2e53 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -57,13 +57,13 @@ ufmt-write = "0.1.0" # IMPORTANT: # Each supported device MUST have its PAC included below along with a # corresponding feature. -esp32 = { version = "0.35.0", features = ["critical-section", "rt"], optional = true } -esp32c2 = { version = "0.24.0", features = ["critical-section", "rt"], optional = true } -esp32c3 = { version = "0.27.0", features = ["critical-section", "rt"], optional = true } -esp32c6 = { version = "0.18.0", features = ["critical-section", "rt"], optional = true } -esp32h2 = { version = "0.14.0", features = ["critical-section", "rt"], optional = true } -esp32s2 = { version = "0.26.0", features = ["critical-section", "rt"], optional = true } -esp32s3 = { version = "0.30.0", features = ["critical-section", "rt"], optional = true } +esp32 = { version = "0.35.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "cab435a", optional = true } +esp32c2 = { version = "0.24.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "cab435a", optional = true } +esp32c3 = { version = "0.27.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "cab435a", optional = true } +esp32c6 = { version = "0.18.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "cab435a", optional = true } +esp32h2 = { version = "0.14.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "cab435a", optional = true } +esp32s2 = { version = "0.26.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "cab435a", optional = true } +esp32s3 = { version = "0.30.0", features = ["critical-section", "rt"], git = "https://github.com/esp-rs/esp-pacs", rev = "cab435a", optional = true } [target.'cfg(target_arch = "riscv32")'.dependencies] riscv = { version = "0.12.1" } diff --git a/esp-hal/src/system.rs b/esp-hal/src/system.rs index f010faa755..1c6465abf3 100755 --- a/esp-hal/src/system.rs +++ b/esp-hal/src/system.rs @@ -741,15 +741,11 @@ impl PeripheralClockControl { } #[cfg(uart0)] Peripheral::Uart0 => { - system - .uart0_conf() - .modify(|_, w| w.uart0_clk_en().bit(enable)); + system.uart(0).conf().modify(|_, w| w.clk_en().bit(enable)); } #[cfg(uart1)] Peripheral::Uart1 => { - system - .uart1_conf() - .modify(|_, w| w.uart1_clk_en().bit(enable)); + system.uart(1).conf().modify(|_, w| w.clk_en().bit(enable)); } #[cfg(rsa)] Peripheral::Rsa => { @@ -934,21 +930,13 @@ impl PeripheralClockControl { } #[cfg(uart0)] Peripheral::Uart0 => { - system - .uart0_conf() - .modify(|_, w| w.uart0_rst_en().set_bit()); - system - .uart0_conf() - .modify(|_, w| w.uart0_rst_en().clear_bit()); + system.uart(0).conf().modify(|_, w| w.rst_en().set_bit()); + system.uart(0).conf().modify(|_, w| w.rst_en().clear_bit()); } #[cfg(uart1)] Peripheral::Uart1 => { - system - .uart1_conf() - .modify(|_, w| w.uart1_rst_en().set_bit()); - system - .uart1_conf() - .modify(|_, w| w.uart1_rst_en().clear_bit()); + system.uart(1).conf().modify(|_, w| w.rst_en().set_bit()); + system.uart(1).conf().modify(|_, w| w.rst_en().clear_bit()); } #[cfg(rsa)] Peripheral::Rsa => { diff --git a/esp-hal/src/uart.rs b/esp-hal/src/uart.rs index 2e1fa6a18f..4d9b5e3f38 100644 --- a/esp-hal/src/uart.rs +++ b/esp-hal/src/uart.rs @@ -2365,48 +2365,6 @@ impl Info { Ok(()) } - #[cfg(any(esp32c2, esp32c3, esp32s3))] - fn change_baud(&self, config: &Config) { - use crate::peripherals::LPWR; - - let clocks = Clocks::get(); - let clk = match config.clock_source { - ClockSource::Apb => clocks.apb_clock.as_hz(), - ClockSource::Xtal => clocks.xtal_clock.as_hz(), - ClockSource::RcFast => crate::soc::constants::RC_FAST_CLK.as_hz(), - }; - - if config.clock_source == ClockSource::RcFast { - LPWR::regs() - .clk_conf() - .modify(|_, w| w.dig_clk8m_en().variant(true)); - // esp_rom_delay_us(SOC_DELAY_RC_FAST_DIGI_SWITCH); - crate::rom::ets_delay_us(5); - } - - let max_div = 0b1111_1111_1111 - 1; - let clk_div = clk.div_ceil(max_div * config.baudrate); - self.regs().clk_conf().write(|w| unsafe { - w.sclk_sel().bits(match config.clock_source { - ClockSource::Apb => 1, - ClockSource::RcFast => 2, - ClockSource::Xtal => 3, - }); - w.sclk_div_a().bits(0); - w.sclk_div_b().bits(0); - w.sclk_div_num().bits(clk_div as u8 - 1); - w.rx_sclk_en().bit(true); - w.tx_sclk_en().bit(true) - }); - - let divider = (clk << 4) / (config.baudrate * clk_div); - let divider_integer = (divider >> 4) as u16; - let divider_frag = (divider & 0xf) as u8; - self.regs() - .clkdiv() - .write(|w| unsafe { w.clkdiv().bits(divider_integer).frag().bits(divider_frag) }); - } - fn is_instance(&self, other: impl Instance) -> bool { self == other.info() } @@ -2415,82 +2373,80 @@ impl Info { sync_regs(self.regs()); } - #[cfg(any(esp32c6, esp32h2))] fn change_baud(&self, config: &Config) { let clocks = Clocks::get(); let clk = match config.clock_source { ClockSource::Apb => clocks.apb_clock.as_hz(), + #[cfg(not(any(esp32, esp32s2)))] ClockSource::Xtal => clocks.xtal_clock.as_hz(), + #[cfg(not(any(esp32, esp32s2)))] ClockSource::RcFast => crate::soc::constants::RC_FAST_CLK.as_hz(), + #[cfg(any(esp32, esp32s2))] + ClockSource::RefTick => crate::soc::constants::REF_TICK.as_hz(), }; - let max_div = 0b1111_1111_1111 - 1; - let clk_div = clk.div_ceil(max_div * config.baudrate); - - // UART clocks are configured via PCR - let pcr = crate::peripherals::PCR::regs(); + cfg_if::cfg_if! { + if #[cfg(any(esp32c2, esp32c3, esp32s3, esp32c6, esp32h2))] { + + const MAX_DIV: u32 = 0b1111_1111_1111 - 1; + let clk_div = (clk.div_ceil(MAX_DIV)).div_ceil(config.baudrate); + + // define `conf` in scope for modification below + cfg_if::cfg_if! { + if #[cfg(any(esp32c2, esp32c3, esp32s3))] { + if matches!(config.clock_source, ClockSource::RcFast) { + crate::peripherals::LPWR::regs() + .clk_conf() + .modify(|_, w| w.dig_clk8m_en().variant(true)); + // small delay whilst the clock source changes (SOC_DELAY_RC_FAST_DIGI_SWITCH from esp-idf) + crate::rom::ets_delay_us(5); + } + + let conf = self.regs().clk_conf(); + } else { + // UART clocks are configured via PCR + let pcr = crate::peripherals::PCR::regs(); + let conf = if self.is_instance(unsafe { crate::peripherals::UART0::steal() }) { + pcr.uart(0).clk_conf() + } else { + pcr.uart(1).clk_conf() + }; + } + }; - if self.is_instance(unsafe { crate::peripherals::UART0::steal() }) { - pcr.uart0_conf() - .modify(|_, w| w.uart0_rst_en().clear_bit().uart0_clk_en().set_bit()); - - pcr.uart0_sclk_conf().modify(|_, w| unsafe { - w.uart0_sclk_div_a().bits(0); - w.uart0_sclk_div_b().bits(0); - w.uart0_sclk_div_num().bits(clk_div as u8 - 1); - w.uart0_sclk_sel().bits(match config.clock_source { - ClockSource::Apb => 1, - ClockSource::RcFast => 2, - ClockSource::Xtal => 3, + conf.write(|w| unsafe { + w.sclk_sel().bits(match config.clock_source { + ClockSource::Apb => 1, + ClockSource::RcFast => 2, + ClockSource::Xtal => 3, + }); + w.sclk_div_a().bits(0); + w.sclk_div_b().bits(0); + w.sclk_div_num().bits(clk_div as u8 - 1) }); - w.uart0_sclk_en().set_bit() - }); - } else { - pcr.uart1_conf() - .modify(|_, w| w.uart1_rst_en().clear_bit().uart1_clk_en().set_bit()); - - pcr.uart1_sclk_conf().modify(|_, w| unsafe { - w.uart1_sclk_div_a().bits(0); - w.uart1_sclk_div_b().bits(0); - w.uart1_sclk_div_num().bits(clk_div as u8 - 1); - w.uart1_sclk_sel().bits(match config.clock_source { - ClockSource::Apb => 1, - ClockSource::RcFast => 2, - ClockSource::Xtal => 3, - }); - w.uart1_sclk_en().set_bit() - }); - } - - let clk = clk / clk_div; - let divider = clk / config.baudrate; - let divider = divider as u16; - self.regs() - .clkdiv() - .write(|w| unsafe { w.clkdiv().bits(divider).frag().bits(0) }); + let divider = (clk << 4) / (config.baudrate * clk_div); + } else { + self.regs().conf0().modify(|_, w| { + w.tick_ref_always_on() + .bit(config.clock_source == ClockSource::Apb) + }); - self.sync_regs(); - } + let divider = (clk << 4) / config.baudrate; + } + } - #[cfg(any(esp32, esp32s2))] - fn change_baud(&self, config: &Config) { - let clk = match config.clock_source { - ClockSource::Apb => Clocks::get().apb_clock.as_hz(), - // ESP32(/-S2) TRM, section 3.2.4.2 (6.2.4.2 for S2) - ClockSource::RefTick => crate::soc::constants::REF_TICK.as_hz(), - }; + let divider_integer = divider >> 4; + let divider_frag = (divider & 0xf) as u8; - self.regs().conf0().modify(|_, w| { - w.tick_ref_always_on() - .bit(config.clock_source == ClockSource::Apb) + self.regs().clkdiv().write(|w| unsafe { + w.clkdiv() + .bits(divider_integer as _) + .frag() + .bits(divider_frag) }); - let divider = clk / config.baudrate; - - self.regs() - .clkdiv() - .write(|w| unsafe { w.clkdiv().bits(divider).frag().bits(0) }); + self.sync_regs(); } fn change_data_bits(&self, data_bits: DataBits) { diff --git a/hil-test/Cargo.toml b/hil-test/Cargo.toml index 8a97eaeb84..aa640568ee 100644 --- a/hil-test/Cargo.toml +++ b/hil-test/Cargo.toml @@ -322,4 +322,4 @@ debug-assertions = true incremental = false opt-level = 3 lto = false # LTO (thin or fat) miscompiles some tests on RISC-V -overflow-checks = false +overflow-checks = true diff --git a/hil-test/tests/uart.rs b/hil-test/tests/uart.rs index 14b6e5a667..4753275b29 100644 --- a/hil-test/tests/uart.rs +++ b/hil-test/tests/uart.rs @@ -72,6 +72,7 @@ mod tests { #[cfg(esp32s2)] (9600, ClockSource::RefTick), (921_600, ClockSource::Apb), + (2_000_000, ClockSource::Apb), ]; let mut byte_to_write = 0xA5;