1use core::ops::{Index, IndexMut};
8use core::sync::atomic::{AtomicUsize, Ordering};
9use kernel::hil;
10use kernel::hil::gpio;
11use kernel::utilities::StaticRef;
12use kernel::utilities::cells::OptionalCell;
13use kernel::utilities::registers::interfaces::{Readable, Writeable};
14use kernel::utilities::registers::{ReadOnly, ReadWrite, WriteOnly, register_structs};
15
16register_structs! {
17 Register {
18 (0x000 => val: ReadWrite<u32>),
19 (0x004 => set: WriteOnly<u32>),
20 (0x008 => clear: WriteOnly<u32>),
21 (0x00C => toggle: WriteOnly<u32>),
22 (0x010 => @END),
23 }
24}
25
26register_structs! {
27 RegisterRC {
28 (0x000 => val: ReadOnly<u32>),
29 (0x004 => reserved0),
30 (0x008 => clear: WriteOnly<u32>),
31 (0x00C => reserved1),
32 (0x010 => @END),
33 }
34}
35
36register_structs! {
37 GpioRegisters {
38 (0x000 => gper: Register),
39 (0x010 => pmr0: Register),
40 (0x020 => pmr1: Register),
41 (0x030 => pmr2: Register),
42 (0x040 => oder: Register),
43 (0x050 => ovr: Register),
44 (0x060 => pvr: ReadOnly<u32>),
45 (0x064 => _reserved0: [u32; 3]),
46 (0x070 => puer: Register),
47 (0x080 => pder: Register),
48 (0x090 => ier: Register),
49 (0x0A0 => imr0: Register),
50 (0x0B0 => imr1: Register),
51 (0x0C0 => gfer: Register),
52 (0x0D0 => ifr: RegisterRC),
53 (0x0E0 => _reserved1: [u32; 8]),
54 (0x100 => ocdr0: Register),
55 (0x110 => ocdr1: Register),
56 (0x120 => _reserved2: [u32; 4]),
57 (0x130 => osrr0: Register),
58 (0x140 => _reserved3: [u32; 8]),
59 (0x160 => ster: Register),
60 (0x170 => _reserved4),
61 (0x180 => ever: Register),
62 (0x190 => _reserved5),
63 (0x1F8 => parameter: u32),
64 (0x1FC => version: u32),
65 (0x200 => @END),
66 }
67}
68
69#[derive(Copy, Clone)]
78pub enum PeripheralFunction {
79 A,
80 B,
81 C,
82 D,
83 E,
84 F,
85 G,
86}
87
88const BASE_ADDRESS: usize = 0x400E1000;
89const SIZE: usize = 0x200;
90
91pub static INTERRUPT_COUNT: AtomicUsize = AtomicUsize::new(0);
102
103#[derive(Copy,Clone)]
110#[rustfmt::skip]
111pub enum Pin {
112 PA00, PA01, PA02, PA03, PA04, PA05, PA06, PA07,
113 PA08, PA09, PA10, PA11, PA12, PA13, PA14, PA15,
114 PA16, PA17, PA18, PA19, PA20, PA21, PA22, PA23,
115 PA24, PA25, PA26, PA27, PA28, PA29, PA30, PA31,
116
117 PB00, PB01, PB02, PB03, PB04, PB05, PB06, PB07,
118 PB08, PB09, PB10, PB11, PB12, PB13, PB14, PB15,
119 PB16, PB17, PB18, PB19, PB20, PB21, PB22, PB23,
120 PB24, PB25, PB26, PB27, PB28, PB29, PB30, PB31,
121
122 PC00, PC01, PC02, PC03, PC04, PC05, PC06, PC07,
123 PC08, PC09, PC10, PC11, PC12, PC13, PC14, PC15,
124 PC16, PC17, PC18, PC19, PC20, PC21, PC22, PC23,
125 PC24, PC25, PC26, PC27, PC28, PC29, PC30, PC31,
126}
127
128pub struct Port<'a> {
147 port: StaticRef<GpioRegisters>,
148 pins: [GPIOPin<'a>; 32],
149}
150
151impl<'a> Index<usize> for Port<'a> {
152 type Output = GPIOPin<'a>;
153
154 fn index(&self, index: usize) -> &GPIOPin<'a> {
155 &self.pins[index]
156 }
157}
158
159impl<'a> IndexMut<usize> for Port<'a> {
160 fn index_mut(&mut self, index: usize) -> &mut GPIOPin<'a> {
161 &mut self.pins[index]
162 }
163}
164
165impl Port<'_> {
166 pub const fn new_port_a() -> Self {
167 Self {
168 port: unsafe { StaticRef::new(BASE_ADDRESS as *const GpioRegisters) },
169 pins: [
170 GPIOPin::new(Pin::PA00),
171 GPIOPin::new(Pin::PA01),
172 GPIOPin::new(Pin::PA02),
173 GPIOPin::new(Pin::PA03),
174 GPIOPin::new(Pin::PA04),
175 GPIOPin::new(Pin::PA05),
176 GPIOPin::new(Pin::PA06),
177 GPIOPin::new(Pin::PA07),
178 GPIOPin::new(Pin::PA08),
179 GPIOPin::new(Pin::PA09),
180 GPIOPin::new(Pin::PA10),
181 GPIOPin::new(Pin::PA11),
182 GPIOPin::new(Pin::PA12),
183 GPIOPin::new(Pin::PA13),
184 GPIOPin::new(Pin::PA14),
185 GPIOPin::new(Pin::PA15),
186 GPIOPin::new(Pin::PA16),
187 GPIOPin::new(Pin::PA17),
188 GPIOPin::new(Pin::PA18),
189 GPIOPin::new(Pin::PA19),
190 GPIOPin::new(Pin::PA20),
191 GPIOPin::new(Pin::PA21),
192 GPIOPin::new(Pin::PA22),
193 GPIOPin::new(Pin::PA23),
194 GPIOPin::new(Pin::PA24),
195 GPIOPin::new(Pin::PA25),
196 GPIOPin::new(Pin::PA26),
197 GPIOPin::new(Pin::PA27),
198 GPIOPin::new(Pin::PA28),
199 GPIOPin::new(Pin::PA29),
200 GPIOPin::new(Pin::PA30),
201 GPIOPin::new(Pin::PA31),
202 ],
203 }
204 }
205
206 pub const fn new_port_b() -> Self {
207 Self {
208 port: unsafe { StaticRef::new((BASE_ADDRESS + 1 * SIZE) as *const GpioRegisters) },
209 pins: [
210 GPIOPin::new(Pin::PB00),
211 GPIOPin::new(Pin::PB01),
212 GPIOPin::new(Pin::PB02),
213 GPIOPin::new(Pin::PB03),
214 GPIOPin::new(Pin::PB04),
215 GPIOPin::new(Pin::PB05),
216 GPIOPin::new(Pin::PB06),
217 GPIOPin::new(Pin::PB07),
218 GPIOPin::new(Pin::PB08),
219 GPIOPin::new(Pin::PB09),
220 GPIOPin::new(Pin::PB10),
221 GPIOPin::new(Pin::PB11),
222 GPIOPin::new(Pin::PB12),
223 GPIOPin::new(Pin::PB13),
224 GPIOPin::new(Pin::PB14),
225 GPIOPin::new(Pin::PB15),
226 GPIOPin::new(Pin::PB16),
227 GPIOPin::new(Pin::PB17),
228 GPIOPin::new(Pin::PB18),
229 GPIOPin::new(Pin::PB19),
230 GPIOPin::new(Pin::PB20),
231 GPIOPin::new(Pin::PB21),
232 GPIOPin::new(Pin::PB22),
233 GPIOPin::new(Pin::PB23),
234 GPIOPin::new(Pin::PB24),
235 GPIOPin::new(Pin::PB25),
236 GPIOPin::new(Pin::PB26),
237 GPIOPin::new(Pin::PB27),
238 GPIOPin::new(Pin::PB28),
239 GPIOPin::new(Pin::PB29),
240 GPIOPin::new(Pin::PB30),
241 GPIOPin::new(Pin::PB31),
242 ],
243 }
244 }
245
246 pub const fn new_port_c() -> Self {
247 Self {
248 port: unsafe { StaticRef::new((BASE_ADDRESS + 2 * SIZE) as *const GpioRegisters) },
249 pins: [
250 GPIOPin::new(Pin::PC00),
251 GPIOPin::new(Pin::PC01),
252 GPIOPin::new(Pin::PC02),
253 GPIOPin::new(Pin::PC03),
254 GPIOPin::new(Pin::PC04),
255 GPIOPin::new(Pin::PC05),
256 GPIOPin::new(Pin::PC06),
257 GPIOPin::new(Pin::PC07),
258 GPIOPin::new(Pin::PC08),
259 GPIOPin::new(Pin::PC09),
260 GPIOPin::new(Pin::PC10),
261 GPIOPin::new(Pin::PC11),
262 GPIOPin::new(Pin::PC12),
263 GPIOPin::new(Pin::PC13),
264 GPIOPin::new(Pin::PC14),
265 GPIOPin::new(Pin::PC15),
266 GPIOPin::new(Pin::PC16),
267 GPIOPin::new(Pin::PC17),
268 GPIOPin::new(Pin::PC18),
269 GPIOPin::new(Pin::PC19),
270 GPIOPin::new(Pin::PC20),
271 GPIOPin::new(Pin::PC21),
272 GPIOPin::new(Pin::PC22),
273 GPIOPin::new(Pin::PC23),
274 GPIOPin::new(Pin::PC24),
275 GPIOPin::new(Pin::PC25),
276 GPIOPin::new(Pin::PC26),
277 GPIOPin::new(Pin::PC27),
278 GPIOPin::new(Pin::PC28),
279 GPIOPin::new(Pin::PC29),
280 GPIOPin::new(Pin::PC30),
281 GPIOPin::new(Pin::PC31),
282 ],
283 }
284 }
285
286 pub fn handle_interrupt(&self) {
287 let port: &GpioRegisters = &self.port;
288
289 let mut fired = port.ifr.val.get() & port.ier.val.get();
292 loop {
293 let pin = fired.trailing_zeros() as usize;
294 if pin < self.pins.len() {
295 fired &= !(1 << pin);
296 self.pins[pin].handle_interrupt();
297 port.ifr.clear.set(1 << pin);
298 } else {
299 break;
300 }
301 }
302 }
303}
304
305pub struct GPIOPin<'a> {
306 port: StaticRef<GpioRegisters>,
307 pin_mask: u32,
308 client: OptionalCell<&'a dyn hil::gpio::Client>,
309}
310
311impl<'a> GPIOPin<'a> {
312 pub const fn new(pin: Pin) -> GPIOPin<'a> {
313 GPIOPin {
314 port: unsafe {
315 StaticRef::new(
316 (BASE_ADDRESS + ((pin as usize) / 32) * SIZE) as *const GpioRegisters,
317 )
318 },
319 pin_mask: 1 << ((pin as u32) % 32),
320 client: OptionalCell::empty(),
321 }
322 }
323
324 pub fn set_client(&self, client: &'a dyn gpio::Client) {
325 self.client.set(client);
326 }
327
328 pub fn select_peripheral(&self, function: PeripheralFunction) {
329 let f = function as u32;
330 let (bit0, bit1, bit2) = (f & 0b1, (f & 0b10) >> 1, (f & 0b100) >> 2);
331 let port: &GpioRegisters = &self.port;
332
333 port.gper.clear.set(self.pin_mask);
335
336 if bit0 == 0 {
338 port.pmr0.clear.set(self.pin_mask);
339 } else {
340 port.pmr0.set.set(self.pin_mask);
341 }
342 if bit1 == 0 {
343 port.pmr1.clear.set(self.pin_mask);
344 } else {
345 port.pmr1.set.set(self.pin_mask);
346 }
347 if bit2 == 0 {
348 port.pmr2.clear.set(self.pin_mask);
349 } else {
350 port.pmr2.set.set(self.pin_mask);
351 }
352 }
353
354 pub fn enable(&self) {
355 let port: &GpioRegisters = &self.port;
356 port.gper.set.set(self.pin_mask);
357 }
358
359 pub fn disable(&self) {
360 let port: &GpioRegisters = &self.port;
361 port.gper.clear.set(self.pin_mask);
362 }
363
364 pub fn is_pending(&self) -> bool {
365 let port: &GpioRegisters = &self.port;
366 (port.ifr.val.get() & self.pin_mask) != 0
367 }
368
369 pub fn enable_output(&self) {
370 let port: &GpioRegisters = &self.port;
371 port.oder.set.set(self.pin_mask);
372 }
373
374 pub fn disable_output(&self) {
375 let port: &GpioRegisters = &self.port;
376 port.oder.clear.set(self.pin_mask);
377 }
378
379 pub fn enable_pull_down(&self) {
380 let port: &GpioRegisters = &self.port;
381 port.pder.set.set(self.pin_mask);
382 }
383
384 pub fn disable_pull_down(&self) {
385 let port: &GpioRegisters = &self.port;
386 port.pder.clear.set(self.pin_mask);
387 }
388
389 pub fn enable_pull_up(&self) {
390 let port: &GpioRegisters = &self.port;
391 port.puer.set.set(self.pin_mask);
392 }
393
394 pub fn disable_pull_up(&self) {
395 let port: &GpioRegisters = &self.port;
396 port.puer.clear.set(self.pin_mask);
397 }
398
399 pub fn set_interrupt_mode(&self, mode: u8) {
412 let port: &GpioRegisters = &self.port;
413 if mode & 0b01 != 0 {
414 port.imr0.set.set(self.pin_mask);
415 } else {
416 port.imr0.clear.set(self.pin_mask);
417 }
418
419 if mode & 0b10 != 0 {
420 port.imr1.set.set(self.pin_mask);
421 } else {
422 port.imr1.clear.set(self.pin_mask);
423 }
424 }
425
426 pub fn enable_interrupt(&self) {
427 let port: &GpioRegisters = &self.port;
428 if port.ier.val.get() & self.pin_mask == 0 {
429 INTERRUPT_COUNT.fetch_add(1, Ordering::Relaxed);
430 port.ier.set.set(self.pin_mask);
431 }
432 }
433
434 pub fn disable_interrupt(&self) {
435 let port: &GpioRegisters = &self.port;
436 if port.ier.val.get() & self.pin_mask != 0 {
437 INTERRUPT_COUNT.fetch_sub(1, Ordering::Relaxed);
438 port.ier.clear.set(self.pin_mask);
439 }
440 }
441
442 pub fn handle_interrupt(&self) {
443 self.client.map(|client| {
444 client.fired();
445 });
446 }
447
448 pub fn disable_schmidtt_trigger(&self) {
449 let port: &GpioRegisters = &self.port;
450 port.ster.clear.set(self.pin_mask);
451 }
452
453 pub fn enable_schmidtt_trigger(&self) {
454 let port: &GpioRegisters = &self.port;
455 port.ster.set.set(self.pin_mask);
456 }
457
458 pub fn read(&self) -> bool {
459 let port: &GpioRegisters = &self.port;
460 (port.pvr.get() & self.pin_mask) > 0
461 }
462
463 pub fn toggle(&self) -> bool {
464 let port: &GpioRegisters = &self.port;
465 port.ovr.toggle.set(self.pin_mask);
466 self.read()
467 }
468
469 pub fn set(&self) {
470 let port: &GpioRegisters = &self.port;
471 port.ovr.set.set(self.pin_mask);
472 }
473
474 pub fn clear(&self) {
475 let port: &GpioRegisters = &self.port;
476 port.ovr.clear.set(self.pin_mask);
477 }
478}
479
480impl hil::Controller for GPIOPin<'_> {
481 type Config = Option<PeripheralFunction>;
482
483 fn configure(&self, config: Self::Config) {
484 match config {
485 Some(c) => self.select_peripheral(c),
486 None => self.enable(),
487 }
488 }
489}
490
491impl gpio::Configure for GPIOPin<'_> {
492 fn set_floating_state(&self, mode: gpio::FloatingState) {
493 match mode {
494 gpio::FloatingState::PullUp => {
495 self.disable_pull_down();
496 self.enable_pull_up();
497 }
498 gpio::FloatingState::PullDown => {
499 self.disable_pull_up();
500 self.enable_pull_down();
501 }
502 gpio::FloatingState::PullNone => {
503 self.disable_pull_up();
504 self.disable_pull_down();
505 }
506 }
507 }
508
509 fn deactivate_to_low_power(&self) {
510 GPIOPin::disable(self);
511 }
512
513 fn make_output(&self) -> gpio::Configuration {
514 self.enable();
515 GPIOPin::enable_output(self);
516 self.disable_schmidtt_trigger();
517 gpio::Configuration::Output
518 }
519
520 fn make_input(&self) -> gpio::Configuration {
521 self.enable();
522 GPIOPin::disable_output(self);
523 self.enable_schmidtt_trigger();
524 gpio::Configuration::Input
525 }
526
527 fn disable_output(&self) -> gpio::Configuration {
528 let port: &GpioRegisters = &self.port;
529 port.oder.clear.set(self.pin_mask);
530 self.configuration()
531 }
532
533 fn disable_input(&self) -> gpio::Configuration {
534 self.configuration()
535 }
536
537 fn is_input(&self) -> bool {
538 let port: &GpioRegisters = &self.port;
539 port.gper.val.get() & self.pin_mask != 0
540 }
541
542 fn is_output(&self) -> bool {
543 let port: &GpioRegisters = &self.port;
544 port.oder.val.get() & self.pin_mask != 0
545 }
546
547 fn floating_state(&self) -> gpio::FloatingState {
548 let port: &GpioRegisters = &self.port;
549 let down = (port.pder.val.get() & self.pin_mask) != 0;
550 let up = (port.puer.val.get() & self.pin_mask) != 0;
551 if down {
552 gpio::FloatingState::PullDown
553 } else if up {
554 gpio::FloatingState::PullUp
555 } else {
556 gpio::FloatingState::PullNone
557 }
558 }
559
560 fn configuration(&self) -> gpio::Configuration {
561 let port: &GpioRegisters = &self.port;
562 let input = self.is_input();
563 let output = self.is_output();
564 let gpio = (port.gper.val.get() & self.pin_mask) == 1;
565 let config = (gpio, input, output);
566 match config {
567 (false, _, _) => gpio::Configuration::Function,
568 (true, false, false) => gpio::Configuration::Other,
569 (true, false, true) => gpio::Configuration::Output,
570 (true, true, false) => gpio::Configuration::Input,
571 (true, true, true) => gpio::Configuration::InputOutput,
572 }
573 }
574}
575
576impl gpio::Input for GPIOPin<'_> {
577 fn read(&self) -> bool {
578 GPIOPin::read(self)
579 }
580}
581
582impl gpio::Output for GPIOPin<'_> {
583 fn toggle(&self) -> bool {
584 GPIOPin::toggle(self)
585 }
586
587 fn set(&self) {
588 GPIOPin::set(self);
589 }
590
591 fn clear(&self) {
592 GPIOPin::clear(self);
593 }
594}
595
596impl<'a> gpio::Interrupt<'a> for GPIOPin<'a> {
597 fn enable_interrupts(&self, mode: gpio::InterruptEdge) {
598 let mode_bits = match mode {
599 hil::gpio::InterruptEdge::EitherEdge => 0b00,
600 hil::gpio::InterruptEdge::RisingEdge => 0b01,
601 hil::gpio::InterruptEdge::FallingEdge => 0b10,
602 };
603 GPIOPin::set_interrupt_mode(self, mode_bits);
604 GPIOPin::enable_interrupt(self);
605 }
606
607 fn disable_interrupts(&self) {
608 GPIOPin::disable_interrupt(self);
609 }
610
611 fn set_client(&self, client: &'a dyn gpio::Client) {
612 GPIOPin::set_client(self, client);
613 }
614
615 fn is_pending(&self) -> bool {
616 GPIOPin::is_pending(self)
617 }
618}