nrf52_components/
startup.rs1use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
11use core::mem::MaybeUninit;
12use kernel::component::Component;
13use nrf52::gpio::Pin;
14use nrf52::uicr::Regulator0Output;
15use segger::rtt::SeggerRtt;
16
17pub struct NrfStartupComponent<'a> {
18 nfc_as_gpios: bool,
19 button_rst_pin: Pin,
20 reg_vout: Regulator0Output,
21 nvmc: &'a nrf52::nvmc::Nvmc,
22}
23
24impl<'a> NrfStartupComponent<'a> {
25 pub fn new(
26 nfc_as_gpios: bool,
27 button_rst_pin: Pin,
28 reg_vout: Regulator0Output,
29 nvmc: &'a nrf52::nvmc::Nvmc,
30 ) -> Self {
31 Self {
32 nfc_as_gpios,
33 button_rst_pin,
34 reg_vout,
35 nvmc,
36 }
37 }
38}
39
40impl Component for NrfStartupComponent<'_> {
41 type StaticInput = ();
42 type Output = ();
43 fn finalize(self, _s: Self::StaticInput) -> Self::Output {
44 let approtect = nrf52::approtect::Approtect::new();
49 approtect.sw_disable_approtect();
50
51 let uicr = nrf52::uicr::Uicr::new();
53
54 let psel0_reset: u32 = uicr.get_psel0_reset_pin().map_or(0, |pin| pin as u32);
57 let psel1_reset: u32 = uicr.get_psel1_reset_pin().map_or(0, |pin| pin as u32);
58 let mut erase_uicr = ((!psel0_reset & (self.button_rst_pin as u32))
59 | (!psel1_reset & (self.button_rst_pin as u32))
60 | (!(uicr.get_vout() as u32) & (self.reg_vout as u32)))
61 != 0;
62
63 if self.nfc_as_gpios {
65 erase_uicr |= !uicr.is_nfc_pins_protection_enabled();
66 }
67
68 if uicr.is_ap_protect_enabled() {
71 erase_uicr = true;
72 }
73
74 if erase_uicr {
75 self.nvmc.erase_uicr();
76 }
77
78 self.nvmc.configure_writeable();
79 while !self.nvmc.is_ready() {}
80
81 let mut needs_soft_reset: bool = false;
82
83 if uicr
85 .get_psel0_reset_pin()
86 .is_none_or(|pin| pin != self.button_rst_pin)
87 {
88 uicr.set_psel0_reset_pin(self.button_rst_pin);
89 while !self.nvmc.is_ready() {}
90 needs_soft_reset = true;
91 }
92 if uicr
93 .get_psel1_reset_pin()
94 .is_none_or(|pin| pin != self.button_rst_pin)
95 {
96 uicr.set_psel1_reset_pin(self.button_rst_pin);
97 while !self.nvmc.is_ready() {}
98 needs_soft_reset = true;
99 }
100
101 if uicr.get_vout() != self.reg_vout {
103 uicr.set_vout(self.reg_vout);
104 while !self.nvmc.is_ready() {}
105 needs_soft_reset = true;
106 }
107
108 if self.nfc_as_gpios {
110 uicr.set_nfc_pins_protection(true);
111 while !self.nvmc.is_ready() {}
112 needs_soft_reset = true;
113 }
114
115 if uicr.is_ap_protect_enabled() {
117 uicr.disable_ap_protect();
118 while !self.nvmc.is_ready() {}
119 needs_soft_reset = true;
120 }
121
122 if needs_soft_reset {
124 unsafe {
125 cortexm4::scb::reset();
126 }
127 }
128 }
129}
130
131pub struct NrfClockComponent<'a> {
132 clock: &'a nrf52::clock::Clock,
133}
134
135impl<'a> NrfClockComponent<'a> {
136 pub fn new(clock: &'a nrf52::clock::Clock) -> Self {
137 Self { clock }
138 }
139}
140
141impl Component for NrfClockComponent<'_> {
142 type StaticInput = ();
143 type Output = ();
144 fn finalize(self, _s: Self::StaticInput) -> Self::Output {
145 self.clock.low_stop();
148 self.clock.high_stop();
149
150 self.clock
151 .low_set_source(nrf52::clock::LowClockSource::XTAL);
152 self.clock.low_start();
153 self.clock.high_start();
154 while !self.clock.low_started() {}
155 while !self.clock.high_started() {}
156 }
157}
158
159#[macro_export]
160macro_rules! uart_channel_component_static {
161 ($A:ty $(,)?) => {{
162 components::segger_rtt_component_static!($A)
163 };};
164}
165
166#[derive(Debug)]
168pub struct UartPins {
169 rts: Option<Pin>,
170 txd: Pin,
171 cts: Option<Pin>,
172 rxd: Pin,
173}
174
175impl UartPins {
176 pub fn new(rts: Option<Pin>, txd: Pin, cts: Option<Pin>, rxd: Pin) -> Self {
177 Self { rts, txd, cts, rxd }
178 }
179}
180
181pub enum UartChannel<'a> {
184 Pins(UartPins),
185 Rtt(components::segger_rtt::SeggerRttMemoryRefs<'a>),
186}
187
188pub struct UartChannelComponent {
189 uart_channel: UartChannel<'static>,
190 mux_alarm: &'static MuxAlarm<'static, nrf52::rtc::Rtc<'static>>,
191 uarte0: &'static nrf52::uart::Uarte<'static>,
192}
193
194impl UartChannelComponent {
195 pub fn new(
196 uart_channel: UartChannel<'static>,
197 mux_alarm: &'static MuxAlarm<'static, nrf52::rtc::Rtc<'static>>,
198 uarte0: &'static nrf52::uart::Uarte<'static>,
199 ) -> Self {
200 Self {
201 uart_channel,
202 mux_alarm,
203 uarte0,
204 }
205 }
206}
207
208impl Component for UartChannelComponent {
209 type StaticInput = (
210 &'static mut MaybeUninit<VirtualMuxAlarm<'static, nrf52::rtc::Rtc<'static>>>,
211 &'static mut MaybeUninit<
212 SeggerRtt<'static, VirtualMuxAlarm<'static, nrf52::rtc::Rtc<'static>>>,
213 >,
214 );
215 type Output = &'static dyn kernel::hil::uart::Uart<'static>;
216
217 fn finalize(self, s: Self::StaticInput) -> Self::Output {
218 match self.uart_channel {
219 UartChannel::Pins(uart_pins) => {
220 unsafe {
221 self.uarte0.initialize(
222 nrf52::pinmux::Pinmux::new(uart_pins.txd as u32),
223 nrf52::pinmux::Pinmux::new(uart_pins.rxd as u32),
224 uart_pins.cts.map(|x| nrf52::pinmux::Pinmux::new(x as u32)),
225 uart_pins.rts.map(|x| nrf52::pinmux::Pinmux::new(x as u32)),
226 )
227 };
228 self.uarte0
229 }
230 UartChannel::Rtt(rtt_memory) => {
231 let rtt =
232 components::segger_rtt::SeggerRttComponent::new(self.mux_alarm, rtt_memory)
233 .finalize(s);
234 rtt
235 }
236 }
237 }
238}