diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..53032f9 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,16 @@ +Change Log +======= + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +# [unreleased] + +# [v0.1.0] + +Initial release. + +[unreleased]: https://egit.irs.uni-stuttgart.de/rust/axi-uartlite/compare/v0.1.0...HEAD +[v0.1.0]: https://egit.irs.uni-stuttgart.de/rust/axi-uartlite/tag/v0.1.0 diff --git a/Cargo.toml b/Cargo.toml index 0f47603..9759aee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,3 +26,6 @@ default = ["1-waker"] 8-wakers = [] 16-wakers = [] 32-wakers = [] + +[package.metadata.docs.rs] +rustdoc-args = ["--generate-link-to-definition"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..55733c6 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +AXI UARTLITE driver +======== + +This is a native Rust driver for the AMD AXI UART Lite v2.0 IP core. + +# Core features + +- Basic driver which can be created with a given IP core base address and supports as basic + byte-level read and write API. +- Support for [`embedded-io`](https://docs.rs/embedded-io/latest/embedded_io/) and + [`embedded-io-async`](https://docs.rs/embedded-io-async/latest/embedded_io_async/) + +# Features + +If the asynchronous support for the TX side is used, the number of statically provided wakers +can be configured using the following features: + +- `1-waker` which is the default +- `2-wakers` +- `4-wakers` +- `8-wakers` +- `16-wakers` +- `32-wakers` diff --git a/justfile b/justfile new file mode 100644 index 0000000..e88ac38 --- /dev/null +++ b/justfile @@ -0,0 +1,32 @@ +all: check build embedded clippy fmt docs coverage + +clippy: + cargo clippy -- -D warnings + +fmt: + cargo fmt --all -- --check + +check: + cargo check + +embedded: + cargo build --target thumbv7em-none-eabihf + +test: + cargo nextest r + cargo test --doc + +build: + cargo build + +docs: + RUSTDOCFLAGS="--cfg docsrs -Z unstable-options --generate-link-to-definition" cargo +nightly doc + +docs-html: + RUSTDOCFLAGS="--cfg docsrs -Z unstable-options --generate-link-to-definition" cargo +nightly doc --open + +coverage: + cargo llvm-cov nextest + +coverage-html: + cargo llvm-cov nextest --html --open diff --git a/src/lib.rs b/src/lib.rs index 7569112..8e08c7c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ //! - `16-wakers` //! - `32-wakers` #![no_std] +#![cfg_attr(docsrs, feature(doc_cfg))] use core::convert::Infallible; use registers::Control; @@ -82,7 +83,7 @@ impl AxiUartlite { /// with the same `base_addr` can lead to unintended behavior if not externally synchronized. /// - The driver performs **volatile** reads and writes to the provided address. pub const unsafe fn new(base_addr: u32) -> Self { - let regs = unsafe { registers::AxiUartlite::new_mmio_at(base_addr as usize) }; + let regs = unsafe { registers::Registers::new_mmio_at(base_addr as usize) }; Self { rx: Rx { regs: unsafe { regs.clone() }, @@ -94,7 +95,7 @@ impl AxiUartlite { } #[inline(always)] - pub const fn regs(&mut self) -> &mut registers::MmioAxiUartlite<'static> { + pub const fn regs(&mut self) -> &mut registers::MmioRegisters<'static> { &mut self.tx.regs } diff --git a/src/registers.rs b/src/registers.rs index 2a68de9..da4bd56 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -41,9 +41,10 @@ pub struct Control { reset_tx_fifo: bool, } +/// AXI UARTLITE register block definition. #[derive(derive_mmio::Mmio)] #[repr(C)] -pub struct AxiUartlite { +pub struct Registers { #[mmio(PureRead)] rx_fifo: RxFifo, tx_fifo: TxFifo, diff --git a/src/rx.rs b/src/rx.rs index 3e5b813..768aca4 100644 --- a/src/rx.rs +++ b/src/rx.rs @@ -1,6 +1,6 @@ use core::convert::Infallible; -use crate::registers::{self, AxiUartlite, Status}; +use crate::registers::{self, Registers, Status}; #[derive(Debug, Default, Copy, Clone, Eq, PartialEq)] pub struct RxErrors { @@ -36,7 +36,7 @@ impl RxErrors { } pub struct Rx { - pub(crate) regs: registers::MmioAxiUartlite<'static>, + pub(crate) regs: registers::MmioRegisters<'static>, pub(crate) errors: Option, } @@ -57,7 +57,7 @@ impl Rx { #[inline] pub const unsafe fn steal(base_addr: usize) -> Self { Self { - regs: unsafe { AxiUartlite::new_mmio_at(base_addr) }, + regs: unsafe { Registers::new_mmio_at(base_addr) }, errors: None, } } diff --git a/src/tx.rs b/src/tx.rs index eb93f21..2cac4f5 100644 --- a/src/tx.rs +++ b/src/tx.rs @@ -6,7 +6,7 @@ use crate::{ }; pub struct Tx { - pub(crate) regs: registers::MmioAxiUartlite<'static>, + pub(crate) regs: registers::MmioRegisters<'static>, pub(crate) errors: Option, } @@ -25,7 +25,7 @@ impl Tx { /// /// The same safey rules specified in [super::AxiUartlite] apply. pub unsafe fn steal(base_addr: usize) -> Self { - let regs = unsafe { registers::AxiUartlite::new_mmio_at(base_addr) }; + let regs = unsafe { registers::Registers::new_mmio_at(base_addr) }; Self { regs, errors: None } } diff --git a/src/tx_async.rs b/src/tx_async.rs index fce964b..854cae3 100644 --- a/src/tx_async.rs +++ b/src/tx_async.rs @@ -173,7 +173,16 @@ impl Future for TxFuture { } impl Drop for TxFuture { - fn drop(&mut self) {} + fn drop(&mut self) { + if !TX_DONE[self.waker_idx].load(core::sync::atomic::Ordering::Relaxed) { + critical_section::with(|cs| { + let context_ref = TX_CONTEXTS[self.waker_idx].borrow(cs); + let mut context_mut = context_ref.borrow_mut(); + context_mut.slice.set_null(); + context_mut.progress = 0; + }); + } + } } pub struct TxAsync {