sel4_sp804_driver/
device.rs

1//
2// Copyright 2023, Colias Group, LLC
3//
4// SPDX-License-Identifier: BSD-2-Clause
5//
6
7// TODO *const vs *mut
8
9use core::ops::Deref;
10
11use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
12use tock_registers::registers::{ReadOnly, ReadWrite, WriteOnly};
13use tock_registers::{register_bitfields, register_structs};
14
15register_structs! {
16    #[allow(non_snake_case)]
17    pub TimerRegisterBlock {
18        (0x00 => Load: ReadWrite<u32>),
19        (0x04 => Value: ReadWrite<u32>),
20        (0x08 => Control: ReadWrite<u32, Control::Register>),
21        (0x0c => IntClr: WriteOnly<u32>),
22        (0x10 => RIS: ReadOnly<u32, RIS::Register>),
23        (0x14 => MIS: ReadOnly<u32, MIS::Register>),
24        (0x18 => BGLoad: ReadWrite<u32>),
25        (0x1c => _reserved0),
26        (0x20 => @END),
27    }
28}
29
30register_bitfields! {
31    u32,
32
33    pub Control [
34        TimerEn OFFSET(7) NUMBITS(1) [
35            Disabled = 0,
36            Enabled = 1,
37        ],
38        TimerMode OFFSET(6) NUMBITS(1) [
39            FreeRunning = 0,
40            Periodic = 1,
41        ],
42        IntEnable OFFSET(5) NUMBITS(1) [
43            Disabled = 0,
44            Enabled = 1,
45        ],
46        TimerPre OFFSET(2) NUMBITS(2) [
47            Div1 = 0b00,
48            Div16 = 0b01,
49            Div256 = 0b10
50        ],
51        TimerSize OFFSET(1) NUMBITS(1) [
52            Use16Bit = 0,
53            Use32Bit = 1,
54        ],
55        OneShot OFFSET(0) NUMBITS(1) [
56            Wrapping = 0,
57            OneShot = 1,
58        ]
59    ],
60
61    RIS [
62        RIS OFFSET(0) NUMBITS(1) [],
63    ],
64
65    MIS [
66        MIS OFFSET(0) NUMBITS(1) [],
67    ],
68}
69
70pub struct Device {
71    timer_1: Timer,
72    timer_2: Timer,
73}
74
75impl Device {
76    pub const unsafe fn new(ptr: *const ()) -> Self {
77        let ptr = ptr.cast::<TimerRegisterBlock>();
78        Device {
79            timer_1: Timer::new(ptr.offset(0)),
80            timer_2: Timer::new(ptr.offset(1)),
81        }
82    }
83
84    pub fn timer_1(&self) -> &Timer {
85        &self.timer_1
86    }
87
88    pub fn timer_2(&self) -> &Timer {
89        &self.timer_2
90    }
91}
92
93pub struct Timer {
94    ptr: *const TimerRegisterBlock,
95}
96
97#[allow(dead_code)]
98impl Timer {
99    pub const unsafe fn new(ptr: *const TimerRegisterBlock) -> Self {
100        Self { ptr }
101    }
102
103    fn ptr(&self) -> *const TimerRegisterBlock {
104        self.ptr
105    }
106
107    pub fn get_load(&self) -> u32 {
108        self.Load.get()
109    }
110
111    pub fn set_load(&self, value: u32) {
112        self.Load.set(value)
113    }
114
115    pub fn current_value(&self) -> u32 {
116        self.Value.get()
117    }
118
119    pub fn control(&self) -> &ReadWrite<u32, Control::Register> {
120        &self.Control
121    }
122
123    pub fn set_free_running_mode(&self) {
124        self.Control
125            .modify(Control::TimerMode::FreeRunning + Control::OneShot::Wrapping)
126    }
127
128    pub fn set_periodic_mode(&self) {
129        self.Control
130            .modify(Control::TimerMode::Periodic + Control::OneShot::Wrapping)
131    }
132
133    pub fn set_one_shot_mode(&self) {
134        self.Control.modify(Control::OneShot::OneShot)
135    }
136
137    pub fn set_backgroun_load(&self, value: u32) {
138        self.BGLoad.set(value)
139    }
140
141    pub fn clear_interrupt(&self) {
142        let value = 1; // arbitrary
143        self.IntClr.set(value);
144    }
145
146    pub fn raw_interrupt_status(&self) -> bool {
147        self.RIS.read(RIS::RIS) != 0
148    }
149
150    pub fn masked_interrupt_status(&self) -> bool {
151        self.MIS.read(MIS::MIS) != 0
152    }
153}
154
155impl Deref for Timer {
156    type Target = TimerRegisterBlock;
157
158    fn deref(&self) -> &Self::Target {
159        unsafe { &*self.ptr() }
160    }
161}