1#![deny(missing_docs)]
35#![deny(warnings)]
36#![no_std]
37
38pub trait GPIOExtras<T> {
40 fn write_pin_range(&self, offset: usize, count: usize, data: u16);
44
45 fn write_pin(&self, offset: usize, bit: bool) {
47 self.write_pin_range(offset, 1, if bit { 1 } else { 0 });
48 }
49
50 fn read_pin_range(&self, offset: usize, count: usize) -> u16;
52
53 fn read_pin(&self, offset: usize) -> bool {
55 self.read_pin_range(offset, 1) != 0
56 }
57
58 fn pin_config(&self, pin: usize) -> &T;
60}
61
62#[cfg(feature = "stm32f103xx")]
64mod stm32f1xx {
65 extern crate vcell;
66 use self::vcell::VolatileCell;
67
68 pub struct GPIOBitbandConfigBlock {
70 mode_low: VolatileCell<u32>,
71 mode_high: VolatileCell<u32>,
72 cnf_low: VolatileCell<u32>,
73 cnf_high: VolatileCell<u32>,
74 }
75
76 impl GPIOBitbandConfigBlock {
77 pub fn input(&self) -> &Self {
79 self.mode_low.set(0);
80 self.mode_high.set(0);
81 self
82 }
83
84 pub fn output2(&self) -> &Self {
86 self.mode_low.set(0);
87 self.mode_high.set(1);
88 self
89 }
90
91 pub fn output10(&self) -> &Self {
93 self.mode_low.set(1);
94 self.mode_high.set(0);
95 self
96 }
97
98 pub fn output50(&self) -> &Self {
100 self.mode_low.set(1);
101 self.mode_high.set(1);
102 self
103 }
104
105 pub fn push_pull(&self) -> &Self {
109 self.cnf_low.set(0);
110 self
111 }
112
113 pub fn open_drain(&self) -> &Self {
115 self.cnf_low.set(1);
116 self
117 }
118
119 pub fn general(&self) -> &Self {
121 self.cnf_high.set(0);
122 self
123 }
124
125 pub fn alternate(&self) -> &Self {
127 self.cnf_high.set(1);
128 self
129 }
130
131 pub fn analog(&self) -> &Self {
135 self.cnf_low.set(0);
136 self.cnf_high.set(0);
137 self
138 }
139
140 pub fn floating(&self) -> &Self {
142 self.cnf_high.set(0);
144 self.cnf_low.set(1);
145 self
146 }
147
148 pub fn pull_up_down(&self) -> &Self {
150 self.cnf_low.set(0);
151 self.cnf_high.set(1);
152 self
153 }
154 }
155
156 #[repr(C)]
158 pub struct GPIOBitbandRegisterBlock {
159 config: [GPIOBitbandConfigBlock; 16],
160 }
161
162 impl GPIOBitbandRegisterBlock {
163 pub fn config(&self, pin: usize) -> &GPIOBitbandConfigBlock {
165 &self.config[pin]
166 }
167 }
168}
169
170#[cfg(feature = "stm32f103xx")]
171mod stm32f103 {
172 extern crate stm32f103xx;
173 use self::stm32f103xx::gpioa;
174 use super::stm32f1xx::GPIOBitbandRegisterBlock;
175 use super::stm32f1xx::GPIOBitbandConfigBlock;
176 use super::GPIOExtras;
177
178 const PERIPHERALS_BASE: usize = 0x4000_0000;
179 const PERIPHERALS_ALIAS: usize = 0x4200_0000;
180
181 fn to_bitband_address<S, T>(port: &T) -> &'static S {
182 let byte_offset = (port as *const T as usize) - PERIPHERALS_BASE;
183 let address = PERIPHERALS_ALIAS + byte_offset * 32;
184 let ptr = address as *const S;
185 unsafe { &*ptr }
186 }
187
188 impl GPIOExtras<GPIOBitbandConfigBlock> for gpioa::RegisterBlock {
189 fn write_pin_range(&self, offset: usize, count: usize, data: u16) {
190 let mask = (1 << count) - 1;
191 let bits = u32::from(data & mask) | (u32::from(!data & mask) << 16); self.bsrr.write(|w| unsafe { w.bits(bits << offset) });
194 }
195
196 fn read_pin_range(&self, offset: usize, count: usize) -> u16 {
197 let mask = (1 << count) - 1;
198 ((self.idr.read().bits() >> offset) as u16) & mask
199 }
200
201 fn pin_config(&self, pin: usize) -> &GPIOBitbandConfigBlock {
202 let registers: &GPIOBitbandRegisterBlock = to_bitband_address(self);
203 ®isters.config(pin)
204 }
205 }
206}