stm32f303xc/
gpio.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5use cortexm4f::support::atomic;
6use enum_primitive::cast::FromPrimitive;
7use enum_primitive::enum_from_primitive;
8use kernel::hil;
9use kernel::platform::chip::ClockInterface;
10use kernel::utilities::cells::OptionalCell;
11use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
12use kernel::utilities::registers::{register_bitfields, ReadOnly, ReadWrite, WriteOnly};
13use kernel::utilities::StaticRef;
14
15use crate::exti::{self, LineId};
16use crate::rcc;
17
18/// General-purpose I/Os
19#[repr(C)]
20struct GpioRegisters {
21    /// GPIO port mode register
22    moder: ReadWrite<u32, MODER::Register>,
23    /// GPIO port output type register
24    otyper: ReadWrite<u32, OTYPER::Register>,
25    /// GPIO port output speed register
26    ospeedr: ReadWrite<u32, OSPEEDR::Register>,
27    /// GPIO port pull-up/pull-down register
28    pupdr: ReadWrite<u32, PUPDR::Register>,
29    /// GPIO port input data register
30    idr: ReadOnly<u32, IDR::Register>,
31    /// GPIO port output data register
32    odr: ReadWrite<u32, ODR::Register>,
33    /// GPIO port bit set/reset register
34    bsrr: WriteOnly<u32, BSRR::Register>,
35    /// GPIO port configuration lock register
36    lckr: ReadWrite<u32, LCKR::Register>,
37    /// GPIO alternate function low register
38    afrl: ReadWrite<u32, AFRL::Register>,
39    /// GPIO alternate function high register
40    afrh: ReadWrite<u32, AFRH::Register>,
41}
42
43register_bitfields![u32,
44    MODER [
45        /// Port x configuration bits (y = 0..15)
46        MODER15 OFFSET(30) NUMBITS(2) [],
47        /// Port x configuration bits (y = 0..15)
48        MODER14 OFFSET(28) NUMBITS(2) [],
49        /// Port x configuration bits (y = 0..15)
50        MODER13 OFFSET(26) NUMBITS(2) [],
51        /// Port x configuration bits (y = 0..15)
52        MODER12 OFFSET(24) NUMBITS(2) [],
53        /// Port x configuration bits (y = 0..15)
54        MODER11 OFFSET(22) NUMBITS(2) [],
55        /// Port x configuration bits (y = 0..15)
56        MODER10 OFFSET(20) NUMBITS(2) [],
57        /// Port x configuration bits (y = 0..15)
58        MODER9 OFFSET(18) NUMBITS(2) [],
59        /// Port x configuration bits (y = 0..15)
60        MODER8 OFFSET(16) NUMBITS(2) [],
61        /// Port x configuration bits (y = 0..15)
62        MODER7 OFFSET(14) NUMBITS(2) [],
63        /// Port x configuration bits (y = 0..15)
64        MODER6 OFFSET(12) NUMBITS(2) [],
65        /// Port x configuration bits (y = 0..15)
66        MODER5 OFFSET(10) NUMBITS(2) [],
67        /// Port x configuration bits (y = 0..15)
68        MODER4 OFFSET(8) NUMBITS(2) [],
69        /// Port x configuration bits (y = 0..15)
70        MODER3 OFFSET(6) NUMBITS(2) [],
71        /// Port x configuration bits (y = 0..15)
72        MODER2 OFFSET(4) NUMBITS(2) [],
73        /// Port x configuration bits (y = 0..15)
74        MODER1 OFFSET(2) NUMBITS(2) [],
75        /// Port x configuration bits (y = 0..15)
76        MODER0 OFFSET(0) NUMBITS(2) []
77    ],
78    OTYPER [
79        /// Port x configuration bits (y = 0..15)
80        OT15 OFFSET(15) NUMBITS(1) [],
81        /// Port x configuration bits (y = 0..15)
82        OT14 OFFSET(14) NUMBITS(1) [],
83        /// Port x configuration bits (y = 0..15)
84        OT13 OFFSET(13) NUMBITS(1) [],
85        /// Port x configuration bits (y = 0..15)
86        OT12 OFFSET(12) NUMBITS(1) [],
87        /// Port x configuration bits (y = 0..15)
88        OT11 OFFSET(11) NUMBITS(1) [],
89        /// Port x configuration bits (y = 0..15)
90        OT10 OFFSET(10) NUMBITS(1) [],
91        /// Port x configuration bits (y = 0..15)
92        OT9 OFFSET(9) NUMBITS(1) [],
93        /// Port x configuration bits (y = 0..15)
94        OT8 OFFSET(8) NUMBITS(1) [],
95        /// Port x configuration bits (y = 0..15)
96        OT7 OFFSET(7) NUMBITS(1) [],
97        /// Port x configuration bits (y = 0..15)
98        OT6 OFFSET(6) NUMBITS(1) [],
99        /// Port x configuration bits (y = 0..15)
100        OT5 OFFSET(5) NUMBITS(1) [],
101        /// Port x configuration bits (y = 0..15)
102        OT4 OFFSET(4) NUMBITS(1) [],
103        /// Port x configuration bits (y = 0..15)
104        OT3 OFFSET(3) NUMBITS(1) [],
105        /// Port x configuration bits (y = 0..15)
106        OT2 OFFSET(2) NUMBITS(1) [],
107        /// Port x configuration bits (y = 0..15)
108        OT1 OFFSET(1) NUMBITS(1) [],
109        /// Port x configuration bits (y = 0..15)
110        OT0 OFFSET(0) NUMBITS(1) []
111    ],
112    OSPEEDR [
113        /// Port x configuration bits (y = 0..15)
114        OSPEEDR15 OFFSET(30) NUMBITS(2) [],
115        /// Port x configuration bits (y = 0..15)
116        OSPEEDR14 OFFSET(28) NUMBITS(2) [],
117        /// Port x configuration bits (y = 0..15)
118        OSPEEDR13 OFFSET(26) NUMBITS(2) [],
119        /// Port x configuration bits (y = 0..15)
120        OSPEEDR12 OFFSET(24) NUMBITS(2) [],
121        /// Port x configuration bits (y = 0..15)
122        OSPEEDR11 OFFSET(22) NUMBITS(2) [],
123        /// Port x configuration bits (y = 0..15)
124        OSPEEDR10 OFFSET(20) NUMBITS(2) [],
125        /// Port x configuration bits (y = 0..15)
126        OSPEEDR9 OFFSET(18) NUMBITS(2) [],
127        /// Port x configuration bits (y = 0..15)
128        OSPEEDR8 OFFSET(16) NUMBITS(2) [],
129        /// Port x configuration bits (y = 0..15)
130        OSPEEDR7 OFFSET(14) NUMBITS(2) [],
131        /// Port x configuration bits (y = 0..15)
132        OSPEEDR6 OFFSET(12) NUMBITS(2) [],
133        /// Port x configuration bits (y = 0..15)
134        OSPEEDR5 OFFSET(10) NUMBITS(2) [],
135        /// Port x configuration bits (y = 0..15)
136        OSPEEDR4 OFFSET(8) NUMBITS(2) [],
137        /// Port x configuration bits (y = 0..15)
138        OSPEEDR3 OFFSET(6) NUMBITS(2) [],
139        /// Port x configuration bits (y = 0..15)
140        OSPEEDR2 OFFSET(4) NUMBITS(2) [],
141        /// Port x configuration bits (y = 0..15)
142        OSPEEDR1 OFFSET(2) NUMBITS(2) [],
143        /// Port x configuration bits (y = 0..15)
144        OSPEEDR0 OFFSET(0) NUMBITS(2) []
145    ],
146    PUPDR [
147        /// Port x configuration bits (y = 0..15)
148        PUPDR15 OFFSET(30) NUMBITS(2) [],
149        /// Port x configuration bits (y = 0..15)
150        PUPDR14 OFFSET(28) NUMBITS(2) [],
151        /// Port x configuration bits (y = 0..15)
152        PUPDR13 OFFSET(26) NUMBITS(2) [],
153        /// Port x configuration bits (y = 0..15)
154        PUPDR12 OFFSET(24) NUMBITS(2) [],
155        /// Port x configuration bits (y = 0..15)
156        PUPDR11 OFFSET(22) NUMBITS(2) [],
157        /// Port x configuration bits (y = 0..15)
158        PUPDR10 OFFSET(20) NUMBITS(2) [],
159        /// Port x configuration bits (y = 0..15)
160        PUPDR9 OFFSET(18) NUMBITS(2) [],
161        /// Port x configuration bits (y = 0..15)
162        PUPDR8 OFFSET(16) NUMBITS(2) [],
163        /// Port x configuration bits (y = 0..15)
164        PUPDR7 OFFSET(14) NUMBITS(2) [],
165        /// Port x configuration bits (y = 0..15)
166        PUPDR6 OFFSET(12) NUMBITS(2) [],
167        /// Port x configuration bits (y = 0..15)
168        PUPDR5 OFFSET(10) NUMBITS(2) [],
169        /// Port x configuration bits (y = 0..15)
170        PUPDR4 OFFSET(8) NUMBITS(2) [],
171        /// Port x configuration bits (y = 0..15)
172        PUPDR3 OFFSET(6) NUMBITS(2) [],
173        /// Port x configuration bits (y = 0..15)
174        PUPDR2 OFFSET(4) NUMBITS(2) [],
175        /// Port x configuration bits (y = 0..15)
176        PUPDR1 OFFSET(2) NUMBITS(2) [],
177        /// Port x configuration bits (y = 0..15)
178        PUPDR0 OFFSET(0) NUMBITS(2) []
179    ],
180    IDR [
181        /// Port input data (y = 0..15)
182        IDR15 OFFSET(15) NUMBITS(1) [],
183        /// Port input data (y = 0..15)
184        IDR14 OFFSET(14) NUMBITS(1) [],
185        /// Port input data (y = 0..15)
186        IDR13 OFFSET(13) NUMBITS(1) [],
187        /// Port input data (y = 0..15)
188        IDR12 OFFSET(12) NUMBITS(1) [],
189        /// Port input data (y = 0..15)
190        IDR11 OFFSET(11) NUMBITS(1) [],
191        /// Port input data (y = 0..15)
192        IDR10 OFFSET(10) NUMBITS(1) [],
193        /// Port input data (y = 0..15)
194        IDR9 OFFSET(9) NUMBITS(1) [],
195        /// Port input data (y = 0..15)
196        IDR8 OFFSET(8) NUMBITS(1) [],
197        /// Port input data (y = 0..15)
198        IDR7 OFFSET(7) NUMBITS(1) [],
199        /// Port input data (y = 0..15)
200        IDR6 OFFSET(6) NUMBITS(1) [],
201        /// Port input data (y = 0..15)
202        IDR5 OFFSET(5) NUMBITS(1) [],
203        /// Port input data (y = 0..15)
204        IDR4 OFFSET(4) NUMBITS(1) [],
205        /// Port input data (y = 0..15)
206        IDR3 OFFSET(3) NUMBITS(1) [],
207        /// Port input data (y = 0..15)
208        IDR2 OFFSET(2) NUMBITS(1) [],
209        /// Port input data (y = 0..15)
210        IDR1 OFFSET(1) NUMBITS(1) [],
211        /// Port input data (y = 0..15)
212        IDR0 OFFSET(0) NUMBITS(1) []
213    ],
214    ODR [
215        /// Port output data (y = 0..15)
216        ODR15 OFFSET(15) NUMBITS(1) [],
217        /// Port output data (y = 0..15)
218        ODR14 OFFSET(14) NUMBITS(1) [],
219        /// Port output data (y = 0..15)
220        ODR13 OFFSET(13) NUMBITS(1) [],
221        /// Port output data (y = 0..15)
222        ODR12 OFFSET(12) NUMBITS(1) [],
223        /// Port output data (y = 0..15)
224        ODR11 OFFSET(11) NUMBITS(1) [],
225        /// Port output data (y = 0..15)
226        ODR10 OFFSET(10) NUMBITS(1) [],
227        /// Port output data (y = 0..15)
228        ODR9 OFFSET(9) NUMBITS(1) [],
229        /// Port output data (y = 0..15)
230        ODR8 OFFSET(8) NUMBITS(1) [],
231        /// Port output data (y = 0..15)
232        ODR7 OFFSET(7) NUMBITS(1) [],
233        /// Port output data (y = 0..15)
234        ODR6 OFFSET(6) NUMBITS(1) [],
235        /// Port output data (y = 0..15)
236        ODR5 OFFSET(5) NUMBITS(1) [],
237        /// Port output data (y = 0..15)
238        ODR4 OFFSET(4) NUMBITS(1) [],
239        /// Port output data (y = 0..15)
240        ODR3 OFFSET(3) NUMBITS(1) [],
241        /// Port output data (y = 0..15)
242        ODR2 OFFSET(2) NUMBITS(1) [],
243        /// Port output data (y = 0..15)
244        ODR1 OFFSET(1) NUMBITS(1) [],
245        /// Port output data (y = 0..15)
246        ODR0 OFFSET(0) NUMBITS(1) []
247    ],
248    BSRR [
249        /// Port x reset bit y (y = 0..15)
250        BR15 OFFSET(31) NUMBITS(1) [],
251        /// Port x reset bit y (y = 0..15)
252        BR14 OFFSET(30) NUMBITS(1) [],
253        /// Port x reset bit y (y = 0..15)
254        BR13 OFFSET(29) NUMBITS(1) [],
255        /// Port x reset bit y (y = 0..15)
256        BR12 OFFSET(28) NUMBITS(1) [],
257        /// Port x reset bit y (y = 0..15)
258        BR11 OFFSET(27) NUMBITS(1) [],
259        /// Port x reset bit y (y = 0..15)
260        BR10 OFFSET(26) NUMBITS(1) [],
261        /// Port x reset bit y (y = 0..15)
262        BR9 OFFSET(25) NUMBITS(1) [],
263        /// Port x reset bit y (y = 0..15)
264        BR8 OFFSET(24) NUMBITS(1) [],
265        /// Port x reset bit y (y = 0..15)
266        BR7 OFFSET(23) NUMBITS(1) [],
267        /// Port x reset bit y (y = 0..15)
268        BR6 OFFSET(22) NUMBITS(1) [],
269        /// Port x reset bit y (y = 0..15)
270        BR5 OFFSET(21) NUMBITS(1) [],
271        /// Port x reset bit y (y = 0..15)
272        BR4 OFFSET(20) NUMBITS(1) [],
273        /// Port x reset bit y (y = 0..15)
274        BR3 OFFSET(19) NUMBITS(1) [],
275        /// Port x reset bit y (y = 0..15)
276        BR2 OFFSET(18) NUMBITS(1) [],
277        /// Port x reset bit y (y = 0..15)
278        BR1 OFFSET(17) NUMBITS(1) [],
279        /// Port x set bit y (y= 0..15)
280        BR0 OFFSET(16) NUMBITS(1) [],
281        /// Port x set bit y (y= 0..15)
282        BS15 OFFSET(15) NUMBITS(1) [],
283        /// Port x set bit y (y= 0..15)
284        BS14 OFFSET(14) NUMBITS(1) [],
285        /// Port x set bit y (y= 0..15)
286        BS13 OFFSET(13) NUMBITS(1) [],
287        /// Port x set bit y (y= 0..15)
288        BS12 OFFSET(12) NUMBITS(1) [],
289        /// Port x set bit y (y= 0..15)
290        BS11 OFFSET(11) NUMBITS(1) [],
291        /// Port x set bit y (y= 0..15)
292        BS10 OFFSET(10) NUMBITS(1) [],
293        /// Port x set bit y (y= 0..15)
294        BS9 OFFSET(9) NUMBITS(1) [],
295        /// Port x set bit y (y= 0..15)
296        BS8 OFFSET(8) NUMBITS(1) [],
297        /// Port x set bit y (y= 0..15)
298        BS7 OFFSET(7) NUMBITS(1) [],
299        /// Port x set bit y (y= 0..15)
300        BS6 OFFSET(6) NUMBITS(1) [],
301        /// Port x set bit y (y= 0..15)
302        BS5 OFFSET(5) NUMBITS(1) [],
303        /// Port x set bit y (y= 0..15)
304        BS4 OFFSET(4) NUMBITS(1) [],
305        /// Port x set bit y (y= 0..15)
306        BS3 OFFSET(3) NUMBITS(1) [],
307        /// Port x set bit y (y= 0..15)
308        BS2 OFFSET(2) NUMBITS(1) [],
309        /// Port x set bit y (y= 0..15)
310        BS1 OFFSET(1) NUMBITS(1) [],
311        /// Port x set bit y (y= 0..15)
312        BS0 OFFSET(0) NUMBITS(1) []
313    ],
314    LCKR [
315        /// Port x lock bit y (y= 0..15)
316        LCKK OFFSET(16) NUMBITS(1) [],
317        /// Port x lock bit y (y= 0..15)
318        LCK15 OFFSET(15) NUMBITS(1) [],
319        /// Port x lock bit y (y= 0..15)
320        LCK14 OFFSET(14) NUMBITS(1) [],
321        /// Port x lock bit y (y= 0..15)
322        LCK13 OFFSET(13) NUMBITS(1) [],
323        /// Port x lock bit y (y= 0..15)
324        LCK12 OFFSET(12) NUMBITS(1) [],
325        /// Port x lock bit y (y= 0..15)
326        LCK11 OFFSET(11) NUMBITS(1) [],
327        /// Port x lock bit y (y= 0..15)
328        LCK10 OFFSET(10) NUMBITS(1) [],
329        /// Port x lock bit y (y= 0..15)
330        LCK9 OFFSET(9) NUMBITS(1) [],
331        /// Port x lock bit y (y= 0..15)
332        LCK8 OFFSET(8) NUMBITS(1) [],
333        /// Port x lock bit y (y= 0..15)
334        LCK7 OFFSET(7) NUMBITS(1) [],
335        /// Port x lock bit y (y= 0..15)
336        LCK6 OFFSET(6) NUMBITS(1) [],
337        /// Port x lock bit y (y= 0..15)
338        LCK5 OFFSET(5) NUMBITS(1) [],
339        /// Port x lock bit y (y= 0..15)
340        LCK4 OFFSET(4) NUMBITS(1) [],
341        /// Port x lock bit y (y= 0..15)
342        LCK3 OFFSET(3) NUMBITS(1) [],
343        /// Port x lock bit y (y= 0..15)
344        LCK2 OFFSET(2) NUMBITS(1) [],
345        /// Port x lock bit y (y= 0..15)
346        LCK1 OFFSET(1) NUMBITS(1) [],
347        /// Port x lock bit y (y= 0..15)
348        LCK0 OFFSET(0) NUMBITS(1) []
349    ],
350    AFRL [
351        /// Alternate function selection for port x bit y (y = 0..7)
352        AFRL7 OFFSET(28) NUMBITS(4) [],
353        /// Alternate function selection for port x bit y (y = 0..7)
354        AFRL6 OFFSET(24) NUMBITS(4) [],
355        /// Alternate function selection for port x bit y (y = 0..7)
356        AFRL5 OFFSET(20) NUMBITS(4) [],
357        /// Alternate function selection for port x bit y (y = 0..7)
358        AFRL4 OFFSET(16) NUMBITS(4) [],
359        /// Alternate function selection for port x bit y (y = 0..7)
360        AFRL3 OFFSET(12) NUMBITS(4) [],
361        /// Alternate function selection for port x bit y (y = 0..7)
362        AFRL2 OFFSET(8) NUMBITS(4) [],
363        /// Alternate function selection for port x bit y (y = 0..7)
364        AFRL1 OFFSET(4) NUMBITS(4) [],
365        /// Alternate function selection for port x bit y (y = 0..7)
366        AFRL0 OFFSET(0) NUMBITS(4) []
367    ],
368    AFRH [
369        /// Alternate function selection for port x bit y (y = 8..15)
370        AFRH15 OFFSET(28) NUMBITS(4) [],
371        /// Alternate function selection for port x bit y (y = 8..15)
372        AFRH14 OFFSET(24) NUMBITS(4) [],
373        /// Alternate function selection for port x bit y (y = 8..15)
374        AFRH13 OFFSET(20) NUMBITS(4) [],
375        /// Alternate function selection for port x bit y (y = 8..15)
376        AFRH12 OFFSET(16) NUMBITS(4) [],
377        /// Alternate function selection for port x bit y (y = 8..15)
378        AFRH11 OFFSET(12) NUMBITS(4) [],
379        /// Alternate function selection for port x bit y (y = 8..15)
380        AFRH10 OFFSET(8) NUMBITS(4) [],
381        /// Alternate function selection for port x bit y (y = 8..15)
382        AFRH9 OFFSET(4) NUMBITS(4) [],
383        /// Alternate function selection for port x bit y (y = 8..15)
384        AFRH8 OFFSET(0) NUMBITS(4) []
385    ]
386];
387
388const GPIOF_BASE: StaticRef<GpioRegisters> =
389    unsafe { StaticRef::new(0x48001400 as *const GpioRegisters) };
390
391const GPIOE_BASE: StaticRef<GpioRegisters> =
392    unsafe { StaticRef::new(0x48001000 as *const GpioRegisters) };
393
394const GPIOD_BASE: StaticRef<GpioRegisters> =
395    unsafe { StaticRef::new(0x48000C00 as *const GpioRegisters) };
396
397const GPIOC_BASE: StaticRef<GpioRegisters> =
398    unsafe { StaticRef::new(0x48000800 as *const GpioRegisters) };
399
400const GPIOB_BASE: StaticRef<GpioRegisters> =
401    unsafe { StaticRef::new(0x48000400 as *const GpioRegisters) };
402
403const GPIOA_BASE: StaticRef<GpioRegisters> =
404    unsafe { StaticRef::new(0x48000000 as *const GpioRegisters) };
405
406/// STM32F303VCT6 has six GPIO ports labeled from A-F [^1]. This is represented
407/// by three bits.
408///
409/// [^1]: Figure 20. STM32F303xB/C table, page 54 of the datasheet
410#[repr(u32)]
411pub enum PortId {
412    A = 0b000,
413    B = 0b001,
414    C = 0b010,
415    D = 0b011,
416    E = 0b100,
417    F = 0b101,
418}
419
420/// Name of the GPIO pin on the STM32303vct6.
421///
422/// The "Pinout and pin description" section [^1] of the STM32303vct6 datasheet
423/// shows the mapping between the names and the hardware pins on different chip
424/// packages.
425///
426/// The first three bits represent the port and last four bits represent the
427/// pin.
428///
429/// [^1]: Section 4, Pinout and pin description, pages 41-45
430#[rustfmt::skip]
431#[repr(u8)]
432#[derive(Copy, Clone)]
433pub enum PinId {
434    PA00 = 0b0000000, PA01 = 0b0000001, PA02 = 0b0000010, PA03 = 0b0000011,
435    PA04 = 0b0000100, PA05 = 0b0000101, PA06 = 0b0000110, PA07 = 0b0000111,
436    PA08 = 0b0001000, PA09 = 0b0001001, PA10 = 0b0001010, PA11 = 0b0001011,
437    PA12 = 0b0001100, PA13 = 0b0001101, PA14 = 0b0001110, PA15 = 0b0001111,
438
439    PB00 = 0b0010000, PB01 = 0b0010001, PB02 = 0b0010010, PB03 = 0b0010011,
440    PB04 = 0b0010100, PB05 = 0b0010101, PB06 = 0b0010110, PB07 = 0b0010111,
441    PB08 = 0b0011000, PB09 = 0b0011001, PB10 = 0b0011010, PB11 = 0b0011011,
442    PB12 = 0b0011100, PB13 = 0b0011101, PB14 = 0b0011110, PB15 = 0b0011111,
443
444    PC00 = 0b0100000, PC01 = 0b0100001, PC02 = 0b0100010, PC03 = 0b0100011,
445    PC04 = 0b0100100, PC05 = 0b0100101, PC06 = 0b0100110, PC07 = 0b0100111,
446    PC08 = 0b0101000, PC09 = 0b0101001, PC10 = 0b0101010, PC11 = 0b0101011,
447    PC12 = 0b0101100, PC13 = 0b0101101, PC14 = 0b0101110, PC15 = 0b0101111,
448
449    PD00 = 0b0110000, PD01 = 0b0110001, PD02 = 0b0110010, PD03 = 0b0110011,
450    PD04 = 0b0110100, PD05 = 0b0110101, PD06 = 0b0110110, PD07 = 0b0110111,
451    PD08 = 0b0111000, PD09 = 0b0111001, PD10 = 0b0111010, PD11 = 0b0111011,
452    PD12 = 0b0111100, PD13 = 0b0111101, PD14 = 0b0111110, PD15 = 0b0111111,
453
454    PE00 = 0b1000000, PE01 = 0b1000001, PE02 = 0b1000010, PE03 = 0b1000011,
455    PE04 = 0b1000100, PE05 = 0b1000101, PE06 = 0b1000110, PE07 = 0b1000111,
456    PE08 = 0b1001000, PE09 = 0b1001001, PE10 = 0b1001010, PE11 = 0b1001011,
457    PE12 = 0b1001100, PE13 = 0b1001101, PE14 = 0b1001110, PE15 = 0b1001111,
458
459    PF00 = 0b1010000, PF01 = 0b1010001, PF02 = 0b1010010, PF03 = 0b1010011,
460    PF04 = 0b1010100, PF05 = 0b1010101, PF06 = 0b1010110, PF07 = 0b1010111,
461    PF08 = 0b1011000, PF09 = 0b1011001, PF10 = 0b1011010, PF11 = 0b1011011,
462    PF12 = 0b1011100, PF13 = 0b1011101, PF14 = 0b1011110, PF15 = 0b1011111,
463}
464
465impl<'a> GpioPorts<'a> {
466    pub fn get_pin(&self, pinid: PinId) -> Option<&Pin<'a>> {
467        let mut port_num: u8 = pinid as u8;
468
469        // Right shift p by 4 bits, so we can get rid of pin bits
470        port_num >>= 4;
471
472        let mut pin_num: u8 = pinid as u8;
473        // Mask top 3 bits, so can get only the suffix
474        pin_num &= 0b0001111;
475
476        self.pins[usize::from(port_num)][usize::from(pin_num)].as_ref()
477    }
478
479    pub fn get_port(&self, pinid: PinId) -> &Port {
480        let mut port_num: u8 = pinid as u8;
481
482        // Right shift p by 4 bits, so we can get rid of pin bits
483        port_num >>= 4;
484        &self.ports[usize::from(port_num)]
485    }
486
487    pub fn get_port_from_port_id(&self, portid: PortId) -> &Port {
488        &self.ports[portid as usize]
489    }
490}
491
492impl PinId {
493    // extract the last 4 bits. [3:0] is the pin number, [6:4] is the port
494    // number
495    pub fn get_pin_number(&self) -> u8 {
496        let mut pin_num = *self as u8;
497
498        pin_num &= 0b00001111;
499        pin_num
500    }
501
502    // extract bits [6:4], which is the port number
503    pub fn get_port_number(&self) -> u8 {
504        let mut port_num: u8 = *self as u8;
505
506        // Right shift p by 4 bits, so we can get rid of pin bits
507        port_num >>= 4;
508        port_num
509    }
510}
511
512enum_from_primitive! {
513    #[repr(u32)]
514    #[derive(PartialEq)]
515    /// GPIO pin mode [^1]
516    ///
517    /// [^1]: Section 7.1.4, page 187 of reference manual
518    pub enum Mode {
519        Input = 0b00,
520        GeneralPurposeOutputMode = 0b01,
521        AlternateFunctionMode = 0b10,
522        AnalogMode = 0b11,
523    }
524}
525
526/// Alternate functions that may be assigned to a `Pin`.
527///
528/// GPIO pins on the STM32303vct6 may serve multiple functions. In addition to
529/// the default functionality, each pin can be assigned up to sixteen different
530/// alternate functions. The various functions for each pin are described in
531/// "Alternate Function"" section of the STM32303vct6 datasheet[^1].
532///
533/// Alternate Function bit mapping is shown here[^2].
534///
535/// [^1]: Section 4, Pinout and pin description, Table 14. Alternate function,
536///       pages 45-52
537///
538/// [^2]: Section 7.4.9, page 192 of Reference Manual // TODO
539#[repr(u32)]
540pub enum AlternateFunction {
541    AF0 = 0b0000,
542    AF1 = 0b0001,
543    AF2 = 0b0010,
544    AF3 = 0b0011,
545    AF4 = 0b0100,
546    AF5 = 0b0101,
547    AF6 = 0b0110,
548    AF7 = 0b0111,
549    AF8 = 0b1000,
550    AF9 = 0b1001,
551    AF10 = 0b1010,
552    AF11 = 0b1011,
553    AF12 = 0b1100,
554    AF13 = 0b1101,
555    AF14 = 0b1110,
556    AF15 = 0b1111,
557}
558
559enum_from_primitive! {
560    #[repr(u32)]
561    /// GPIO pin internal pull-up and pull-down [^1]
562    ///
563    /// [^1]: Section 11.4.4, page 238 of reference manual
564    enum PullUpPullDown {
565        NoPullUpPullDown = 0b00,
566        PullUp = 0b01,
567        PullDown = 0b10,
568    }
569}
570
571macro_rules! declare_gpio_pins {
572    ($($pin:ident)*, $exti:expr) => {
573        [
574            $(Some(Pin::new(PinId::$pin, $exti)), )*
575        ]
576    }
577}
578
579// Note: This would probably be better structured as each port holding
580// the pins associated with it, but here they are kept separate for
581// historical reasons. If writing new GPIO code, look elsewhere for
582// a template on how to structure the relationship between ports and pins.
583pub struct GpioPorts<'a> {
584    ports: [Port<'a>; 6],
585    pins: [[Option<Pin<'a>>; 16]; 6],
586}
587
588impl<'a> GpioPorts<'a> {
589    pub fn new(rcc: &'a rcc::Rcc, exti: &'a exti::Exti<'a>) -> Self {
590        Self {
591            ports: [
592                Port {
593                    registers: GPIOA_BASE,
594                    clock: PortClock(rcc::PeripheralClock::new(
595                        rcc::PeripheralClockType::AHB(rcc::HCLK::GPIOA),
596                        rcc,
597                    )),
598                },
599                Port {
600                    registers: GPIOB_BASE,
601                    clock: PortClock(rcc::PeripheralClock::new(
602                        rcc::PeripheralClockType::AHB(rcc::HCLK::GPIOB),
603                        rcc,
604                    )),
605                },
606                Port {
607                    registers: GPIOC_BASE,
608                    clock: PortClock(rcc::PeripheralClock::new(
609                        rcc::PeripheralClockType::AHB(rcc::HCLK::GPIOC),
610                        rcc,
611                    )),
612                },
613                Port {
614                    registers: GPIOD_BASE,
615                    clock: PortClock(rcc::PeripheralClock::new(
616                        rcc::PeripheralClockType::AHB(rcc::HCLK::GPIOD),
617                        rcc,
618                    )),
619                },
620                Port {
621                    registers: GPIOE_BASE,
622                    clock: PortClock(rcc::PeripheralClock::new(
623                        rcc::PeripheralClockType::AHB(rcc::HCLK::GPIOE),
624                        rcc,
625                    )),
626                },
627                Port {
628                    registers: GPIOF_BASE,
629                    clock: PortClock(rcc::PeripheralClock::new(
630                        rcc::PeripheralClockType::AHB(rcc::HCLK::GPIOF),
631                        rcc,
632                    )),
633                },
634            ],
635            pins: [
636                declare_gpio_pins! {
637                    PA00 PA01 PA02 PA03 PA04 PA05 PA06 PA07
638                    PA08 PA09 PA10 PA11 PA12 PA13 PA14 PA15, exti
639                },
640                declare_gpio_pins! {
641                    PB00 PB01 PB02 PB03 PB04 PB05 PB06 PB07
642                    PB08 PB09 PB10 PB11 PB12 PB13 PB14 PB15, exti
643                },
644                declare_gpio_pins! {
645                    PC00 PC01 PC02 PC03 PC04 PC05 PC06 PC07
646                    PC08 PC09 PC10 PC11 PC12 PC13 PC14 PC15, exti
647                },
648                declare_gpio_pins! {
649                    PD00 PD01 PD02 PD03 PD04 PD05 PD06 PD07
650                    PD08 PD09 PD10 PD11 PD12 PD13 PD14 PD15, exti
651                },
652                declare_gpio_pins! {
653                    PE00 PE01 PE02 PE03 PE04 PE05 PE06 PE07
654                    PE08 PE09 PE10 PE11 PE12 PE13 PE14 PE15, exti
655                },
656                [
657                    Some(Pin::new(PinId::PF00, exti)),
658                    Some(Pin::new(PinId::PF01, exti)),
659                    Some(Pin::new(PinId::PF02, exti)),
660                    Some(Pin::new(PinId::PF03, exti)),
661                    Some(Pin::new(PinId::PF04, exti)),
662                    Some(Pin::new(PinId::PF05, exti)),
663                    Some(Pin::new(PinId::PF06, exti)),
664                    Some(Pin::new(PinId::PF07, exti)),
665                    Some(Pin::new(PinId::PF08, exti)),
666                    Some(Pin::new(PinId::PF09, exti)),
667                    Some(Pin::new(PinId::PF10, exti)),
668                    None,
669                    None,
670                    None,
671                    None,
672                    None,
673                ],
674            ],
675        }
676    }
677
678    pub fn setup_circular_deps(&'a self) {
679        for pin_group in self.pins.iter() {
680            for pin in pin_group {
681                pin.as_ref().map(|p| p.set_ports_ref(self));
682            }
683        }
684    }
685}
686
687pub struct Port<'a> {
688    registers: StaticRef<GpioRegisters>,
689    clock: PortClock<'a>,
690}
691
692impl Port<'_> {
693    pub fn is_enabled_clock(&self) -> bool {
694        self.clock.is_enabled()
695    }
696
697    pub fn enable_clock(&self) {
698        self.clock.enable();
699    }
700
701    pub fn disable_clock(&self) {
702        self.clock.disable();
703    }
704}
705
706struct PortClock<'a>(rcc::PeripheralClock<'a>);
707
708impl ClockInterface for PortClock<'_> {
709    fn is_enabled(&self) -> bool {
710        self.0.is_enabled()
711    }
712
713    fn enable(&self) {
714        self.0.enable();
715    }
716
717    fn disable(&self) {
718        self.0.disable();
719    }
720}
721
722// `exti_lineid` is used to configure EXTI settings for the Pin.
723pub struct Pin<'a> {
724    pinid: PinId,
725    ports_ref: OptionalCell<&'a GpioPorts<'a>>,
726    exti: &'a exti::Exti<'a>,
727    client: OptionalCell<&'a dyn hil::gpio::Client>,
728    exti_lineid: OptionalCell<exti::LineId>,
729}
730
731impl<'a> Pin<'a> {
732    pub const fn new(pinid: PinId, exti: &'a exti::Exti<'a>) -> Self {
733        Self {
734            pinid,
735            ports_ref: OptionalCell::empty(),
736            exti,
737            client: OptionalCell::empty(),
738            exti_lineid: OptionalCell::empty(),
739        }
740    }
741
742    pub fn set_ports_ref(&self, ports: &'a GpioPorts<'a>) {
743        self.ports_ref.set(ports);
744    }
745
746    pub fn set_client(&self, client: &'a dyn hil::gpio::Client) {
747        self.client.set(client);
748    }
749
750    pub fn handle_interrupt(&self) {
751        self.client.map(|client| client.fired());
752    }
753
754    pub fn get_mode(&self) -> Mode {
755        let port = self.ports_ref.unwrap_or_panic().get_port(self.pinid); // Unwrap fail = Err
756
757        let val = match self.pinid.get_pin_number() {
758            0b0000 => port.registers.moder.read(MODER::MODER0),
759            0b0001 => port.registers.moder.read(MODER::MODER1),
760            0b0010 => port.registers.moder.read(MODER::MODER2),
761            0b0011 => port.registers.moder.read(MODER::MODER3),
762            0b0100 => port.registers.moder.read(MODER::MODER4),
763            0b0101 => port.registers.moder.read(MODER::MODER5),
764            0b0110 => port.registers.moder.read(MODER::MODER6),
765            0b0111 => port.registers.moder.read(MODER::MODER7),
766            0b1000 => port.registers.moder.read(MODER::MODER8),
767            0b1001 => port.registers.moder.read(MODER::MODER9),
768            0b1010 => port.registers.moder.read(MODER::MODER10),
769            0b1011 => port.registers.moder.read(MODER::MODER11),
770            0b1100 => port.registers.moder.read(MODER::MODER12),
771            0b1101 => port.registers.moder.read(MODER::MODER13),
772            0b1110 => port.registers.moder.read(MODER::MODER14),
773            0b1111 => port.registers.moder.read(MODER::MODER15),
774            _ => 0,
775        };
776
777        Mode::from_u32(val).unwrap_or(Mode::Input)
778    }
779
780    pub fn set_mode(&self, mode: Mode) {
781        let port = self.ports_ref.unwrap_or_panic().get_port(self.pinid); // Unwrap fail =
782
783        match self.pinid.get_pin_number() {
784            0b0000 => port.registers.moder.modify(MODER::MODER0.val(mode as u32)),
785            0b0001 => port.registers.moder.modify(MODER::MODER1.val(mode as u32)),
786            0b0010 => port.registers.moder.modify(MODER::MODER2.val(mode as u32)),
787            0b0011 => port.registers.moder.modify(MODER::MODER3.val(mode as u32)),
788            0b0100 => port.registers.moder.modify(MODER::MODER4.val(mode as u32)),
789            0b0101 => port.registers.moder.modify(MODER::MODER5.val(mode as u32)),
790            0b0110 => port.registers.moder.modify(MODER::MODER6.val(mode as u32)),
791            0b0111 => port.registers.moder.modify(MODER::MODER7.val(mode as u32)),
792            0b1000 => port.registers.moder.modify(MODER::MODER8.val(mode as u32)),
793            0b1001 => port.registers.moder.modify(MODER::MODER9.val(mode as u32)),
794            0b1010 => port.registers.moder.modify(MODER::MODER10.val(mode as u32)),
795            0b1011 => port.registers.moder.modify(MODER::MODER11.val(mode as u32)),
796            0b1100 => port.registers.moder.modify(MODER::MODER12.val(mode as u32)),
797            0b1101 => port.registers.moder.modify(MODER::MODER13.val(mode as u32)),
798            0b1110 => port.registers.moder.modify(MODER::MODER14.val(mode as u32)),
799            0b1111 => port.registers.moder.modify(MODER::MODER15.val(mode as u32)),
800            _ => {}
801        }
802    }
803
804    pub fn set_alternate_function(&self, af: AlternateFunction) {
805        let port = self.ports_ref.unwrap_or_panic().get_port(self.pinid); // Unwrap fail =
806
807        match self.pinid.get_pin_number() {
808            0b0000 => port.registers.afrl.modify(AFRL::AFRL0.val(af as u32)),
809            0b0001 => port.registers.afrl.modify(AFRL::AFRL1.val(af as u32)),
810            0b0010 => port.registers.afrl.modify(AFRL::AFRL2.val(af as u32)),
811            0b0011 => port.registers.afrl.modify(AFRL::AFRL3.val(af as u32)),
812            0b0100 => port.registers.afrl.modify(AFRL::AFRL4.val(af as u32)),
813            0b0101 => port.registers.afrl.modify(AFRL::AFRL5.val(af as u32)),
814            0b0110 => port.registers.afrl.modify(AFRL::AFRL6.val(af as u32)),
815            0b0111 => port.registers.afrl.modify(AFRL::AFRL7.val(af as u32)),
816            0b1000 => port.registers.afrh.modify(AFRH::AFRH8.val(af as u32)),
817            0b1001 => port.registers.afrh.modify(AFRH::AFRH9.val(af as u32)),
818            0b1010 => port.registers.afrh.modify(AFRH::AFRH10.val(af as u32)),
819            0b1011 => port.registers.afrh.modify(AFRH::AFRH11.val(af as u32)),
820            0b1100 => port.registers.afrh.modify(AFRH::AFRH12.val(af as u32)),
821            0b1101 => port.registers.afrh.modify(AFRH::AFRH13.val(af as u32)),
822            0b1110 => port.registers.afrh.modify(AFRH::AFRH14.val(af as u32)),
823            0b1111 => port.registers.afrh.modify(AFRH::AFRH15.val(af as u32)),
824            _ => {}
825        }
826    }
827
828    pub fn get_pinid(&self) -> PinId {
829        self.pinid
830    }
831
832    pub unsafe fn enable_interrupt(&'static self) {
833        let exti_line_id = LineId::from_u8(self.pinid.get_pin_number()).unwrap();
834
835        self.exti.associate_line_gpiopin(exti_line_id, self);
836    }
837
838    pub fn set_exti_lineid(&self, lineid: exti::LineId) {
839        self.exti_lineid.set(lineid);
840    }
841
842    fn set_mode_output_pushpull(&self) {
843        let port = self.ports_ref.unwrap_or_panic().get_port(self.pinid); // Unwrap fail =
844
845        match self.pinid.get_pin_number() {
846            0b0000 => port.registers.otyper.modify(OTYPER::OT0::CLEAR),
847            0b0001 => port.registers.otyper.modify(OTYPER::OT1::CLEAR),
848            0b0010 => port.registers.otyper.modify(OTYPER::OT2::CLEAR),
849            0b0011 => port.registers.otyper.modify(OTYPER::OT3::CLEAR),
850            0b0100 => port.registers.otyper.modify(OTYPER::OT4::CLEAR),
851            0b0101 => port.registers.otyper.modify(OTYPER::OT5::CLEAR),
852            0b0110 => port.registers.otyper.modify(OTYPER::OT6::CLEAR),
853            0b0111 => port.registers.otyper.modify(OTYPER::OT7::CLEAR),
854            0b1000 => port.registers.otyper.modify(OTYPER::OT8::CLEAR),
855            0b1001 => port.registers.otyper.modify(OTYPER::OT9::CLEAR),
856            0b1010 => port.registers.otyper.modify(OTYPER::OT10::CLEAR),
857            0b1011 => port.registers.otyper.modify(OTYPER::OT11::CLEAR),
858            0b1100 => port.registers.otyper.modify(OTYPER::OT12::CLEAR),
859            0b1101 => port.registers.otyper.modify(OTYPER::OT13::CLEAR),
860            0b1110 => port.registers.otyper.modify(OTYPER::OT14::CLEAR),
861            0b1111 => port.registers.otyper.modify(OTYPER::OT15::CLEAR),
862            _ => {}
863        }
864    }
865
866    fn get_pullup_pulldown(&self) -> PullUpPullDown {
867        let port = self.ports_ref.unwrap_or_panic().get_port(self.pinid); // Unwrap fail =
868
869        let val = match self.pinid.get_pin_number() {
870            0b0000 => port.registers.pupdr.read(PUPDR::PUPDR0),
871            0b0001 => port.registers.pupdr.read(PUPDR::PUPDR1),
872            0b0010 => port.registers.pupdr.read(PUPDR::PUPDR2),
873            0b0011 => port.registers.pupdr.read(PUPDR::PUPDR3),
874            0b0100 => port.registers.pupdr.read(PUPDR::PUPDR4),
875            0b0101 => port.registers.pupdr.read(PUPDR::PUPDR5),
876            0b0110 => port.registers.pupdr.read(PUPDR::PUPDR6),
877            0b0111 => port.registers.pupdr.read(PUPDR::PUPDR7),
878            0b1000 => port.registers.pupdr.read(PUPDR::PUPDR8),
879            0b1001 => port.registers.pupdr.read(PUPDR::PUPDR9),
880            0b1010 => port.registers.pupdr.read(PUPDR::PUPDR10),
881            0b1011 => port.registers.pupdr.read(PUPDR::PUPDR11),
882            0b1100 => port.registers.pupdr.read(PUPDR::PUPDR12),
883            0b1101 => port.registers.pupdr.read(PUPDR::PUPDR13),
884            0b1110 => port.registers.pupdr.read(PUPDR::PUPDR14),
885            0b1111 => port.registers.pupdr.read(PUPDR::PUPDR15),
886            _ => 0,
887        };
888
889        PullUpPullDown::from_u32(val).unwrap_or(PullUpPullDown::NoPullUpPullDown)
890    }
891
892    fn set_pullup_pulldown(&self, pupd: PullUpPullDown) {
893        let port = self.ports_ref.unwrap_or_panic().get_port(self.pinid); // Unwrap fail =
894
895        match self.pinid.get_pin_number() {
896            0b0000 => port.registers.pupdr.modify(PUPDR::PUPDR0.val(pupd as u32)),
897            0b0001 => port.registers.pupdr.modify(PUPDR::PUPDR1.val(pupd as u32)),
898            0b0010 => port.registers.pupdr.modify(PUPDR::PUPDR2.val(pupd as u32)),
899            0b0011 => port.registers.pupdr.modify(PUPDR::PUPDR3.val(pupd as u32)),
900            0b0100 => port.registers.pupdr.modify(PUPDR::PUPDR4.val(pupd as u32)),
901            0b0101 => port.registers.pupdr.modify(PUPDR::PUPDR5.val(pupd as u32)),
902            0b0110 => port.registers.pupdr.modify(PUPDR::PUPDR6.val(pupd as u32)),
903            0b0111 => port.registers.pupdr.modify(PUPDR::PUPDR7.val(pupd as u32)),
904            0b1000 => port.registers.pupdr.modify(PUPDR::PUPDR8.val(pupd as u32)),
905            0b1001 => port.registers.pupdr.modify(PUPDR::PUPDR9.val(pupd as u32)),
906            0b1010 => port.registers.pupdr.modify(PUPDR::PUPDR10.val(pupd as u32)),
907            0b1011 => port.registers.pupdr.modify(PUPDR::PUPDR11.val(pupd as u32)),
908            0b1100 => port.registers.pupdr.modify(PUPDR::PUPDR12.val(pupd as u32)),
909            0b1101 => port.registers.pupdr.modify(PUPDR::PUPDR13.val(pupd as u32)),
910            0b1110 => port.registers.pupdr.modify(PUPDR::PUPDR14.val(pupd as u32)),
911            0b1111 => port.registers.pupdr.modify(PUPDR::PUPDR15.val(pupd as u32)),
912            _ => {}
913        }
914    }
915
916    fn set_output_high(&self) {
917        let port = self.ports_ref.unwrap_or_panic().get_port(self.pinid); // Unwrap fail =
918
919        match self.pinid.get_pin_number() {
920            0b0000 => port.registers.bsrr.write(BSRR::BS0::SET),
921            0b0001 => port.registers.bsrr.write(BSRR::BS1::SET),
922            0b0010 => port.registers.bsrr.write(BSRR::BS2::SET),
923            0b0011 => port.registers.bsrr.write(BSRR::BS3::SET),
924            0b0100 => port.registers.bsrr.write(BSRR::BS4::SET),
925            0b0101 => port.registers.bsrr.write(BSRR::BS5::SET),
926            0b0110 => port.registers.bsrr.write(BSRR::BS6::SET),
927            0b0111 => port.registers.bsrr.write(BSRR::BS7::SET),
928            0b1000 => port.registers.bsrr.write(BSRR::BS8::SET),
929            0b1001 => port.registers.bsrr.write(BSRR::BS9::SET),
930            0b1010 => port.registers.bsrr.write(BSRR::BS10::SET),
931            0b1011 => port.registers.bsrr.write(BSRR::BS11::SET),
932            0b1100 => port.registers.bsrr.write(BSRR::BS12::SET),
933            0b1101 => port.registers.bsrr.write(BSRR::BS13::SET),
934            0b1110 => port.registers.bsrr.write(BSRR::BS14::SET),
935            0b1111 => port.registers.bsrr.write(BSRR::BS15::SET),
936            _ => {}
937        }
938    }
939
940    fn set_output_low(&self) {
941        let port = self.ports_ref.unwrap_or_panic().get_port(self.pinid); // Unwrap fail =
942
943        match self.pinid.get_pin_number() {
944            0b0000 => port.registers.bsrr.write(BSRR::BR0::SET),
945            0b0001 => port.registers.bsrr.write(BSRR::BR1::SET),
946            0b0010 => port.registers.bsrr.write(BSRR::BR2::SET),
947            0b0011 => port.registers.bsrr.write(BSRR::BR3::SET),
948            0b0100 => port.registers.bsrr.write(BSRR::BR4::SET),
949            0b0101 => port.registers.bsrr.write(BSRR::BR5::SET),
950            0b0110 => port.registers.bsrr.write(BSRR::BR6::SET),
951            0b0111 => port.registers.bsrr.write(BSRR::BR7::SET),
952            0b1000 => port.registers.bsrr.write(BSRR::BR8::SET),
953            0b1001 => port.registers.bsrr.write(BSRR::BR9::SET),
954            0b1010 => port.registers.bsrr.write(BSRR::BR10::SET),
955            0b1011 => port.registers.bsrr.write(BSRR::BR11::SET),
956            0b1100 => port.registers.bsrr.write(BSRR::BR12::SET),
957            0b1101 => port.registers.bsrr.write(BSRR::BR13::SET),
958            0b1110 => port.registers.bsrr.write(BSRR::BR14::SET),
959            0b1111 => port.registers.bsrr.write(BSRR::BR15::SET),
960            _ => {}
961        }
962    }
963
964    fn is_output_high(&self) -> bool {
965        let port = self.ports_ref.unwrap_or_panic().get_port(self.pinid); // Unwrap fail =
966
967        match self.pinid.get_pin_number() {
968            0b0000 => port.registers.odr.is_set(ODR::ODR0),
969            0b0001 => port.registers.odr.is_set(ODR::ODR1),
970            0b0010 => port.registers.odr.is_set(ODR::ODR2),
971            0b0011 => port.registers.odr.is_set(ODR::ODR3),
972            0b0100 => port.registers.odr.is_set(ODR::ODR4),
973            0b0101 => port.registers.odr.is_set(ODR::ODR5),
974            0b0110 => port.registers.odr.is_set(ODR::ODR6),
975            0b0111 => port.registers.odr.is_set(ODR::ODR7),
976            0b1000 => port.registers.odr.is_set(ODR::ODR8),
977            0b1001 => port.registers.odr.is_set(ODR::ODR9),
978            0b1010 => port.registers.odr.is_set(ODR::ODR10),
979            0b1011 => port.registers.odr.is_set(ODR::ODR11),
980            0b1100 => port.registers.odr.is_set(ODR::ODR12),
981            0b1101 => port.registers.odr.is_set(ODR::ODR13),
982            0b1110 => port.registers.odr.is_set(ODR::ODR14),
983            0b1111 => port.registers.odr.is_set(ODR::ODR15),
984            _ => false,
985        }
986    }
987
988    fn toggle_output(&self) -> bool {
989        if self.is_output_high() {
990            self.set_output_low();
991            false
992        } else {
993            self.set_output_high();
994            true
995        }
996    }
997
998    fn read_input(&self) -> bool {
999        let port = self.ports_ref.unwrap_or_panic().get_port(self.pinid); // Unwrap fail =
1000
1001        match self.pinid.get_pin_number() {
1002            0b0000 => port.registers.idr.is_set(IDR::IDR0),
1003            0b0001 => port.registers.idr.is_set(IDR::IDR1),
1004            0b0010 => port.registers.idr.is_set(IDR::IDR2),
1005            0b0011 => port.registers.idr.is_set(IDR::IDR3),
1006            0b0100 => port.registers.idr.is_set(IDR::IDR4),
1007            0b0101 => port.registers.idr.is_set(IDR::IDR5),
1008            0b0110 => port.registers.idr.is_set(IDR::IDR6),
1009            0b0111 => port.registers.idr.is_set(IDR::IDR7),
1010            0b1000 => port.registers.idr.is_set(IDR::IDR8),
1011            0b1001 => port.registers.idr.is_set(IDR::IDR9),
1012            0b1010 => port.registers.idr.is_set(IDR::IDR10),
1013            0b1011 => port.registers.idr.is_set(IDR::IDR11),
1014            0b1100 => port.registers.idr.is_set(IDR::IDR12),
1015            0b1101 => port.registers.idr.is_set(IDR::IDR13),
1016            0b1110 => port.registers.idr.is_set(IDR::IDR14),
1017            0b1111 => port.registers.idr.is_set(IDR::IDR15),
1018            _ => false,
1019        }
1020    }
1021}
1022
1023impl hil::gpio::Configure for Pin<'_> {
1024    /// Output mode default is push-pull
1025    fn make_output(&self) -> hil::gpio::Configuration {
1026        self.set_mode(Mode::GeneralPurposeOutputMode);
1027        self.set_mode_output_pushpull();
1028        hil::gpio::Configuration::Output
1029    }
1030
1031    /// Input mode default is no internal pull-up, no pull-down (i.e.,
1032    /// floating). Also upon setting the mode as input, the internal schmitt
1033    /// trigger is automatically activated. Schmitt trigger is deactivated in
1034    /// AnalogMode.
1035    fn make_input(&self) -> hil::gpio::Configuration {
1036        self.set_mode(Mode::Input);
1037        hil::gpio::Configuration::Input
1038    }
1039
1040    /// According to AN4899, Section 6.1, setting to AnalogMode, disables
1041    /// internal schmitt trigger. We do not disable clock to the GPIO port,
1042    /// because there could be other pins active on the port.
1043    fn deactivate_to_low_power(&self) {
1044        self.set_mode(Mode::AnalogMode);
1045    }
1046
1047    fn disable_output(&self) -> hil::gpio::Configuration {
1048        self.set_mode(Mode::AnalogMode);
1049        hil::gpio::Configuration::LowPower
1050    }
1051
1052    fn disable_input(&self) -> hil::gpio::Configuration {
1053        self.set_mode(Mode::AnalogMode);
1054        hil::gpio::Configuration::LowPower
1055    }
1056
1057    fn set_floating_state(&self, mode: hil::gpio::FloatingState) {
1058        match mode {
1059            hil::gpio::FloatingState::PullUp => self.set_pullup_pulldown(PullUpPullDown::PullUp),
1060            hil::gpio::FloatingState::PullDown => {
1061                self.set_pullup_pulldown(PullUpPullDown::PullDown)
1062            }
1063            hil::gpio::FloatingState::PullNone => {
1064                self.set_pullup_pulldown(PullUpPullDown::NoPullUpPullDown)
1065            }
1066        }
1067    }
1068
1069    fn floating_state(&self) -> hil::gpio::FloatingState {
1070        match self.get_pullup_pulldown() {
1071            PullUpPullDown::PullUp => hil::gpio::FloatingState::PullUp,
1072            PullUpPullDown::PullDown => hil::gpio::FloatingState::PullDown,
1073            PullUpPullDown::NoPullUpPullDown => hil::gpio::FloatingState::PullNone,
1074        }
1075    }
1076
1077    fn configuration(&self) -> hil::gpio::Configuration {
1078        match self.get_mode() {
1079            Mode::Input => hil::gpio::Configuration::Input,
1080            Mode::GeneralPurposeOutputMode => hil::gpio::Configuration::Output,
1081            Mode::AnalogMode => hil::gpio::Configuration::LowPower,
1082            Mode::AlternateFunctionMode => hil::gpio::Configuration::Function,
1083        }
1084    }
1085
1086    fn is_input(&self) -> bool {
1087        self.get_mode() == Mode::Input
1088    }
1089
1090    fn is_output(&self) -> bool {
1091        self.get_mode() == Mode::GeneralPurposeOutputMode
1092    }
1093}
1094
1095impl hil::gpio::Output for Pin<'_> {
1096    fn set(&self) {
1097        self.set_output_high();
1098    }
1099
1100    fn clear(&self) {
1101        self.set_output_low();
1102    }
1103
1104    fn toggle(&self) -> bool {
1105        self.toggle_output()
1106    }
1107}
1108
1109impl hil::gpio::Input for Pin<'_> {
1110    fn read(&self) -> bool {
1111        self.read_input()
1112    }
1113}
1114
1115impl<'a> hil::gpio::Interrupt<'a> for Pin<'a> {
1116    fn enable_interrupts(&self, mode: hil::gpio::InterruptEdge) {
1117        unsafe {
1118            atomic(|| {
1119                self.exti_lineid.map(|lineid| {
1120                    let l = lineid;
1121
1122                    // disable the interrupt
1123                    self.exti.mask_interrupt(l);
1124                    self.exti.clear_pending(l);
1125
1126                    match mode {
1127                        hil::gpio::InterruptEdge::EitherEdge => {
1128                            self.exti.select_rising_trigger(l);
1129                            self.exti.select_falling_trigger(l);
1130                        }
1131                        hil::gpio::InterruptEdge::RisingEdge => {
1132                            self.exti.select_rising_trigger(l);
1133                            self.exti.deselect_falling_trigger(l);
1134                        }
1135                        hil::gpio::InterruptEdge::FallingEdge => {
1136                            self.exti.deselect_rising_trigger(l);
1137                            self.exti.select_falling_trigger(l);
1138                        }
1139                    }
1140
1141                    self.exti.unmask_interrupt(l);
1142                });
1143            });
1144        }
1145    }
1146
1147    fn disable_interrupts(&self) {
1148        unsafe {
1149            atomic(|| {
1150                self.exti_lineid.map(|lineid| {
1151                    let l = lineid;
1152                    self.exti.mask_interrupt(l);
1153                    self.exti.clear_pending(l);
1154                });
1155            });
1156        }
1157    }
1158
1159    fn set_client(&self, client: &'a dyn hil::gpio::Client) {
1160        self.client.set(client);
1161    }
1162
1163    fn is_pending(&self) -> bool {
1164        self.exti_lineid
1165            .map_or(false, |lineid| self.exti.is_pending(lineid))
1166    }
1167}