From 1e7b6e508cf276cbec03dfd71d62213960b23d3d Mon Sep 17 00:00:00 2001 From: Lionel Flandrin Date: Mon, 20 Oct 2014 21:36:57 +0200 Subject: [PATCH] UART works! --- apps/app_blink_tiva_c.rs | 6 ++-- apps/app_uart_tiva_c.rs | 55 ++++++++++++++--------------------- src/zinc/hal/tiva_c/io.rs | 1 - src/zinc/hal/tiva_c/pin.rs | 51 +++++++++++++++++++++++++------- src/zinc/hal/tiva_c/pin_pt.rs | 4 +-- src/zinc/hal/tiva_c/sysctl.rs | 10 +++---- src/zinc/hal/tiva_c/uart.rs | 31 ++++++++++++-------- 7 files changed, 92 insertions(+), 66 deletions(-) diff --git a/apps/app_blink_tiva_c.rs b/apps/app_blink_tiva_c.rs index ab4a98bf..37029455 100644 --- a/apps/app_blink_tiva_c.rs +++ b/apps/app_blink_tiva_c.rs @@ -15,8 +15,11 @@ platformtree!( } gpio { + PortA { + led1@1 { direction = "out"; } + } PortF { - led1@1 { direction = "out"; } + led2@2 { direction = "out"; } } } @@ -44,7 +47,6 @@ platformtree!( } ) -#[no_split_stack] pub fn run(args: &pt::run_args) { use zinc::hal::pin::GPIO; use zinc::hal::timer::Timer; diff --git a/apps/app_uart_tiva_c.rs b/apps/app_uart_tiva_c.rs index cc4cb752..73527f1a 100644 --- a/apps/app_uart_tiva_c.rs +++ b/apps/app_uart_tiva_c.rs @@ -24,11 +24,6 @@ platformtree!( } } - uart { - uart@0 { - mode = "9600,8n1"; - } - } gpio { PortA { @@ -37,15 +32,21 @@ platformtree!( function = 1; } uart_tx@1 { - direction = "out"; + direction = "in"; function = 1; } } PortF { - led1@1 { direction = "out"; } - led2@3 { direction = "out"; } + txled@2 { direction = "out"; } } } + + uart { + uart@0 { + mode = "115200,8n1"; + } + } + } os { @@ -54,42 +55,30 @@ platformtree!( args { timer = &timer; uart = &uart; - led1 = &led1; - led2 = &led2; + txled = &txled; + uart_tx = &uart_tx; } } } ) -#[no_stack_check] fn run(args: &pt::run_args) { use zinc::drivers::chario::CharIO; + use zinc::hal::timer::Timer; use zinc::hal::pin::GPIO; - args.led1.set_high(); + args.uart.puts("Hello, world\n"); - args.uart.putc('@'); - - args.led1.set_low(); - args.led2.set_high(); - + let mut i = 0; loop { - args.uart.putc('|'); - } + args.txled.set_high(); + args.uart.puts("Waiting for "); + args.uart.puti(i); + args.uart.puts(" seconds...\n"); + i += 1; + args.txled.set_low(); - //args.led2.set_high(); - - // let mut i = 0; - // loop { - // //args.txled.set_high(); - // args.uart.puts("Waiting for "); - // //args.uart.puti(i); - // args.uart.puts(" seconds...\n"); - - // i += 1; - // args.txled.set_low(); - - // args.timer.wait(1); - // } + args.timer.wait(1); + } } diff --git a/src/zinc/hal/tiva_c/io.rs b/src/zinc/hal/tiva_c/io.rs index ccd62ebc..4588b007 100644 --- a/src/zinc/hal/tiva_c/io.rs +++ b/src/zinc/hal/tiva_c/io.rs @@ -1,6 +1,5 @@ //! Custom register access interface -use util::volatile_cell::VolatileCell; use core::intrinsics::{volatile_load, volatile_store}; /// Hardware register interface diff --git a/src/zinc/hal/tiva_c/pin.rs b/src/zinc/hal/tiva_c/pin.rs index f201a50c..81812dc3 100644 --- a/src/zinc/hal/tiva_c/pin.rs +++ b/src/zinc/hal/tiva_c/pin.rs @@ -64,16 +64,23 @@ impl Pin { // is driven by another peripheral. When AFSEL is 1 the actual function // config goes into the CTL register. let afsel = Reg::new(self.base + AFSEL); - let ctl = Reg::new(self.base + CTL); + let pctl = Reg::new(self.base + PCTL); + + + afsel.bitband_write(self.index, true); match function { 0 => afsel.bitband_write(self.index, false), f => { afsel.bitband_write(self.index, true); - let mut reg = ctl.read32(); - reg |= (f as u32) << ((self.index as uint) * 4); - ctl.write32(reg); + // let pctl_offset = (self.index as uint) * 4; + + // let mut reg = pctl.read32(); + // reg &= !(0xf << pctl_offset); + // reg |= (f as u32) << pctl_offset; + + // pctl.write32(reg); } } @@ -82,7 +89,23 @@ impl Pin { 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 + let drive = Reg::new(self.base + DR4R); + drive.bitband_write(self.index, false); + + let drive = Reg::new(self.base + DR8R); + drive.bitband_write(self.index, false); + + let drive = Reg::new(self.base + SLR); + drive.bitband_write(self.index, false); + + // XXX TODO: configure open drain/pull up/pull down/slew rate if necessary + + let typ = Reg::new(self.base + ODR); + typ.bitband_write(self.index, false); + let typ = Reg::new(self.base + PUR); + typ.bitband_write(self.index, false); + let typ = Reg::new(self.base + PDR); + typ.bitband_write(self.index, false); // Enable GPIO den.bitband_write(self.index, true); @@ -145,9 +168,15 @@ static PORT_E_BASE: u32 = 0x40024000; static PORT_F_BASE: u32 = 0x40025000; // Register offsets from port base -static DATA : u32 = 0x000; -static DIR : u32 = 0x400; -static AFSEL : u32 = 0x420; -static DR2R : u32 = 0x500; -static CTL : u32 = 0x52C; -static DEN : u32 = 0x51C; +static DATA : u32 = 0x000; /* 0 */ +static DIR : u32 = 0x400; /* 0 */ +static AFSEL : u32 = 0x420; /* 3 */ +static DR2R : u32 = 0x500; /* 0xff */ +static DR4R : u32 = 0x504; /* 0 */ +static DR8R : u32 = 0x508; /* 0 */ +static ODR : u32 = 0x50C; /* 0 */ +static PUR : u32 = 0x510; /* 0 */ +static PDR : u32 = 0x514; /* 0 */ +static SLR : u32 = 0x518; /* 0 */ +static DEN : u32 = 0x51C; /* 3 */ +static PCTL : u32 = 0x52C; /* 222211 */ diff --git a/src/zinc/hal/tiva_c/pin_pt.rs b/src/zinc/hal/tiva_c/pin_pt.rs index 985b717c..d04a94b0 100644 --- a/src/zinc/hal/tiva_c/pin_pt.rs +++ b/src/zinc/hal/tiva_c/pin_pt.rs @@ -49,9 +49,9 @@ fn build_pin(builder: &mut Builder, cx: &mut ExtCtxt, node: Rc) { let direction = TokenString(direction_str.to_string()); - let function = match node.get_string_attr("function") { + let function = match node.get_int_attr("function") { None => 0, /* Default to GPIO function */ - Some(attr) => from_str::(attr.as_slice()).unwrap(), + Some(f) => f as u8, }; let pin_str = match from_str::(node.path.as_slice()).unwrap() { diff --git a/src/zinc/hal/tiva_c/sysctl.rs b/src/zinc/hal/tiva_c/sysctl.rs index b465bbd0..ded9bccf 100644 --- a/src/zinc/hal/tiva_c/sysctl.rs +++ b/src/zinc/hal/tiva_c/sysctl.rs @@ -3,8 +3,7 @@ pub mod clock { //! Clock tree configuration - use core::iter::range; - use core::option::{Option, None, Some}; + use core::option::{Option, Some}; use hal::tiva_c::io::Reg; /// Clock sources available on the system. The values are the RCC/RCC2 OSCSRC @@ -17,7 +16,7 @@ pub mod clock { /// The Precision Internal Oscillator @16MHz PIOSC = 1, /// PIOSC divided by 4, resulting in a 4MHz source. - PIOSC_4MHz = 2, + PIOSC4MHz = 2, /// The Low Frequency Internal Oscillator @30kHz LFIOSC = 3, /// The Hibernation Oscillator, external crystal/oscillator on XOSC pins. @@ -28,6 +27,7 @@ pub mod clock { /// The chip supports a finite list of crystal frequencies for the MOSC, each /// having its own ID used to configure the PLL to output 400MHz. #[allow(missing_doc)] + #[allow(non_camel_case_types)] pub enum MOSCFreq { X5_0MHz = 0x09, X5_12MHz = 0x0A, @@ -97,8 +97,8 @@ pub mod clock { rcc_val &= !((3 << 4) | 0x1f << 6); rcc2_val &= !(7 << 4); - rcc_val |= ((source as u32) << 4); - rcc2_val |= ((source as u32) << 4); + rcc_val |= (source as u32) << 4; + rcc2_val |= (source as u32) << 4; if source == MOSC { // Set XTAL value diff --git a/src/zinc/hal/tiva_c/uart.rs b/src/zinc/hal/tiva_c/uart.rs index da1ad13c..f12873b4 100644 --- a/src/zinc/hal/tiva_c/uart.rs +++ b/src/zinc/hal/tiva_c/uart.rs @@ -17,9 +17,6 @@ use hal::tiva_c::sysctl; use hal::tiva_c::io::Reg; -use hal::timer; - -use core::intrinsics::abort; use drivers::chario::CharIO; use hal::uart; @@ -69,9 +66,6 @@ impl UART { periph.ensure_enabled(); - let port = sysctl::periph::gpio::PORT_A; - port.ensure_enabled(); - uart.configure(baudrate, word_len, parity, stop_bits); uart @@ -83,7 +77,7 @@ impl UART { word_len: u8, parity: uart::Parity, stop_bits: u8) { - let sysclk = 80_000_000u; + let sysclk = 16_000_000u; /* compute the baud rate divisor rounded to the nearest */ let brd = ((((sysclk / 16) << 6) + baudrate / 2) / baudrate) as u32; @@ -92,25 +86,37 @@ impl UART { /* Disable the UART before configuration */ ctl.bitband_write(0, false); + /* Enable TX */ + ctl.bitband_write(8, true); + /* Disable RX */ + ctl.bitband_write(9, false); + ctl.bitband_write(5, false); + + ctl.write32(0x301); + let ibrd = Reg::new(self.base + IBRD); - ctl.write32(brd >> 6); + ibrd.write32(brd >> 6); let fbrd = Reg::new(self.base + FBRD); - ctl.write32(brd & ((1 << 6) - 1)); + fbrd.write32(brd & ((1 << 6) - 1)); - let crh = Reg::new(self.base + CRH); + let lcrh = Reg::new(self.base + CRH); /* This is where we can do the real config. */ - crh.write32(0x60); + lcrh.write32(0x70); /* Enable the UART */ - ctl.bitband_write(0, true); + ctl.write32(0x301); } } impl CharIO for UART { fn putc(&self, value: char) { let data = Reg::new(self.base + DATA); + let fr = Reg::new(self.base + FR); + + while fr.read32() & (1 << 5) != 0 { + } data.write32(value as u32); } @@ -126,6 +132,7 @@ static UART_6_BASE: u32 = 0x40012000; static UART_7_BASE: u32 = 0x40013000; static DATA : u32 = 0x00; +static FR : u32 = 0x18; static CTL : u32 = 0x30; static IBRD : u32 = 0x24; static FBRD : u32 = 0x28;