tm4c_hal/
i2c.rs

1//! Common I2C code for TM4C123 and TM4C129
2
3/// I2C error
4#[derive(Debug)]
5#[non_exhaustive]
6pub enum Error {
7    /// Bus Busy
8    BusBusy,
9
10    /// Arbitration loss
11    Arbitration,
12
13    /// Missing Data ACK
14    DataAck,
15
16    /// Missing Address ACK
17    AdrAck,
18
19    /// I2C Timeout
20    Timeout,
21}
22
23#[macro_export]
24/// Implements the traits for an I2C peripheral
25macro_rules! i2c_pins {
26    ($I2Cn:ident,
27        scl: [$(($($sclgpio: ident)::*, $sclaf: ident)),*],
28        sda: [$(($($sdagpio: ident)::*, $sdaaf: ident)),*],
29    ) => {
30        $(
31            impl<T> SclPin<$I2Cn> for $($sclgpio)::*<AlternateFunction<$sclaf, T>>
32            where
33                T: OutputMode,
34            {}
35        )*
36
37        $(
38            impl<T> SdaPin<$I2Cn> for $($sdagpio)::*<AlternateFunction<$sdaaf, T>>
39            where
40                T: OutputMode,
41            {}
42        )*
43    }
44}
45
46#[macro_export]
47/// Spins until the controler is ready (mcs.busy is clear) and optionally on
48/// another field of the mcs register until it is clear or set (depending on op
49/// parameter).
50macro_rules! i2c_busy_wait {
51    ($i2c:expr $(, $field:ident, $op:ident)? ) => {{
52        // in 'release' builds, the time between setting the `run` bit and checking the `busy`
53        // bit is too short and the `busy` bit is not reliably set by the time you get there,
54        // it can take up to 8 clock cycles for the `run` to begin so this delay allows time
55        // for that hardware synchronization
56        delay(8);
57
58        // Allow 1,000 clock cycles before we timeout. At 100 kHz, this is 10 ms.
59        $i2c.mclkocnt
60            .write(|w| unsafe { w.cntl().bits((1_000 >> 4) as u8) });
61
62        let mcs = loop {
63            let mcs = $i2c.mcs.read();
64
65            if mcs.busy().bit_is_clear() {
66                break mcs;
67            }
68        };
69
70
71        if mcs.clkto().bit_is_set() {
72            return Err(Error::Timeout)
73        } else if mcs.arblst().bit_is_set() {
74            return Err(Error::Arbitration)
75        } else if mcs.error().bit_is_set() {
76            if mcs.adrack().bit_is_set() {
77                return Err(Error::AdrAck);
78            } else { // if mcs.datack().bit_is_set() {
79                return Err(Error::DataAck);
80            }
81        }
82
83        $( loop {
84            if mcs.clkto().bit_is_set() {
85                return Err(Error::Timeout)
86            } else if mcs.arblst().bit_is_set() {
87                return Err(Error::Arbitration)
88            } else if mcs.error().bit_is_set() {
89                if mcs.adrack().bit_is_set() {
90                    return Err(Error::AdrAck);
91                } else { // if mcs.datack().bit_is_set() {
92                    return Err(Error::DataAck);
93                }
94            } else if mcs.$field().$op() {
95                break;
96            } else {
97                // try again
98            }
99        };)?
100
101        Ok(())
102    }};
103}
104
105#[macro_export]
106/// Implements embedded-hal for an TM4C I2C peripheral
107macro_rules! i2c_hal {
108    ($($I2CX:ident: ($powerDomain:ident, $i2cX:ident),)+) => {
109        $(
110            impl<SCL, SDA> I2c<$I2CX, (SCL, SDA)> {
111                /// Configures the I2C peripheral to work in master mode
112                pub fn $i2cX<F>(
113                    i2c: $I2CX,
114                    pins: (SCL, SDA),
115                    freq: F,
116                    clocks: &Clocks,
117                    pc: &sysctl::PowerControl,
118                ) -> Self where
119                    F: Into<Hertz>,
120                    SCL: SclPin<$I2CX>,
121                    SDA: SdaPin<$I2CX>,
122                {
123                    sysctl::control_power(
124                        pc, sysctl::Domain::$powerDomain,
125                        sysctl::RunMode::Run, sysctl::PowerState::On);
126                    sysctl::reset(pc, sysctl::Domain::$powerDomain);
127
128                    // set Master Function Enable, and clear other bits.
129                    i2c.mcr.write(|w| w.mfe().set_bit());
130
131                    // Write TimerPeriod configuration and clear other bits.
132                    let freq = freq.into().0;
133                    let tpr = ((clocks.sysclk.0/(2*10*freq))-1) as u8;
134
135                    i2c.mtpr.write(|w| unsafe {w.tpr().bits(tpr)});
136
137                    I2c { i2c, pins }
138                }
139
140                /// Releases the I2C peripheral and associated pins
141                pub fn free(self) -> ($I2CX, (SCL, SDA)) {
142                    (self.i2c, self.pins)
143                }
144            }
145
146            impl<PINS> Write for I2c<$I2CX, PINS> {
147                type Error = Error;
148
149                fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
150                    // Write Slave address and clear Receive bit
151                    self.i2c.msa.write(|w| unsafe {
152                        w.sa().bits(addr)
153                    });
154
155                    // Put first byte in data register
156                    self.i2c.mdr.write(|w| unsafe {
157                        w.data().bits(bytes[0])
158                    });
159
160                    let sz = bytes.len();
161
162                    i2c_busy_wait!(self.i2c, busbsy, bit_is_clear)?;
163
164                    // Send START + RUN
165                    // If single byte transfer, set STOP
166                    self.i2c.mcs.write(|w| {
167                        if sz == 1 {
168                            w.stop().set_bit();
169                        }
170                        w.start().set_bit()
171                            .run().set_bit()
172                    });
173
174                    for (i,byte) in (&bytes[1..]).iter().enumerate() {
175                        i2c_busy_wait!(self.i2c)?;
176
177                        // Put next byte in data register
178                        self.i2c.mdr.write(|w| unsafe {
179                            w.data().bits(*byte)
180                        });
181
182                        // Send RUN command (Burst continue)
183                        // Set STOP on last byte
184                        self.i2c.mcs.write(|w| {
185                            if (i+1) == (sz-1) {
186                                w.stop().set_bit();
187                            }
188                            w.run().set_bit()
189                        });
190                    }
191
192                    i2c_busy_wait!(self.i2c)?;
193
194                    Ok(())
195                }
196            }
197
198            impl<PINS> Read for I2c<$I2CX, PINS> {
199                type Error = Error;
200
201                fn read(
202                    &mut self,
203                    addr: u8,
204                    buffer: &mut [u8],
205                ) -> Result<(), Error> {
206
207                    // Write Slave address and set Receive bit
208                    self.i2c.msa.write(|w| unsafe {
209                        w.sa().bits(addr)
210                            .rs().set_bit()
211                    });
212
213                    i2c_busy_wait!(self.i2c, busbsy, bit_is_clear)?;
214
215                    let recv_sz = buffer.len();
216
217                    if recv_sz == 1 {
218                        // Single receive
219                        self.i2c.mcs.write(|w| {
220                            w.run().set_bit()
221                                .start().set_bit()
222                                .stop().set_bit()
223                        });
224
225                        i2c_busy_wait!(self.i2c)?;
226                        buffer[0] = self.i2c.mdr.read().data().bits();
227                    } else {
228                        self.i2c.mcs.write(|w| {
229                            w.start().set_bit()
230                                .run().set_bit()
231                                .ack().set_bit()
232                        });
233
234                        i2c_busy_wait!(self.i2c)?;
235                        buffer[0] = self.i2c.mdr.read().data().bits();
236
237                        for byte in &mut buffer[1..recv_sz-1] {
238                            self.i2c.mcs.write(|w| {
239                                w.run().set_bit()
240                                    .ack().set_bit()
241                            });
242                            i2c_busy_wait!(self.i2c)?;
243                            *byte = self.i2c.mdr.read().data().bits();
244                        }
245                        self.i2c.mcs.write(|w| {
246                            w.run().set_bit()
247                                .stop().set_bit()
248                        });
249
250                        i2c_busy_wait!(self.i2c)?;
251                        buffer[recv_sz-1] = self.i2c.mdr.read().data().bits();
252                    }
253
254                    Ok(())
255                }
256            }
257
258            impl<PINS> WriteRead for I2c<$I2CX, PINS> {
259                type Error = Error;
260
261                fn write_read(
262                    &mut self,
263                    addr: u8,
264                    bytes: &[u8],
265                    buffer: &mut [u8],
266                ) -> Result<(), Error> {
267
268                    let write_len = bytes.len();
269
270                    if buffer.len() == 0 {
271                       return self.write(addr, bytes);
272                    }
273
274                    if bytes.len() == 0 {
275                        return self.read(addr, buffer);
276                    }
277
278                    // Write Slave address and clear Receive bit
279                    self.i2c.msa.write(|w| unsafe {
280                        w.sa().bits(addr)
281                    });
282
283                    // send first byte
284                    self.i2c.mdr.write(|w| unsafe {
285                        w.data().bits(bytes[0])
286                    });
287
288                    i2c_busy_wait!(self.i2c, busbsy, bit_is_clear)?;
289                    self.i2c.mcs.write(|w| {
290                        w.start().set_bit()
291                            .run().set_bit()
292                    });
293
294                    i2c_busy_wait!(self.i2c)?;
295                    for byte in (&bytes[1..write_len]).iter() {
296                        self.i2c.mdr.write(|w| unsafe {
297                            w.data().bits(*byte)
298                        });
299
300                        self.i2c.mcs.write(|w| {
301                            w.run().set_bit()
302                        });
303
304                        i2c_busy_wait!(self.i2c)?;
305                    }
306
307                    // Write Slave address and set Receive bit
308                    self.i2c.msa.write(|w| unsafe {
309                        w.sa().bits(addr)
310                            .rs().set_bit()
311                    });
312
313                    let recv_sz = buffer.len();
314
315                    if recv_sz == 1 {
316                        // emit Repeated START and STOP for single receive
317                        self.i2c.mcs.write(|w| {
318                            w.run().set_bit()
319                                .start().set_bit()
320                                .stop().set_bit()
321                        });
322
323                        i2c_busy_wait!(self.i2c)?;
324                        buffer[0] = self.i2c.mdr.read().data().bits();
325                    } else {
326                        // emit Repeated START
327                        self.i2c.mcs.write(|w| {
328                            w.run().set_bit()
329                                .start().set_bit()
330                                .ack().set_bit()
331                        });
332
333                        i2c_busy_wait!(self.i2c)?;
334                        buffer[0] = self.i2c.mdr.read().data().bits();
335
336                        for byte in &mut buffer[1..recv_sz-1] {
337                            self.i2c.mcs.write(|w| {
338                                w.run().set_bit()
339                                    .ack().set_bit()
340                            });
341                            i2c_busy_wait!(self.i2c)?;
342                            *byte = self.i2c.mdr.read().data().bits();
343                        }
344
345                        self.i2c.mcs.write(|w| {
346                            w.run().set_bit()
347                                .stop().set_bit()
348                        });
349
350                        i2c_busy_wait!(self.i2c)?;
351                        buffer[recv_sz-1] = self.i2c.mdr.read().data().bits();
352                    }
353
354                    Ok(())
355                }
356            }
357        )+
358    }
359}