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