stm32_rust_template/driver/gpio/
stm32f407.rs1#[cfg(feature = "stm32f407")]
2extern crate alloc;
3
4use super::{Direction, EventTrigger, EventType, Gpio, OutputMode, Pin, PullResistor, Result};
5use crate::mcu::stm32f407::{self, gpio, rcc};
6use alloc::boxed::Box;
7use core::ops::FnMut;
8
9#[derive(Clone, Copy, Debug)]
11pub struct GpioConfig {
12 pub direction: Direction,
13 pub output_mode: OutputMode,
14 pub pull_resistor: PullResistor,
15 pub event_trigger: EventTrigger,
16}
17
18impl Default for GpioConfig {
19 fn default() -> Self {
20 Self {
21 direction: Direction::Input,
22 output_mode: OutputMode::PushPull,
23 pull_resistor: PullResistor::None,
24 event_trigger: EventTrigger::None,
25 }
26 }
27}
28
29pub struct GpioDriver<'a> {
31 callbacks: [Option<Box<dyn FnMut(Pin, EventType) + 'a>>; 16],
33 configs: [GpioConfig; 16],
35}
36
37impl<'a> GpioDriver<'a> {
38 pub fn new() -> Self {
39 Self {
40 callbacks: [
41 None, None, None, None, None, None, None, None, None, None, None, None, None, None,
42 None, None,
43 ],
44 configs: [GpioConfig::default(); 16],
45 }
46 }
47
48 pub fn new_gpioa() -> Self {
50 Self::new()
51 }
52
53 pub fn new_gpiob() -> Self {
55 Self::new()
56 }
57
58 pub fn new_gpioc() -> Self {
60 Self::new()
61 }
62
63 pub fn new_gpiod() -> Self {
65 Self::new()
66 }
67
68 pub fn new_gpioe() -> Self {
70 Self::new()
71 }
72
73 fn get_gpio_regs(port: u8) -> *mut gpio::RegisterBlock {
75 match port {
76 0 => stm32f407::GPIOA_BASEADDR as *mut gpio::RegisterBlock, 1 => stm32f407::GPIOB_BASEADDR as *mut gpio::RegisterBlock, 2 => stm32f407::GPIOC_BASEADDR as *mut gpio::RegisterBlock, 3 => stm32f407::GPIOD_BASEADDR as *mut gpio::RegisterBlock, 4 => stm32f407::GPIOE_BASEADDR as *mut gpio::RegisterBlock, _ => stm32f407::GPIOA_BASEADDR as *mut gpio::RegisterBlock, }
83 }
84
85 fn get_rcc_regs() -> *mut rcc::RegisterBlock {
87 stm32f407::RCC_BASEADDR as *mut rcc::RegisterBlock
88 }
89
90 fn enable_gpio_clock(port: u8) {
92 let rcc = unsafe { &mut *Self::get_rcc_regs() };
93 let mask = match port {
94 0 => rcc::AHB1ENR_GPIOAEN_MASK, 1 => rcc::AHB1ENR_GPIOBEN_MASK, 2 => rcc::AHB1ENR_GPIOCEN_MASK, 3 => rcc::AHB1ENR_GPIODEN_MASK, 4 => rcc::AHB1ENR_GPIOEEN_MASK, _ => rcc::AHB1ENR_GPIOAEN_MASK, };
101 unsafe {
102 rcc.ahb1enr |= mask;
103 }
104 }
105
106 fn decode_pin(pin: Pin) -> (u8, u8) {
111 let port = ((pin >> 4) & 0xF) as u8;
112 let pin_num = (pin & 0xF) as u8;
113 (port, pin_num)
114 }
115
116 fn encode_pin(port: u8, pin_num: u8) -> Pin {
118 ((port as u32) << 4) | (pin_num as u32)
119 }
120
121 fn configure_pin(&mut self, pin: Pin, config: GpioConfig) -> Result<()> {
123 let (port, pin_num) = Self::decode_pin(pin);
124
125 if pin_num >= 16 {
126 return Err(-1); }
128
129 Self::enable_gpio_clock(port);
131
132 let gpio_regs = unsafe { &mut *Self::get_gpio_regs(port) };
133
134 let mode_val = match config.direction {
136 Direction::Input => gpio::MODER_INPUT,
137 Direction::Output => gpio::MODER_OUTPUT,
138 };
139 let shift = pin_num * 2;
140 let mask = 0x3 << shift;
141 unsafe {
142 gpio_regs.moder = (gpio_regs.moder & !mask) | (mode_val << shift);
143 }
144
145 if config.direction == Direction::Output {
147 let otype_val = match config.output_mode {
148 OutputMode::PushPull => gpio::OTYPER_PUSHPULL,
149 OutputMode::OpenDrain => gpio::OTYPER_OPENDRAIN,
150 };
151 unsafe {
152 if otype_val == gpio::OTYPER_OPENDRAIN {
153 gpio_regs.otyper |= 1 << pin_num;
154 } else {
155 gpio_regs.otyper &= !(1 << pin_num);
156 }
157 }
158 }
159
160 let pupd_val = match config.pull_resistor {
162 PullResistor::None => gpio::PUPDR_FLOATING,
163 PullResistor::PullUp => gpio::PUPDR_PULLUP,
164 PullResistor::PullDown => gpio::PUPDR_PULLDOWN,
165 };
166 let shift = pin_num * 2;
167 let mask = 0x3 << shift;
168 unsafe {
169 gpio_regs.pupdr = (gpio_regs.pupdr & !mask) | (pupd_val << shift);
170 }
171
172 let shift = pin_num * 2;
174 let mask = 0x3 << shift;
175 unsafe {
176 gpio_regs.ospeedr = (gpio_regs.ospeedr & !mask) | (gpio::OSPEEDR_MEDIUMSPEED << shift);
177 }
178
179 self.configs[pin_num as usize] = config;
181
182 Ok(())
183 }
184}
185
186impl<'a> Gpio<'a> for GpioDriver<'a> {
187 fn setup(&mut self, pin: Pin, callback: impl FnMut(Pin, EventType) + 'a) -> Result<()> {
188 let (_, pin_num) = Self::decode_pin(pin);
189
190 if pin_num >= 16 {
191 return Err(-1); }
193
194 self.callbacks[pin_num as usize] = Some(Box::new(callback));
196
197 let config = GpioConfig::default();
199 self.configure_pin(pin, config)?;
200
201 Ok(())
202 }
203
204 fn set_direction(&mut self, pin: Pin, direction: Direction) -> Result<()> {
205 let (_, pin_num) = Self::decode_pin(pin);
206
207 if pin_num >= 16 {
208 return Err(-1); }
210
211 let mut config = self.configs[pin_num as usize];
212 config.direction = direction;
213 self.configure_pin(pin, config)
214 }
215
216 fn set_output_mode(&mut self, pin: Pin, mode: OutputMode) -> Result<()> {
217 let (_, pin_num) = Self::decode_pin(pin);
218
219 if pin_num >= 16 {
220 return Err(-1); }
222
223 let mut config = self.configs[pin_num as usize];
224 config.output_mode = mode;
225 self.configure_pin(pin, config)
226 }
227
228 fn set_pull_resistor(&mut self, pin: Pin, resistor: PullResistor) -> Result<()> {
229 let (_, pin_num) = Self::decode_pin(pin);
230
231 if pin_num >= 16 {
232 return Err(-1); }
234
235 let mut config = self.configs[pin_num as usize];
236 config.pull_resistor = resistor;
237 self.configure_pin(pin, config)
238 }
239
240 fn set_event_trigger(&mut self, pin: Pin, trigger: EventTrigger) -> Result<()> {
241 let (_, pin_num) = Self::decode_pin(pin);
242
243 if pin_num >= 16 {
244 return Err(-1); }
246
247 let mut config = self.configs[pin_num as usize];
248 config.event_trigger = trigger;
249 self.configure_pin(pin, config)?;
250
251 Ok(())
255 }
256
257 fn set_output(&mut self, pin: Pin, value: bool) {
258 let (port, pin_num) = Self::decode_pin(pin);
259
260 if pin_num >= 16 {
261 return; }
263
264 let gpio_regs = unsafe { &mut *Self::get_gpio_regs(port) };
265
266 unsafe {
267 if value {
268 gpio_regs.bsrr = 1 << pin_num; } else {
270 gpio_regs.bsrr = 1 << (pin_num + 16); }
272 }
273 }
274
275 fn get_input(&self, pin: Pin) -> bool {
276 let (port, pin_num) = Self::decode_pin(pin);
277
278 if pin_num >= 16 {
279 return false; }
281
282 let gpio_regs = unsafe { &*Self::get_gpio_regs(port) };
283
284 unsafe { (gpio_regs.idr & (1 << pin_num)) != 0 }
285 }
286}
287
288pub mod pins {
290 use super::Pin;
291
292 pub const PA0: Pin = 0x00;
294 pub const PA1: Pin = 0x01;
295 pub const PA2: Pin = 0x02;
296 pub const PA3: Pin = 0x03;
297 pub const PA4: Pin = 0x04;
298 pub const PA5: Pin = 0x05;
299 pub const PA6: Pin = 0x06;
300 pub const PA7: Pin = 0x07;
301 pub const PA8: Pin = 0x08;
302 pub const PA9: Pin = 0x09;
303 pub const PA10: Pin = 0x0A;
304 pub const PA11: Pin = 0x0B;
305 pub const PA12: Pin = 0x0C;
306 pub const PA13: Pin = 0x0D;
307 pub const PA14: Pin = 0x0E;
308 pub const PA15: Pin = 0x0F;
309
310 pub const PB0: Pin = 0x10;
312 pub const PB1: Pin = 0x11;
313 pub const PB2: Pin = 0x12;
314 pub const PB3: Pin = 0x13;
315 pub const PB4: Pin = 0x14;
316 pub const PB5: Pin = 0x15;
317 pub const PB6: Pin = 0x16;
318 pub const PB7: Pin = 0x17;
319 pub const PB8: Pin = 0x18;
320 pub const PB9: Pin = 0x19;
321 pub const PB10: Pin = 0x1A;
322 pub const PB11: Pin = 0x1B;
323 pub const PB12: Pin = 0x1C;
324 pub const PB13: Pin = 0x1D;
325 pub const PB14: Pin = 0x1E;
326 pub const PB15: Pin = 0x1F;
327
328 pub const PC0: Pin = 0x20;
330 pub const PC1: Pin = 0x21;
331 pub const PC2: Pin = 0x22;
332 pub const PC3: Pin = 0x23;
333 pub const PC4: Pin = 0x24;
334 pub const PC5: Pin = 0x25;
335 pub const PC6: Pin = 0x26;
336 pub const PC7: Pin = 0x27;
337 pub const PC8: Pin = 0x28;
338 pub const PC9: Pin = 0x29;
339 pub const PC10: Pin = 0x2A;
340 pub const PC11: Pin = 0x2B;
341 pub const PC12: Pin = 0x2C;
342 pub const PC13: Pin = 0x2D;
343 pub const PC14: Pin = 0x2E;
344 pub const PC15: Pin = 0x2F;
345
346 pub const PD0: Pin = 0x30;
348 pub const PD1: Pin = 0x31;
349 pub const PD2: Pin = 0x32;
350 pub const PD3: Pin = 0x33;
351 pub const PD4: Pin = 0x34;
352 pub const PD5: Pin = 0x35;
353 pub const PD6: Pin = 0x36;
354 pub const PD7: Pin = 0x37;
355 pub const PD8: Pin = 0x38;
356 pub const PD9: Pin = 0x39;
357 pub const PD10: Pin = 0x3A;
358 pub const PD11: Pin = 0x3B;
359 pub const PD12: Pin = 0x3C;
360 pub const PD13: Pin = 0x3D;
361 pub const PD14: Pin = 0x3E;
362 pub const PD15: Pin = 0x3F;
363
364 pub const PE0: Pin = 0x40;
366 pub const PE1: Pin = 0x41;
367 pub const PE2: Pin = 0x42;
368 pub const PE3: Pin = 0x43;
369 pub const PE4: Pin = 0x44;
370 pub const PE5: Pin = 0x45;
371 pub const PE6: Pin = 0x46;
372 pub const PE7: Pin = 0x47;
373 pub const PE8: Pin = 0x48;
374 pub const PE9: Pin = 0x49;
375 pub const PE10: Pin = 0x4A;
376 pub const PE11: Pin = 0x4B;
377 pub const PE12: Pin = 0x4C;
378 pub const PE13: Pin = 0x4D;
379 pub const PE14: Pin = 0x4E;
380 pub const PE15: Pin = 0x4F;
381}