progress
This commit is contained in:
8
.gitignore
vendored
8
.gitignore
vendored
@@ -4,12 +4,4 @@
|
||||
Cargo.lock
|
||||
target/
|
||||
|
||||
# editor files
|
||||
.vscode/*
|
||||
!.vscode/*.md
|
||||
!.vscode/*.svd
|
||||
!.vscode/launch.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
.history/
|
||||
|
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
// https://github.com/rust-lang/vscode-rust/issues/729#issuecomment-635977755
|
||||
{
|
||||
"rust-analyzer.cargo.target": "thumbv7em-none-eabihf",
|
||||
"rust-analyzer.checkOnSave.allTargets": false
|
||||
}
|
@@ -24,6 +24,9 @@ panic-halt = "0.2.0"
|
||||
# features = ["stm32f303", "rt"]
|
||||
# version = "0.7.1"
|
||||
|
||||
[lib]
|
||||
path = "src/lib/mod.rs"
|
||||
|
||||
# this lets you use `cargo fix`!
|
||||
[[bin]]
|
||||
name = "test-cortex-m4-rust"
|
||||
|
BIN
new-main.bin
BIN
new-main.bin
Binary file not shown.
56
src/lib.rs
56
src/lib.rs
@@ -1,56 +0,0 @@
|
||||
#![no_std]
|
||||
|
||||
pub struct Board;
|
||||
|
||||
impl Board {
|
||||
pub fn setup_gpio_port(port: Port, options: PortSetup) -> PortIO {
|
||||
PortIO
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Port {
|
||||
A,
|
||||
F,
|
||||
}
|
||||
|
||||
pub struct PortSetup;
|
||||
|
||||
pub struct PortIO;
|
||||
|
||||
impl PortIO {
|
||||
pub fn setup_pin(pin: Pin, options: PinSetup) -> PinIO {
|
||||
PinIO
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Pin {
|
||||
Zero = 0,
|
||||
One = 1,
|
||||
Two = 2,
|
||||
Three = 3,
|
||||
Four = 4,
|
||||
Five = 5,
|
||||
Six = 6,
|
||||
Seven = 7,
|
||||
}
|
||||
|
||||
pub struct PinSetup;
|
||||
|
||||
pub struct PinIO;
|
||||
|
||||
impl PinIO {
|
||||
pub fn clear(&mut self) {
|
||||
todo!();
|
||||
}
|
||||
pub fn set(&mut self) {
|
||||
todo!();
|
||||
}
|
||||
pub fn toggle(&mut self) {
|
||||
todo!();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn setup_board() -> Board {
|
||||
Board
|
||||
}
|
83
src/lib/memory.rs
Normal file
83
src/lib/memory.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
//! Interact with memory
|
||||
|
||||
use core::ptr;
|
||||
|
||||
use crate::{Bit, L};
|
||||
|
||||
pub unsafe fn read(address: *mut u32) -> u32 {
|
||||
ptr::read_volatile(address)
|
||||
}
|
||||
pub unsafe fn write(address: *mut u32, new: u32) {
|
||||
ptr::write_volatile(address, new);
|
||||
}
|
||||
|
||||
pub unsafe fn update<Updater: Fn(u32) -> u32>(address: *mut u32, updater: Updater) {
|
||||
write(address, updater(read(address)));
|
||||
}
|
||||
|
||||
pub unsafe fn read_bits<const N: usize>(address: *mut u32, bits: &[u32; N]) -> [bool; N] {
|
||||
let current = read(address);
|
||||
let mut result = [L; N];
|
||||
|
||||
// TODO: look up accumulate or reduce or something
|
||||
for (i, bit) in bits.iter().enumerate() {
|
||||
result[i] = (current & (1 << bit)) != 0;
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
pub unsafe fn write_bits<const N: usize>(address: *mut u32, bits: &[u32; N], values: [bool; N]) {
|
||||
update(address, |current| {
|
||||
let mut new = current;
|
||||
// TODO: look up accumulate or reduce or something
|
||||
for (bit, set) in bits.iter().zip(values) {
|
||||
if set {
|
||||
new |= (1 << bit);
|
||||
} else {
|
||||
new &= !(1 << bit);
|
||||
}
|
||||
}
|
||||
new
|
||||
})
|
||||
}
|
||||
|
||||
pub unsafe fn update_bits<const N: usize, Updater: Fn([bool; N]) -> [bool; N]>(address: *mut u32, bits: &[Bit; N], updater: Updater) {
|
||||
write_bits(address, bits, updater(read_bits(address, bits)))
|
||||
}
|
||||
|
||||
pub unsafe fn set_bits(address: *mut u32, bits: &[Bit]) {
|
||||
update(address, |current| {
|
||||
let mut new = current;
|
||||
|
||||
// TODO: look up accumulate or reduce or something
|
||||
for bit in bits {
|
||||
new |= (1 << bit);
|
||||
}
|
||||
|
||||
new
|
||||
})
|
||||
}
|
||||
pub unsafe fn clear_bits(address: *mut u32, bits: &[Bit]) {
|
||||
update(address, |current| {
|
||||
let mut new = current;
|
||||
|
||||
// TODO: look up accumulate or reduce or something
|
||||
for bit in bits {
|
||||
new &= !(1 << bit);
|
||||
}
|
||||
|
||||
new
|
||||
})
|
||||
}
|
||||
pub unsafe fn toggle_bits(address: *mut u32, bits: &[Bit]) {
|
||||
update(address, |current| {
|
||||
let mut new = current;
|
||||
|
||||
// TODO: look up accumulate or reduce or something
|
||||
for bit in bits {
|
||||
new ^= (1 << bit);
|
||||
}
|
||||
|
||||
new
|
||||
})
|
||||
}
|
343
src/lib/mod.rs
Normal file
343
src/lib/mod.rs
Normal file
@@ -0,0 +1,343 @@
|
||||
#![no_std]
|
||||
|
||||
mod memory;
|
||||
mod registers;
|
||||
|
||||
pub const H: bool = true;
|
||||
pub const L: bool = false;
|
||||
|
||||
pub struct Board;
|
||||
// TODO: check page 704 for timers
|
||||
// TODO: impl Drop trait so that tasks all run before the main function ends?
|
||||
|
||||
impl Board {
|
||||
pub fn setup_gpio_port(&self, port: Port, options: PortSetup) -> PortIO {
|
||||
let port_io = PortIO { port };
|
||||
|
||||
unsafe {
|
||||
memory::set_bits(registers::system::RCGCGPIO, &[port_io.run_mode_clock_gate_control()]);
|
||||
}
|
||||
|
||||
port_io
|
||||
}
|
||||
}
|
||||
|
||||
// Page 684 of the data sheet for how the lock mechanism works
|
||||
const UNLOCK: u32 = 0x4C4F434B;
|
||||
|
||||
pub enum Port {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
F,
|
||||
}
|
||||
|
||||
pub struct PortSetup;
|
||||
|
||||
pub struct PortIO {
|
||||
port: Port,
|
||||
}
|
||||
|
||||
impl PortIO {
|
||||
/// The memory address of the analog mode select (AMSEL) register for this port
|
||||
fn analog_mode_select(&self) -> *mut u32 {
|
||||
match self.port {
|
||||
Port::A => registers::gpio::amsel::PORT_A,
|
||||
Port::F => registers::gpio::amsel::PORT_F,
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// The memory address of the commit (CR register for this port
|
||||
fn commit(&self) -> *mut u32 {
|
||||
match self.port {
|
||||
Port::A => registers::gpio::cr::PORT_A,
|
||||
Port::F => registers::gpio::cr::PORT_F,
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// The memory address of the data (DATA) register for this port
|
||||
fn data(&self) -> *mut u32 {
|
||||
match self.port {
|
||||
Port::A => registers::gpio::data::PORT_A,
|
||||
Port::F => registers::gpio::data::PORT_F,
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// The memory address of the direction (DIR) register for this port
|
||||
fn direction(&self) -> *mut u32 {
|
||||
match self.port {
|
||||
Port::A => registers::gpio::dir::PORT_A,
|
||||
Port::F => registers::gpio::dir::PORT_F,
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// The memory address of the lock (LOCK) register
|
||||
fn lock(&self) -> *mut u32 {
|
||||
match self.port {
|
||||
Port::A => registers::gpio::lock::PORT_A,
|
||||
Port::F => registers::gpio::lock::PORT_F,
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// The memory address of the port control (PCTL) register for this port
|
||||
fn port_control(&self) -> *mut u32 {
|
||||
match self.port {
|
||||
Port::A => registers::gpio::pctl::PORT_A,
|
||||
Port::F => registers::gpio::pctl::PORT_F,
|
||||
_ => todo!(),
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// The memory address of the pull-down resistor select (PDR) register for this port
|
||||
fn pull_down_select(&self) -> *mut u32 {
|
||||
match self.port {
|
||||
Port::A => registers::gpio::pdr::PORT_A,
|
||||
Port::F => registers::gpio::pdr::PORT_F,
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
/// The memory address of the pull-up resistor select (PUR) register for this port
|
||||
fn pull_up_select(&self) -> *mut u32 {
|
||||
match self.port {
|
||||
Port::A => registers::gpio::pur::PORT_A,
|
||||
Port::F => registers::gpio::pur::PORT_F,
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
// Note to self: page 1351 of data sheet for PWM
|
||||
// Apparently also for ADC!
|
||||
}
|
||||
|
||||
|
||||
impl PortIO {
|
||||
/// The corresponding bit for this port in system's run-mode clock gate control (RCGC) register
|
||||
fn run_mode_clock_gate_control(&self) -> Bit {
|
||||
match self.port {
|
||||
Port::A => Bit::Zero,
|
||||
Port::B => Bit::One,
|
||||
Port::C => Bit::Two,
|
||||
Port::D => Bit::Three,
|
||||
Port::E => Bit::Four,
|
||||
Port::F => Bit::Five,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PortIO {
|
||||
pub fn setup_readable_pins<const N: usize>(
|
||||
&self,
|
||||
bits: &[Bit; N],
|
||||
options: ReadablePinSetup,
|
||||
) -> ReadablePins<N> {
|
||||
// Unlock the pins
|
||||
unsafe {
|
||||
memory::write(self.lock(), UNLOCK);
|
||||
|
||||
memory::set_bits(self.commit(), bits);
|
||||
}
|
||||
|
||||
// Disable analog when it's not selected (and enable analog if it is)
|
||||
match options.function {
|
||||
Function::Analog => unsafe {
|
||||
memory::set_bits(self.analog_mode_select(), bits);
|
||||
},
|
||||
_ => unsafe {
|
||||
memory::clear_bits(self.analog_mode_select(), bits);
|
||||
},
|
||||
}
|
||||
|
||||
unsafe {
|
||||
memory::clear_bits(self.direction(), bits);
|
||||
}
|
||||
|
||||
// TODO: finish
|
||||
|
||||
let data_address = self.data();
|
||||
|
||||
let pins: [ReadablePin; N] = bits.map(|bit| ReadablePin { data_address, bit });
|
||||
|
||||
ReadablePins { data_address, pins }
|
||||
}
|
||||
|
||||
pub fn setup_writable_pins<const N: usize>(
|
||||
&self,
|
||||
bits: &[Bit; N],
|
||||
options: WritablePinSetup,
|
||||
) -> WritablePins<N> {
|
||||
// Unlock the pins
|
||||
unsafe {
|
||||
memory::write(self.lock(), UNLOCK);
|
||||
|
||||
memory::set_bits(self.commit(), bits);
|
||||
}
|
||||
|
||||
// Disable analog when it's not selected (and enable analog if it is)
|
||||
match options.function {
|
||||
Function::Analog => unsafe {
|
||||
memory::set_bits(self.analog_mode_select(), bits);
|
||||
},
|
||||
_ => unsafe {
|
||||
memory::clear_bits(self.analog_mode_select(), bits);
|
||||
},
|
||||
}
|
||||
|
||||
unsafe {
|
||||
memory::set_bits(self.direction(), bits);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
for bit in bits {
|
||||
let memory_bits = [0; N];
|
||||
let values = match options.function {
|
||||
Function::Analog => todo!(),
|
||||
Function::Digital => todo!(),
|
||||
Function::CAN => todo!(),
|
||||
Function::I2C => todo!(),
|
||||
Function::PWM => todo!(),
|
||||
Function::UART => todo!(),
|
||||
};
|
||||
memory::write_bits(self.port_control(), memory_bits, values);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: check page 671 or 682 (+ more prob) for a table showing initial pin states
|
||||
|
||||
// TODO: finish
|
||||
|
||||
let data_address = self.data();
|
||||
|
||||
let pins: [WritablePin; N] = bits.map(|bit| WritablePin { data_address, bit });
|
||||
|
||||
WritablePins { data_address, pins }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Bit {
|
||||
Zero = 0,
|
||||
One = 1,
|
||||
Two = 2,
|
||||
Three = 3,
|
||||
Four = 4,
|
||||
Five = 5,
|
||||
Six = 6,
|
||||
Seven = 7,
|
||||
}
|
||||
|
||||
/// Page 1351 of data sheet
|
||||
pub enum Function {
|
||||
Analog,
|
||||
Digital,
|
||||
CAN,
|
||||
I2C,
|
||||
PWM,
|
||||
UART,
|
||||
}
|
||||
|
||||
pub struct ReadablePinSetup {
|
||||
pub function: Function,
|
||||
}
|
||||
pub struct ReadablePins<const N: usize> {
|
||||
data_address: *mut u32,
|
||||
pins: [ReadablePin; N],
|
||||
}
|
||||
impl<const N: usize> ReadablePins<N> {
|
||||
pub fn pins(&self) -> [ReadablePin; N] {
|
||||
self.pins
|
||||
}
|
||||
|
||||
pub fn read_all(&self) -> [bool; N] {
|
||||
unsafe { memory::read_bits(self.data_address, &self.pins.map(|pin| pin.bit)) }
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ReadablePin {
|
||||
data_address: *mut u32,
|
||||
bit: Bit,
|
||||
}
|
||||
impl ReadablePin {
|
||||
pub fn read(&self) -> bool {
|
||||
let current = unsafe { memory::read(self.data_address) };
|
||||
current & (1 << self.bit as u32) != 0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WritablePinSetup {
|
||||
pub function: Function,
|
||||
}
|
||||
pub struct WritablePins<const N: usize> {
|
||||
data_address: *mut u32,
|
||||
pins: [WritablePin; N],
|
||||
}
|
||||
impl<const N: usize> WritablePins<N> {
|
||||
pub fn pins(&self) -> [WritablePin; N] {
|
||||
self.pins
|
||||
}
|
||||
|
||||
pub fn read_all(&self) -> [bool; N] {
|
||||
unsafe { memory::read_bits(self.data_address, &self.pins.map(|pin| pin.bit)) }
|
||||
}
|
||||
pub fn write_all(&mut self, values: [bool; N]) {
|
||||
unsafe { memory::write_bits(self.data_address, &self.pins.map(|pin| pin.bit), values) }
|
||||
}
|
||||
pub fn update_all<Updater: Fn([bool; N]) -> [bool; N]>(&mut self, updater: Updater) {
|
||||
self.write_all(updater(self.read_all()));
|
||||
}
|
||||
|
||||
pub fn clear_all(&mut self) {
|
||||
unsafe {
|
||||
memory::clear_bits(self.data_address, &self.pins.map(|pin| pin.bit));
|
||||
}
|
||||
}
|
||||
pub fn set_all(&mut self) {
|
||||
unsafe {
|
||||
memory::set_bits(self.data_address, &self.pins.map(|pin| pin.bit));
|
||||
}
|
||||
}
|
||||
pub fn toggle_all(&mut self) {
|
||||
unsafe {
|
||||
memory::toggle_bits(self.data_address, &self.pins.map(|pin| pin.bit));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct WritablePin {
|
||||
data_address: *mut u32,
|
||||
bit: Bit,
|
||||
}
|
||||
impl WritablePin {
|
||||
pub fn read(&self) -> bool {
|
||||
let current = unsafe { memory::read(self.data_address) };
|
||||
current & (1 << self.bit as u32) != 0
|
||||
}
|
||||
pub fn clear(&mut self) {
|
||||
unsafe {
|
||||
memory::clear_bits(self.data_address, &[self.bit]);
|
||||
}
|
||||
}
|
||||
pub fn set(&mut self) {
|
||||
unsafe {
|
||||
memory::set_bits(self.data_address, &[self.bit]);
|
||||
}
|
||||
}
|
||||
pub fn toggle(&mut self) {
|
||||
unsafe {
|
||||
memory::toggle_bits(self.data_address, &[self.bit]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup_board() -> Board {
|
||||
Board
|
||||
}
|
106
src/lib/registers.rs
Normal file
106
src/lib/registers.rs
Normal file
@@ -0,0 +1,106 @@
|
||||
//! Memory addresses of registers
|
||||
//! Data sheet: https://www.ti.com/lit/ds/spms376e/spms376e.pdf
|
||||
|
||||
// TODO: check page 92-94 for more features ("Memory Map" table)!
|
||||
|
||||
// TODO: check page 1230 onward for PWM
|
||||
|
||||
/// Modeled after page 660 of data sheet (GPIO Register Map)
|
||||
pub mod gpio {
|
||||
mod base {
|
||||
pub const PORT_A: u32 = 0x4000_4000;
|
||||
pub const PORT_F: u32 = 0x4002_5000;
|
||||
}
|
||||
|
||||
/// Page 671 of data sheet
|
||||
pub mod afsel {
|
||||
const OFFSET: u32 = 0x420;
|
||||
|
||||
pub const PORT_A: *mut u32 = (super::base::PORT_A + OFFSET) as *mut u32;
|
||||
pub const PORT_F: *mut u32 = (super::base::PORT_F + OFFSET) as *mut u32;
|
||||
}
|
||||
|
||||
/// Page 687 of data sheet
|
||||
pub mod amsel {
|
||||
const OFFSET: u32 = 0x52C;
|
||||
|
||||
pub const PORT_A: *mut u32 = (super::base::PORT_A + OFFSET) as *mut u32;
|
||||
pub const PORT_F: *mut u32 = (super::base::PORT_F + OFFSET) as *mut u32;
|
||||
}
|
||||
|
||||
/// Page 685 of data sheet
|
||||
pub mod cr {
|
||||
const OFFSET: u32 = 0x524;
|
||||
|
||||
pub const PORT_A: *mut u32 = (super::base::PORT_A + OFFSET) as *mut u32;
|
||||
pub const PORT_F: *mut u32 = (super::base::PORT_F + OFFSET) as *mut u32;
|
||||
}
|
||||
|
||||
/// Page 662 of data sheet
|
||||
pub mod data {
|
||||
const OFFSET: u32 = 0x000;
|
||||
|
||||
pub const PORT_A: *mut u32 = (super::base::PORT_A + OFFSET) as *mut u32;
|
||||
pub const PORT_F: *mut u32 = (super::base::PORT_F + OFFSET) as *mut u32;
|
||||
}
|
||||
|
||||
/// Page 682 of data sheet
|
||||
pub mod den {
|
||||
const OFFSET: u32 = 0x51C;
|
||||
|
||||
pub const PORT_A: *mut u32 = (super::base::PORT_A + OFFSET) as *mut u32;
|
||||
pub const PORT_F: *mut u32 = (super::base::PORT_F + OFFSET) as *mut u32;
|
||||
}
|
||||
|
||||
/// Page 663 of data sheet
|
||||
pub mod dir {
|
||||
const OFFSET: u32 = 0x400;
|
||||
|
||||
pub const PORT_A: *mut u32 = (super::base::PORT_A + OFFSET) as *mut u32;
|
||||
pub const PORT_F: *mut u32 = (super::base::PORT_F + OFFSET) as *mut u32;
|
||||
}
|
||||
|
||||
/// Page 684 of data sheet
|
||||
pub mod lock {
|
||||
const OFFSET: u32 = 0x520;
|
||||
|
||||
pub const PORT_A: *mut u32 = (super::base::PORT_A + OFFSET) as *mut u32;
|
||||
pub const PORT_F: *mut u32 = (super::base::PORT_F + OFFSET) as *mut u32;
|
||||
}
|
||||
|
||||
/// Page 688 of data sheet
|
||||
pub mod pctl {
|
||||
const OFFSET: u32 = 0x52C;
|
||||
|
||||
pub const PORT_A: *mut u32 = (super::base::PORT_A + OFFSET) as *mut u32;
|
||||
pub const PORT_F: *mut u32 = (super::base::PORT_F + OFFSET) as *mut u32;
|
||||
}
|
||||
|
||||
/// Page 679 of data sheet
|
||||
pub mod pdr {
|
||||
const OFFSET: u32 = 0x514;
|
||||
|
||||
pub const PORT_A: *mut u32 = (super::base::PORT_A + OFFSET) as *mut u32;
|
||||
pub const PORT_F: *mut u32 = (super::base::PORT_F + OFFSET) as *mut u32;
|
||||
}
|
||||
|
||||
/// Page 677 of data sheet
|
||||
pub mod pur {
|
||||
const OFFSET: u32 = 0x510;
|
||||
|
||||
pub const PORT_A: *mut u32 = (super::base::PORT_A + OFFSET) as *mut u32;
|
||||
pub const PORT_F: *mut u32 = (super::base::PORT_F + OFFSET) as *mut u32;
|
||||
}
|
||||
|
||||
// TODO: examine page 670 for when (if) I do interrupts
|
||||
}
|
||||
|
||||
// TODO: examine page 690 (ADC) for applicability
|
||||
|
||||
/// Page 231 of data sheet
|
||||
pub mod system {
|
||||
const BASE: u32 = 0x400F_E000;
|
||||
|
||||
// TODO: page 340
|
||||
pub const RCGCGPIO: *mut u32 = (BASE + 0x608) as *mut u32;
|
||||
}
|
72
src/main.rs
72
src/main.rs
@@ -6,6 +6,8 @@ use core::ptr;
|
||||
use panic_halt as _; // you can put a breakpoint on `rust_begin_unwind` to catch panics
|
||||
|
||||
use cortex_m_rt::entry;
|
||||
use test_cortex_m4_rust::{Function, Bit, ReadablePinSetup, WritablePinSetup, PortSetup, Port, setup_board, H, L};
|
||||
// use test_cortex_m4_rust::setup_board;
|
||||
|
||||
// Begin .h file contents
|
||||
|
||||
@@ -15,9 +17,9 @@ const GPIO_PORTF_DIR_R: *mut u32 = 0x40025400 as *mut u32;
|
||||
const GPIO_PORTF_AFSEL_R: *mut u32 = 0x40025420 as *mut u32;
|
||||
const GPIO_PORTF_PUR_R: *mut u32 = 0x40025510 as *mut u32;
|
||||
const GPIO_PORTF_DEN_R: *mut u32 = 0x4002551C as *mut u32;
|
||||
const GPIO_PORTF_LOCK_R: *mut u32 = 0x40025520 as *mut u32;
|
||||
const GPIO_PORTF_CR_R: *mut u32 = 0x40025524 as *mut u32;
|
||||
const GPIO_PORTF_AMSEL_R: *mut u32 = 0x40025528 as *mut u32;
|
||||
const GPIOLOCK_PORT_F: *mut u32 = 0x40025520 as *mut u32;
|
||||
const GPIOCR_PORT_F: *mut u32 = 0x40025524 as *mut u32;
|
||||
const GPIOAMSEL_PORT_F: *mut u32 = 0x40025528 as *mut u32;
|
||||
const GPIO_PORTF_PCTL_R: *mut u32 = 0x4002552C as *mut u32;
|
||||
|
||||
const SYSCTL_RCGCPIO_R: *mut u32 = 0x400FE608 as *mut u32;
|
||||
@@ -41,26 +43,26 @@ const BLUE: u8 = 0b0000_0100;
|
||||
|
||||
fn setup_port_f() {
|
||||
// 1) activate clock for Port F
|
||||
unsafe {
|
||||
ptr::write_volatile(
|
||||
SYSCTL_RCGCPIO_R,
|
||||
ptr::read_volatile(SYSCTL_RCGCPIO_R) | 0x00_00_00_20,
|
||||
);
|
||||
}
|
||||
// unsafe {
|
||||
// ptr::write_volatile(
|
||||
// SYSCTL_RCGCPIO_R,
|
||||
// ptr::read_volatile(SYSCTL_RCGCPIO_R) | 0x00_00_00_20,
|
||||
// );
|
||||
// }
|
||||
|
||||
// Delay
|
||||
for _ in 0u8..2u8 {}
|
||||
// for _ in 0u8..2u8 {}
|
||||
|
||||
// 2) unlock GPIO Port F
|
||||
unsafe {
|
||||
ptr::write_volatile(GPIO_PORTF_LOCK_R, 0x4C4F434B);
|
||||
// allow changes to PF4-0
|
||||
// only PF0 needs to be unlocked, other bits can't be locked
|
||||
ptr::write_volatile(GPIO_PORTF_CR_R, 0b0001_1111);
|
||||
}
|
||||
// unsafe {
|
||||
// ptr::write_volatile(GPIOLOCK_PORT_F, 0x4C4F434B);
|
||||
// // allow changes to PF4-0
|
||||
// // only PF0 needs to be unlocked, other bits can't be locked
|
||||
// ptr::write_volatile(GPIOCR_PORT_F, 0b0001_1111);
|
||||
// }
|
||||
|
||||
// 3) disable analog on PF
|
||||
unsafe { ptr::write_volatile(GPIO_PORTF_AMSEL_R, 0x00) }
|
||||
// unsafe { ptr::write_volatile(GPIOAMSEL_PORT_F, 0x00) }
|
||||
|
||||
// 4) PCTL GPIO on PF4-0
|
||||
unsafe {
|
||||
@@ -68,9 +70,9 @@ fn setup_port_f() {
|
||||
}
|
||||
|
||||
// 5) PF4,PF0 in, PF3-1 out
|
||||
unsafe {
|
||||
ptr::write_volatile(GPIO_PORTF_DIR_R, 0x0E);
|
||||
}
|
||||
// unsafe {
|
||||
// ptr::write_volatile(GPIO_PORTF_DIR_R, 0x0E);
|
||||
// }
|
||||
// 6) disable alt funct on PF7-0
|
||||
unsafe {
|
||||
ptr::write_volatile(GPIO_PORTF_AFSEL_R, 0x00);
|
||||
@@ -97,6 +99,26 @@ fn output_to_port_f(value: u8) {
|
||||
}
|
||||
}
|
||||
|
||||
// #[entry]
|
||||
// fn main() -> ! {
|
||||
// let board = setup_board();
|
||||
// let port_f = board.setup_gpio_port(Port::F, PortSetup);
|
||||
|
||||
// let switches = port_f.setup_readable_pins([Bit::Zero, Bit::Four], ReadablePinSetup);
|
||||
// let [sw1, sw2] = switches.pins();
|
||||
|
||||
// let mut rgb_led = port_f.setup_writable_pins(&[Bit::One, Bit::Three, Bit::Two], WritablePinSetup { drive: PinDrive::Digital });
|
||||
|
||||
// loop {
|
||||
// match switches.read_all() {
|
||||
// [L, L] => rgb_led.write_all([L, H, L]),
|
||||
// [L, H] => rgb_led.write_all([L, L, H]),
|
||||
// [H, L] => rgb_led.write_all([L, H, L]),
|
||||
// [H, H] => rgb_led.write_all([L, L, L]),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
#[entry]
|
||||
fn main() -> ! {
|
||||
setup_port_f();
|
||||
@@ -105,12 +127,14 @@ fn main() -> ! {
|
||||
let status = input_from_port_f();
|
||||
|
||||
match status {
|
||||
0x01 => output_to_port_f(BLUE),
|
||||
0x10 => output_to_port_f(RED),
|
||||
0x00 => output_to_port_f(GREEN),
|
||||
0x00 => output_to_port_f(RED | GREEN),
|
||||
0x01 => output_to_port_f(RED),
|
||||
0x10 => output_to_port_f(GREEN),
|
||||
0x11 => output_to_port_f(BLACK),
|
||||
// Impossible case
|
||||
_ => output_to_port_f(RED | BLUE),
|
||||
_ => output_to_port_f(BLUE),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: implement an extremely simple example of the task system (using a timer trigger) that is a traffic light (green -> yellow -> red -> green...)
|
||||
|
Reference in New Issue
Block a user