Skip to content

Commit 1fe8aed

Browse files
committed
[rust, hal] Add the timer implementation
Signed-off-by: Douglas Reis <[email protected]>
1 parent b51feb9 commit 1fe8aed

File tree

7 files changed

+174
-22
lines changed

7 files changed

+174
-22
lines changed

data/ibex.svd

+10-10
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@
283283
</interrupt>
284284
</peripheral>
285285
<peripheral>
286-
<name>TIMER</name>
286+
<name>TIMER0</name>
287287
<version>1</version>
288288
<description>Controls timer</description>
289289
<baseAddress>0x80002000</baseAddress>
@@ -295,18 +295,18 @@
295295
</addressBlock>
296296
<interrupt>
297297
<name>TIMER_IRQ_0</name>
298-
<value>0</value>
298+
<value>7</value>
299299
</interrupt>
300300
<registers>
301301
<register>
302-
<name>MTIME</name>
303-
<description>mtime</description>
302+
<name>MTIMEL</name>
303+
<description>mtime low</description>
304304
<addressOffset>0x0000</addressOffset>
305305
<resetValue>0x00000000</resetValue>
306306
<fields>
307307
<field>
308308
<name>VALUE</name>
309-
<description>mtime low.</description>
309+
<description>mtime low</description>
310310
<bitRange>[31:0]</bitRange>
311311
<access>read-write</access>
312312
</field>
@@ -320,21 +320,21 @@
320320
<fields>
321321
<field>
322322
<name>VALUE</name>
323-
<description>mtime high.</description>
323+
<description>mtime high</description>
324324
<bitRange>[31:0]</bitRange>
325325
<access>read-write</access>
326326
</field>
327327
</fields>
328328
</register>
329329
<register>
330-
<name>MTIMECMP</name>
331-
<description>mtime cmp</description>
330+
<name>MTIMECMPL</name>
331+
<description>mtime cmp low</description>
332332
<addressOffset>0x0008</addressOffset>
333333
<resetValue>0x00000000</resetValue>
334334
<fields>
335335
<field>
336336
<name>VALUE</name>
337-
<description>mtime cmp.</description>
337+
<description>mtime cmp low</description>
338338
<bitRange>[31:0]</bitRange>
339339
<access>read-write</access>
340340
</field>
@@ -348,7 +348,7 @@
348348
<fields>
349349
<field>
350350
<name>VALUE</name>
351-
<description>mtime cmp high.</description>
351+
<description>mtime cmp high</description>
352352
<bitRange>[31:0]</bitRange>
353353
<access>read-write</access>
354354
</field>

sw/rust/Cargo.lock

+19
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sw/rust/demo/pwm_hal/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ riscv-rt = "0.11.0"
1616
ibex-demo-system-hal = {path = "../../ibex-demo-system-hal"}
1717
embedded-hal = "0.2.7"
1818
smart-leds = "0.3.0"
19+
nb = "1.1.0"
20+
fugit = "0.3.7"

sw/rust/demo/pwm_hal/src/main.rs

+17-12
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@
88
extern crate panic_halt as _;
99

1010
use core::iter;
11-
use riscv::delay::McycleDelay;
11+
use embedded_hal::timer::CountDown;
1212
use riscv_rt::entry;
1313

1414
use embedded_hal;
15-
use embedded_hal::{blocking::delay::DelayMs, PwmPin};
15+
use embedded_hal::PwmPin;
1616

1717
use crate::hal::pac;
18+
use fugit::{ExtU32, RateExtU32};
1819
use ibex_demo_system_hal as hal;
1920

2021
use smart_leds as leds;
@@ -61,9 +62,11 @@ where
6162

6263
#[entry]
6364
fn main() -> ! {
64-
let mut delay = McycleDelay::new(CPU_CLOCK_HZ);
6565
let p = pac::Peripherals::take().unwrap();
6666

67+
let timer = hal::timer::Timer::new(p.TIMER0, CPU_CLOCK_HZ.Hz());
68+
let mut count_down = timer.new_count_down();
69+
6770
let pwm0 = hal::pwm::Pwm::new(p.PWM0);
6871
let pwm1 = hal::pwm::Pwm::new(p.PWM1);
6972
let pwm2 = hal::pwm::Pwm::new(p.PWM2);
@@ -83,16 +86,18 @@ fn main() -> ! {
8386
let mut led3 = RgbLed::new(pwm9, pwm10, pwm11);
8487

8588
let mut n: u8 = 128;
86-
89+
count_down.start(30u32.millis());
8790
loop {
88-
delay.delay_ms(30);
89-
90-
let color = wheel(n);
91-
n = n.wrapping_add(1);
92-
led0.set_color(color);
93-
led1.set_color(color);
94-
led2.set_color(color);
95-
led3.set_color(color);
91+
if count_down.wait().is_ok() {
92+
let color = wheel(n);
93+
n = n.wrapping_add(1);
94+
led0.set_color(color);
95+
led1.set_color(color);
96+
led2.set_color(color);
97+
led3.set_color(color);
98+
99+
count_down.start(30u32.millis());
100+
}
96101
}
97102
}
98103

sw/rust/ibex-demo-system-hal/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ edition = "2021"
1111

1212
[dependencies]
1313
embedded-hal = { features = ["unproven"], version = "0.2.7" }
14+
fugit = "0.3.7"
1415
ibex-demo-system-pac = {path = "../ibex-demo-system-pac"}
1516
nb = "1.1.0"
1617
riscv = "0.10.1"
18+
void = { version = "1.0.2", default-features = false }

sw/rust/ibex-demo-system-hal/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ pub mod gpio;
1212
pub mod pwm;
1313
pub mod serial;
1414
pub mod spi;
15+
pub mod timer;
1516
pub mod utils;
1617

1718
#[cfg(test)]
+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
use core::ops::Deref;
2+
use embedded_hal::timer;
3+
use fugit::{Hertz, NanosDurationU64};
4+
use ibex_demo_system_pac as pac;
5+
6+
pub struct Timer<T: Deref<Target = pac::timer0::RegisterBlock>> {
7+
device: T,
8+
clock_rate: Hertz<u64>,
9+
}
10+
11+
pub struct CountDown<'a, T: Deref<Target = pac::timer0::RegisterBlock>> {
12+
timer: &'a Timer<T>,
13+
timeout: Option<u64>,
14+
}
15+
16+
impl<T: Deref<Target = pac::timer0::RegisterBlock>> Timer<T> {
17+
pub fn new<H>(timer: T, clock_rate: H) -> Self
18+
where
19+
H: Into<Hertz<u64>>,
20+
{
21+
let mut timer = Self {
22+
device: timer,
23+
clock_rate: clock_rate.into(),
24+
};
25+
timer.set_counter(0);
26+
timer.set_cmp(u64::MAX);
27+
timer
28+
}
29+
30+
pub fn new_count_down(&self) -> CountDown<'_, T> {
31+
CountDown {
32+
timer: self,
33+
timeout: None,
34+
}
35+
}
36+
37+
pub fn get_counter(&self) -> u64 {
38+
let mut timeh;
39+
let mut timel;
40+
loop {
41+
timeh = self.device.mtimeh.read().value().bits();
42+
timel = self.device.mtimel.read().value().bits();
43+
if timeh == self.device.mtimeh.read().value().bits() {
44+
break;
45+
}
46+
}
47+
(timeh as u64) << 32 | (timel as u64)
48+
}
49+
50+
pub fn set_cmp(&mut self, value: u64) {
51+
self.device.mtimecmpl.write(|w| {
52+
w.value().variant(u32::MAX);
53+
w
54+
});
55+
self.device.mtimecmph.write(|w| {
56+
w.value().variant((value >> 32) as u32);
57+
w
58+
});
59+
self.device.mtimecmpl.write(|w| {
60+
w.value().variant((value) as u32);
61+
w
62+
});
63+
}
64+
65+
pub fn get_cmp(&self) -> u64 {
66+
let mut comph;
67+
let mut compl;
68+
loop {
69+
comph = self.device.mtimecmph.read().value().bits();
70+
compl = self.device.mtimecmpl.read().value().bits();
71+
if comph == self.device.mtimecmph.read().value().bits() {
72+
break;
73+
}
74+
}
75+
(comph as u64) << 32 | (compl as u64)
76+
}
77+
78+
pub fn set_counter(&mut self, value: u64) {
79+
self.device.mtimel.write(|w| {
80+
w.value().variant(u32::MAX);
81+
w
82+
});
83+
self.device.mtimeh.write(|w| {
84+
w.value().variant((value >> 32) as u32);
85+
w
86+
});
87+
self.device.mtimel.write(|w| {
88+
w.value().variant((value) as u32);
89+
w
90+
});
91+
}
92+
}
93+
94+
impl<U: Deref<Target = pac::timer0::RegisterBlock>> timer::CountDown for CountDown<'_, U> {
95+
type Time = NanosDurationU64;
96+
fn start<T>(&mut self, count: T)
97+
where
98+
T: Into<Self::Time>,
99+
{
100+
let count = count.into().to_nanos();
101+
let period: NanosDurationU64 = self.timer.clock_rate.into_duration();
102+
let period = period.to_nanos();
103+
104+
self.timeout = Some((count / period).wrapping_add(self.timer.get_counter()));
105+
}
106+
107+
fn wait(&mut self) -> nb::Result<(), void::Void> {
108+
let Some(timeout) = self.timeout else { panic!("Countdown not started"); };
109+
110+
if self.timer.get_counter() < timeout {
111+
return Err(nb::Error::WouldBlock);
112+
}
113+
Ok(())
114+
}
115+
}
116+
117+
impl<U: Deref<Target = pac::timer0::RegisterBlock>> timer::Cancel for CountDown<'_, U> {
118+
type Error = super::utils::Error;
119+
fn cancel(&mut self) -> Result<(), Self::Error> {
120+
self.timeout = None;
121+
Ok(())
122+
}
123+
}

0 commit comments

Comments
 (0)