Skip to content
This repository was archived by the owner on Jul 6, 2019. It is now read-only.

Commit 1ea86b2

Browse files
committed
Merge pull request #325 from darayus/stm32f4-pin
Modernize STM32F4 GPIO implementation
2 parents 1ff9930 + 3a09256 commit 1ea86b2

File tree

4 files changed

+108
-95
lines changed

4 files changed

+108
-95
lines changed

examples/app_blink_stm32f4.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,20 @@ extern crate core;
66
extern crate zinc;
77

88
use zinc::hal::timer::Timer;
9+
use zinc::hal::pin::Gpio;
910
use zinc::hal::stm32f4::{pin, timer};
1011

1112
#[zinc_main]
1213
pub fn main() {
1314
zinc::hal::mem_init::init_stack();
1415
zinc::hal::mem_init::init_data();
1516

16-
let led1 = pin::PinConf{
17+
let led1 = pin::Pin {
1718
port: pin::Port::PortD,
1819
pin: 13u8,
1920
function: pin::Function::GPIOOut
2021
};
21-
let led2 = pin::PinConf{
22+
let led2 = pin::Pin {
2223
port: pin::Port::PortD,
2324
pin: 14u8,
2425
function: pin::Function::GPIOOut

src/hal/stm32f4/gpio.rs

-42
This file was deleted.

src/hal/stm32f4/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
//! HAL for STM32F4.
1717
1818
pub mod init;
19-
pub mod gpio;
2019
pub mod peripheral_clock;
2120
pub mod pin;
2221
pub mod timer;

src/hal/stm32f4/pin.rs

+105-50
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
//! Some pins that could be configured here may be missing from actual MCU
1919
//! depending on the package.
2020
21+
use hal::pin::{Gpio, GpioDirection, GpioLevel};
2122
use super::peripheral_clock;
2223
use core::intrinsics::abort;
2324

@@ -68,12 +69,9 @@ impl Port {
6869
}
6970
}
7071

71-
/// Pin configuration.
72-
///
73-
/// This structure shouldn't be used directly, pinmap.rs, available via pin::map
74-
/// has all possible pin configurations.
72+
/// Pin configuration
7573
#[derive(Clone, Copy)]
76-
pub struct PinConf {
74+
pub struct Pin {
7775
/// Pin port, mcu-specific.
7876
pub port: Port,
7977
/// Pin number.
@@ -82,58 +80,33 @@ pub struct PinConf {
8280
pub function: Function,
8381
}
8482

85-
impl PinConf {
83+
impl Pin {
8684
/// Setup the pin.
8785
#[inline(always)]
8886
pub fn setup(&self) {
8987
use self::Function::*;
88+
use self::reg::GPIO_moder_mode as RegMode;
9089

9190
self.port.clock().enable(); // TODO(farcaller): should be done once per port
9291

93-
let offset: u32 = self.pin as u32 * 2;
92+
let offset = self.pin as usize;
9493
let gpreg = self.get_reg();
9594

96-
let bits: u32 = match self.function {
97-
GPIOOut => 0b01 << offset as usize,
98-
GPIOIn => 0b00 << offset as usize,
95+
let val = match self.function {
96+
GPIOOut => RegMode::Output,
97+
GPIOIn => RegMode::Input,
9998
_ => unsafe { abort() }, // FIXME(farcaller): not implemented
10099
};
101-
let mask: u32 = !(0b11 << offset as usize);
102-
let val: u32 = gpreg.MODER();
103100

104-
gpreg.set_MODER(val & mask | bits);
105-
}
106-
107-
/// Sets output GPIO value to high.
108-
pub fn set_high(&self) {
109-
let bit: u32 = 1 << self.pin as usize;
110-
self.get_reg().set_BSRR(bit);
111-
}
112-
113-
/// Sets output GPIO value to low.
114-
pub fn set_low(&self) {
115-
let bit: u32 = 1 << (self.pin as usize + 16);
116-
self.get_reg().set_BSRR(bit);
101+
gpreg.moder.set_mode(offset, val);
117102
}
118103

119104
/// Toggles the GPIO value
120105
pub fn toggle(&self) {
121-
let bit: u32 = 1 << self.pin as usize;
122106
let reg = self.get_reg();
123-
let val: u32 = reg.ODR();
107+
let offset = self.pin as usize;
124108

125-
reg.set_ODR(val ^ bit);
126-
}
127-
128-
/// Returns input GPIO level.
129-
pub fn level(&self) -> ::hal::pin::GpioLevel {
130-
let bit: u32 = 1 << (self.pin as usize);
131-
let reg = self.get_reg();
132-
133-
match reg.IDR() & bit {
134-
0 => ::hal::pin::Low,
135-
_ => ::hal::pin::High,
136-
}
109+
reg.odr.set_od(offset, !reg.odr.od(offset));
137110
}
138111

139112
fn get_reg(&self) -> &reg::GPIO {
@@ -151,21 +124,103 @@ impl PinConf {
151124
}
152125
}
153126

127+
impl Gpio for Pin {
128+
/// Sets output GPIO value to high.
129+
fn set_high(&self) {
130+
let offset = self.pin as usize;
131+
self.get_reg().bsrr.set_bs(offset, true);
132+
}
133+
134+
/// Sets output GPIO value to low.
135+
fn set_low(&self) {
136+
let offset = self.pin as usize;
137+
self.get_reg().bsrr.set_br(offset, true);
138+
}
139+
140+
/// Returns input GPIO level.
141+
fn level(&self) -> GpioLevel {
142+
let offset = self.pin as usize;
143+
let reg = self.get_reg();
144+
145+
match reg.idr.id(offset) {
146+
false => GpioLevel::Low,
147+
_ => GpioLevel::High,
148+
}
149+
}
150+
151+
/// Sets output GPIO direction.
152+
fn set_direction(&self, new_mode: GpioDirection) {
153+
// TODO(darayus): Verify that this works
154+
// TODO(darayus): Change the Pin.function field to the new mode
155+
use self::reg::GPIO_moder_mode as RegMode;
156+
let offset = self.pin as usize;
157+
let reg = self.get_reg();
158+
159+
let val = match new_mode {
160+
GpioDirection::Out => RegMode::Output,
161+
GpioDirection::In => RegMode::Input,
162+
};
163+
164+
reg.moder.set_mode(offset, val);
165+
}
166+
}
167+
154168
#[allow(dead_code)]
155169
mod reg {
170+
use core::ops::Drop;
156171
use volatile_cell::VolatileCell;
157172

158-
ioreg_old!(GPIO: u32, MODER, OTYPER, OSPEEDER, PUPDR, IDR, ODR, BSRR, LCKR, AFRL, AFRH);
159-
reg_rw!(GPIO, u32, MODER, set_MODER, MODER);
160-
reg_rw!(GPIO, u32, OTYPER, set_OTYPER, OTYPER);
161-
reg_rw!(GPIO, u32, OSPEEDER, set_OSPEEDER, OSPEEDER);
162-
reg_rw!(GPIO, u32, PUPDR, set_PUPDR, PUPDR);
163-
reg_rw!(GPIO, u32, IDR, set_IDR, IDR);
164-
reg_rw!(GPIO, u32, ODR, set_ODR, ODR);
165-
reg_rw!(GPIO, u32, BSRR, set_BSRR, BSRR);
166-
reg_rw!(GPIO, u32, LCKR, set_LCKR, LCKR);
167-
reg_rw!(GPIO, u32, AFRL, set_AFRL, AFRL);
168-
reg_rw!(GPIO, u32, AFRH, set_AFRH, AFRH);
173+
ioregs!(GPIO = {
174+
0x0 => reg32 moder {
175+
0..31 => mode[16] {
176+
0 => Input,
177+
1 => Output,
178+
3 => Alternate,
179+
4 => Analog
180+
}
181+
}
182+
0x04 => reg32 otyper {
183+
0..15 => ot[16] {
184+
0 => PushPull,
185+
1 => OpenDrain
186+
}
187+
}
188+
0x08 => reg32 ospeedr {
189+
0..31 => ospeed[16] {
190+
0 => Low,
191+
1 => Medium,
192+
2 => Fast,
193+
3 => High
194+
}
195+
}
196+
0x0c => reg32 pupdr {
197+
0..31 => pupd[16] {
198+
0 => None,
199+
1 => PullUp,
200+
2 => PullDown
201+
}
202+
}
203+
0x10 => reg32 idr {
204+
0..15 => id[16]: ro
205+
}
206+
0x14 => reg32 odr {
207+
0..15 => od[16]
208+
}
209+
0x18 => reg32 bsrr {
210+
0..15 => bs[16]: wo,
211+
16..31 => br[16]: wo
212+
}
213+
0x1c => reg32 lckr {
214+
0..15 => lck[16],
215+
16 => lckk
216+
}
217+
0x20 => reg32 afrl {
218+
0..31 => afrl[8]
219+
}
220+
0x24 => reg32 afrh {
221+
0..31 => afrh[8]
222+
}
223+
});
169224

170225
extern {
171226
#[link_name="stm32f4_iomem_GPIOA"] pub static GPIO_A: GPIO;

0 commit comments

Comments
 (0)