diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 0000000..93c7ed7 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,5 @@ +[build] +target = "aarch64-unknown-none" + +[unstable] +build-std = ["core", "compiler_builtins", "alloc"] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..72e66ef --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,179 @@ +name: CI + +on: + pull_request: + branches: + - development + - release + push: + branches: + - development + - release + +jobs: + build: + name: Compile The Crate + runs-on: ubuntu-latest + + steps: + # Checkout the current code from github into the CI machine + - name: Checkout Code + uses: actions/checkout@v2 + + - name: Install aarch64 gcc toolchain + run: sudo apt-get install -y gcc-aarch64-linux-gnu + + # install toolchain based on rust-toolchain file + - name: Install Rust Nightly and Cargo + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly-2021-09-05 + profile: minimal + components: rust-src, llvm-tools-preview + target: aarch64-unknown-none + override: true + + - name: Install Cargo Make + uses: davidB/rust-cargo-make@v1 + with: + version: 'latest' + + - if: ${{ github.event_name != 'pull_request' }} + name: Remove patches if not a PR build + run: | + sed -i "/{^\[patch\.crates-io\] /{:a;N;/\Z}/!ba};/^ruspiro-.*\(git\|path\).*/d" Cargo.toml; + cat Cargo.toml + + - name: Compile + run: cargo make pi3 --profile pipeline + + publish_dry: + name: Run Cargo Publish Dry-Run + runs-on: ubuntu-latest + + steps: + # Checkout the current code from github into the CI machine + - name: Checkout Code + uses: actions/checkout@v2 + + - name: Install aarch64 gcc toolchain + run: sudo apt-get install -y gcc-aarch64-linux-gnu + + - name: Install Rust Nightly and Cargo + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly-2021-09-05 + profile: minimal + components: rust-src, llvm-tools-preview + target: aarch64-unknown-none + override: true + + - name: Install Cargo Make + uses: davidB/rust-cargo-make@v1 + with: + version: 'latest' + + - name: Publish-Dry-Run + run: cargo make publish_dry --profile pipeline + + prepare_release: + needs: [build, publish_dry] + if: ${{ github.ref == 'refs/heads/development' }} + name: Prepare Release - Create Release PR + runs-on: ubuntu-latest + steps: + - name: Create PR against the release branch + uses: tretuna/sync-branches@1.2.0 + with: + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + FROM_BRANCH: "development" + TO_BRANCH: "release" + PULL_REQUEST_TITLE: "Prepare Release and crates.io publishing" + PULL_REQUEST_BODY: "Automatic PR to the release branch as preperation to publish the library" + + deploy: + needs: [build, publish_dry] + if: ${{ github.ref == 'refs/heads/release' }} + name: Create Release + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v2 + + - name: Prepre Crate Release Version + run: | + # extract current crate version from Cargo.toml + echo 'CRATE_VERSION=v'$(sed -En 's/^version.*=.*\"(.*)\".*$/\1/p' < Cargo.toml) >> $GITHUB_ENV + # retrieve last release version from github + echo 'LAST_VERSION='$(curl --silent "https://api.github.com/repos/$GITHUB_REPOSITORY/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/') >> $GITHUB_ENV + + - if: ${{ env.LAST_VERSION == '' }} + name: Set base version + run: echo 'LAST_VERSION='v0.0.0 >> $GITHUB_ENV + + - name: Create Tag + run: | + echo ${{ env.CRATE_VERSION }} + echo ${{ env.LAST_VERSION }} + git config --local user.name "2ndTaleStudio" + git config --local user.email "43264484+2ndTaleStudio@users.noreply.github.com" + # create the TAG required for the release + git tag ${{ env.CRATE_VERSION }} -m "${{ env.CRATE_VERSION }}" + # extract the release notes of the current release from the changelog + sed -En '/##.*:.*:.*'"${{ env.LAST_VERSION }}"'/q;p' CHANGELOG.md > RELEASENOTES.md + sed -i -e 's/^# Changelog/# Release Notes/g' RELEASENOTES.md + + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token + with: + tag_name: ${{ env.CRATE_VERSION }} + release_name: Release ${{ env.CRATE_VERSION }} + body_path: RELEASENOTES.md + draft: false + prerelease: false + + publish: + if: ${{ github.ref == 'refs/heads/release' }} + needs: deploy + name: Run Cargo Publish + runs-on: ubuntu-latest + + steps: + # Checkout the current code from github into the CI machine + - name: Checkout Code + uses: actions/checkout@v2 + + - name: Install aarch64 gcc toolchain + run: sudo apt-get install -y gcc-aarch64-linux-gnu + + - name: Install Rust Nightly and Cargo + uses: actions-rs/toolchain@v1 + with: + toolchain: nightly-2021-09-05 + profile: minimal + components: rust-src, llvm-tools-preview + target: aarch64-unknown-none + override: true + + - name: Install Cargo Make + uses: davidB/rust-cargo-make@v1 + with: + version: 'latest' + + - name: Get current version + run: echo 'CRATE_VERSION='$(sed -En 's/^version.*=.*\"(.*)\".*$/\1/p' < Cargo.toml) >> $GITHUB_ENV + + - name: Update version place holder in files + run: | + # before actually publishing replace the final version for doc and repository in the Crago.toml + sed -i -e 's/||VERSION||/'$CRATE_VERSION'/g' Cargo.toml + # also update the version in the lib.rs doc root url + sed -i -e 's/||VERSION||/'$CRATE_VERSION'/g' src/lib.rs + # and the README.md + sed -i -e 's/||VERSION||/'$CRATE_VERSION'/g' README.md + + - name: Publish-Dry-Run + run: cargo make publish --env CRATES_TOKEN=${{ secrets.CRATES_TOKEN }} --profile pipeline diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..387df85 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,2 @@ +# use a default of 2 spaces for indention levels +tab_spaces = 2 \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e488f73..0000000 --- a/.travis.yml +++ /dev/null @@ -1,53 +0,0 @@ -# build only master branch on commit's -# all other branches build on PullRequest creation -branches: - only: - - master - -language: rust - -rust: -# build nightly only for the time beeing - - nightly - -matrix: - fast_finish: true - include: - - name: "build 64Bit" - install: - - sudo apt-get install gcc-aarch64-linux-gnu - - cargo install cargo-xbuild - - cargo install cargo-make - - rustup target add aarch64-unknown-linux-gnu - - rustup component add rust-src - - rustup component add llvm-tools-preview - # if we not build a PR we remove the patch of the dependencies to their github repo's - - 'if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then sed -i "/{^\[patch\.crates-io\] /{:a;N;/\Z}/!ba};/^ruspiro-.*\(git\|path\).*/d" Cargo.toml; fi' - script: cargo make --profile a64-travis pi3 - - - name: "build 32Bit" - install: - - sudo apt-get install gcc-arm-linux-gnueabihf - - cargo install cargo-xbuild - - cargo install cargo-make - - rustup target add armv7-unknown-linux-gnueabihf - - rustup component add rust-src - - rustup component add llvm-tools-preview - # if we not build a PR we remove the patch of the dependencies to their github repo's - - 'if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then sed -i "/{^\[patch\.crates-io\] /{:a;N;/\Z}/!ba};/^ruspiro-.*\(git\|path\).*/d" Cargo.toml; fi' - script: cargo make --profile a32 pi3 - - - name: "unit tests" - install: - # if we not build a PR we remove the patch of the dependencies to their github repo's - - 'if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then sed -i "/{^\[patch\.crates-io\] /{:a;N;/\Z}/!ba};/^ruspiro-.*\(git\|path\).*/d" Cargo.toml; fi' - script: cargo test --tests --features ruspiro_pi3 - - - name: "doc tests" - install: - # if we not build a PR we remove the patch of the dependencies to their github repo's - - 'if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then sed -i "/{^\[patch\.crates-io\] /{:a;N;/\Z}/!ba};/^ruspiro-.*\(git\|path\).*/d" Cargo.toml; fi' - - cat Cargo.toml - script: cargo test --doc --features ruspiro_pi3 - - \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dda716..51d934e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog + +## :peach: v0.4.0 + +- ### :wrench: Maintenance + + - update travis pipeline build to support convenient publishing + - implement `core::fmt::Write` for both Uart types to enable them to be used with the latest `ruspiro_console::Console` + - upgrade the dependency for `ruspiro_register` and add `ruspiro_mmio_register` crate + - add MIT licencing in addition to Apache-2.0 + ## :banana: v0.3.1 - - ### :detective: Fixes - - remove `asm!` macro usages and replace with `llvm_asm!` - - use `cargo make` to stabilize cross-platform builds + +- ### :detective: Fixes + + - remove `asm!` macro usages and replace with `llvm_asm!` + - use `cargo make` to stabilize cross-platform builds diff --git a/Cargo.toml b/Cargo.toml index 3cf1cba..bcfea8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,14 @@ [package] name = "ruspiro-uart" authors = ["André Borrmann "] -version = "0.3.1" # remember to update html_root_url +version = "0.4.0" # remember to update html_root_url description = """ Simple and convinient access API to the Raspberry Pi 3 UART0 (PL011) and UART1 (miniUART) peripherals """ -license = "Apache-2.0" -repository = "https://github.com/RusPiRo/ruspiro-uart/tree/v0.3.1" -documentation = "https://docs.rs/ruspiro-uart/0.3.1" +license = "MIT | Apache-2.0" +repository = "https://github.com/RusPiRo/ruspiro-uart/tree/v||VERSION||" +documentation = "https://docs.rs/ruspiro-uart/||VERSION||" readme = "README.md" keywords = ["RusPiRo", "uart", "baremetal", "raspberrypi"] categories = ["no-std", "embedded"] @@ -22,20 +22,19 @@ maintenance = { status = "actively-developed" } [lib] [dependencies] -ruspiro-gpio = "0.4" -ruspiro-register = "0.4" -ruspiro-timer = "0.4" -ruspiro-console = "0.3" +ruspiro-gpio = "~0.4.3" +ruspiro-register = "~0.5.4" +ruspiro-mmio-register = "~0.1.3" +ruspiro-timer = "~0.5.2" [features] -default = ["ruspiro_pi3"] ruspiro_pi3 = [ "ruspiro-gpio/ruspiro_pi3", "ruspiro-timer/ruspiro_pi3" ] [patch.crates-io] -ruspiro-gpio = { git = "https://github.com/RusPiRo/ruspiro-gpio.git" } -ruspiro-register = { git = "https://github.com/RusPiRo/ruspiro-register.git" } -ruspiro-timer = { git = "https://github.com/RusPiRo/ruspiro-timer.git" } -ruspiro-console = { git = "https://github.com/RusPiRo/ruspiro-console.git" } +ruspiro-gpio = { git = "https://github.com/RusPiRo/ruspiro-gpio.git", branch = "development" } +ruspiro-register = { git = "https://github.com/RusPiRo/ruspiro-register.git", branch = "development" } +ruspiro-timer = { git = "https://github.com/RusPiRo/ruspiro-timer.git", branch = "development" } +ruspiro-mmio-register = { git = "https://github.com/RusPiRo/ruspiro-mmio-register.git", branch = "development" } diff --git a/LICENSE b/LICENSE-APACHE similarity index 100% rename from LICENSE rename to LICENSE-APACHE diff --git a/LICENSE-MIT b/LICENSE-MIT new file mode 100644 index 0000000..11fdb53 --- /dev/null +++ b/LICENSE-MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 André Borrmann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile.toml b/Makefile.toml index a6feee0..04a4f33 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -1,41 +1,49 @@ #*********************************************************************************************************************** # cargo make tasks to build the example for the Raspberry Pi #*********************************************************************************************************************** -[env.a64] + +# AARCH64 specific profile environment varialbles +[env.development] CC = "aarch64-none-elf-gcc" AR = "aarch64-none-elf-ar" -OC = "aarch64-none-elf-objcopy" CFLAGS = "-march=armv8-a -Wall -O3 -nostdlib -nostartfiles -ffreestanding -mtune=cortex-a53" -RUSTFLAGS = "-C linker=${CC} -C target-cpu=cortex-a53 -C link-arg=-nostartfiles -C link-arg=-T./link64.ld" -BUILD_TARGET = "aarch64-unknown-linux-gnu" - -[env.a32] -CC = "arm-none-eabi-gcc" -AR = "arm-none-eabi-ar" -OC = "arm-none-eabi-objcopy" -CFLAGS = "-mcpu=cortex-a53 -march=armv7-a -mfpu=neon -mfloat-abi=softfp -Wall -O3 -nostdlib -nostartfiles" -RUSTFLAGS = "-C linker=${CC} -C target-cpu=cortex-a53 -C link-arg=-nostartfiles" -BUILD_TARGET = "armv7a-none-eabi" - -# Travis CI need a different CC/AR alltogether as the aarch64-none-elf is not available there as it seems -[env.a64-travis] +RUSTFLAGS = "-C linker=${CC} -C target-cpu=cortex-a53" + +# AARCH64 specific pipeline CI env. variables. "aarch64-none-elf" is not available there as it seems +[env.pipeline] CC = "aarch64-linux-gnu-gcc" AR = "aarch64-linux-gnu-ar" -OC = "aarch64-linux-gnu-objcopy" CFLAGS = "-march=armv8-a -Wall -O3 -nostdlib -nostartfiles -ffreestanding -mtune=cortex-a53" -RUSTFLAGS = "-C linker=${CC} -C target-cpu=cortex-a53 -C link-arg=-nostartfiles" -BUILD_TARGET = "aarch64-unknown-linux-gnu" +RUSTFLAGS = "-C linker=${CC} -C target-cpu=cortex-a53" -[tasks.xbuild] +[tasks.build] command = "cargo" -args = ["xbuild", "--target", "${BUILD_TARGET}", "--release", "--features", "${FEATURES}"] +args = ["build", "--release", "--features", "${FEATURES}"] [tasks.pi3] env = { FEATURES = "ruspiro_pi3" } -run_task = [ - { name = "xbuild" } -] +run_task = "build" + +[tasks.clippy] +env = { FEATURES = "ruspiro_pi3" } +command = "cargo" +args = ["clippy", "--features", "${FEATURES}"] + +[tasks.doc] +env = { FEATURES = "ruspiro_pi3" } +command = "cargo" +args = ["doc", "--target", "aarch64-unknown-linux-gnu", "--open", "--features", "${FEATURES}"] [tasks.clean] command = "cargo" -args = ["clean"] \ No newline at end of file +args = ["clean"] + +[tasks.publish_dry] +env = { FEATURES = "ruspiro_pi3" } +command = "cargo" +args = ["publish", "--dry-run", "--features", "${FEATURES}"] + +[tasks.publish] +env = { FEATURES = "ruspiro_pi3" } +command = "cargo" +args = ["publish", "--token", "${CRATES_TOKEN}", "--allow-dirty", "--features", "${FEATURES}"] \ No newline at end of file diff --git a/README.md b/README.md index 9deeec2..4188b40 100644 --- a/README.md +++ b/README.md @@ -5,17 +5,18 @@ development to use a terminal console connected to the miniUART of the Raspberry while the program is executed on the device. Especialy if the program is in a state where there is no other output option and blinking LEDs are not sufficient. -[![Travis-CI Status](https://api.travis-ci.org/RusPiRo/ruspiro-uart.svg?branch=master)](https://travis-ci.org/RusPiRo/ruspiro-uart) +![CI](https://github.com/RusPiRo/ruspiro-uart/workflows/CI/badge.svg?branch=development) [![Latest Version](https://img.shields.io/crates/v/ruspiro-uart.svg)](https://crates.io/crates/ruspiro-uart) [![Documentation](https://docs.rs/ruspiro-uart/badge.svg)](https://docs.rs/ruspiro-uart) [![License](https://img.shields.io/crates/l/ruspiro-uart.svg)](https://github.com/RusPiRo/ruspiro-uart#license) ## Usage + To use the crate just add the following dependency to your ``Cargo.toml`` file: ```toml [dependencies] -ruspiro-uart = "0.3" +ruspiro-uart = "||VERSION||" ``` Once done the access to the UART abstraction is available in your rust files like so: @@ -35,28 +36,28 @@ In this example the Uart1 will be no longer be available once it goes out of sco to use it in a real world example. Therefore the proposed usage of the UART is to use it as a generic console output channel. To do so, please refer to the [ruspiro-console crate](https://crates.io/crates/ruspiro-console). But in case you would like to use the uart without the console abstraction it is recommended to wrap it into a singleton -to guaranty safe cross core access and only 1 time initialization. In the example we pass a fixed core clock rate to +to guaranty safe cross core access and only one-time initialization. In the example we pass a fixed core clock rate to the initialization function. However, the real core clock rate could be optained with a call to the mailbox property tag interface of the Raspberry Pi (see [ruspiro-mailbox](https://crates.io/crates/ruspiro-mailbox) for details.). This mailbox crate is not linked into the Uart crate to ensure usability of this crate with as less dependencies as possible. ```rust -use ruspiro_singleton::Singleton; // don't forget the dependency to be setup +use ruspiro_singleton::Singleton; use ruspiro_uart::Uart1; static UART: Singleton = Singleton::new(Uart1::new()); fn demo() { - let _ = UART.take_for(|uart| uart.initialize(250_000_000, 115_200)).expect("unable to init uart1"); + let _ = UART.with_mut(|uart| uart.initialize(250_000_000, 115_200)).expect("unable to init uart1"); print_something("Hello Uart..."); } fn print_something(s: &str) { - UART.take_for(|uart| uart.send_string(s)); + UART.with_ref(|uart| uart.send_string(s)); } ``` ## License -Licensed under Apache License, Version 2.0, ([LICENSE](LICENSE) or [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)) +Licensed under Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) or MIT ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)) at your choice. diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..96aec65 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "nightly-2021-09-05" +components = [ "rust-src", "llvm-tools-preview" ] +profile = "minimal" \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 801ee9c..020c83b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,9 +4,8 @@ * Author: André Borrmann * License: Apache License 2.0 **********************************************************************************************************************/ -#![doc(html_root_url = "https://docs.rs/ruspiro-uart/0.3.0")] +#![doc(html_root_url = "https://docs.rs/ruspiro-uart/||VERSION||")] #![no_std] -#![feature(llvm_asm)] //! # UART API for Raspberry Pi //! //! This crate provides access to the Uart0 (PL011) and the Uart1 (miniUART) peripheral of the Raspberry Pi. It is quite @@ -16,29 +15,30 @@ //! //! # Example //! -//! The proposed usage of the UART is to attach it to a generic console as an output channel instead of using it +//! The proposed usage of the UART is to attach it to a generic console as an output channel instead of using it //! directly. To do so, please refer to the [``ruspiro-console`` crate](https://crates.io/crates/ruspiro-console). //! -//! But in case you would like to use the uart without the console abstraction it is recommended to wrap it into a -//! singleton to guaranty safe cross core access and ensure only one time initialization. In the example we pass a -//! fixed core clock rate to the initialization function. However, the real core clock rate could be optained with a -//! call to the mailbox property tag interface of the Raspberry Pi (see [`ruspiro-mailbox` crate](https://crates.io/crates/ruspiro-mailbox) for details.). +//! But in case you would like to use the uart without the console abstraction it is recommended to wrap it into a +//! singleton to guaranty safe cross core access and ensure only one time initialization. In the example we pass a +//! fixed core clock rate to the initialization function. However, the real core clock rate could be optained with a +//! call to the mailbox property tag interface of the Raspberry Pi +//! (see [`ruspiro-mailbox` crate](https://crates.io/crates/ruspiro-mailbox) for details.). //! //! ```ignore -//! use ruspiro_singleton::Singleton; // don't forget the dependency to be setup in ``Cargo.toml`` +//! use ruspiro_singleton::Singleton; //! use ruspiro_uart::Uart1; //! //! static UART: Singleton = Singleton::new(Uart1::new()); //! //! fn main() { -//! let _ = UART.take_for(|uart| uart.initialize(250_000_000, 115_200)); +//! let _ = UART.with_mut(|uart| uart.initialize(250_000_000, 115_200)); //! // initialize(...) gives a [Result], you may want to panic if there is an Error returned. //! //! print_something("Hello Uart..."); //! } //! //! fn print_something(s: &str) { -//! UART.take_for(|uart| uart.send_string(s)); +//! UART.with_mut(|uart| uart.send_string(s)); //! } //! ``` diff --git a/src/uart0/interface.rs b/src/uart0/interface.rs index dd607c2..ec0577b 100644 --- a/src/uart0/interface.rs +++ b/src/uart0/interface.rs @@ -2,24 +2,25 @@ * Copyright (c) 2019 by the authors * * Author: André Borrmann - * License: Apache License 2.0 + * License: MIT / Apache License 2.0 **********************************************************************************************************************/ //! # Low-Level Uart0 interface implementation //! use ruspiro_gpio::GPIO; -use ruspiro_register::{define_mmio_register, RegisterFieldValue}; +use ruspiro_mmio_register::define_mmio_register; +use ruspiro_register::RegisterFieldValue; use ruspiro_timer as timer; use crate::UartResult; // Peripheral MMIO base address - depends on the right feature #[cfg(feature = "ruspiro_pi3")] -const PERIPHERAL_BASE: u32 = 0x3F00_0000; +const PERIPHERAL_BASE: usize = 0x3F00_0000; // UART0 MMIO base address -const UART0_BASE: u32 = PERIPHERAL_BASE + 0x0020_1000; +const UART0_BASE: usize = PERIPHERAL_BASE + 0x0020_1000; /// Initialize the Uart0 based on the given core rate and baud rate. /// For the time beeing the Uart0 will be bridged to the Raspberry Pi @@ -28,12 +29,12 @@ const UART0_BASE: u32 = PERIPHERAL_BASE + 0x0020_1000; /// Is there a way to do some compile time checks, that only valid pins /// are passed? pub(crate) fn init(clock_rate: u32, baud_rate: u32) -> UartResult<()> { - GPIO.take_for(|gpio| { + GPIO.with_mut(|gpio| { let _ = gpio.get_pin(32).map(|pin| pin.into_alt_f3()); let _ = gpio.get_pin(33).map(|pin| pin.into_alt_f3()); Ok(()) }) - .and_then(|_| { + .map(|_| { let baud16: u32 = baud_rate * 16; let int_div: u32 = clock_rate / baud16; let frac_div2 = (clock_rate % baud16) * 8 / baud_rate; @@ -61,14 +62,12 @@ pub(crate) fn init(clock_rate: u32, baud_rate: u32) -> UartResult<()> { | RegisterFieldValue::::new(UART0_IMSC::INT_RT, 0x1) | RegisterFieldValue::::new(UART0_IMSC::INT_OE, 0x1), ); - // UART0 is now ready to be used - Ok(()) }) } pub(crate) fn release() { - GPIO.take_for(|gpio| { + GPIO.with_mut(|gpio| { gpio.free_pin(32); gpio.free_pin(33); }); @@ -83,18 +82,13 @@ pub(crate) fn write_byte(data: u8) { } pub(crate) fn read_byte() -> Option { - /*if UART0_FR::Register.read(UART0_FR::RXFE) == 1 { - None - } else { - Some((UART0_DR::Register.get() & 0xFF) as u8) - }*/ while UART0_FR::Register.read(UART0_FR::RXFE) == 1 { timer::sleepcycles(10); } Some((UART0_DR::Register.get() & 0xFF) as u8) } -#[allow(dead_code, non_camel_case_types)] +#[allow(dead_code, non_camel_case_types, clippy::enum_variant_names)] enum Ifsel { Filled_1_8 = 0, Filled_1_4 = 1, @@ -158,7 +152,7 @@ define_mmio_register![ INT_RX OFFSET(4), // receive FiFo reached water mark INT_DSRM OFFSET(3), INT_DCDM OFFSET(2), - INT_CTSM OFFSET(1) + INT_CTSM OFFSET(1) }, UART0_RIS@(UART0_BASE + 0x3C)>, UART0_MIS@(UART0_BASE + 0x40)>, diff --git a/src/uart0/mod.rs b/src/uart0/mod.rs index b50ff8f..08cf103 100644 --- a/src/uart0/mod.rs +++ b/src/uart0/mod.rs @@ -2,7 +2,7 @@ * Copyright (c) 2019 by the authors * * Author: André Borrmann - * License: Apache License 2.0 + * License: MIT / Apache License 2.0 **********************************************************************************************************************/ //! # Uart0 (Pl011) API @@ -11,8 +11,6 @@ //! communication bridge to other peripherals like the buit in bluetooth low energy chip. //! -use ruspiro_console::*; - mod interface; /// Uart0 peripheral representation @@ -93,14 +91,10 @@ impl Drop for Uart0 { } } -/// to use the Uart0 as a console to output strings implement the respective trait -impl ConsoleImpl for Uart0 { - fn putc(&self, c: char) { - let data: [u8; 1] = [c as u8]; - self.write_data(&data); - } - - fn puts(&self, s: &str) { +impl core::fmt::Write for Uart0 { + fn write_str(&mut self, s: &str) -> core::fmt::Result { self.write_data(s.as_bytes()); + + Ok(()) } } diff --git a/src/uart1/interface.rs b/src/uart1/interface.rs index 0460318..5d64cf8 100644 --- a/src/uart1/interface.rs +++ b/src/uart1/interface.rs @@ -2,29 +2,30 @@ * Copyright (c) 2019 by the authors * * Author: André Borrmann - * License: Apache License 2.0 + * License: MIT / Apache License 2.0 **********************************************************************************************************************/ //! # Low-Level UART interface implementation //! use ruspiro_gpio::GPIO; -use ruspiro_register::{define_mmio_register, RegisterFieldValue}; +use ruspiro_mmio_register::define_mmio_register; +use ruspiro_register::RegisterFieldValue; use ruspiro_timer as timer; use crate::InterruptType; // Peripheral MMIO base address - depends on the right feature #[cfg(feature = "ruspiro_pi3")] -const PERIPHERAL_BASE: u32 = 0x3F00_0000; +const PERIPHERAL_BASE: usize = 0x3F00_0000; // AUX MMIO base address -const AUX_BASE: u32 = PERIPHERAL_BASE + 0x0021_5000; +const AUX_BASE: usize = PERIPHERAL_BASE + 0x0021_5000; // initialize the UART1 peripheral of the Raspberry Pi3. This will reserve 2 GPIO pins for UART1 usage. // Those pins actually are GPIO14 and 15. pub(crate) fn uart1_init(clock_rate: u32, baud_rate: u32) -> Result<(), &'static str> { - GPIO.take_for(|gpio| { + GPIO.with_mut(|gpio| { let tx = gpio .get_pin(14) .map(|pin| pin.into_alt_f5().into_pud_disabled()); @@ -59,7 +60,7 @@ pub(crate) fn uart1_init(clock_rate: u32, baud_rate: u32) -> Result<(), &'static // release the UART1 peripheral, this will also free the pins reserved for UART1 till now pub(crate) fn uart1_release() { - GPIO.take_for(|gpio| { + GPIO.with_mut(|gpio| { gpio.free_pin(14); gpio.free_pin(15); }); diff --git a/src/uart1/mod.rs b/src/uart1/mod.rs index 5511e74..4d2a47f 100644 --- a/src/uart1/mod.rs +++ b/src/uart1/mod.rs @@ -2,25 +2,25 @@ * Copyright (c) 2019 by the authors * * Author: André Borrmann - * License: Apache License 2.0 + * License: MIT / Apache License 2.0 **********************************************************************************************************************/ //! # Uart1 (miniUart) API //! -//! As per the Raspberry Pi peripheral document the miniUART is a lightweight serial communication channel that does only -//! need 3 wires (TX, RX, GND) to be connected to the device. The miniUART is typically used to connect the device to -//! a PC or Mac that runs a terminal console application and is able to display the characters received through this +//! As per the Raspberry Pi peripheral document the miniUART is a lightweight serial communication channel that does +//! only need 3 wires (TX, RX, GND) to be connected to the device. The miniUART is typically used to connect the device +//! to a PC or Mac that runs a terminal console application and is able to display the characters received through this //! channel. This allows to pass debug information from the device running the bare metal kernel to improve root cause //! analysis. //! //! There is no singleton accessor provided for this peripheral as it will be quite likely attached to a ``Console`` -//! abstraction that will than **own** this peripheral and should itself providing exclusive access to the inner accessor -//! of the actual device. Please refer to the [``ruspiro-console`` crate](https://crates.io/crates/ruspiro-console). +//! abstraction that will than **own** this peripheral and should itself providing exclusive access to the inner +//! accessor of the actual device. Please refer to the +//! [`ruspiro-console` crate](https://crates.io/crates/ruspiro-console). //! extern crate alloc; use crate::InterruptType; -use ruspiro_console::ConsoleImpl; mod interface; @@ -35,7 +35,7 @@ impl Uart1 { /// ```no_run /// # use ruspiro_uart::uart1::*; /// # fn doc() { - /// let _miniUart = Uart1::new(); + /// let uart = Uart1::new(); /// # } /// ``` pub const fn new() -> Self { @@ -274,13 +274,11 @@ impl Drop for Uart1 { } } -// to use the Uart1 as a console to output strings implement the respective trait -impl ConsoleImpl for Uart1 { - fn putc(&self, c: char) { - self.send_char(c); - } - - fn puts(&self, s: &str) { +// implement the `Write` trait to allow the uart to be used as console output device +impl core::fmt::Write for Uart1 { + fn write_str(&mut self, s: &str) -> core::fmt::Result { self.send_string(s); + + Ok(()) } }