-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathlib.rs
More file actions
128 lines (107 loc) · 4.21 KB
/
lib.rs
File metadata and controls
128 lines (107 loc) · 4.21 KB
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#![feature(type_alias_impl_trait)]
use solid::{interrupt, singleton::pin_singleton, thread::CpuCx};
#[no_mangle]
pub extern "C" fn slo_main() {
println!("Starting LED blinker");
// Configure the LED port
green_led::init();
// Configure the AP804 instance
ap804::init(1_000_000);
// Tracks the latest LED state. Moved into the handler closure when
// we create `solid::interrupt::Handler`.
let mut state = false;
// Construct an interrupt handler object on a global variable
let handler = pin_singleton!(: Handler<_> = interrupt::Handler::new(
move |_: CpuCx<'_>| {
// Clear the AP804 instance's interrupt flag
ap804::clear_int();
// Determine the next LED state
state = !state;
// Toggle the LED
green_led::update(state);
},
))
.unwrap();
// Register the interrupt handler
assert!(
handler
.register_static(
&interrupt::HandlerOptions::new(ap804::INTNO, 10)
.with_level_triggered()
.with_target_processor(1)
)
.expect("unable to register interrupt handler"),
"interrupt handler was already registered"
);
// Enable the AP804 interrupt line
ap804::INTNO
.enable()
.expect("unable to enable interrupt line");
// Start the AP804 timer
ap804::start();
}
mod green_led {
use bcm2711_pac::gpio;
use tock_registers::interfaces::{ReadWriteable, Writeable};
const GPIO_NUM: usize = 42;
fn gpio_regs() -> &'static gpio::Registers {
// Safety: SOLID for RaPi4B provides an identity mapping in this area, and we don't alter
// the mapping
unsafe { &*(gpio::BASE.to_arm_pa().unwrap() as usize as *const gpio::Registers) }
}
pub fn init() {
// Configure the GPIO pin for output
gpio_regs().gpfsel[GPIO_NUM / gpio::GPFSEL::PINS_PER_REGISTER].modify(
gpio::GPFSEL::pin(GPIO_NUM % gpio::GPFSEL::PINS_PER_REGISTER).val(gpio::GPFSEL::OUTPUT),
);
}
pub fn update(new_state: bool) {
if new_state {
gpio_regs().gpset[GPIO_NUM / gpio::GPSET::PINS_PER_REGISTER]
.write(gpio::GPSET::set(GPIO_NUM % gpio::GPSET::PINS_PER_REGISTER));
} else {
gpio_regs().gpclr[GPIO_NUM / gpio::GPCLR::PINS_PER_REGISTER].write(gpio::GPCLR::clear(
GPIO_NUM % gpio::GPCLR::PINS_PER_REGISTER,
));
}
}
}
mod ap804 {
use bcm2711_pac::ap804;
use tock_registers::interfaces::Writeable;
pub const INTNO: solid::interrupt::Number = solid::interrupt::Number(64);
fn ap804_regs() -> &'static ap804::Registers {
// Safety: SOLID for RaPi4B provides an identity mapping in this area, and we don't alter
// the mapping
unsafe { &*(ap804::BASE.to_arm_pa().unwrap() as usize as *const ap804::Registers) }
}
pub fn init(load: u32) {
ap804_regs().control.write(
ap804::CONTROL::_32BIT::ThirtyTwoBitCounter
+ ap804::CONTROL::DIV::DivideBy1
+ ap804::CONTROL::IE::Disable
+ ap804::CONTROL::ENABLE::Disable
+ ap804::CONTROL::DBGHALT::KeepRunning
+ ap804::CONTROL::ENAFREE::Disable
+ ap804::CONTROL::FREEDIV.val(0x3e),
);
ap804_regs().load.set(load);
ap804_regs().reload.set(load);
ap804_regs().prediv.write(ap804::PREDIV::PREDIV.val(0x7d));
ap804_regs().irqcntl.write(ap804::IRQCNTL::INT::Clear);
}
pub fn start() {
ap804_regs().control.write(
ap804::CONTROL::_32BIT::ThirtyTwoBitCounter
+ ap804::CONTROL::DIV::DivideBy1
+ ap804::CONTROL::IE::Enable // <--
+ ap804::CONTROL::ENABLE::Enable // <--
+ ap804::CONTROL::DBGHALT::KeepRunning
+ ap804::CONTROL::ENAFREE::Disable
+ ap804::CONTROL::FREEDIV.val(0x3e),
);
}
pub fn clear_int() {
ap804_regs().irqcntl.write(ap804::IRQCNTL::INT::Clear);
}
}