From a459ddf4bfe00f956bf0ffffe70d57585e889501 Mon Sep 17 00:00:00 2001 From: Determinant Date: Thu, 21 Sep 2017 23:04:45 -0400 Subject: sync with ds3231 every 10s --- src/ds3231.rs | 5 +++-- src/i2c.rs | 69 +++++++++++++++++++++++++++++----------------------------- src/main.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 94 insertions(+), 50 deletions(-) diff --git a/src/ds3231.rs b/src/ds3231.rs index 6b20958..0e1d561 100644 --- a/src/ds3231.rs +++ b/src/ds3231.rs @@ -22,8 +22,9 @@ pub struct Date { } impl<'a> DS3231<'a> { - pub fn new(i2c_reg: &'a stm32f103xx::i2c1::RegisterBlock) -> DS3231<'a> { - DS3231{i2c: I2C::new(i2c_reg)} + pub fn new(i2c_reg: &'a stm32f103xx::i2c1::RegisterBlock, + rcc_reg: &'a stm32f103xx::rcc::RegisterBlock) -> DS3231<'a> { + DS3231{i2c: I2C::new(i2c_reg, rcc_reg)} } fn bcd2dec(bcd: u8) -> u8 { diff --git a/src/i2c.rs b/src/i2c.rs index 6a8d7a4..8904730 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -20,6 +20,7 @@ const I2C_ACK_ENABLE: u16 = 0x0400; pub struct I2C<'a> { i2c: &'a stm32f103xx::i2c1::RegisterBlock, + rcc: &'a stm32f103xx::rcc::RegisterBlock, } pub enum TransDir { @@ -28,52 +29,50 @@ pub enum TransDir { } impl<'a> I2C<'a> { - pub fn new(reg: &'a stm32f103xx::i2c1::RegisterBlock) -> I2C<'a> { - I2C{i2c: reg} + pub fn new(i2c_reg: &'a stm32f103xx::i2c1::RegisterBlock, + rcc_reg: &'a stm32f103xx::rcc::RegisterBlock) -> I2C<'a> { + I2C{i2c: i2c_reg, rcc: rcc_reg} } - fn get_pclk1() -> u32 { - unsafe { - use stm32f103xx::rcc::cfgr::{SWSR, PLLSRCR, PLLXTPRER}; - let rcc: &stm32f103xx::rcc::RegisterBlock = &*RCC.get(); - let cfgr = rcc.cfgr.read(); - let sysclk_freq = match cfgr.sws() { - SWSR::HSI => HSI_VALUE, - SWSR::HSE => HSE_VALUE, - SWSR::PLL => { - let pllmull = cfgr.pllmul().bits(); - let pllsource = cfgr.pllsrc(); - let pllmull = (pllmull as u32 >> 18) + 2; - match pllsource { - PLLSRCR::INTERNAL => { - (HSI_VALUE >> 1) * pllmull - }, - PLLSRCR::EXTERNAL => { - match cfgr.pllxtpre() { - PLLXTPRER::DIV2 => (HSE_VALUE >> 1) * pllmull, - PLLXTPRER::DIV1 => HSE_VALUE * pllmull - } + fn get_pclk1(&self) -> u32 { + use stm32f103xx::rcc::cfgr::{SWSR, PLLSRCR, PLLXTPRER}; + let cfgr = self.rcc.cfgr.read(); + let sysclk_freq = match cfgr.sws() { + SWSR::HSI => HSI_VALUE, + SWSR::HSE => HSE_VALUE, + SWSR::PLL => { + let pllmull = cfgr.pllmul().bits(); + let pllsource = cfgr.pllsrc(); + let pllmull = (pllmull as u32 >> 18) + 2; + match pllsource { + PLLSRCR::INTERNAL => { + (HSI_VALUE >> 1) * pllmull + }, + PLLSRCR::EXTERNAL => { + match cfgr.pllxtpre() { + PLLXTPRER::DIV2 => (HSE_VALUE >> 1) * pllmull, + PLLXTPRER::DIV1 => HSE_VALUE * pllmull } } } - _ => HSI_VALUE - }; - let div_table: [u8; 16] = [0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9]; - let hclk_freq = sysclk_freq >> div_table[cfgr.hpre().bits() as usize]; - let pclk1_freq = hclk_freq >> div_table[cfgr.ppre1().bits() as usize]; - pclk1_freq - } + } + _ => HSI_VALUE + }; + let div_table: [u8; 16] = [0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9]; + let hclk_freq = sysclk_freq >> div_table[cfgr.hpre().bits() as usize]; + let pclk1_freq = hclk_freq >> div_table[cfgr.ppre1().bits() as usize]; + pclk1_freq } + /// TODO: support for standard mode (100khz) pub fn init(&self) { let i2c = &self.i2c; unsafe { - let rcc: &stm32f103xx::rcc::RegisterBlock = &*RCC.get(); - rcc.apb1rstr.modify(|_, w| w.i2c1rst().set_bit()); - rcc.apb1rstr.modify(|_, w| w.i2c1rst().clear_bit()); + self.rcc.apb1rstr.modify(|_, w| w.i2c1rst().set_bit()); + self.rcc.apb1rstr.modify(|_, w| w.i2c1rst().clear_bit()); self.pe(true); /* PE = 1, enable I2C */ /* CR2 configuration */ - let pclk1 = I2C::get_pclk1(); + let pclk1 = self.get_pclk1(); let freq_range: u16 = (pclk1 / 1000000) as u16; i2c.cr2.modify(|r, w| w.bits(r.bits()).freq().bits(freq_range as u8)); /* CCR configuration */ @@ -84,7 +83,7 @@ impl<'a> I2C<'a> { } /* TRISE configuration */ i2c.trise.write(|w| w.bits(((freq_range * 300) / 1000 + 1) as u32)); - i2c.ccr.modify(|r, w| w.bits((res | CCR_FS_SET) as u32)); + i2c.ccr.write(|w| w.bits((res | CCR_FS_SET) as u32)); self.pe(true); /* PE = 1, enable I2C */ /* CR1 configuration */ i2c.cr1.modify(|r, w| w.bits(((r.bits() as u16 & CR1_CLEAR_MASK) | I2C_ACK_ENABLE) as u32)); diff --git a/src/main.rs b/src/main.rs index 6690828..219764f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,17 +12,21 @@ struct ShiftRegister<'a> { width: u8, } +struct Clock { + sec: u8, + min: u8, + hr: u8, + reset: u8 +} + +const RESET_PERIOD: u8 = 10; static mut SR: Option = None; static mut RTC: Option = None; -static mut N: u16 = 0; static mut DIGITS: [u8; 6] = [0; 6]; +static mut TIME: Clock = Clock{sec: 0, min: 0, hr: 0, reset: 0}; -fn systick_handler() { +fn update_clock() { unsafe { - /* - SR.as_mut().unwrap().output_bits(N as u32); - N += 1; - */ /* SR.as_mut().unwrap().output_bits(digits2bcds(&DIGITS[..])); let mut i = 0; @@ -33,14 +37,28 @@ fn systick_handler() { i += 1; } */ - let ds3231::Date{second: sec, minute: min, hour: hr, ..} = RTC.as_mut().unwrap().read_fulldate(); - DIGITS[4] = sec / 10; DIGITS[5] = sec % 10; - DIGITS[2] = min / 10; DIGITS[3] = min % 10; - DIGITS[0] = hr / 10; DIGITS[1] = hr % 10; + if !TIME.tick() { + let ds3231::Date{second: sec, + minute: min, + hour: hr, ..} = RTC.as_mut().unwrap() + .read_fulldate(); + TIME = Clock{sec: sec, + min: min, + hr: hr, + reset: RESET_PERIOD}; + } + + DIGITS[4] = TIME.sec / 10; DIGITS[5] = TIME.sec - DIGITS[4] * 10; + DIGITS[2] = TIME.min / 10; DIGITS[3] = TIME.min - DIGITS[2] * 10; + DIGITS[0] = TIME.hr / 10; DIGITS[1] = TIME.hr - DIGITS[0] * 10; SR.as_mut().unwrap().output_bits(digits2bcds(&DIGITS[..])); } } +fn systick_handler() { + update_clock(); +} + exception!(SYS_TICK, systick_handler); impl<'a> ShiftRegister<'a> { @@ -77,6 +95,31 @@ fn digits2bcds(digs: &[u8]) -> u32 { res } +impl Clock { + fn tick(&mut self) -> bool { + if self.reset == 0 { + return false; + } + + self.sec += 1; + if self.sec == 60 { + self.min += 1; + self.sec = 0; + } + + if self.min == 60 { + self.hr += 1; + self.min = 0; + } + + if self.hr == 24 { + self.hr = 0; + } + self.reset -= 1; + true + } +} + fn main() { let gpioa: &stm32f103xx::gpioa::RegisterBlock = unsafe { &*GPIOA.get() }; @@ -86,7 +129,7 @@ fn main() { let syst: &cortex_m::peripheral::SYST = unsafe { &*SYST.get() }; syst.set_clock_source(SystClkSource::Core); - syst.set_reload(100_000); + syst.set_reload(8_000_000); syst.enable_interrupt(); syst.enable_counter(); rcc.apb2enr.modify(|_, w| w.iopaen().enabled() @@ -104,12 +147,11 @@ fn main() { rcc.apb1enr.modify(|_, w| w.i2c1en().enabled()); unsafe { - RTC = Some(ds3231::DS3231::new(i2c)); + RTC = Some(ds3231::DS3231::new(i2c, rcc)); SR = Some(ShiftRegister::new(gpioa, 24)); SR.as_mut().unwrap().output_bits(0); let rtc = RTC.as_mut().unwrap(); rtc.init(); - let x = rtc.read_fulldate(); /* rtc.write_fulldate(&ds3231::Date{second: 30, minute: 48, @@ -122,4 +164,6 @@ fn main() { am_enable: false}); */ } + + update_clock(); } -- cgit v1.2.3