From a6cb8962b589d08f334821b12bb6c4c75d3f0e08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Quentin?= Date: Fri, 23 Jul 2021 12:09:51 +0200 Subject: [PATCH] Implement RTC (#26) * implement rtc * fix rtc --- .cargo/config.toml | 2 +- .vscode/settings.json | 4 +++ Cargo.toml | 2 +- examples/rtc.rs | 61 +++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/rtc.rs | 57 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 examples/rtc.rs create mode 100644 src/rtc.rs diff --git a/.cargo/config.toml b/.cargo/config.toml index a4bd81f..320e324 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -4,7 +4,7 @@ rustflags = [ "-C", "link-arg=-Tlink.x", "-C", "link-arg=-Thal_defaults.x", ] -runner = "cargo blflash --port=/dev/ttyUSB0" +runner = "blash --" [build] target = "riscv32imac-unknown-none-elf" diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..bd6243f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "rust-analyzer.cargo.target": "riscv32imac-unknown-none-elf", + "rust-analyzer.checkOnSave.allTargets": false +} diff --git a/Cargo.toml b/Cargo.toml index fa09581..cb15719 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ description = "HAL for the bl602 microcontroller" [dependencies] bl602-pac = { git = "https://github.com/sipeed/bl602-pac", branch = "main" } embedded-hal = "1.0.0-alpha.4" -embedded-time = "0.10" +embedded-time = "0.12.0" riscv = "0.6.0" nb = "1.0" paste = "1.0" diff --git a/examples/rtc.rs b/examples/rtc.rs new file mode 100644 index 0000000..49a8bb5 --- /dev/null +++ b/examples/rtc.rs @@ -0,0 +1,61 @@ +#![no_std] +#![no_main] + +use bl602_hal as hal; +use core::{convert::TryFrom, fmt::Write}; +use embedded_time::{duration::Seconds, Clock}; +use hal::{ + clock::{Strict, SysclkFreq, UART_PLL_FREQ}, + pac, + prelude::*, + rtc::Rtc, + serial::*, +}; +use panic_halt as _; + +#[riscv_rt::entry] +fn main() -> ! { + let dp = pac::Peripherals::take().unwrap(); + let mut parts = dp.GLB.split(); + + // Set up all the clocks we need + let clocks = Strict::new() + .use_pll(40_000_000u32.Hz()) + .sys_clk(SysclkFreq::Pll160Mhz) + .uart_clk(UART_PLL_FREQ.Hz()) + .freeze(&mut parts.clk_cfg); + + // Set up uart output. Since this microcontroller has a pin matrix, + // we need to set up both the pins and the muxs + let pin16 = parts.pin16.into_uart_sig0(); + let pin7 = parts.pin7.into_uart_sig7(); + let mux0 = parts.uart_mux0.into_uart0_tx(); + let mux7 = parts.uart_mux7.into_uart0_rx(); + + // Configure our UART to 115200Baud, and use the pins we configured above + let mut serial = Serial::uart0( + dp.UART, + Config::default().baudrate(115_200.Bd()), + ((pin16, mux0), (pin7, mux7)), + clocks, + ); + + // Create RTC + let rtc = Rtc::rtc(dp.HBN); + + loop { + write!( + serial, + "Current millis since start of the rtc: {}\r\n", + rtc.get_millis() + ) + .ok(); + + let seconds = + Seconds::::try_from(rtc.try_now().unwrap().duration_since_epoch()).unwrap(); + write!(serial, "Current instant in seconds: {}\r\n", seconds).ok(); + + let timer = rtc.new_timer(Seconds(1u32)).into_oneshot(); + timer.start().unwrap().wait().ok(); + } +} diff --git a/src/lib.rs b/src/lib.rs index bf32007..7c296b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,6 +40,7 @@ pub mod delay; pub mod gpio; pub mod i2c; pub mod interrupts; +pub mod rtc; pub mod serial; pub mod spi; pub mod timer; diff --git a/src/rtc.rs b/src/rtc.rs new file mode 100644 index 0000000..d1dc1ab --- /dev/null +++ b/src/rtc.rs @@ -0,0 +1,57 @@ +/*! + # Real Time Clock + A clock that constantly counts up starting at the time of it's creation. + + ## Initialisation example + ```rust + let rtc = Rtc::rtc(dp.HBN); + ``` +*/ + +use bl602_pac::HBN; +use embedded_time::Clock; + +pub struct Rtc { + hbn: HBN, +} + +impl Rtc { + /// Creates and starts the RTC + pub fn rtc(hbn: HBN) -> Rtc { + // clear counter + hbn.hbn_ctl + .modify(|r, w| unsafe { w.rtc_ctl().bits(r.rtc_ctl().bits() & 0xfe) }); + // enable counter + hbn.hbn_ctl + .modify(|r, w| unsafe { w.rtc_ctl().bits(r.rtc_ctl().bits() | 1) }); + + Rtc { hbn } + } + + /// Get elapsed milliseconds since the RTC was created + pub fn get_millis(&self) -> u64 { + self.hbn + .rtc_time_h + .modify(|r, w| unsafe { w.bits(r.bits() | 1 << 31) }); + + let h = self.hbn.rtc_time_h.read().bits(); + let l = self.hbn.rtc_time_l.read().bits(); + let ts = (h as u64) << 32 | l as u64; // in counter units + + // from IOT SDK: + // #define BL_RTC_COUNTER_TO_MS(CNT) (((CNT) >> 5) - ((CNT) >> 11) - ((CNT) >> 12)) // ((CNT)*(1024-16-8)/32768) + // see https://github.com/bouffalolab/bl_iot_sdk/blob/90acb7b46d11343d27db9518c4f86d94572c6629/components/hal_drv/bl602_hal/bl_rtc.c + ts * (1024 - 16 - 8) / 32768 + } +} + +impl Clock for Rtc { + type T = u64; + + const SCALING_FACTOR: embedded_time::fraction::Fraction = + ::new(1, 1_000); + + fn try_now(&self) -> Result, embedded_time::clock::Error> { + Ok(embedded_time::Instant::new(self.get_millis())) + } +}