rust: UART/network optimizations

This commit is contained in:
Wladimir J. van der Laan 2019-08-18 14:37:16 +00:00
parent 2840ec0cf9
commit f8f7235daa
4 changed files with 31 additions and 9 deletions

View File

@ -10,9 +10,10 @@ use core::sync::atomic::{AtomicUsize, Ordering};
use k210_hal::pac; use k210_hal::pac;
use k210_shared::soc::sysctl; use k210_shared::soc::sysctl;
use pac::interrupt::Interrupt; use pac::interrupt::Interrupt;
use riscv::asm;
use riscv::register::{mcause, mhartid, mie, mip, mstatus}; use riscv::register::{mcause, mhartid, mie, mip, mstatus};
const UART_BUFSIZE: usize = 4096; const UART_BUFSIZE: usize = 8192;
/** UART ring buffer */ /** UART ring buffer */
struct UartInstance { struct UartInstance {
buf: [u8; UART_BUFSIZE], buf: [u8; UART_BUFSIZE],
@ -57,12 +58,17 @@ fn interrupt_uart1() {
UART_INTERRUPT_RECEIVE | UART_INTERRUPT_CHARACTER_TIMEOUT => { UART_INTERRUPT_RECEIVE | UART_INTERRUPT_CHARACTER_TIMEOUT => {
// Read recv FIFO into receive ringbuffer // Read recv FIFO into receive ringbuffer
let mut head = irecv.head.load(Ordering::SeqCst); let mut head = irecv.head.load(Ordering::SeqCst);
let tail = irecv.head.load(Ordering::SeqCst);
while ((*uart).lsr.read().bits() & 1) != 0 { while ((*uart).lsr.read().bits() & 1) != 0 {
irecv.buf[head] = ((*uart).rbr_dll_thr.read().bits() & 0xff) as u8; irecv.buf[head] = ((*uart).rbr_dll_thr.read().bits() & 0xff) as u8;
head += 1; head += 1;
if head == UART_BUFSIZE { if head == UART_BUFSIZE {
head = 0; head = 0;
} }
// TODO: signal overflows in a less catastropic way ?
if head == tail {
panic!("UART recv buffer overflow");
}
} }
irecv.head.store(head, Ordering::SeqCst); irecv.head.store(head, Ordering::SeqCst);
} }
@ -193,7 +199,7 @@ fn uart_enable_intr(recv: bool) {
} }
} }
/** Send data to UART */ /** Send data to UART (blocking) */
pub fn send(s: &[u8]) { pub fn send(s: &[u8]) {
let uart = pac::UART1::ptr(); let uart = pac::UART1::ptr();
for &c in s { for &c in s {
@ -205,10 +211,13 @@ pub fn send(s: &[u8]) {
} }
/** Receive data from UART (non-blocking, returns number of bytes received) */ /** Receive data from UART (non-blocking, returns number of bytes received) */
pub fn recv(s: &mut [u8]) -> usize { pub fn recv_nb(s: &mut [u8]) -> usize {
let irecv = unsafe { &mut UART1_INSTANCE_RECV }; let irecv = unsafe { &mut UART1_INSTANCE_RECV };
let head = irecv.head.load(Ordering::SeqCst); let head = irecv.head.load(Ordering::SeqCst);
let mut tail = irecv.tail.load(Ordering::SeqCst); let mut tail = irecv.tail.load(Ordering::SeqCst);
if head == tail { // Early-out without tail.store if ring buffer empty
return 0;
}
let mut ptr = 0; let mut ptr = 0;
while ptr < s.len() && tail != head { while ptr < s.len() && tail != head {
s[ptr] = irecv.buf[tail]; s[ptr] = irecv.buf[tail];
@ -222,6 +231,21 @@ pub fn recv(s: &mut [u8]) -> usize {
ptr ptr
} }
/** Receive data from UART (blocks for at least one byte if the buffer can hold one, returns number
* of bytes received) */
pub fn recv(s: &mut [u8]) -> usize {
if s.len() == 0 {
return 0;
}
loop {
let n = recv_nb(s);
if n != 0 {
return n;
}
unsafe { asm::wfi(); }
}
}
/** Initialize interrupts and buffered UART handling */ /** Initialize interrupts and buffered UART handling */
pub fn init() { pub fn init() {
unsafe { unsafe {

View File

@ -27,7 +27,6 @@ use buffered_uart;
mod config; mod config;
const DEFAULT_BAUD: u32 = 115_200; const DEFAULT_BAUD: u32 = 115_200;
const TIMEOUT: usize = 390_000_000 * 40 / 115200;
struct WriteAdapter; struct WriteAdapter;
@ -106,7 +105,7 @@ fn main() -> ! {
sh.start(false).unwrap(); sh.start(false).unwrap();
writeln!(console, "∙ Connecting to AP").unwrap(); writeln!(console, "∙ Connecting to AP").unwrap();
let mut serial_buf = [0u8; 8192]; let mut serial_buf = [0u8; 3000]; // needs to accomodate one whole response which is 2*TCP MSS(=2920)+some
let mut ofs: usize = 0; let mut ofs: usize = 0;
loop { loop {

View File

@ -27,7 +27,6 @@ use buffered_uart;
mod config; mod config;
const DEFAULT_BAUD: u32 = 115_200; const DEFAULT_BAUD: u32 = 115_200;
const TIMEOUT: usize = 390_000_000 * 40 / 115200;
struct WriteAdapter; struct WriteAdapter;
@ -106,7 +105,7 @@ fn main() -> ! {
sh.start(false).unwrap(); sh.start(false).unwrap();
writeln!(console, "∙ Connecting to AP").unwrap(); writeln!(console, "∙ Connecting to AP").unwrap();
let mut serial_buf = [0u8; 8192]; let mut serial_buf = [0u8; 3000]; // needs to accomodate one whole response which is 2*TCP MSS(=2920)+some
let mut ofs: usize = 0; let mut ofs: usize = 0;
let mut cur_link = 0; let mut cur_link = 0;

View File

@ -128,8 +128,8 @@ where
Response::Echo(data) => { Response::Echo(data) => {
writeln!(debug, "→ {}", str::from_utf8(data).unwrap_or("???")).unwrap(); writeln!(debug, "→ {}", str::from_utf8(data).unwrap_or("???")).unwrap();
} }
Response::Data(link, _) => { Response::Data(link, d) => {
writeln!(debug, "← Data({}, [...])", link).unwrap(); writeln!(debug, "← Data({}, [...] {})", link, d.len()).unwrap();
} }
_ => { _ => {
writeln!(debug, "← {:?}", resp).unwrap(); writeln!(debug, "← {:?}", resp).unwrap();