Add minimal JTAG boot

pull/19/head
Andre Richter 5 years ago committed by Andre Richter
parent 36ab2efbd6
commit 8da8c0e33f

@ -0,0 +1,6 @@
[target.aarch64-unknown-none]
rustflags = [
"-C", "link-arg=-Tlink.ld",
"-C", "target-feature=-fp-armv8",
"-C", "target-cpu=cortex-a53",
]

@ -0,0 +1,57 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "cortex-a"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"register 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "jtag_boot"
version = "0.1.0"
dependencies = [
"cortex-a 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"raspi3_boot 0.1.0",
"register 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "panic-abort"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "r0"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "raspi3_boot"
version = "0.1.0"
dependencies = [
"cortex-a 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"panic-abort 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "register"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"tock-registers 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "tock-registers"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum cortex-a 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "12425c4491f31f28f539c74382ade69ee9db4f1f597aa177f43e072595562e46"
"checksum panic-abort 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c14a66511ed17b6a8b4256b868d7fd207836d891db15eea5195dbcaf87e630f"
"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f"
"checksum register 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a0f44a6dc9a98359515541a0c46ef4e3630a30879c1d7a4038f31dd533570bfb"
"checksum tock-registers 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c758f5195a2e0df9d9fecf6f506506b2766ff74cf64db1e995c87e2761a5c3e2"

@ -0,0 +1,13 @@
[package]
name = "jtag_boot"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
edition = "2018"
[dependencies]
raspi3_boot = { path = "raspi3_boot" }
cortex-a = "2.3.1"
register = "0.3.2"
[package.metadata.cargo-xbuild]
sysroot_path = "../xbuild_sysroot"

@ -0,0 +1,65 @@
#
# MIT License
#
# Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
#
# 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.
#
TARGET = aarch64-unknown-none
SOURCES = $(wildcard **/*.rs) $(wildcard **/*.S) link.ld
OBJCOPY = cargo objcopy --
OBJCOPY_PARAMS = --strip-all -O binary
UTILS_CONTAINER = andrerichter/raspi3-utils
DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work
DOCKER_TTY = --privileged -v /dev:/dev
QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel jtag_boot.img
RASPBOOT_CMD = raspbootcom /dev/ttyUSB0 jtag_boot.img
.PHONY: all qemu raspboot clippy clean objdump nm
all: clean jtag_boot.img
target/$(TARGET)/release/jtag_boot: $(SOURCES)
cargo xbuild --target=$(TARGET) --release
jtag_boot.img: target/$(TARGET)/release/jtag_boot
cp $< .
$(OBJCOPY) $(OBJCOPY_PARAMS) $< jtag_boot.img
qemu: all
$(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial null -serial stdio
raspboot: all
$(DOCKER_CMD) $(DOCKER_TTY) $(UTILS_CONTAINER) $(RASPBOOT_CMD)
clippy:
cargo xclippy --target=$(TARGET)
clean:
cargo clean
objdump:
cargo objdump --target $(TARGET) -- -disassemble -print-imm-hex jtag_boot
nm:
cargo nm --target $(TARGET) -- jtag_boot | sort

@ -0,0 +1,4 @@
# Xtra 1 - JTAG boot
Not much is happening here. The binary configures the RPi's GPIO pins for `JTAG`
mode and waits for a debugger to connect.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,55 @@
/*
* MIT License
*
* Copyright (c) 2018 Andre Richter <andre.o.richter@gmail.com>
*
* 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.
*/
ENTRY(_boot_cores);
SECTIONS
{
. = 0x80000;
.text :
{
KEEP(*(.text.boot)) *(.text .text.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
.data :
{
*(.data .data.*)
}
.bss ALIGN(8):
{
__bss_start = .;
*(.bss .bss.*)
*(COMMON)
__bss_end = .;
}
/DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
}

@ -0,0 +1,10 @@
[package]
name = "raspi3_boot"
version = "0.1.0"
authors = ["Andre Richter <andre.o.richter@gmail.com>"]
edition = "2018"
[dependencies]
cortex-a = "2.3.1"
panic-abort = "0.3.1"
r0 = "0.2.2"

@ -0,0 +1,90 @@
/*
* MIT License
*
* Copyright (c) 2018 Jorge Aparicio
* Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
*
* 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.
*/
#![deny(missing_docs)]
#![deny(warnings)]
#![no_std]
//! Low-level boot of the Raspberry's processor
extern crate panic_abort;
/// Type check the user-supplied entry function.
#[macro_export]
macro_rules! entry {
($path:path) => {
#[export_name = "main"]
pub unsafe fn __main() -> ! {
// type check the given path
let f: fn() -> ! = $path;
f()
}
};
}
/// Reset function.
///
/// Initializes the bss section before calling into the user's `main()`.
unsafe fn reset() -> ! {
extern "C" {
// Boundaries of the .bss section, provided by the linker script
static mut __bss_start: u64;
static mut __bss_end: u64;
}
// Zeroes the .bss section
r0::zero_bss(&mut __bss_start, &mut __bss_end);
extern "Rust" {
fn main() -> !;
}
main();
}
/// Entrypoint of the processor.
///
/// Parks all cores except core0, and then jumps to the internal
/// `reset()` function.
#[link_section = ".text.boot"]
#[no_mangle]
pub unsafe extern "C" fn _boot_cores() -> ! {
use cortex_a::{asm, regs::*};
const CORE_0: u64 = 0;
const CORE_MASK: u64 = 0x3;
const STACK_START: u64 = 0x80_000;
if CORE_0 == MPIDR_EL1.get() & CORE_MASK {
SP.set(STACK_START);
reset()
} else {
// if not core0, infinitely wait for events
loop {
asm::wfe();
}
}
}

@ -0,0 +1,166 @@
/*
* MIT License
*
* Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
* Copyright (c) 2019 Nao Taco <naotaco@gmail.com>
*
* 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.
*/
use core::ops;
use register::{mmio::ReadWrite, register_bitfields};
// Descriptions taken from
// https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf
register_bitfields! {
u32,
/// GPIO Function Select 1
GPFSEL1 [
/// Pin 15
FSEL15 OFFSET(15) NUMBITS(3) [
Input = 0b000,
Output = 0b001,
RXD0 = 0b100, // UART0 - Alternate function 0
RXD1 = 0b010 // Mini UART - Alternate function 5
],
/// Pin 14
FSEL14 OFFSET(12) NUMBITS(3) [
Input = 0b000,
Output = 0b001,
TXD0 = 0b100, // UART0 - Alternate function 0
TXD1 = 0b010 // Mini UART - Alternate function 5
]
],
/// GPIO Function Select 2
GPFSEL2 [
/// Pin 27
FSEL27 OFFSET(21) NUMBITS(3)[
Input = 0b000,
Output = 0b001,
ARM_TMS = 0b011 // JTAG TMS - Alternate function 4
],
/// Pin 26
FSEL26 OFFSET(18) NUMBITS(3)[
Input = 0b000,
Output = 0b001,
ARM_TDI = 0b011 // JTAG TDI - Alternate function 4
],
/// Pin 25
FSEL25 OFFSET(15) NUMBITS(3)[
Input = 0b000,
Output = 0b001,
ARM_TCK = 0b011 // JTAG TCK - Alternate function 4
],
/// Pin 24
FSEL24 OFFSET(12) NUMBITS(3)[ // GPIO24
Input = 0b000,
Output = 0b001,
ARM_TDO = 0b011 // JTAG TDO - Alternate function 4
],
/// Pin 23
FSEL23 OFFSET(9) NUMBITS(3)[
Input = 0b000,
Output = 0b001,
ARM_RTCK = 0b011 // JTAG RTCK - Alternate function 4
],
/// Pin 22
FSEL22 OFFSET(6) NUMBITS(3)[
Input = 0b000,
Output = 0b001,
ARM_TRST = 0b011 // JTAG TRST - Alternate function 4
]
],
/// GPIO Pull-up/down Clock Register 0
GPPUDCLK0 [
/// Pin 15
PUDCLK15 OFFSET(15) NUMBITS(1) [
NoEffect = 0,
AssertClock = 1
],
/// Pin 14
PUDCLK14 OFFSET(14) NUMBITS(1) [
NoEffect = 0,
AssertClock = 1
]
]
}
#[allow(non_snake_case)]
#[repr(C)]
pub struct RegisterBlock {
pub GPFSEL0: ReadWrite<u32>, // 0x00
pub GPFSEL1: ReadWrite<u32, GPFSEL1::Register>, // 0x04
pub GPFSEL2: ReadWrite<u32, GPFSEL2::Register>, // 0x08
pub GPFSEL3: ReadWrite<u32>, // 0x0C
pub GPFSEL4: ReadWrite<u32>, // 0x10
pub GPFSEL5: ReadWrite<u32>, // 0x14
__reserved_0: u32, // 0x18
GPSET0: ReadWrite<u32>, // 0x1C
GPSET1: ReadWrite<u32>, // 0x20
__reserved_1: u32, //
GPCLR0: ReadWrite<u32>, // 0x28
__reserved_2: [u32; 2], //
GPLEV0: ReadWrite<u32>, // 0x34
GPLEV1: ReadWrite<u32>, // 0x38
__reserved_3: u32, //
GPEDS0: ReadWrite<u32>, // 0x40
GPEDS1: ReadWrite<u32>, // 0x44
__reserved_4: [u32; 7], //
GPHEN0: ReadWrite<u32>, // 0x64
GPHEN1: ReadWrite<u32>, // 0x68
__reserved_5: [u32; 10], //
pub GPPUD: ReadWrite<u32>, // 0x94
pub GPPUDCLK0: ReadWrite<u32, GPPUDCLK0::Register>, // 0x98
pub GPPUDCLK1: ReadWrite<u32>, // 0x9C
}
/// Public interface to the GPIO MMIO area
pub struct GPIO {
base_addr: usize,
}
impl ops::Deref for GPIO {
type Target = RegisterBlock;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr() }
}
}
impl GPIO {
pub fn new(base_addr: usize) -> GPIO {
GPIO { base_addr }
}
/// Returns a pointer to the register block
fn ptr(&self) -> *const RegisterBlock {
self.base_addr as *const _
}
}

@ -0,0 +1,65 @@
/*
* MIT License
*
* Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
*
* 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.
*/
#![no_std]
#![no_main]
const MMIO_BASE: usize = 0x3F00_0000;
const GPIO_BASE: usize = MMIO_BASE + 0x0020_0000;
const MINI_UART_BASE: usize = MMIO_BASE + 0x0021_5000;
mod gpio;
mod mini_uart;
pub fn setup_jtag(gpio: &gpio::GPIO) {
gpio.GPFSEL2.modify(
gpio::GPFSEL2::FSEL27::ARM_TMS
+ gpio::GPFSEL2::FSEL26::ARM_TDI
+ gpio::GPFSEL2::FSEL25::ARM_TCK
+ gpio::GPFSEL2::FSEL24::ARM_TDO
+ gpio::GPFSEL2::FSEL23::ARM_RTCK
+ gpio::GPFSEL2::FSEL22::ARM_TRST,
);
}
fn kernel_entry() -> ! {
let gpio = gpio::GPIO::new(GPIO_BASE);
//------------------------------------------------------------
// Instantiate MiniUart
//------------------------------------------------------------
let mini_uart = mini_uart::MiniUart::new(MINI_UART_BASE);
mini_uart.init(&gpio);
//------------------------------------------------------------
// Configure JTAG pins
//------------------------------------------------------------
setup_jtag(&gpio);
mini_uart.puts("\n[i] JTAG is live. Please connect.\n");
loop {}
}
raspi3_boot::entry!(kernel_entry);

@ -0,0 +1,218 @@
/*
* MIT License
*
* Copyright (c) 2018-2019 Andre Richter <andre.o.richter@gmail.com>
*
* 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.
*/
use super::gpio;
use core::ops;
use cortex_a::asm;
use register::{mmio::*, register_bitfields};
/// Auxilary mini UART registers
//
// Descriptions taken from
// https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf
register_bitfields! {
u32,
/// Auxiliary enables
AUX_ENABLES [
/// If set the mini UART is enabled. The UART will immediately
/// start receiving data, especially if the UART1_RX line is
/// low.
/// If clear the mini UART is disabled. That also disables any
/// mini UART register access
MINI_UART_ENABLE OFFSET(0) NUMBITS(1) []
],
/// Mini Uart Interrupt Identify
AUX_MU_IIR [
/// Writing with bit 1 set will clear the receive FIFO
/// Writing with bit 2 set will clear the transmit FIFO
FIFO_CLEAR OFFSET(1) NUMBITS(2) [
Rx = 0b01,
Tx = 0b10,
All = 0b11
]
],
/// Mini Uart Line Control
AUX_MU_LCR [
/// Mode the UART works in
DATA_SIZE OFFSET(0) NUMBITS(2) [
SevenBit = 0b00,
EightBit = 0b11
]
],
/// Mini Uart Line Status
AUX_MU_LSR [
/// This bit is set if the transmit FIFO is empty and the transmitter is
/// idle. (Finished shifting out the last bit).
TX_IDLE OFFSET(6) NUMBITS(1) [],
/// This bit is set if the transmit FIFO can accept at least
/// one byte.
TX_EMPTY OFFSET(5) NUMBITS(1) [],
/// This bit is set if the receive FIFO holds at least 1
/// symbol.
DATA_READY OFFSET(0) NUMBITS(1) []
],
/// Mini Uart Extra Control
AUX_MU_CNTL [
/// If this bit is set the mini UART transmitter is enabled.
/// If this bit is clear the mini UART transmitter is disabled.
TX_EN OFFSET(1) NUMBITS(1) [
Disabled = 0,
Enabled = 1
],
/// If this bit is set the mini UART receiver is enabled.
/// If this bit is clear the mini UART receiver is disabled.
RX_EN OFFSET(0) NUMBITS(1) [
Disabled = 0,
Enabled = 1
]
],
/// Mini Uart Baudrate
AUX_MU_BAUD [
/// Mini UART baudrate counter
RATE OFFSET(0) NUMBITS(16) []
]
}
#[allow(non_snake_case)]
#[repr(C)]
pub struct RegisterBlock {
__reserved_0: u32, // 0x00
AUX_ENABLES: ReadWrite<u32, AUX_ENABLES::Register>, // 0x04
__reserved_1: [u32; 14], // 0x08
AUX_MU_IO: ReadWrite<u32>, // 0x40 - Mini Uart I/O Data
AUX_MU_IER: WriteOnly<u32>, // 0x44 - Mini Uart Interrupt Enable
AUX_MU_IIR: WriteOnly<u32, AUX_MU_IIR::Register>, // 0x48
AUX_MU_LCR: WriteOnly<u32, AUX_MU_LCR::Register>, // 0x4C
AUX_MU_MCR: WriteOnly<u32>, // 0x50
AUX_MU_LSR: ReadOnly<u32, AUX_MU_LSR::Register>, // 0x54
__reserved_2: [u32; 2], // 0x58
AUX_MU_CNTL: WriteOnly<u32, AUX_MU_CNTL::Register>, // 0x60
__reserved_3: u32, // 0x64
AUX_MU_BAUD: WriteOnly<u32, AUX_MU_BAUD::Register>, // 0x68
}
pub struct MiniUart {
base_addr: usize,
}
/// Deref to RegisterBlock
///
/// Allows writing
/// ```
/// self.MU_IER.read()
/// ```
/// instead of something along the lines of
/// ```
/// unsafe { (*MiniUart::ptr()).MU_IER.read() }
/// ```
impl ops::Deref for MiniUart {
type Target = RegisterBlock;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr() }
}
}
impl MiniUart {
pub fn new(base_addr: usize) -> MiniUart {
MiniUart { base_addr }
}
/// Returns a pointer to the register block
fn ptr(&self) -> *const RegisterBlock {
self.base_addr as *const _
}
///Set baud rate and characteristics (115200 8N1) and map to GPIO
pub fn init(&self, gpio: &gpio::GPIO) {
// initialize UART
self.AUX_ENABLES.modify(AUX_ENABLES::MINI_UART_ENABLE::SET);
self.AUX_MU_IER.set(0);
self.AUX_MU_CNTL.set(0);
self.AUX_MU_LCR.write(AUX_MU_LCR::DATA_SIZE::EightBit);
self.AUX_MU_MCR.set(0);
self.AUX_MU_IER.set(0);
self.AUX_MU_IIR.write(AUX_MU_IIR::FIFO_CLEAR::All);
self.AUX_MU_BAUD.write(AUX_MU_BAUD::RATE.val(270)); // 115200 baud
// map UART1 to GPIO pins
gpio.GPFSEL1
.modify(gpio::GPFSEL1::FSEL14::TXD1 + gpio::GPFSEL1::FSEL15::RXD1);
gpio.GPPUD.set(0); // enable pins 14 and 15
for _ in 0..150 {
asm::nop();
}
gpio.GPPUDCLK0
.write(gpio::GPPUDCLK0::PUDCLK14::AssertClock + gpio::GPPUDCLK0::PUDCLK15::AssertClock);
for _ in 0..150 {
asm::nop();
}
gpio.GPPUDCLK0.set(0);
self.AUX_MU_CNTL
.write(AUX_MU_CNTL::RX_EN::Enabled + AUX_MU_CNTL::TX_EN::Enabled);
// Clear FIFOs before using the device
self.AUX_MU_IIR.write(AUX_MU_IIR::FIFO_CLEAR::All);
}
/// Send a character
fn putc(&self, c: char) {
// wait until we can send
loop {
if self.AUX_MU_LSR.is_set(AUX_MU_LSR::TX_EMPTY) {
break;
}
asm::nop();
}
// write the character to the buffer
self.AUX_MU_IO.set(c as u32);
}
/// Display a string
pub fn puts(&self, string: &str) {
for c in string.chars() {
// convert newline to carrige return + newline
if c == '\n' {
self.putc('\r')
}
self.putc(c);
}
}
}
Loading…
Cancel
Save