Skip to content
This repository has been archived by the owner on Jul 6, 2019. It is now read-only.

Commit

Permalink
Basic timers are now working. app_blink works!
Browse files Browse the repository at this point in the history
  • Loading branch information
simias committed Oct 22, 2014
1 parent a0529ce commit 0449066
Show file tree
Hide file tree
Showing 9 changed files with 363 additions and 43 deletions.
27 changes: 24 additions & 3 deletions apps/app_blink_tm4c123gh6pm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,18 @@ platformtree!(

gpio {
PortF {
led1@1 { direction = "out"; }
led2@2 { direction = "out"; }
led1@2 { direction = "out"; }
led2@3 { direction = "out"; }
}
}

timer {
/* The mcu contain both 16/32bit and "wide" 32/64bit timers. */
timer@w0 {
/* prescale sysclk to 1Mhz since the wait code expects 1us
* granularity */
prescale = 16;
mode = "periodic";
}
}
}
Expand All @@ -26,6 +36,7 @@ platformtree!(
single_task {
loop = "run";
args {
timer = &timer;
led1 = &led1;
led2 = &led2;
}
Expand All @@ -35,8 +46,18 @@ platformtree!(

#[no_split_stack]
pub fn run(args: &pt::run_args) {
use zinc::hal::pin::GPIO;
use zinc::hal::pin::GPIO;
use zinc::hal::timer::Timer;

loop {
args.led1.set_high();
args.led2.set_low();

args.timer.wait(1);

args.led1.set_low();
args.led2.set_high();

args.timer.wait(1);
}
}
5 changes: 5 additions & 0 deletions src/platformtree/platformtree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@
#![experimental]
#![feature(quote)]
#![feature(phase)]
#![crate_name="platformtree"]
#![crate_type="rlib"]

#[phase(plugin)]

extern crate regex_macros;
extern crate regex;
extern crate syntax;
#[cfg(test)] extern crate hamcrest;

Expand Down
1 change: 1 addition & 0 deletions src/zinc/hal/tm4c123gh6pm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
pub mod io;
pub mod sysctl;
pub mod pin;
pub mod timer;

#[path="../../util/ioreg.rs"] mod util;
50 changes: 22 additions & 28 deletions src/zinc/hal/tm4c123gh6pm/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use hal::tm4c123gh6pm::sysctl;
use hal::tm4c123gh6pm::io::Reg;

/// The pins are accessed through ports. Each port has 8 pins and are identified
/// by a letter (PortA, PortB, etc...)
/// by a letter (PortA, PortB, etc...).
#[allow(missing_doc)]
pub enum PortID {
PortA,
Expand All @@ -18,16 +18,10 @@ pub enum PortID {
PortF,
}

/// Structure describing a single GPIO port. Each port contains 8 pins.
struct Port {
/// Base address of the port
base: u32,
}

/// Structure describing a single HW pin
pub struct Pin {
/// Port containing this pin
port: Port,
/// Base address for the port containing the pin
base: u32,
/// Pin index in the port
index: u8,
}
Expand All @@ -39,18 +33,18 @@ impl Pin {
dir: GPIODirection) -> Pin {

// Retrieve GPIO port peripheral to enable it
let (periph, port) = match pid {
PortA => (sysctl::periph::gpio::PORT_A, PORT_A),
PortB => (sysctl::periph::gpio::PORT_B, PORT_B),
PortC => (sysctl::periph::gpio::PORT_C, PORT_C),
PortD => (sysctl::periph::gpio::PORT_D, PORT_D),
PortE => (sysctl::periph::gpio::PORT_E, PORT_E),
PortF => (sysctl::periph::gpio::PORT_F, PORT_F),
let (periph, base) = match pid {
PortA => (sysctl::periph::gpio::PORT_A, PORT_A_BASE),
PortB => (sysctl::periph::gpio::PORT_B, PORT_B_BASE),
PortC => (sysctl::periph::gpio::PORT_C, PORT_C_BASE),
PortD => (sysctl::periph::gpio::PORT_D, PORT_D_BASE),
PortE => (sysctl::periph::gpio::PORT_E, PORT_E_BASE),
PortF => (sysctl::periph::gpio::PORT_F, PORT_F_BASE),
};

periph.ensure_enabled();

let pin = Pin { port: port, index: pin_index };
let pin = Pin { base: base, index: pin_index };

pin.configure(dir);

Expand All @@ -60,19 +54,19 @@ impl Pin {
/// Configure GPIO pin
fn configure(&self, dir: GPIODirection) {
// Disable the GPIO during reconfig
let den = Reg::new(self.port.base + DEN);
let den = Reg::new(self.base + DEN);
den.bitband_write(self.index, false);

self.set_direction(dir);

// Configure the "alternate function". 0 means GPIO, 1 means the port is
// driven by another peripheral.
let afsel = Reg::new(self.port.base + AFSEL);
let afsel = Reg::new(self.base + AFSEL);
afsel.bitband_write(self.index, false);

// We can chose to drive each GPIO at either 2, 4 or 8mA. Default to 2mA for
// now.
let drive = Reg::new(self.port.base + DR2R);
let drive = Reg::new(self.base + DR2R);
drive.bitband_write(self.index, true);

// XXX TODO: configure open drain/pull up/pull down/slew rate if necessary
Expand All @@ -89,7 +83,7 @@ impl Pin {
fn data_reg(&self) -> Reg {
let off: u32 = 1u32 << ((self.index as uint) + 2);

Reg::new(self.port.base + DATA + off)
Reg::new(self.base + DATA + off)
}
}

Expand Down Expand Up @@ -121,7 +115,7 @@ impl GPIO for Pin {

/// Sets output GPIO direction.
fn set_direction(&self, dir: GPIODirection) {
let reg = Reg::new(self.port.base + DIR);
let reg = Reg::new(self.base + DIR);
reg.bitband_write(self.index,
match dir {
In => false,
Expand All @@ -130,12 +124,12 @@ impl GPIO for Pin {
}
}

static PORT_A: Port = Port { base: 0x40004000 };
static PORT_B: Port = Port { base: 0x40005000 };
static PORT_C: Port = Port { base: 0x40006000 };
static PORT_D: Port = Port { base: 0x40007000 };
static PORT_E: Port = Port { base: 0x40024000 };
static PORT_F: Port = Port { base: 0x40025000 };
static PORT_A_BASE: u32 = 0x40004000;
static PORT_B_BASE: u32 = 0x40005000;
static PORT_C_BASE: u32 = 0x40006000;
static PORT_D_BASE: u32 = 0x40007000;
static PORT_E_BASE: u32 = 0x40024000;
static PORT_F_BASE: u32 = 0x40025000;

// Register offsets from port base
static DATA : u32 = 0x000;
Expand Down
8 changes: 3 additions & 5 deletions src/zinc/hal/tm4c123gh6pm/pin_pt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ pub fn verify(_: &mut Builder, cx: &mut ExtCtxt, node: Rc<node::Node>) {
fn build_pin(builder: &mut Builder, cx: &mut ExtCtxt, node: Rc<node::Node>) {
let port_node = node.parent.clone().unwrap().upgrade().unwrap();
let ref port_path = port_node.path;
let port = TokenString(port_path.clone());

let error = | err: &str | {
cx.parse_sess().span_diagnostic.span_err(port_node.path_span, err);
};

let port = TokenString(port_path.clone());

if node.name.is_none() {
error("pin node must have a name");
Expand All @@ -41,7 +41,6 @@ fn build_pin(builder: &mut Builder, cx: &mut ExtCtxt, node: Rc<node::Node>) {
"out" => "zinc::hal::pin::Out",
"in" => "zinc::hal::pin::In",
bad => {
let attr = node.get_attr("direction");
error(format!("unknown direction `{}`, allowed values: `in`, `out`",
bad).as_slice());
return;
Expand All @@ -53,9 +52,8 @@ fn build_pin(builder: &mut Builder, cx: &mut ExtCtxt, node: Rc<node::Node>) {
let pin_str = match from_str::<uint>(node.path.as_slice()).unwrap() {
0 ...7 => &node.path,
other => {
cx.parse_sess().span_diagnostic.span_err(node.path_span,
format!("unknown pin `{}`, allowed values: 0...7",
other).as_slice());
error(format!("unknown pin `{}`, allowed values: 0...7",
other).as_slice());
return;
}
};
Expand Down
4 changes: 3 additions & 1 deletion src/zinc/hal/tm4c123gh6pm/platformtree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use builder::{Builder, add_node_dependency};
use node;

mod pin_pt;
mod timer_pt;

pub fn attach(builder: &mut Builder, cx: &mut ExtCtxt, node: Rc<node::Node>) {
node.materializer.set(Some(verify));
Expand All @@ -28,14 +29,15 @@ pub fn attach(builder: &mut Builder, cx: &mut ExtCtxt, node: Rc<node::Node>) {

match sub.path.as_slice() {
"gpio" => pin_pt::attach(builder, cx, sub.clone()),
"timer" => timer_pt::attach(builder, cx, sub.clone()),
_ => (),
}
}
}

fn verify(_: &mut Builder, cx: &mut ExtCtxt, node: Rc<node::Node>) {
node.expect_no_attributes(cx);
node.expect_subnodes(cx, ["clock", "gpio"]);
node.expect_subnodes(cx, ["clock", "gpio", "timer"]);
}

pub fn add_node_dependency_on_clock(builder: &mut Builder,
Expand Down
45 changes: 39 additions & 6 deletions src/zinc/hal/tm4c123gh6pm/sysctl.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
//! Low level system control (PLL, clock gating, ...)
/// SysCtl base address
static BASE: u32 = 0x400FE000;

pub mod periph {
//! peripheral system control
use core::iter::range;
use hal::tm4c123gh6pm::io::Reg;

/// Run mode clock gating control offset
static RMCGC_OFFSET: u32 = 0x600;

/// Sysctl can reset/clock gate each module, as well as set various sleep and
/// deep-sleep mode behaviour.
pub struct Periph {
Expand Down Expand Up @@ -71,4 +65,43 @@ pub mod periph {
pub static PORT_F: super::Periph = super::Periph { class: CLASS, id: 5 };
}

pub mod timer {
//! Timer system control peripherals. Each timer has two independent
//! counters (A and B).
static TIMER_CLASS: u8 = 0x4;
static TIMER_W_CLASS: u8 = 0x5c;

pub static TIMER_0: super::Periph = super::Periph { class: TIMER_CLASS,
id: 0 };
pub static TIMER_1: super::Periph = super::Periph { class: TIMER_CLASS,
id: 1 };
pub static TIMER_2: super::Periph = super::Periph { class: TIMER_CLASS,
id: 2 };
pub static TIMER_3: super::Periph = super::Periph { class: TIMER_CLASS,
id: 3 };
pub static TIMER_4: super::Periph = super::Periph { class: TIMER_CLASS,
id: 4 };
pub static TIMER_5: super::Periph = super::Periph { class: TIMER_CLASS,
id: 5 };

pub static TIMER_W_0: super::Periph = super::Periph { class: TIMER_W_CLASS,
id: 0 };
pub static TIMER_W_1: super::Periph = super::Periph { class: TIMER_W_CLASS,
id: 1 };
pub static TIMER_W_2: super::Periph = super::Periph { class: TIMER_W_CLASS,
id: 2 };
pub static TIMER_W_3: super::Periph = super::Periph { class: TIMER_W_CLASS,
id: 3 };
pub static TIMER_W_4: super::Periph = super::Periph { class: TIMER_W_CLASS,
id: 4 };
pub static TIMER_W_5: super::Periph = super::Periph { class: TIMER_W_CLASS,
id: 5 };
}

/// Run mode clock gating control offset
static RMCGC_OFFSET: u32 = 0x600;
}

/// SysCtl base address
static BASE: u32 = 0x400FE000;
Loading

0 comments on commit 0449066

Please sign in to comment.