mirror of
https://github.com/laanwj/k210-sdk-stuff.git
synced 2025-01-18 21:17:09 +04:00
rust: Use buffered UART1 in term-server and weather
This commit is contained in:
parent
1118d708b1
commit
213ca1d50e
@ -1,6 +1,8 @@
|
||||
Maix Go / K210 stuff
|
||||
=====================
|
||||
|
||||
Some demo projects (mostly in rust) for the Maix Go.
|
||||
|
||||
Building the C projects
|
||||
-----------------------
|
||||
|
||||
@ -52,7 +54,7 @@ Running ELF
|
||||
-----------
|
||||
|
||||
There is no need anymore to convert to raw binary, as ELF executables can be executed directly on
|
||||
the device (no flashing) using a recent checkout of [kflash](https://github.com/kendryte/kflash.py)
|
||||
the device (without flashing) using a recent checkout of [kflash](https://github.com/kendryte/kflash.py)
|
||||
|
||||
```bash
|
||||
kflash.py -t -s -p /dev/ttyUSB1 -B goE "${ELF_NAME}"
|
||||
@ -64,7 +66,8 @@ and run code on the device through JTAG and OpenOCD, but I have never got this t
|
||||
|
||||
Currently, rust generates ELF executables based at address `0xffffffff80000000`
|
||||
instead of the expected `0x80000000`, to work around lack of medany memory
|
||||
model support in LLVM. To make this work with kflash I had to patch the
|
||||
model support in LLVM (this has ben fixed but hasn't reached stable yet at the
|
||||
time of writing). To make this work with kflash I had to patch the
|
||||
following:
|
||||
|
||||
```patch
|
||||
|
@ -18,4 +18,4 @@ members = [
|
||||
|
||||
[patch.crates-io]
|
||||
k210-hal = { git = "https://github.com/riscv-rust/k210-hal.git", rev = "b83e843c19a2f0bc4eb7f56322ae844818709298" }
|
||||
k210-pac = { git = "https://github.com/riscv-rust/k210-pac.git", rev = "91b421e17729b549566271a66ba19ce6fc205178" }
|
||||
k210-pac = { git = "https://github.com/riscv-rust/k210-pac.git", rev = "dc1acb925b0ee45b7c5fefb6897dc8cf3c32838d" }
|
||||
|
4
rust/buffered-uart/.cargo/config
Normal file
4
rust/buffered-uart/.cargo/config
Normal file
@ -0,0 +1,4 @@
|
||||
[target.riscv64gc-unknown-none-elf]
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Ttrap.x",
|
||||
]
|
2
rust/buffered-uart/.gitignore
vendored
Normal file
2
rust/buffered-uart/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
/target
|
||||
**/*.rs.bk
|
12
rust/buffered-uart/Cargo.toml
Normal file
12
rust/buffered-uart/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "buffered-uart"
|
||||
version = "0.1.0"
|
||||
authors = ["W.J. van der Laan <laanwj@protonmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
bare-metal = "0.2.0"
|
||||
riscv-rt = "0.6"
|
||||
k210-hal = "0.1.0"
|
||||
riscv = { version = "0.5", features = ["inline-asm"] }
|
||||
k210-shared = { path = "../k210-shared" }
|
2
rust/buffered-uart/README.md
Normal file
2
rust/buffered-uart/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
# `buffered-uart`
|
||||
|
13
rust/buffered-uart/build.rs
Normal file
13
rust/buffered-uart/build.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use std::{env, fs};
|
||||
use std::path::PathBuf;
|
||||
use std::io::Write;
|
||||
|
||||
fn main() {
|
||||
// Put the linker script somewhere the linker can find it
|
||||
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
|
||||
println!("cargo:rustc-link-search={}", out_dir.display());
|
||||
|
||||
fs::File::create(out_dir.join("trap.x")).unwrap()
|
||||
.write_all(include_bytes!("trap.x")).unwrap();
|
||||
println!("cargo:rerun-if-changed=trap.x");
|
||||
}
|
238
rust/buffered-uart/src/lib.rs
Normal file
238
rust/buffered-uart/src/lib.rs
Normal file
@ -0,0 +1,238 @@
|
||||
#![no_std]
|
||||
#![allow(dead_code)]
|
||||
/** Buffered UART, using interrupts — currently only receiving is buffered because this is most
|
||||
* important, avoiding loss of data when the FIFO fills up. Buffered sending is slightly less
|
||||
* interesting without a fully fledged scheduling OS.
|
||||
*/
|
||||
// Yep, this is an awful hack, many things are hardcoded that should not be, just a proof of concept…
|
||||
use bare_metal::Nr;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
use k210_hal::pac;
|
||||
use k210_shared::soc::sysctl;
|
||||
use pac::interrupt::Interrupt;
|
||||
use riscv::register::{mcause, mhartid, mie, mip, mstatus};
|
||||
|
||||
const UART_BUFSIZE: usize = 4096;
|
||||
/** UART ring buffer */
|
||||
struct UartInstance {
|
||||
buf: [u8; UART_BUFSIZE],
|
||||
/** writing happens at head */
|
||||
head: AtomicUsize,
|
||||
/** reading happens at tail, until tail==head */
|
||||
tail: AtomicUsize,
|
||||
}
|
||||
|
||||
static mut UART1_INSTANCE_RECV: UartInstance = UartInstance {
|
||||
buf: [0; UART_BUFSIZE],
|
||||
head: AtomicUsize::new(0),
|
||||
tail: AtomicUsize::new(0),
|
||||
};
|
||||
|
||||
/** UART IIR interrupt reason */
|
||||
const UART_INTERRUPT_SEND: u8 = 0x02;
|
||||
const UART_INTERRUPT_RECEIVE: u8 = 0x04;
|
||||
const UART_INTERRUPT_CHARACTER_TIMEOUT: u8 = 0x0C;
|
||||
|
||||
/** Receive FIFO trigger */
|
||||
const UART_RECEIVE_FIFO_1: u32 = 0;
|
||||
const UART_RECEIVE_FIFO_4: u32 = 1;
|
||||
const UART_RECEIVE_FIFO_8: u32 = 2;
|
||||
const UART_RECEIVE_FIFO_14: u32 = 3;
|
||||
|
||||
/** Send FIFO trigger */
|
||||
const UART_SEND_FIFO_0: u32 = 0;
|
||||
const UART_SEND_FIFO_2: u32 = 1;
|
||||
const UART_SEND_FIFO_4: u32 = 2;
|
||||
const UART_SEND_FIFO_8: u32 = 3;
|
||||
|
||||
const UART_IER_ERBFI: u32 = 1;
|
||||
|
||||
/** Handle UARTx interrupt */
|
||||
fn interrupt_uart1() {
|
||||
unsafe {
|
||||
let uart = pac::UART1::ptr();
|
||||
let irecv = &mut UART1_INSTANCE_RECV;
|
||||
|
||||
match ((*uart).fcr_iir.read().bits() & 0xf) as u8 {
|
||||
UART_INTERRUPT_RECEIVE | UART_INTERRUPT_CHARACTER_TIMEOUT => {
|
||||
// Read recv FIFO into receive ringbuffer
|
||||
let mut head = irecv.head.load(Ordering::SeqCst);
|
||||
while ((*uart).lsr.read().bits() & 1) != 0 {
|
||||
irecv.buf[head] = ((*uart).rbr_dll_thr.read().bits() & 0xff) as u8;
|
||||
head += 1;
|
||||
if head == UART_BUFSIZE {
|
||||
head = 0;
|
||||
}
|
||||
}
|
||||
irecv.head.store(head, Ordering::SeqCst);
|
||||
}
|
||||
UART_INTERRUPT_SEND => {
|
||||
// TODO
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Global trap handler */
|
||||
#[no_mangle]
|
||||
fn my_trap_handler() {
|
||||
let hartid = mhartid::read();
|
||||
let cause = mcause::read().cause();
|
||||
match cause {
|
||||
// PLIC interrupts
|
||||
mcause::Trap::Interrupt(mcause::Interrupt::MachineExternal) => {
|
||||
if mip::read().mext() {
|
||||
unsafe {
|
||||
let plic = pac::PLIC::ptr();
|
||||
let target = &(*plic).targets[hartid * 2];
|
||||
let int_num = target.claim.read().bits();
|
||||
let int = Interrupt::try_from(int_num as u8).unwrap();
|
||||
|
||||
// Does this really need the 'disable other interrupts, change threshold' dance
|
||||
// as done in handle_irq_m_ext in plic.c?
|
||||
match int {
|
||||
Interrupt::UART1 => interrupt_uart1(),
|
||||
// We'll get a spurious UARTHS interrupt, ignore it
|
||||
Interrupt::UARTHS => {}
|
||||
_ => {
|
||||
panic!(
|
||||
"unknown machineexternal {:?} on {}, int {:?}",
|
||||
cause, hartid, int
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Perform IRQ complete
|
||||
target.claim.write(|w| w.bits(int_num));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
panic!("unknown trap {:?}", cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Enable or disable a PLIC interrupt for the current core */
|
||||
fn plic_irq_enable(interrupt: Interrupt, enabled: bool) {
|
||||
let targetid = mhartid::read() * 2;
|
||||
let irq_nr = interrupt.nr();
|
||||
unsafe {
|
||||
let plic = pac::PLIC::ptr();
|
||||
let bit = 1 << ((irq_nr as u32) % 32);
|
||||
if enabled {
|
||||
(*plic).target_enables[targetid].enable[(irq_nr as usize) / 32]
|
||||
.modify(|r, w| w.bits(r.bits() | bit));
|
||||
} else {
|
||||
(*plic).target_enables[targetid].enable[(irq_nr as usize) / 32]
|
||||
.modify(|r, w| w.bits(r.bits() & !bit));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Set interrupt priority (0-7) */
|
||||
fn plic_set_priority(interrupt: Interrupt, priority: u32) {
|
||||
let irq_nr = interrupt.nr();
|
||||
unsafe {
|
||||
let plic = pac::PLIC::ptr();
|
||||
(*plic).priority[irq_nr as usize].write(|w| w.bits(priority));
|
||||
}
|
||||
}
|
||||
|
||||
/** Initialize UART */
|
||||
fn uart_init(baud_rate: u32) {
|
||||
let uart = pac::UART1::ptr();
|
||||
sysctl::clock_enable(sysctl::clock::UART1);
|
||||
sysctl::reset(sysctl::reset::UART1);
|
||||
|
||||
// Hardcode these for now:
|
||||
let data_width = 8; // 8 data bits
|
||||
let stopbit_val = 0; // 1 stop bit
|
||||
let parity_val = 0; // No parity
|
||||
let divisor = sysctl::clock_get_freq(sysctl::clock::APB0) / baud_rate;
|
||||
let dlh = ((divisor >> 12) & 0xff) as u8;
|
||||
let dll = ((divisor >> 4) & 0xff) as u8;
|
||||
let dlf = (divisor & 0xf) as u8;
|
||||
unsafe {
|
||||
// Set Divisor Latch Access Bit (enables DLL DLH) to set baudrate
|
||||
(*uart).lcr.write(|w| w.bits(1 << 7));
|
||||
(*uart).dlh_ier.write(|w| w.bits(dlh.into()));
|
||||
(*uart).rbr_dll_thr.write(|w| w.bits(dll.into()));
|
||||
(*uart).dlf.write(|w| w.bits(dlf.into()));
|
||||
// Clear Divisor Latch Access Bit after setting baudrate
|
||||
(*uart)
|
||||
.lcr
|
||||
.write(|w| w.bits((data_width - 5) | (stopbit_val << 2) | (parity_val << 3)));
|
||||
// Write IER
|
||||
(*uart).dlh_ier.write(|w| w.bits(0x80)); /* THRE */
|
||||
// Write FCT
|
||||
(*uart)
|
||||
.fcr_iir
|
||||
.write(|w| w.bits(UART_RECEIVE_FIFO_4 << 6 | UART_SEND_FIFO_8 << 4 | 0x1 << 3 | 0x1));
|
||||
}
|
||||
}
|
||||
|
||||
/** Enable or disable UART interrupt */
|
||||
fn uart_enable_intr(recv: bool) {
|
||||
unsafe {
|
||||
let uart = pac::UART1::ptr();
|
||||
if recv {
|
||||
(*uart)
|
||||
.dlh_ier
|
||||
.modify(|r, w| w.bits(r.bits() | UART_IER_ERBFI));
|
||||
plic_set_priority(Interrupt::UART1, 6);
|
||||
plic_irq_enable(Interrupt::UART1, true);
|
||||
} else {
|
||||
(*uart)
|
||||
.dlh_ier
|
||||
.modify(|r, w| w.bits(r.bits() & !UART_IER_ERBFI));
|
||||
plic_set_priority(Interrupt::UART1, 0);
|
||||
plic_irq_enable(Interrupt::UART1, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Send data to UART */
|
||||
pub fn send(s: &[u8]) {
|
||||
let uart = pac::UART1::ptr();
|
||||
for &c in s {
|
||||
unsafe {
|
||||
while ((*uart).lsr.read().bits() & (1 << 5)) != 0 {}
|
||||
(*uart).rbr_dll_thr.write(|w| w.bits(c.into()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Receive data from UART (non-blocking, returns number of bytes received) */
|
||||
pub fn recv(s: &mut [u8]) -> usize {
|
||||
let irecv = unsafe { &mut UART1_INSTANCE_RECV };
|
||||
let head = irecv.head.load(Ordering::SeqCst);
|
||||
let mut tail = irecv.tail.load(Ordering::SeqCst);
|
||||
let mut ptr = 0;
|
||||
while ptr < s.len() && tail != head {
|
||||
s[ptr] = irecv.buf[tail];
|
||||
tail += 1;
|
||||
if tail == UART_BUFSIZE {
|
||||
tail = 0;
|
||||
}
|
||||
ptr += 1;
|
||||
}
|
||||
irecv.tail.store(tail, Ordering::SeqCst);
|
||||
ptr
|
||||
}
|
||||
|
||||
/** Initialize interrupts and buffered UART handling */
|
||||
pub fn init() {
|
||||
unsafe {
|
||||
// Enable interrupts in general
|
||||
mstatus::set_mie();
|
||||
// Set the Machine-Software bit in MIE
|
||||
mie::set_msoft();
|
||||
// Set the Machine-External bit in MIE
|
||||
mie::set_mext();
|
||||
}
|
||||
|
||||
uart_init(115_200);
|
||||
uart_enable_intr(true);
|
||||
}
|
2
rust/buffered-uart/trap.x
Normal file
2
rust/buffered-uart/trap.x
Normal file
@ -0,0 +1,2 @@
|
||||
/* set our own trap handler */
|
||||
trap_handler = my_trap_handler;
|
4
rust/term-server/.cargo/config
Normal file
4
rust/term-server/.cargo/config
Normal file
@ -0,0 +1,4 @@
|
||||
[target.riscv64gc-unknown-none-elf]
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Ttrap.x",
|
||||
]
|
@ -13,3 +13,4 @@ riscv = "0.5"
|
||||
k210-shared = { path = "../k210-shared" }
|
||||
k210-console = { path = "../k210-console" }
|
||||
esp8266at = { path = "../../util/esp8266at", default-features = false }
|
||||
buffered-uart = { path = "../buffered-uart" }
|
||||
|
@ -5,7 +5,6 @@
|
||||
#![no_main]
|
||||
|
||||
use core::str;
|
||||
use embedded_hal::serial;
|
||||
use esp8266at::handler::{NetworkEvent, SerialNetworkHandler};
|
||||
use esp8266at::response::{parse, ParseResult};
|
||||
use esp8266at::traits;
|
||||
@ -21,42 +20,27 @@ use k210_shared::soc::gpiohs;
|
||||
use k210_shared::soc::sleep::usleep;
|
||||
use k210_shared::soc::spi::SPIExt;
|
||||
use k210_shared::soc::sysctl;
|
||||
use nb::block;
|
||||
use riscv::register::mcycle;
|
||||
use riscv_rt::entry;
|
||||
use k210_console::console::{Console, ScreenImage, DISP_HEIGHT, DISP_WIDTH, DISP_PIXELS};
|
||||
use buffered_uart;
|
||||
|
||||
mod config;
|
||||
|
||||
const DEFAULT_BAUD: u32 = 115_200;
|
||||
const TIMEOUT: usize = 390_000_000 * 40 / 115200;
|
||||
|
||||
struct WriteAdapter<'a, TX>
|
||||
where
|
||||
TX: serial::Write<u8>,
|
||||
{
|
||||
tx: &'a mut TX,
|
||||
}
|
||||
impl<'a, TX> WriteAdapter<'a, TX>
|
||||
where
|
||||
TX: serial::Write<u8>,
|
||||
TX::Error: core::fmt::Debug,
|
||||
{
|
||||
fn new(tx: &'a mut TX) -> Self {
|
||||
Self { tx }
|
||||
struct WriteAdapter;
|
||||
|
||||
impl WriteAdapter {
|
||||
fn new() -> Self {
|
||||
Self { }
|
||||
}
|
||||
}
|
||||
impl<'a, TX> traits::Write for WriteAdapter<'a, TX>
|
||||
where
|
||||
TX: serial::Write<u8>,
|
||||
TX::Error: core::fmt::Debug,
|
||||
{
|
||||
type Error = TX::Error;
|
||||
impl traits::Write for WriteAdapter {
|
||||
type Error = ();
|
||||
|
||||
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
|
||||
for ch in buf {
|
||||
block!(self.tx.write(*ch))?;
|
||||
}
|
||||
buffered_uart::send(buf);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -97,14 +81,15 @@ fn main() -> ! {
|
||||
// Configure UART1 (→WIFI)
|
||||
sysctl::clock_enable(sysctl::clock::UART1);
|
||||
sysctl::reset(sysctl::reset::UART1);
|
||||
fpioa::set_function(io::WIFI_RX, fpioa::function::UART1_TX);
|
||||
fpioa::set_function(io::WIFI_TX, fpioa::function::UART1_RX);
|
||||
fpioa::set_function(io::WIFI_EN, fpioa::function::GPIOHS8);
|
||||
fpioa::set_io_pull(io::WIFI_EN, fpioa::pull::DOWN);
|
||||
gpiohs::set_pin(8, true);
|
||||
gpiohs::set_direction(8, gpio::direction::OUTPUT);
|
||||
let wifi_serial = p.UART1.configure((p.pins.pin7, p.pins.pin6), DEFAULT_BAUD.bps(), &clocks);
|
||||
let (mut wtx, mut wrx) = wifi_serial.split();
|
||||
|
||||
let mut wa = WriteAdapter::new(&mut wtx);
|
||||
buffered_uart::init();
|
||||
let mut wa = WriteAdapter::new();
|
||||
let mut sh = SerialNetworkHandler::new(&mut wa, config::APNAME.as_bytes(), config::APPASS.as_bytes());
|
||||
|
||||
// LCD ini
|
||||
@ -133,21 +118,7 @@ fn main() -> ! {
|
||||
}
|
||||
|
||||
// Receive into buffer
|
||||
let mut lastrecv = mcycle::read();
|
||||
while ofs < serial_buf.len() {
|
||||
// Read until we stop receiving for a certain duration
|
||||
// This is a hack around the fact that in the time that the parser runs,
|
||||
// more than one FIFO full of characters can be received so characters could be
|
||||
// lost. The right way would be to receive in an interrupt handler, but,
|
||||
// we don't have that yet.
|
||||
if let Ok(ch) = wrx.read() {
|
||||
serial_buf[ofs] = ch;
|
||||
ofs += 1;
|
||||
lastrecv = mcycle::read();
|
||||
} else if (mcycle::read().wrapping_sub(lastrecv)) >= TIMEOUT {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ofs += buffered_uart::recv(&mut serial_buf[ofs..]);
|
||||
//writeln!(debug, "ofs: {} received {} chars {:?}", ofs0, ofs - ofs0,
|
||||
// &serial_buf[ofs0..ofs]).unwrap();
|
||||
|
||||
|
4
rust/weather/.cargo/config
Normal file
4
rust/weather/.cargo/config
Normal file
@ -0,0 +1,4 @@
|
||||
[target.riscv64gc-unknown-none-elf]
|
||||
rustflags = [
|
||||
"-C", "link-arg=-Ttrap.x",
|
||||
]
|
@ -13,3 +13,4 @@ riscv = "0.5"
|
||||
k210-shared = { path = "../k210-shared" }
|
||||
k210-console = { path = "../k210-console" }
|
||||
esp8266at = { path = "../../util/esp8266at", default-features = false }
|
||||
buffered-uart = { path = "../buffered-uart" }
|
||||
|
@ -5,7 +5,6 @@
|
||||
#![no_main]
|
||||
|
||||
use core::str;
|
||||
use embedded_hal::serial;
|
||||
use esp8266at::handler::{NetworkEvent, SerialNetworkHandler};
|
||||
use esp8266at::response::{parse, ConnectionType, ParseResult};
|
||||
use esp8266at::traits::{self, Write};
|
||||
@ -21,42 +20,27 @@ use k210_shared::soc::gpiohs;
|
||||
use k210_shared::soc::sleep::usleep;
|
||||
use k210_shared::soc::spi::SPIExt;
|
||||
use k210_shared::soc::sysctl;
|
||||
use nb::block;
|
||||
use riscv::register::mcycle;
|
||||
use riscv_rt::entry;
|
||||
use k210_console::console::{Console, ScreenImage, DISP_HEIGHT, DISP_WIDTH, DISP_PIXELS};
|
||||
use buffered_uart;
|
||||
|
||||
mod config;
|
||||
|
||||
const DEFAULT_BAUD: u32 = 115_200;
|
||||
const TIMEOUT: usize = 390_000_000 * 40 / 115200;
|
||||
|
||||
struct WriteAdapter<'a, TX>
|
||||
where
|
||||
TX: serial::Write<u8>,
|
||||
{
|
||||
tx: &'a mut TX,
|
||||
}
|
||||
impl<'a, TX> WriteAdapter<'a, TX>
|
||||
where
|
||||
TX: serial::Write<u8>,
|
||||
TX::Error: core::fmt::Debug,
|
||||
{
|
||||
fn new(tx: &'a mut TX) -> Self {
|
||||
Self { tx }
|
||||
struct WriteAdapter;
|
||||
|
||||
impl WriteAdapter {
|
||||
fn new() -> Self {
|
||||
Self { }
|
||||
}
|
||||
}
|
||||
impl<'a, TX> traits::Write for WriteAdapter<'a, TX>
|
||||
where
|
||||
TX: serial::Write<u8>,
|
||||
TX::Error: core::fmt::Debug,
|
||||
{
|
||||
type Error = TX::Error;
|
||||
impl traits::Write for WriteAdapter {
|
||||
type Error = ();
|
||||
|
||||
fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
|
||||
for ch in buf {
|
||||
block!(self.tx.write(*ch))?;
|
||||
}
|
||||
buffered_uart::send(buf);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -97,17 +81,18 @@ fn main() -> ! {
|
||||
// Configure UART1 (→WIFI)
|
||||
sysctl::clock_enable(sysctl::clock::UART1);
|
||||
sysctl::reset(sysctl::reset::UART1);
|
||||
fpioa::set_function(io::WIFI_RX, fpioa::function::UART1_TX);
|
||||
fpioa::set_function(io::WIFI_TX, fpioa::function::UART1_RX);
|
||||
fpioa::set_function(io::WIFI_EN, fpioa::function::GPIOHS8);
|
||||
fpioa::set_io_pull(io::WIFI_EN, fpioa::pull::DOWN);
|
||||
gpiohs::set_pin(8, true);
|
||||
gpiohs::set_direction(8, gpio::direction::OUTPUT);
|
||||
let wifi_serial = p.UART1.configure((p.pins.pin7, p.pins.pin6), DEFAULT_BAUD.bps(), &clocks);
|
||||
let (mut wtx, mut wrx) = wifi_serial.split();
|
||||
|
||||
let mut wa = WriteAdapter::new(&mut wtx);
|
||||
buffered_uart::init();
|
||||
let mut wa = WriteAdapter::new();
|
||||
let mut sh = SerialNetworkHandler::new(&mut wa, config::APNAME.as_bytes(), config::APPASS.as_bytes());
|
||||
|
||||
// LCD ini
|
||||
// LCD init
|
||||
let dmac = p.DMAC.configure();
|
||||
let spi = p.SPI0.constrain();
|
||||
let mut lcd = LCD::new(spi, &dmac, dma_channel::CHANNEL0);
|
||||
@ -145,21 +130,7 @@ fn main() -> ! {
|
||||
}
|
||||
|
||||
// Receive into buffer
|
||||
let mut lastrecv = mcycle::read();
|
||||
while ofs < serial_buf.len() {
|
||||
// Read until we stop receiving for a certain duration
|
||||
// This is a hack around the fact that in the time that the parser runs,
|
||||
// more than one FIFO full of characters can be received so characters could be
|
||||
// lost. The right way would be to receive in an interrupt handler, but,
|
||||
// we don't have that yet.
|
||||
if let Ok(ch) = wrx.read() {
|
||||
serial_buf[ofs] = ch;
|
||||
ofs += 1;
|
||||
lastrecv = mcycle::read();
|
||||
} else if (mcycle::read().wrapping_sub(lastrecv)) >= TIMEOUT {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ofs += buffered_uart::recv(&mut serial_buf[ofs..]);
|
||||
//writeln!(debug, "ofs: {} received {} chars {:?}", ofs0, ofs - ofs0,
|
||||
// &serial_buf[ofs0..ofs]).unwrap();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user