1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
// Licensed under the Apache License, Version 2.0 or the MIT License.
// SPDX-License-Identifier: Apache-2.0 OR MIT
// Copyright Tock Contributors 2022.

//! Test that a Timer implementation is working by trying a few edge
//! cases on the interval, including intervals of 1 and 0. Depends
//! on a working UART and debug! macro. Tries repeating as well as
//! one-shot Timers.
//!
//! Author: Philip Levis <plevis@google.com>
//! Last Modified: 6/22/2020

use core::cell::Cell;

use kernel::debug;
use kernel::hil::time::{ConvertTicks, Ticks, Timer, TimerClient};

pub struct TestRandomTimer<'a, T: 'a> {
    timer: &'a T,
    interval: Cell<u32>,
    counter: Cell<u32>,
    iv: Cell<u32>,
    _id: char,
}

impl<'a, T: Timer<'a>> TestRandomTimer<'a, T> {
    pub fn new(timer: &'a T, value: usize, ch: char) -> TestRandomTimer<'a, T> {
        TestRandomTimer {
            timer,
            interval: Cell::new(0),
            counter: Cell::new(0),
            iv: Cell::new(value as u32),
            _id: ch,
        }
    }

    pub fn run(&self) {
        debug!("Starting random timer test Test{}.", self._id);
        self.set_next_timer();
    }

    fn set_next_timer(&self) {
        let iv = self.iv.get();
        self.iv.set(iv + 1);

        let counter = self.counter.get();
        if counter == 0 {
            let mut us: u32 = (iv * 745939) % 115843;
            if us % 11 == 0 {
                // Try delays of zero in 1 of 11 cases
                us = 0;
            }
            let new_interval = self.timer.ticks_from_us(us);
            self.interval.set(new_interval.into_u32());
            if us % 7 == 0 {
                let new_counter = 2 + self.interval.get() * 23 % 13;
                self.counter.set(new_counter);
                //debug!("Timer{} repeating with interval {}", self._id, self.interval.get());
                self.timer.repeating(new_interval);
            } else {
                //debug!("Timer{} oneshot with interval {}", self._id, self.interval.get());
                self.timer.oneshot(new_interval);
            }
        } else {
            self.counter.set(counter - 1);
        }
    }
}

impl<'a, T: Timer<'a>> TimerClient for TestRandomTimer<'a, T> {
    fn timer(&self) {
        debug!(
            "Timer{} fired with interval {}, count {},  fired at {}.",
            self._id,
            self.interval.get(),
            self.counter.get(),
            self.timer.now().into_u32()
        );
        self.set_next_timer();
    }
}