diff --git a/CHANGELOG.md b/CHANGELOG.md index c4c9dce58e2..5f174c58dd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix circular DMA (#1189) - Fix esp32c3 uart initialization (#1156) - Fix ESP32-S2 I2C read (#1214) +- Reset/init UART if it's not the console UART (#1213) ### Changed diff --git a/esp-hal/src/system.rs b/esp-hal/src/system.rs index b338e82255c..8f5f9f41e2d 100755 --- a/esp-hal/src/system.rs +++ b/esp-hal/src/system.rs @@ -393,6 +393,210 @@ impl PeripheralClockControl { } }); } + + /// Resets the given peripheral + pub(crate) fn reset(peripheral: Peripheral) { + let system = unsafe { &*SYSTEM::PTR }; + + #[cfg(esp32)] + let (perip_rst_en0, peri_rst_en) = { (&system.perip_rst_en(), &system.peri_rst_en()) }; + #[cfg(not(any(esp32, esp32p4)))] + let perip_rst_en0 = { &system.perip_rst_en0() }; + + #[cfg(any(esp32c2, esp32c3, esp32s2, esp32s3))] + let perip_rst_en1 = { &system.perip_rst_en1() }; + + critical_section::with(|_cs| match peripheral { + #[cfg(spi2)] + Peripheral::Spi2 => { + perip_rst_en0.modify(|_, w| w.spi2_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.spi2_rst().clear_bit()); + } + #[cfg(spi3)] + Peripheral::Spi3 => { + perip_rst_en0.modify(|_, w| w.spi3_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.spi3_rst().clear_bit()); + } + #[cfg(all(i2c0, esp32))] + Peripheral::I2cExt0 => { + perip_rst_en0.modify(|_, w| w.i2c0_ext0_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.i2c0_ext0_rst().clear_bit()); + } + #[cfg(all(i2c0, not(esp32)))] + Peripheral::I2cExt0 => { + perip_rst_en0.modify(|_, w| w.i2c_ext0_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.i2c_ext0_rst().clear_bit()); + } + #[cfg(i2c1)] + Peripheral::I2cExt1 => { + perip_rst_en0.modify(|_, w| w.i2c_ext1_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.i2c_ext1_rst().clear_bit()); + } + #[cfg(rmt)] + Peripheral::Rmt => { + perip_rst_en0.modify(|_, w| w.rmt_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.rmt_rst().clear_bit()); + } + #[cfg(ledc)] + Peripheral::Ledc => { + perip_rst_en0.modify(|_, w| w.ledc_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.ledc_rst().clear_bit()); + } + #[cfg(mcpwm0)] + Peripheral::Mcpwm0 => { + perip_rst_en0.modify(|_, w| w.pwm0_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.pwm0_rst().clear_bit()); + } + #[cfg(mcpwm1)] + Peripheral::Mcpwm1 => { + perip_rst_en0.modify(|_, w| w.pwm1_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.pwm1_rst().clear_bit()); + } + #[cfg(pcnt)] + Peripheral::Pcnt => { + perip_rst_en0.modify(|_, w| w.pcnt_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.pcnt_rst().clear_bit()); + } + #[cfg(apb_saradc)] + Peripheral::ApbSarAdc => { + perip_rst_en0.modify(|_, w| w.apb_saradc_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.apb_saradc_rst().clear_bit()); + } + #[cfg(gdma)] + Peripheral::Gdma => { + perip_rst_en1.modify(|_, w| w.dma_rst().set_bit()); + perip_rst_en1.modify(|_, w| w.dma_rst().clear_bit()); + } + #[cfg(esp32)] + Peripheral::Dma => { + perip_rst_en0.modify(|_, w| w.spi_dma_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.spi_dma_rst().clear_bit()); + } + #[cfg(esp32s2)] + Peripheral::Dma => { + perip_rst_en0.modify(|_, w| w.spi2_dma_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.spi2_dma_rst().clear_bit()); + perip_rst_en0.modify(|_, w| w.spi3_dma_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.spi3_dma_rst().clear_bit()); + } + #[cfg(esp32c3)] + Peripheral::I2s0 => { + // on ESP32-C3 note that i2s1_clk_en / rst is really I2s0 + perip_rst_en0.modify(|_, w| w.i2s1_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.i2s1_rst().clear_bit()); + } + #[cfg(any(esp32s3, esp32, esp32s2))] + Peripheral::I2s0 => { + perip_rst_en0.modify(|_, w| w.i2s0_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.i2s0_rst().clear_bit()); + } + #[cfg(any(esp32s3, esp32))] + Peripheral::I2s1 => { + perip_rst_en0.modify(|_, w| w.i2s1_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.i2s1_rst().clear_bit()); + } + #[cfg(usb0)] + Peripheral::Usb => { + perip_rst_en0.modify(|_, w| w.usb_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.usb_rst().clear_bit()); + } + #[cfg(twai0)] + Peripheral::Twai0 => { + perip_rst_en0.modify(|_, w| w.twai_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.twai_rst().clear_bit()); + } + #[cfg(esp32)] + Peripheral::Aes => { + peri_rst_en.modify(|r, w| unsafe { w.bits(r.bits() | 1) }); + peri_rst_en.modify(|r, w| unsafe { w.bits(r.bits() & (!1)) }); + } + #[cfg(any(esp32c3, esp32s2, esp32s3))] + Peripheral::Aes => { + perip_rst_en1.modify(|_, w| w.crypto_aes_rst().set_bit()); + perip_rst_en1.modify(|_, w| w.crypto_aes_rst().clear_bit()); + } + #[cfg(timg0)] + Peripheral::Timg0 => { + #[cfg(any(esp32c3, esp32s2, esp32s3))] + perip_rst_en0.modify(|_, w| w.timers_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.timergroup_rst().set_bit()); + #[cfg(any(esp32c3, esp32s2, esp32s3))] + perip_rst_en0.modify(|_, w| w.timers_rst().clear_bit()); + perip_rst_en0.modify(|_, w| w.timergroup_rst().clear_bit()); + } + #[cfg(timg1)] + Peripheral::Timg1 => { + #[cfg(any(esp32c3, esp32s2, esp32s3))] + perip_rst_en0.modify(|_, w| w.timers_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.timergroup1_rst().set_bit()); + #[cfg(any(esp32c3, esp32s2, esp32s3))] + perip_rst_en0.modify(|_, w| w.timers_rst().clear_bit()); + perip_rst_en0.modify(|_, w| w.timergroup1_rst().clear_bit()); + } + #[cfg(sha)] + Peripheral::Sha => { + #[cfg(not(esp32))] + perip_rst_en1.modify(|_, w| w.crypto_sha_rst().set_bit()); + #[cfg(not(esp32))] + perip_rst_en1.modify(|_, w| w.crypto_sha_rst().clear_bit()); + } + #[cfg(esp32c3)] + Peripheral::UsbDevice => { + perip_rst_en0.modify(|_, w| w.usb_device_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.usb_device_rst().clear_bit()); + } + #[cfg(esp32s3)] + Peripheral::UsbDevice => { + perip_rst_en1.modify(|_, w| w.usb_device_rst().set_bit()); + perip_rst_en1.modify(|_, w| w.usb_device_rst().clear_bit()); + } + #[cfg(uart0)] + Peripheral::Uart0 => { + perip_rst_en0.modify(|_, w| w.uart_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.uart_rst().clear_bit()); + } + #[cfg(uart1)] + Peripheral::Uart1 => { + perip_rst_en0.modify(|_, w| w.uart1_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.uart1_rst().clear_bit()); + } + #[cfg(all(uart2, esp32s3))] + Peripheral::Uart2 => { + perip_rst_en1.modify(|_, w| w.uart2_rst().set_bit()); + perip_rst_en1.modify(|_, w| w.uart2_rst().clear_bit()); + } + #[cfg(all(uart2, esp32))] + Peripheral::Uart2 => { + perip_rst_en0.modify(|_, w| w.uart2_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.uart2_rst().clear_bit()); + } + #[cfg(all(rsa, esp32))] + Peripheral::Rsa => { + peri_rst_en.modify(|r, w| unsafe { w.bits(r.bits() | 1 << 2) }); + peri_rst_en.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << 2)) }); + } + #[cfg(all(rsa, any(esp32c3, esp32s2, esp32s3)))] + Peripheral::Rsa => { + perip_rst_en1.modify(|_, w| w.crypto_rsa_rst().set_bit()); + perip_rst_en1.modify(|_, w| w.crypto_rsa_rst().clear_bit()); + } + #[cfg(hmac)] + Peripheral::Hmac => { + perip_rst_en1.modify(|_, w| w.crypto_hmac_rst().set_bit()); + perip_rst_en1.modify(|_, w| w.crypto_hmac_rst().clear_bit()); + } + #[cfg(ecc)] + Peripheral::Ecc => { + perip_rst_en1.modify(|_, w| w.crypto_ecc_rst().set_bit()); + perip_rst_en1.modify(|_, w| w.crypto_ecc_rst().clear_bit()); + } + #[cfg(lcd_cam)] + Peripheral::LcdCam => { + perip_rst_en1.modify(|_, w| w.lcd_cam_rst().set_bit()); + perip_rst_en1.modify(|_, w| w.lcd_cam_rst().clear_bit()); + } + }); + } } #[cfg(any(esp32c6, esp32h2))] @@ -603,6 +807,198 @@ impl PeripheralClockControl { } } } + + /// Resets the given peripheral + pub(crate) fn reset(peripheral: Peripheral) { + let system = unsafe { &*SYSTEM::PTR }; + + match peripheral { + #[cfg(spi2)] + Peripheral::Spi2 => { + system.spi2_conf().modify(|_, w| w.spi2_rst_en().set_bit()); + system + .spi2_conf() + .modify(|_, w| w.spi2_rst_en().clear_bit()); + } + #[cfg(i2c0)] + Peripheral::I2cExt0 => { + #[cfg(any(esp32c6, esp32h2))] + { + system.i2c0_conf().modify(|_, w| w.i2c0_rst_en().set_bit()); + system + .i2c0_conf() + .modify(|_, w| w.i2c0_rst_en().clear_bit()); + } + } + #[cfg(i2c1)] + Peripheral::I2cExt1 => { + #[cfg(esp32h2)] + { + system.i2c1_conf().modify(|_, w| w.i2c1_rst_en().set_bit()); + system + .i2c1_conf() + .modify(|_, w| w.i2c1_rst_en().clear_bit()); + } + } + #[cfg(rmt)] + Peripheral::Rmt => { + system.rmt_conf().modify(|_, w| w.rmt_rst_en().set_bit()); + system.rmt_conf().modify(|_, w| w.rmt_rst_en().clear_bit()); + } + #[cfg(ledc)] + Peripheral::Ledc => { + system.ledc_conf().modify(|_, w| w.ledc_rst_en().set_bit()); + system + .ledc_conf() + .modify(|_, w| w.ledc_rst_en().clear_bit()); + } + #[cfg(mcpwm0)] + Peripheral::Mcpwm0 => { + system.pwm_conf().modify(|_, w| w.pwm_rst_en().set_bit()); + system.pwm_conf().modify(|_, w| w.pwm_rst_en().clear_bit()); + } + #[cfg(mcpwm1)] + Peripheral::Mcpwm1 => { + system.pwm_conf.modify(|_, w| w.pwm_rst_en().set_bit()); + system.pwm_conf.modify(|_, w| w.pwm_rst_en().clear_bit()); + } + #[cfg(apb_saradc)] + Peripheral::ApbSarAdc => { + system + .saradc_conf() + .modify(|_, w| w.saradc_reg_rst_en().set_bit()); + system + .saradc_conf() + .modify(|_, w| w.saradc_reg_rst_en().clear_bit()); + } + #[cfg(gdma)] + Peripheral::Gdma => { + system.gdma_conf().modify(|_, w| w.gdma_rst_en().set_bit()); + system + .gdma_conf() + .modify(|_, w| w.gdma_rst_en().clear_bit()); + } + #[cfg(i2s0)] + Peripheral::I2s0 => { + system.i2s_conf().modify(|_, w| w.i2s_rst_en().set_bit()); + system.i2s_conf().modify(|_, w| w.i2s_rst_en().clear_bit()); + } + #[cfg(twai0)] + Peripheral::Twai0 => { + system + .twai0_conf() + .modify(|_, w| w.twai0_rst_en().set_bit()); + system + .twai0_conf() + .modify(|_, w| w.twai0_rst_en().clear_bit()); + } + #[cfg(twai1)] + Peripheral::Twai1 => { + system + .twai1_conf() + .modify(|_, w| w.twai1_rst_en().set_bit()); + system + .twai1_conf() + .modify(|_, w| w.twai1_rst_en().clear_bit()); + } + #[cfg(aes)] + Peripheral::Aes => { + system.aes_conf().modify(|_, w| w.aes_rst_en().set_bit()); + system.aes_conf().modify(|_, w| w.aes_rst_en().clear_bit()); + } + #[cfg(pcnt)] + Peripheral::Pcnt => { + system.pcnt_conf().modify(|_, w| w.pcnt_rst_en().set_bit()); + system + .pcnt_conf() + .modify(|_, w| w.pcnt_rst_en().clear_bit()); + } + #[cfg(timg0)] + Peripheral::Timg0 => { + // no reset? + } + #[cfg(timg1)] + Peripheral::Timg1 => { + // no reset? + } + #[cfg(lp_wdt)] + Peripheral::Wdt => { + // no reset? + } + #[cfg(sha)] + Peripheral::Sha => { + system.sha_conf().modify(|_, w| w.sha_rst_en().set_bit()); + system.sha_conf().modify(|_, w| w.sha_rst_en().clear_bit()); + } + #[cfg(usb_device)] + Peripheral::UsbDevice => { + system + .usb_device_conf() + .modify(|_, w| w.usb_device_rst_en().set_bit()); + system + .usb_device_conf() + .modify(|_, w| w.usb_device_rst_en().clear_bit()); + } + #[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()); + } + #[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()); + } + #[cfg(rsa)] + Peripheral::Rsa => { + system.rsa_conf().modify(|_, w| w.rsa_rst_en().set_bit()); + system.rsa_conf().modify(|_, w| w.rsa_rst_en().clear_bit()); + } + #[cfg(parl_io)] + Peripheral::ParlIo => { + system + .parl_io_conf() + .modify(|_, w| w.parl_rst_en().set_bit()); + system + .parl_io_conf() + .modify(|_, w| w.parl_rst_en().clear_bit()); + } + #[cfg(hmac)] + Peripheral::Hmac => { + system.hmac_conf().modify(|_, w| w.hmac_rst_en().set_bit()); + system + .hmac_conf() + .modify(|_, w| w.hmac_rst_en().clear_bit()); + } + #[cfg(ecc)] + Peripheral::Ecc => { + system.ecc_conf().modify(|_, w| w.ecc_rst_en().set_bit()); + system.ecc_conf().modify(|_, w| w.ecc_rst_en().clear_bit()); + } + #[cfg(soc_etm)] + Peripheral::Etm => { + system.etm_conf().modify(|_, w| w.etm_rst_en().set_bit()); + system.etm_conf().modify(|_, w| w.etm_rst_en().clear_bit()); + } + #[cfg(trace0)] + Peripheral::Trace0 => { + system + .trace_conf() + .modify(|_, w| w.trace_rst_en().set_bit()); + system + .trace_conf() + .modify(|_, w| w.trace_rst_en().clear_bit()); + } + } + } } #[cfg(esp32p4)] diff --git a/esp-hal/src/uart.rs b/esp-hal/src/uart.rs index b720d97919e..08bd24cbe90 100644 --- a/esp-hal/src/uart.rs +++ b/esp-hal/src/uart.rs @@ -53,6 +53,7 @@ use crate::{ system::PeripheralClockControl, }; +const CONSOLE_UART_NUM: usize = 0; const UART_FIFO_SIZE: u16 = 128; /// Custom serial error type @@ -447,7 +448,7 @@ where impl<'d, T> Uart<'d, T> where - T: Instance, + T: Instance + 'd, { /// Create a new UART instance with defaults pub fn new_with_config
( @@ -494,7 +495,7 @@ where } /// Split the Uart into a transmitter and receiver, which is - /// particuarly useful when having two tasks correlating to + /// particularly useful when having two tasks correlating to /// transmitting and receiving. pub fn split(self) -> (UartTx<'d, T>, UartRx<'d, T>) { (self.tx, self.rx) @@ -902,7 +903,7 @@ where .write(|w| unsafe { w.clkdiv().bits(divider).frag().bits(0) }); } - #[cfg(esp32c3)] + #[cfg(any(esp32c2, esp32c3, esp32s3))] #[inline(always)] fn init() { let system = unsafe { crate::peripherals::SYSTEM::steal() }; @@ -914,48 +915,69 @@ where // initialize peripheral by setting clk_enable and clearing uart_reset bits T::enable_peripheral(); + Self::uart_peripheral_reset(); + T::disable_rx_interrupts(); + T::disable_tx_interrupts(); + } + #[cfg(any(esp32c6, esp32h2))] + #[inline(always)] + fn init() { T::register_block() - .clk_conf() - .modify(|_, w| w.rst_core().set_bit()); - - // TODO use T::reset_peripheral() as soon as it is present in esp-hal - system - .perip_rst_en0() - .modify(|_, w| match T::uart_number() { - 0 => w.uart_rst().set_bit(), - 1 => w.uart1_rst().set_bit(), - _ => panic!("Unknown Uart Device!"), - }); - system - .perip_rst_en0() - .modify(|_, w| match T::uart_number() { - 0 => w.uart_rst().clear_bit(), - 1 => w.uart1_rst().clear_bit(), - _ => panic!("Unknown Uart Device!"), - }); - T::register_block() - .clk_conf() - .modify(|_, w| w.rst_core().clear_bit()); + .conf0() + .modify(|_, w| w.mem_clk_en().set_bit()); + + // initialize peripheral by setting clk_enable and clearing uart_reset bits + T::enable_peripheral(); + Self::uart_peripheral_reset(); T::disable_rx_interrupts(); T::disable_tx_interrupts(); } - #[cfg(not(esp32c3))] + #[cfg(any(esp32, esp32s2))] #[inline(always)] fn init() { T::enable_peripheral(); + Self::uart_peripheral_reset(); T::disable_rx_interrupts(); T::disable_tx_interrupts(); } - #[cfg(any(esp32c3, esp32c6, esp32h2))] // TODO introduce a cfg symbol for this + #[inline(always)] + fn uart_peripheral_reset() { + // don't reset the console UART - this will cause trouble (i.e. the UART will + // start to transmit garbage) + // + // We should only reset the console UART if it was absolutely unused before. + // Apparently the bootloader (and maybe the ROM code) writing to the UART is + // already enough to make this a no-go. (i.e. one needs to mute the ROM + // code via efuse / strapping pin AND use a silent bootloader) + // + // Ideally this should be configurable once we have a solution for https://github.com/esp-rs/esp-hal/issues/1111 + // see https://github.com/espressif/esp-idf/blob/5f4249357372f209fdd57288265741aaba21a2b1/components/esp_driver_uart/src/uart.c#L179 + if T::uart_number() != CONSOLE_UART_NUM { + #[cfg(not(any(esp32, esp32s2)))] + T::register_block() + .clk_conf() + .modify(|_, w| w.rst_core().set_bit()); + + // reset peripheral + T::reset_peripheral(); + + #[cfg(not(any(esp32, esp32s2)))] + T::register_block() + .clk_conf() + .modify(|_, w| w.rst_core().clear_bit()); + } + } + + #[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))] // TODO introduce a cfg symbol for this #[inline(always)] fn sync_regs(&self) { #[cfg(any(esp32c6, esp32h2))] let update_reg = T::register_block().reg_update(); - #[cfg(esp32c3)] + #[cfg(any(esp32c3, esp32s3))] let update_reg = T::register_block().id(); update_reg.modify(|_, w| w.reg_update().set_bit()); @@ -965,7 +987,7 @@ where } } - #[cfg(not(any(esp32c3, esp32c6, esp32h2)))] + #[cfg(not(any(esp32c3, esp32c6, esp32h2, esp32s3)))] #[inline(always)] fn sync_regs(&mut self) {} } @@ -1106,6 +1128,7 @@ pub trait Instance { fn cts_signal() -> InputSignal; fn rts_signal() -> OutputSignal; fn enable_peripheral(); + fn reset_peripheral(); } macro_rules! impl_instance { @@ -1140,6 +1163,10 @@ macro_rules! impl_instance { fn enable_peripheral() { PeripheralClockControl::enable(crate::system::Peripheral::$peri); } + + fn reset_peripheral() { + PeripheralClockControl::reset(crate::system::Peripheral::$peri); + } } }; } @@ -1516,7 +1543,7 @@ mod asynch { impl<'d, T: Instance> Drop for UartRxFuture<'d, T> { fn drop(&mut self) { - // Although the isr disables the interrupt that occured directly, we need to + // Although the isr disables the interrupt that occurred directly, we need to // disable the other interrupts (= the ones that did not occur), as // soon as this future goes out of scope. let int_ena = &T::register_block().int_ena(); @@ -1678,7 +1705,7 @@ mod asynch { /// /// The interrupts in question are enabled during the body of this /// function. The method immediately returns when the interrupt - /// has already occured before calling this method (e.g. status + /// has already occurred before calling this method (e.g. status /// bit set, but interrupt not enabled) /// /// # Params diff --git a/examples/src/bin/advanced_serial.rs b/examples/src/bin/advanced_serial.rs index 8c8954beb9b..5cc6405397d 100644 --- a/examples/src/bin/advanced_serial.rs +++ b/examples/src/bin/advanced_serial.rs @@ -4,8 +4,8 @@ //! of the configuration change the output signal. //! //! The following wiring is assumed: -//! - TX => GPIO1 -//! - RX => GPIO2 +//! - TX => GPIO4 +//! - RX => GPIO5 //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3