rust: uart-passthrough set baudrate and reset

This commit is contained in:
Wladimir J. van der Laan 2019-05-21 12:00:54 +00:00
parent d07fd84160
commit 72a5434397
5 changed files with 82 additions and 8 deletions

View File

@ -67,14 +67,16 @@ fn main() -> ! {
writeln!(stdout, "Clocks:").unwrap(); writeln!(stdout, "Clocks:").unwrap();
writeln!( writeln!(
stdout, stdout,
" CPU {}", " CPU {} (HAL assumes {})",
sysctl::clock_get_freq(sysctl::clock::CPU) sysctl::clock_get_freq(sysctl::clock::CPU),
clocks.cpu().0,
) )
.unwrap(); .unwrap();
writeln!( writeln!(
stdout, stdout,
" APB0 {}", " APB0 {} (HAL assumes {})",
sysctl::clock_get_freq(sysctl::clock::APB0) sysctl::clock_get_freq(sysctl::clock::APB0),
clocks.apb0().0,
) )
.unwrap(); .unwrap();
writeln!( writeln!(

View File

@ -1,7 +1,7 @@
use k210_hal::pac; use k210_hal::pac;
use crate::soc::gpio; use crate::soc::gpio;
use crate::soc::utils::set_bit; use crate::soc::utils::{set_bit,get_bit};
pub fn set_direction(pin: u8, direction: gpio::direction) { pub fn set_direction(pin: u8, direction: gpio::direction) {
unsafe { unsafe {
@ -23,3 +23,10 @@ pub fn set_pin(pin: u8, value: bool) {
.modify(|r, w| w.bits(set_bit(r.bits(), pin, value))); .modify(|r, w| w.bits(set_bit(r.bits(), pin, value)));
} }
} }
pub fn get_pin(pin: u8) -> bool {
unsafe {
let ptr = pac::GPIOHS::ptr();
get_bit((*ptr).input_val.read().bits(), pin)
}
}

View File

@ -5,3 +5,7 @@ pub fn set_bit(inval: u32, bit: u8, state: bool) -> u32 {
inval & !(1 << (bit as u32)) inval & !(1 << (bit as u32))
} }
} }
pub fn get_bit(inval: u32, bit: u8) -> bool {
(inval & (1 << (bit as u32))) != 0
}

View File

@ -3,4 +3,22 @@
Pass through UART from host to the ESP8285 WIFI chip. Pass through UART from host to the ESP8285 WIFI chip.
Any input from the host is forwarded to the ESP8285, and any input from the ESP8285 Any input from the host is forwarded to the ESP8285, and any input from the ESP8285
is forwarded to the host. Currently only supports a fixed baudrate of 115200. is forwarded to the host.
Allows setting the baudrate through an out-of-band protocol. Pulling DTR low will
reset the baudrate to the safe default of 115200, accepting two commands:
```
0x23 <baudrate 32-bit LE>
Set baudrate (both to host and ESP)
0x42
Reset ESP8285 MCU (toggle WIFI_EN pin)
others: no op
```
The connection from the K210 to the ESP can handle up to `115200*40=4608000` baud,
however the connection to the host seems to get stuck at a lower number. Use
`AT+UART_CUR=` (not `UART_DEF` !) to set the baudrate at the ESP side so that
it is always possible to reset the MCU to get back to 115200 baud.

View File

@ -8,17 +8,22 @@ use k210_hal::pac;
use k210_hal::prelude::*; use k210_hal::prelude::*;
use k210_shared::board::def::io; use k210_shared::board::def::io;
use k210_shared::soc::fpioa; use k210_shared::soc::fpioa;
use k210_shared::soc::gpio;
use k210_shared::soc::gpiohs;
use k210_shared::soc::sleep::usleep;
use k210_shared::soc::sysctl; use k210_shared::soc::sysctl;
use nb::block; use nb::block;
use riscv_rt::entry; use riscv_rt::entry;
const DEFAULT_BAUD: u32 = 115_200;
#[entry] #[entry]
fn main() -> ! { fn main() -> ! {
let p = pac::Peripherals::take().unwrap(); let p = pac::Peripherals::take().unwrap();
let clocks = k210_hal::clock::Clocks::new(); let clocks = k210_hal::clock::Clocks::new();
// Configure UARTHS (→host) // Configure UARTHS (→host)
let serial = p.UARTHS.constrain(115_200.bps(), &clocks); let mut serial = p.UARTHS.constrain(DEFAULT_BAUD.bps(), &clocks);
let (mut tx, mut rx) = serial.split(); let (mut tx, mut rx) = serial.split();
// Configure UART1 (→WIFI) // Configure UART1 (→WIFI)
@ -26,11 +31,49 @@ fn main() -> ! {
sysctl::reset(sysctl::reset::UART1); sysctl::reset(sysctl::reset::UART1);
fpioa::set_function(io::WIFI_RX as u8, fpioa::function::UART1_TX); fpioa::set_function(io::WIFI_RX as u8, fpioa::function::UART1_TX);
fpioa::set_function(io::WIFI_TX as u8, fpioa::function::UART1_RX); fpioa::set_function(io::WIFI_TX as u8, fpioa::function::UART1_RX);
let wifi_serial = p.UART1.constrain(115_200.bps(), &clocks); fpioa::set_function(io::WIFI_EN as u8, fpioa::function::GPIOHS8);
fpioa::set_io_pull(io::WIFI_EN as u8, fpioa::pull::DOWN);
gpiohs::set_pin(8, true);
gpiohs::set_direction(8, gpio::direction::OUTPUT);
let mut wifi_serial = p.UART1.constrain(DEFAULT_BAUD.bps(), &clocks);
let (mut wtx, mut wrx) = wifi_serial.split(); let (mut wtx, mut wrx) = wifi_serial.split();
// Relay characters between UARTs // Relay characters between UARTs
loop { loop {
if !gpiohs::get_pin(0) { // IO16 == DTR pulled low for Out-of-Band command
// OOB restores safe baudrate for UARTHS, to be sure we're able to recover from
// sync failures
let mut rate = DEFAULT_BAUD;
serial = rx.join(tx).free().constrain(rate.bps(), &clocks);
let s = serial.split();
tx = s.0;
rx = s.1;
match block!(rx.read()).unwrap() {
0x23 => { // Set baudrate
let mut d = [0u8; 4];
d.iter_mut().for_each(|x| { *x = block!(rx.read()).unwrap() });
rate = (d[0] as u32) | ((d[1] as u32) << 8) | ((d[2] as u32) << 16) | ((d[3] as u32) << 24);
// re-constrain UARTHS at new rate
serial = rx.join(tx).free().constrain(rate.bps(), &clocks);
let s = serial.split();
tx = s.0;
rx = s.1;
}
0x42 => { // WIFI reset
gpiohs::set_pin(8, false);
usleep(100000);
gpiohs::set_pin(8, true);
}
_ => {}
}
// re-constrain UART1
wifi_serial = wrx.join(wtx).free().constrain(rate.bps(), &clocks);
let s = wifi_serial.split();
wtx = s.0;
wrx = s.1;
}
if let Ok(ch) = wrx.read() { if let Ok(ch) = wrx.read() {
let _res = block!(tx.write(ch)); let _res = block!(tx.write(ch));
} }