esp-rs / esp8266-hal

A experimental hardware abstraction layer for the esp8266 written in Rust.
Apache License 2.0
157 stars 19 forks source link

changing baud rate of UART0 #5

Open kcking opened 4 years ago

kcking commented 4 years ago

Is it possible to set the baud rate of UART0? I am using a NodeMCU ESP8266EX and trying to send debug print statements back to my computer (read with the ArduinIDO Serial Monitor), but they are just showing up as invalid characters. I feel like this might be a baud rate issue but I tried every baud rate available in the serial monitor (including the likely suspects of 9600 and 115200).

If it's helpful here is my current program mostly copied from the blinky example. Thanks!

#![no_std]
#![no_main]

use xtensa_lx106_rt::entry;

use core::panic::PanicInfo;
use esp8266_hal::prelude::*;
use esp8266_hal::target::Peripherals;

#[entry]
fn main() -> ! {
    let dp = unsafe { Peripherals::steal() };
    let pins = dp.GPIO.split();
    let (mut timer1, _) = dp.TIMER.timers();

    let mut gpio1_uart = pins.gpio1.into_uart();
    let mut gpio3_uart = pins.gpio3.into_uart();
    let mut gpio2_uart = pins.gpio2.into_uart();

    use esp8266_hal::prelude::_embedded_hal_serial_Write;
    use embedded_hal::blocking::serial::write::Default;
    use esp8266_hal::uart::UART0Ext;
    use esp8266_hal::uart::UART1Ext;
    use core::fmt::Write;

    let mut serial = dp.UART0.serial(gpio1_uart, gpio3_uart);
    //let mut serial = dp.UART1.serial(gpio2_uart);

    loop {
        timer1.delay_ms(500);
        //led.toggle().unwrap();
        serial.write_str("hello_world\n").unwrap();
        // serial.flush();
    }
}

/// Basic panic handler - just loops
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop {}
}
icewind1991 commented 4 years ago

On boot, the bootloader will print some info to UART0 at a baudrate that is dependent on the frequency of the crystal oscillator used on your board, the most crystal is 26Mhz which will lead to a baud rate of 74880 during boot.

Once the board is booted the clock frequency is adjusted up to 80Mhz, assuming the 26Mhz crystal and the baud rate becomes 115200. If your board is not using the default 26Mhz crystal.

If your board is using a 40Mhz crystal, you'll need to use set_crystal_frequency to get the clock at the expected frequency.

If you're having trouble figuring out the crystal frequency you can also check if the timer delays behave as expected and aren't to slow/fast.

As for changing the baud rate, I'll probably look into it once I'm done yak shaving espflash.

kcking commented 4 years ago

Thanks for the detailed response!

I now realized the timers are definitely off. With the blinky example the light blinks exactly 2.5x faster than it should. This behavior remains consistent whether I call xtensa_lx106_rt::set_crystal_frequency(xtensa_lx106_rt::CrystalFrequency::Crystal26MHz); or xtensa_lx106_rt::set_crystal_frequency(xtensa_lx106_rt::CrystalFrequency::Crystal40MHz); at the start of main.

Any thoughts on what might be causing that?

t-moe commented 1 year ago

for reference, I was able to change the baud rate manually using:

let dp = Peripherals::take().unwrap();
dp.UART0.uart_clkdiv.write(|w| unsafe { w.uart_clkdiv().bits(80e6 as u32 / 115_200) });

I'm using the esp12s here, I think it has a 26Mhz cristal and boot up with 80 Mhz if you dont change anything during startup. (blinking with timer1 was also working with the correct frequency)