From 255b77095b3443c8768c46495616ee05b5adf0f6 Mon Sep 17 00:00:00 2001 From: Chris Pardy Date: Tue, 30 Nov 2021 00:11:08 -0500 Subject: [PATCH] Initial Implementation --- .gitignore | 1 + Cargo.lock | 324 +++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 21 +++ build.rs | 14 ++ flash.py | 43 ++++++ memory.x.in | 44 ++++++ src/main.rs | 103 ++++++++++++++ src/passthrough.rs | 18 +++ 8 files changed, 568 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 build.rs create mode 100755 flash.py create mode 100644 memory.x.in create mode 100644 src/main.rs create mode 100644 src/passthrough.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..c34abc1 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,324 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aligned" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a785a543aea40f5e4e2e93bb2655d31bc21bb391fff65697150973e383f16bb" +dependencies = [ + "as-slice", +] + +[[package]] +name = "as-slice" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" +dependencies = [ + "generic-array 0.12.4", + "generic-array 0.13.3", + "generic-array 0.14.4", + "stable_deref_trait", +] + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version 0.2.3", +] + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "cast" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" +dependencies = [ + "rustc_version 0.4.0", +] + +[[package]] +name = "cortex-m" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9075300b07c6a56263b9b582c214d0ff037b00d45ec9fde1cc711490c56f1bb9" +dependencies = [ + "aligned", + "bare-metal", + "bitfield", + "cortex-m 0.7.3", + "volatile-register", +] + +[[package]] +name = "cortex-m" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ac919ef424449ec8c08d515590ce15d9262c0ca5f0da5b0c901e971a3b783b3" +dependencies = [ + "bare-metal", + "bitfield", + "embedded-hal", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "454f278bf469e2de0a4d22ea019d169d8944f86957c8207a39e3f66c32be2fc6" +dependencies = [ + "cortex-m-rt-macros", + "r0", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3aa52243e26f5922fa522b0814019e0c98fc567e2756d715dce7ad7a81f49" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cortex-m-semihosting" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bffa6c1454368a6aa4811ae60964c38e6996d397ff8095a8b9211b1c1f749bc" +dependencies = [ + "cortex-m 0.7.3", +] + +[[package]] +name = "embedded-hal" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e36cfb62ff156596c892272f3015ef952fe1525e85261fa3a7f327bd6b384ab9" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "generic-array" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" +dependencies = [ + "typenum", +] + +[[package]] +name = "generic-array" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.0.0", +] + +[[package]] +name = "nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" + +[[package]] +name = "proc-macro2" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r0" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver 1.0.4", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "syn" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "tiva-serial" +version = "0.1.0" +dependencies = [ + "cortex-m-rt", + "cortex-m-semihosting", + "embedded-hal", + "nb 1.0.0", + "tm4c123x-hal", +] + +[[package]] +name = "tm4c-hal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f805f472ac1ff0ca60d80c2e64e6621ca3f6b4043531bab2b80ce884cea8e9b" +dependencies = [ + "cast", + "cortex-m 0.6.7", + "embedded-hal", + "nb 1.0.0", +] + +[[package]] +name = "tm4c123x" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "097e7f60cc69f25d9bd189509c682b36057fd5f1519e6485b107aecca15c3e3f" +dependencies = [ + "bare-metal", + "cortex-m 0.6.7", + "vcell", +] + +[[package]] +name = "tm4c123x-hal" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc56eeb40b7b69264083ad913bdd10f5846bd3db2907f0123445b7136615a0b" +dependencies = [ + "cast", + "cortex-m 0.6.7", + "embedded-hal", + "nb 1.0.0", + "tm4c-hal", + "tm4c123x", + "void", +] + +[[package]] +name = "typenum" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" + +[[package]] +name = "unicode-xid" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "version_check" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" +dependencies = [ + "vcell", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..7eebf6d --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "tiva-serial" +version = "0.1.0" +authors = ["Chris Pardy "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[profile.release] +panic="abort" + +[profile.dev] +panic="abort" +debug=true + +[dependencies] +embedded-hal = "0.2" +tm4c123x-hal = "0.10" +cortex-m-rt = "0.6" +cortex-m-semihosting = "0.3.2" +nb = "1.0.0" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..2f23ac9 --- /dev/null +++ b/build.rs @@ -0,0 +1,14 @@ +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + + let memory_x = include_bytes!("memory.x.in"); + let mut f = File::create(out_dir.join("memory.x")).unwrap(); + f.write_all(memory_x).unwrap(); + + println!("cargo:rustc-link-search={}", out_dir.display()); +} diff --git a/flash.py b/flash.py new file mode 100755 index 0000000..7796f8c --- /dev/null +++ b/flash.py @@ -0,0 +1,43 @@ +#!/bin/python3 +import argparse +from genericpath import exists +import subprocess +import os + +def build(release): + cmd = ['cargo', 'build'] + if release: + cmd.append('--release') + subprocess.run(cmd) + +def flash(path): + if not os.path.exists(path): + raise f"binary {path} does not exist" + + subprocess.run(['sudo', 'lm4flash', path]) + +def make_bin(release): + release_path = 'release' if release else 'debug' + exe_name = 'tiva-serial' + exe_path = f"target/thumbv7em-none-eabihf/{release_path}/{exe_name}" + bin_path = exe_path + ".bin" + + if not os.path.exists(exe_path): + raise f"executable {exe_path} does not exist" + + subprocess.run(['arm-none-eabi-objcopy', '-O', 'binary', exe_path, bin_path]) + return bin_path + + +def main(): + parser = argparse.ArgumentParser(description='Create binary and flash it') + parser.add_argument('--release', default = False, action='store_true', help = 'specifies to flash the release binary') + args = parser.parse_args() + + build(args.release) + bin_path = make_bin(args.release) + print(bin_path) + flash(bin_path) + +if __name__ == "__main__": + main() diff --git a/memory.x.in b/memory.x.in new file mode 100644 index 0000000..ba16db3 --- /dev/null +++ b/memory.x.in @@ -0,0 +1,44 @@ +/* +* Copyright (c) 2012, Mauro Scomparin +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of Mauro Scomparin nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY Mauro Scomparin ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL Mauro Scomparin BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +* Author: Mauro Scomparin . +* Author: Jonathan Pallant . +* Description: Linker description file for LM4FXXX microcontrollers. +*/ + +/* +* Memory definition: +* FLASH: start point 0x00, lenght 0x40000. +* SRAM: start point 0x20000000 length 0x8000. +* VAR: enough to hold .data and .bss +* HEAP: All the remaining space, up to... +* STACK: start point 0x20007000 length 0x1000. +*/ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..959a908 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,103 @@ +#![no_std] +#![no_main] + +mod passthrough; +use passthrough::SerialForwarder; + +use core::panic::PanicInfo; +use cortex_m_rt::entry; +use tm4c123x_hal::{self as hal, prelude::*}; + +fn go() -> ! { + let p = hal::Peripherals::take().unwrap(); + + let mut sc = p.SYSCTL.constrain(); + sc.clock_setup.oscillator = hal::sysctl::Oscillator::Main( + hal::sysctl::CrystalFrequency::_16mhz, + hal::sysctl::SystemClock::UsePll(hal::sysctl::PllOutputFrequency::_80_00mhz), + ); + let clocks = sc.clock_setup.freeze(); + + let mut porta = p.GPIO_PORTA.split(&sc.power_control); + let mut portb = p.GPIO_PORTB.split(&sc.power_control); + let mut portc = p.GPIO_PORTC.split(&sc.power_control); + + // create uart objects + let uart0 = hal::serial::Serial::uart0( + p.UART0, + porta + .pa1 + .into_af_push_pull::(&mut porta.control), + porta + .pa0 + .into_af_push_pull::(&mut porta.control), + (), + (), + 115200_u32.bps(), + hal::serial::NewlineMode::SwapLFtoCRLF, + &clocks, + &sc.power_control, + ); + + let uart1 = hal::serial::Serial::uart1( + p.UART1, + portb + .pb1 + .into_af_push_pull::(&mut portb.control), + portb + .pb0 + .into_af_push_pull::(&mut portb.control), + (), + (), + 115200_u32.bps(), + hal::serial::NewlineMode::SwapLFtoCRLF, + &clocks, + &sc.power_control, + ); + + let uart4 = hal::serial::Serial::uart4( + p.UART4, + portc + .pc5 + .into_af_push_pull::(&mut portc.control), + portc + .pc4 + .into_af_push_pull::(&mut portc.control), + (), + (), + 115200_u32.bps(), + hal::serial::NewlineMode::SwapLFtoCRLF, + &clocks, + &sc.power_control, + ); + let mut chars = "Hello World!\r\n".chars().cycle(); + + let (uart0_tx, _uart0_rx) = uart0.split(); + let (mut uart1_tx, uart1_rx) = uart1.split(); + let (uart4_tx, uart4_rx) = uart4.split(); + let mut u1_to_u4 = SerialForwarder::new(uart1_rx, uart4_tx); + let mut u4_to_u0 = SerialForwarder::new(uart4_rx, uart0_tx); + + let mut c = chars.next().unwrap(); + loop { + match uart1_tx.write(c as u8) { + Ok(_) => { + c = chars.next().unwrap(); + } + Err(_) => {} + } + + u1_to_u4.poll_and_forward(); + u4_to_u0.poll_and_forward(); + } +} + +#[entry] +fn main() -> ! { + go() +} + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + loop {} +} diff --git a/src/passthrough.rs b/src/passthrough.rs new file mode 100644 index 0000000..b59d359 --- /dev/null +++ b/src/passthrough.rs @@ -0,0 +1,18 @@ +use embedded_hal::serial::{Read, Write}; +pub(crate) struct SerialForwarder, U: Write> { + src: T, + dest: U, +} + +impl, U: Write> SerialForwarder { + pub fn new(src: T, dest: U) -> Self { + return Self { src, dest }; + } + + pub fn poll_and_forward(&mut self) { + while let Ok(data) = self.src.read() { + // write may return Err if it would block because output fifo is full, just tight poll until write is complete + while let Err(_) = self.dest.write(data) {} + } + } +}