From ebaa820cd68043969e18567299b89aea94c6e832 Mon Sep 17 00:00:00 2001 From: Sergey Chernomorets Date: Wed, 23 May 2018 22:16:17 +0300 Subject: [PATCH 1/3] add examples/timer2.rs --- examples/timer2.rs | 214 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 examples/timer2.rs diff --git a/examples/timer2.rs b/examples/timer2.rs new file mode 100644 index 0000000..8621939 --- /dev/null +++ b/examples/timer2.rs @@ -0,0 +1,214 @@ +// vim: set ts=4 sts=4 sw=4 expandtab: +#![no_std] +#![feature(abi_msp430_interrupt)] +/* + Set timer to count up to 5000 + When counter reach 1000 CCR1 generate interrupt and handler switch port p1.0 (LED1). + When counter reach 4000 CCR2 generate interrupt and handler switch port p1.6 (LED2). +*/ + +extern crate msp430; + +// Some explanations about msp430g2553's API: https://docs.rs/svd2rust/0.11.2/svd2rust/ +#[macro_use(interrupt)] +extern crate msp430g2553; + +use msp430::interrupt; +use msp430g2553::{PORT_1_2, TIMER0_A3, SYSTEM_CLOCK}; + +fn main() { + interrupt::free(|cs| { + // Disable watchdog + let wdt = msp430g2553::WATCHDOG_TIMER.borrow(&cs); + wdt.wdtctl.write(|w| { + unsafe { w.bits(0x5A00) } // password + .wdthold().set_bit() + }); + + + // p1.0 LED1 + // p1.6 LED2 + let port_1_2 = PORT_1_2.borrow(cs); + // dir - direction out? + port_1_2.p1dir.modify(|_, w| w.p0().set_bit() + .p6().set_bit()); + // p0 = 1, p6 = 0 + port_1_2.p1out.modify(|_, w| w.p0().set_bit() + .p6().clear_bit()); + + /* ********* CLOCK ********** + + */ + let clock = SYSTEM_CLOCK.borrow(cs); + // "0x01 - Basic Clock System Control 3" + clock.bcsctl3.modify(|_, w| + // _ - byte read from register (struct bcsctl3::R) + // w - byte write to register (struct bcsctl3::W) + w + // lfxt - Low/high Frequency Oscillator + // Bits 4:5 - Mode 0 for LFXT1 (XTS = 0) -> _LFXT1SW + .lfxt1s() + // Mode 2 for LFXT1 : VLO + .lfxt1s_2() + ); + // "0x05 - Basic Clock System Control 1" + clock.bcsctl1.modify(|_, w| + // bcsctl1::W + w + // Bits 4:5 - ACLK Divider 0 -> _DIVAW + .diva() + // ACLK Divider 1: /2 -> bcsctl1::W + .diva_1() + ); + + /* ********* TIMER *********** + Guide p18 peripherals -> File map + + Timer_An: n = # of CCR's + TAx: Instance of Timer_A + Therefore: + TA0 is the first instance of Timer_A5 + + As we will cover in great detail during this chapter, these timers contain one or more Capture and + Compare Registers (CCR); these are useful for creating sophisticated timings, interrupts and + waveforms. The more CCR registers a timer contains, the more independent waveforms that can + be generated. To this end, the documentation often includes the number of CCR registers when + listing the name of the timer. For example, if TIMER_A on a given device has 5 CCR registers, + they often name it: + `Timer_A5` + + But wait, that’s not all. What happens when a device, such as the ‘F5529 has more than one + instance of TIMER_A? Each of these instances needs to be enumerated as well. This is done by + appending the instance number after the word “Timer”, as in Timer0. + To summarize, here’s the long (and short) names for each of the ‘F5529 TIMER_A modules: + ``` + Instance Long Name Short Name + 0 Timer0_A5 TA0 + 1 Timer1_A3 TA1 + 2 Timer2_A3 TA2 + + The CCR0 (Capture and Control Register 0) is special. That is, it is special in comparison to the + other CCR registers. It is only CCR0 that can be used to define the upper limit of the counter in Up + (or UpDown) count mode. + The other special feature of CCR0 is that it provides a dedicated interrupt (CC0IFG). In other + words, there is an Interrupt Vector location dedicated to CC0IFG. All the other Timer_A interrupts + share a common vector location (i.e. they make up a grouped interrupt). + + + ``` + */ + let timer = TIMER0_A3.borrow(cs); + timer + // timer0_a3::ta0ccr0 - Timer0_A3 Capture/Compare 0 + .ta0ccr0.write(|w| + // w: timer0_a3::ta0ccr0::W + unsafe { + // Writes raw bits to the register + // Count up to CCR0=1200 + w.bits(5000) + } + ); + timer + // "0x32 - Timer0_A3 Control" + // timer0_a3::ta0ctl + .ta0ctl.modify(|_, w| + // w: timer0_a3::ta0ctl::W + w + // Bits 8:9 - Timer A clock source select 1 -> timer0_a3::ta0ctl::_TASSELW + .tassel() + // Timer A clock source select: 1 - ACLK -> timer0_a3::ta0ctl::W + .tassel_1() + // Bits 4:5 - Timer A mode control 1 -> timer0_a3::ta0ctl::_MCW + .mc() + // Timer A mode control: 1 - Up to CCR0 -> timer0_a3::ta0ctl::W + // countiung mode: Up to value of ccr0, then catch interrupt and begin counting from 0 + .mc_1() + ); + timer + // Timer0_A3 Capture/Compare Control 1 + // timer0_a3::ta0cctl1 + .ta0cctl1.modify(|_, w| + // timer0_a3::ta0cctl1::W + w + // Bit 4 - Capture/compare interrupt enable + .ccie() + .set_bit() + ); + timer + // Timer0_A3 Capture/Compare 1 + // timer0_a3::ta0ccr1 + .ta0ccr1.write(|w| + // w: timer0_a3::ta0ccr1::W + // generate interupt when TimerA count to 600 + unsafe { w.bits(1000) } + ); + + // Same as privious but for Timer0_A3 Capture/Compare Control 2 + timer + .ta0cctl2.modify(|_, w| + w + .ccie() + .set_bit() + ); + timer + .ta0ccr2.write(|w| + unsafe { w.bits(4000) } + ); + }); + + unsafe { + interrupt::enable(); + } + + loop {} +} + + +/* + Macro interrupt! replaced by something like this: + ( $NAME: ident , $path: path ) => { + # [ allow ( non_snake_case ) ] + # [ no_mangle ] + pub extern "msp430-interrupt" fn $NAME ( ) { + let _ = $ crate::interrupt::Interrupt::$NAME ; + let f: fn() = $path ; + f() ; + } + } + + msp430g2553::interrupt::Interrupt has 4 names: + TIMER0_A0, TIMER0_A1 + TIMER1_A0, TIMER1_A1 + + + Vector TIMER0_A0 dedicated to CCR0 + Vector TIMER0_A1 dedicated to CCR1..CCRn + +*/ +interrupt!(TIMER0_A1, timer_handler); +fn timer_handler() { + interrupt::free(|cs| { + let timer = TIMER0_A3.borrow(cs); + let port_1_2 = PORT_1_2.borrow(cs); + + let counter = timer.ta0r.read().bits(); + + match counter { + c if c >= 1000 && c < 2000 => { + timer.ta0cctl1.modify(|_, w| w.ccifg().clear_bit()); + // invert bits + port_1_2.p1out.modify(|r, w| w.p0().bit(!r.p0().bit())); + }, + c if c >= 4000 => { + timer.ta0cctl2.modify(|_, w| w.ccifg().clear_bit()); + // invert bits + port_1_2.p1out.modify(|r, w| w.p6().bit(!r.p6().bit())); + }, + _ => {} + } + + // invert bits + //port_1_2.p1out.modify(|r, w| w.p0().bit(!r.p0().bit()) + // .p6().bit(!r.p6().bit())); + }); +} From 01129428f937cfd4b8a178fae8ad9ffacbbc75cc Mon Sep 17 00:00:00 2001 From: Sergey Chernomorets Date: Thu, 24 May 2018 09:56:29 +0300 Subject: [PATCH 2/3] Add "Quick start" to README --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fc8dfaa..7721934 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,15 @@ # `msp430-quickstart` -> WIP +# Quick start for Debian/Ubuntu Linux + +* Install toolchain: [msp430-gcc](http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/latest/index_FDS.html) (at May 2018 it is msp430-gcc-6.4.0.32) +* Install mspdebug: `apt install mspdebug` +* Install rust-nightly: `rustup install nightly` +* Install rust-src: `rustup component add rust-src` +* Clone msp430-quickstart: `git clone https://github.com/japaric/msp430-quickstart.git && cd msp430-quickstart` +* Build project: `xargo rustc --target msp430-none-elf --release` +* Program Launchpad: ` mspdebug rf2500 'prog target/msp430-none-elf/release/msp430-quickstart'` + # License From 86ecdfc80a503b02b859e986f67eb590a79924d0 Mon Sep 17 00:00:00 2001 From: Sergey Chernomorets Date: Thu, 24 May 2018 21:44:17 +0300 Subject: [PATCH 3/3] fix values in comments --- examples/timer2.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/timer2.rs b/examples/timer2.rs index 8621939..d5f0bd3 100644 --- a/examples/timer2.rs +++ b/examples/timer2.rs @@ -104,7 +104,7 @@ fn main() { // w: timer0_a3::ta0ccr0::W unsafe { // Writes raw bits to the register - // Count up to CCR0=1200 + // Count up to CCR0=5000 w.bits(5000) } ); @@ -139,7 +139,7 @@ fn main() { // timer0_a3::ta0ccr1 .ta0ccr1.write(|w| // w: timer0_a3::ta0ccr1::W - // generate interupt when TimerA count to 600 + // generate interupt when TimerA count to 1000 unsafe { w.bits(1000) } );