stm32f4xx/
i2c.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 core::cell::Cell;
6
7use kernel::hil;
8use kernel::hil::i2c::{self, Error, I2CHwMasterClient, I2CMaster};
9use kernel::platform::chip::ClockInterface;
10use kernel::utilities::cells::{OptionalCell, TakeCell};
11use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
12use kernel::utilities::registers::{register_bitfields, ReadWrite};
13use kernel::utilities::StaticRef;
14
15use crate::clocks::{phclk, Stm32f4Clocks};
16
17pub enum I2CSpeed {
18    Speed100k,
19    Speed400k,
20}
21
22/// Inter-Integrated Circuit
23#[repr(C)]
24struct I2CRegisters {
25    /// control register 1
26    cr1: ReadWrite<u32, CR1::Register>,
27    /// control register 2
28    cr2: ReadWrite<u32, CR2::Register>,
29    /// own address register 1
30    oar1: ReadWrite<u32, OAR1::Register>,
31    /// own address register 2
32    oar2: ReadWrite<u32, OAR2::Register>,
33    /// data register
34    dr: ReadWrite<u32, DR::Register>,
35    /// status register 1
36    sr1: ReadWrite<u32, SR1::Register>,
37    /// status register 2
38    sr2: ReadWrite<u32, SR2::Register>,
39    /// clock control register
40    ccr: ReadWrite<u32, CCR::Register>,
41    /// tRise register
42    trise: ReadWrite<u32, TRISE::Register>,
43    /// filter register
44    fltr: ReadWrite<u32, FLTR::Register>,
45}
46
47register_bitfields![u32,
48    CR1 [
49        /// Software reset
50        SWRST OFFSET(15) NUMBITS(1) [],
51        /// SMBus alert
52        ALERT OFFSET(13) NUMBITS(1) [],
53        /// Packet error checking
54        PEC OFFSET(12) NUMBITS(1) [],
55        /// Acknowledge/PEC Position (for data reception)
56        POS OFFSET(11) NUMBITS(1) [],
57        /// Acknowledge enable
58        ACK OFFSET(10) NUMBITS(1) [],
59        /// Stop generation
60        STOP OFFSET(9) NUMBITS(1) [],
61        /// Start generation
62        START OFFSET(8) NUMBITS(1) [],
63        /// Clock stretching disable (Slave mode)
64        NOSTRETCH OFFSET(7) NUMBITS(1) [],
65        /// General call enable
66        ENGC OFFSET(6) NUMBITS(1) [],
67        /// PEC enable
68        ENPEC OFFSET(5) NUMBITS(1) [],
69        /// ARP enable
70        ENARP OFFSET(4) NUMBITS(1) [],
71        /// SMBus type
72        SMBTYPE OFFSET(3) NUMBITS(1) [],
73        /// SMBus mode
74        SMBUS OFFSET(1) NUMBITS(1) [],
75        /// Peripheral enable
76        PE OFFSET(0) NUMBITS(1) []
77    ],
78    CR2 [
79        /// DMA last transfer
80        LAST OFFSET(12) NUMBITS(1) [],
81        /// DMA requests enable
82        DMAEN OFFSET(11) NUMBITS(1) [],
83        /// Buffer interrupt enable
84        ITBUFEN OFFSET(10) NUMBITS(1) [],
85        /// Event interrupt enable
86        ITEVTEN OFFSET(9) NUMBITS(1) [],
87        // Error interrupt enable
88        ITERREN OFFSET(8) NUMBITS(1) [],
89        /// Peripheral clock frequency
90        FREQ OFFSET(0) NUMBITS(6) []
91    ],
92    OAR1 [
93        /// Addressing mode (slave mode)
94        ADDMODE OFFSET(15) NUMBITS(1) [],
95        /// Interface address
96        ADD OFFSET(0) NUMBITS(10) []
97    ],
98    OAR2 [
99        /// Interface address
100        ADD2 OFFSET(1) NUMBITS(7) [],
101        /// Dual addressing mode enable
102        ENDUAL OFFSET(1) NUMBITS(1) []
103    ],
104    DR [
105        /// 8-bit receive data
106        DR OFFSET(0) NUMBITS(8) []
107    ],
108    SR1 [
109        /// SMBus alert
110        SMBALERT OFFSET(15) NUMBITS(1) [],
111        /// Timeout or tLOW detection flag
112        TIMEOUT OFFSET(14) NUMBITS(1) [],
113        /// PEC Error in reception
114        PECERR OFFSET(12) NUMBITS(1) [],
115        /// Overrun/Underrun
116        OVR OFFSET(11) NUMBITS(1) [],
117        /// Acknowledge failure
118        AF OFFSET(10) NUMBITS(1) [],
119        /// Arbitration lost
120        ARLO OFFSET(9) NUMBITS(1) [],
121        /// Bus error
122        BERR OFFSET(8) NUMBITS(1) [],
123        /// Data register empty (transmitters)
124        TXE OFFSET(7) NUMBITS(1) [],
125        /// Data register not empty (receivers)
126        RXNE OFFSET(6) NUMBITS(1) [],
127        /// Stop detection (slave mode)
128        STOPF OFFSET(4) NUMBITS(1) [],
129        /// 10-bit header sent (Master mode)
130        ADD10 OFFSET(3) NUMBITS(1) [],
131        /// Byte transfer finished
132        BTF OFFSET(2) NUMBITS(1) [],
133        /// Address sent (master mode)/matched (slave mode)
134        ADDR OFFSET(1) NUMBITS(1) [],
135        /// Start bit (Master mode)
136        SB OFFSET(0) NUMBITS(1) []
137    ],
138    SR2 [
139        /// Packet error checking register
140        PEC OFFSET(8) NUMBITS(8) [],
141        /// Dual flag (Slave mode)
142        DUALF OFFSET(7) NUMBITS(1) [],
143        /// SMBus host header (Slave mode)
144        SMBHOST OFFSET(6) NUMBITS(1) [],
145        /// SMBus device default address (Slave mode)
146        SMBDEFAULT OFFSET(5) NUMBITS(1) [],
147        /// General call address (Slave mode)
148        GENCALL OFFSET(4) NUMBITS(1) [],
149        /// Transmitter/receiver
150        TRA OFFSET(2) NUMBITS(1) [],
151        /// Bus busy
152        BUSY OFFSET(1) NUMBITS(1) [],
153        /// Master/slave
154        MSL OFFSET(0) NUMBITS(1) []
155    ],
156    CCR [
157        /// I2C master mode selection
158        FS OFFSET(15) NUMBITS(1) [
159            SM_MODE = 0,
160            FM_MODE = 1
161        ],
162        /// Fm mode duty cycle
163        DUTY OFFSET(14) NUMBITS(1) [],
164        /// Clock control register in Fm/Sm mode (Master mode)
165        CCR OFFSET(0) NUMBITS(12) []
166    ],
167    TRISE [
168        /// Maximum rise time in Fm/Sm mode (Master mode)
169        TRISE OFFSET(0) NUMBITS(6) []
170    ],
171    FLTR [
172        /// Analog noise filter OFF
173        ANOFF OFFSET(4) NUMBITS(1) [],
174        /// Digital noise filter
175        DNF OFFSET(0) NUMBITS(4) []
176    ]
177];
178
179const I2C1_BASE: StaticRef<I2CRegisters> =
180    unsafe { StaticRef::new(0x4000_5400 as *const I2CRegisters) };
181// const I2C2_BASE: StaticRef<I2CRegisters> =
182//     unsafe { StaticRef::new(0x4000_5800 as *const I2CRegisters) };
183// const I2C3_BASE: StaticRef<I2CRegisters> =
184//     unsafe { StaticRef::new(0x4000_5C00 as *const I2CRegisters) };
185
186pub struct I2C<'a> {
187    registers: StaticRef<I2CRegisters>,
188    clock: I2CClock<'a>,
189
190    // I2C slave support not yet implemented
191    master_client: OptionalCell<&'a dyn hil::i2c::I2CHwMasterClient>,
192
193    buffer: TakeCell<'static, [u8]>,
194    tx_position: Cell<usize>,
195    rx_position: Cell<usize>,
196    tx_len: Cell<usize>,
197    rx_len: Cell<usize>,
198
199    slave_address: Cell<u8>,
200
201    status: Cell<I2CStatus>,
202}
203
204#[derive(Copy, Clone, PartialEq)]
205enum I2CStatus {
206    Idle,
207    Writing,
208    WritingReading,
209    Reading,
210}
211
212impl<'a> I2C<'a> {
213    pub fn new(clocks: &'a dyn Stm32f4Clocks) -> Self {
214        Self {
215            registers: I2C1_BASE,
216            clock: I2CClock(phclk::PeripheralClock::new(
217                phclk::PeripheralClockType::APB1(phclk::PCLK1::I2C1),
218                clocks,
219            )),
220
221            master_client: OptionalCell::empty(),
222
223            slave_address: Cell::new(0),
224
225            buffer: TakeCell::empty(),
226            tx_position: Cell::new(0),
227            rx_position: Cell::new(0),
228
229            tx_len: Cell::new(0),
230            rx_len: Cell::new(0),
231
232            status: Cell::new(I2CStatus::Idle),
233        }
234    }
235
236    pub fn set_speed(&self, speed: I2CSpeed, system_clock_in_mhz: usize) {
237        self.disable();
238        self.registers
239            .cr2
240            .modify(CR2::FREQ.val(system_clock_in_mhz as u32));
241        match speed {
242            I2CSpeed::Speed100k => {
243                self.registers
244                    .ccr
245                    .modify(CCR::CCR.val(system_clock_in_mhz as u32 * 5) + CCR::FS::SM_MODE);
246                self.registers
247                    .trise
248                    .modify(TRISE::TRISE.val(system_clock_in_mhz as u32 + 1));
249            }
250            I2CSpeed::Speed400k => {
251                self.registers
252                    .ccr
253                    .modify(CCR::CCR.val(system_clock_in_mhz as u32 * 5 / 6) + CCR::FS::FM_MODE);
254                self.registers
255                    .trise
256                    .modify(TRISE::TRISE.val(system_clock_in_mhz as u32 + 1));
257            }
258        }
259        self.enable();
260    }
261
262    pub fn is_enabled_clock(&self) -> bool {
263        self.clock.is_enabled()
264    }
265
266    pub fn enable_clock(&self) {
267        self.clock.enable();
268    }
269
270    pub fn disable_clock(&self) {
271        self.clock.disable();
272    }
273
274    pub fn handle_event(&self) {
275        if self.registers.sr1.is_set(SR1::SB) {
276            let dir = match self.status.get() {
277                I2CStatus::Writing | I2CStatus::WritingReading => 0,
278                I2CStatus::Reading => 1,
279                _ => panic!("invalid i2c state when setting address"),
280            };
281            self.registers
282                .dr
283                .write(DR::DR.val(((self.slave_address.get() << 1) as u32) | dir));
284        }
285        if self.registers.sr1.is_set(SR1::ADDR) {
286            // i2c requires a sr2 read
287            self.registers.sr2.get();
288        }
289        if self.registers.sr1.is_set(SR1::TXE) {
290            // send the next byte
291            if self.buffer.is_some() && self.tx_position.get() < self.tx_len.get() {
292                self.buffer.map(|buf| {
293                    let byte = buf[self.tx_position.get()];
294                    self.registers.dr.write(DR::DR.val(byte as u32));
295                    self.tx_position.set(self.tx_position.get() + 1);
296                });
297            }
298        }
299
300        while self.registers.sr1.is_set(SR1::RXNE) {
301            // send the next byte
302            let byte = self.registers.dr.read(DR::DR);
303            if self.buffer.is_some() && self.rx_position.get() < self.rx_len.get() {
304                self.buffer.map(|buf| {
305                    buf[self.rx_position.get()] = byte as u8;
306                    self.rx_position.set(self.rx_position.get() + 1);
307                });
308            }
309
310            if self.buffer.is_some() && self.rx_position.get() == self.rx_len.get() {
311                self.registers.cr1.modify(CR1::STOP::SET);
312                self.stop();
313                self.master_client.map(|client| {
314                    self.buffer
315                        .take()
316                        .map(|buf| client.command_complete(buf, Ok(())))
317                });
318            }
319        }
320
321        if self.registers.sr1.is_set(SR1::BTF) {
322            match self.status.get() {
323                I2CStatus::Writing | I2CStatus::WritingReading => {
324                    if self.tx_position.get() < self.tx_len.get() {
325                        self.registers.cr1.modify(CR1::STOP::SET);
326                        self.stop();
327                        self.master_client.map(|client| {
328                            self.buffer
329                                .take()
330                                .map(|buf| client.command_complete(buf, Err(Error::DataNak)))
331                        });
332                    } else {
333                        if self.status.get() == I2CStatus::Writing {
334                            self.registers.cr1.modify(CR1::STOP::SET);
335                            self.stop();
336                            self.master_client.map(|client| {
337                                self.buffer
338                                    .take()
339                                    .map(|buf| client.command_complete(buf, Ok(())))
340                            });
341                        } else {
342                            self.status.set(I2CStatus::Reading);
343                            self.start_read();
344                        }
345                    }
346                }
347                I2CStatus::Reading => {
348                    let status = if self.rx_position.get() == self.rx_len.get() {
349                        Ok(())
350                    } else {
351                        Err(Error::DataNak)
352                    };
353                    self.registers.cr1.modify(CR1::STOP::SET);
354                    self.stop();
355                    self.master_client.map(|client| {
356                        self.buffer
357                            .take()
358                            .map(|buf| client.command_complete(buf, status))
359                    });
360                }
361                _ => panic!("i2c status error"),
362            }
363        }
364    }
365
366    pub fn handle_error(&self) {
367        self.master_client.map(|client| {
368            self.buffer
369                .take()
370                .map(|buf| client.command_complete(buf, Err(Error::DataNak)))
371        });
372        self.stop();
373    }
374
375    fn reset(&self) {
376        self.disable();
377        self.enable();
378    }
379
380    fn start_write(&self) {
381        self.tx_position.set(0);
382        self.registers
383            .cr2
384            .modify(CR2::ITEVTEN::SET + CR2::ITERREN::SET + CR2::ITBUFEN::SET);
385        self.registers.cr1.modify(CR1::ACK::SET);
386        self.registers.cr1.modify(CR1::START::SET);
387    }
388
389    fn stop(&self) {
390        self.registers
391            .cr2
392            .modify(CR2::ITEVTEN::CLEAR + CR2::ITERREN::CLEAR + CR2::ITBUFEN::CLEAR);
393        self.registers.cr1.modify(CR1::ACK::CLEAR);
394        self.status.set(I2CStatus::Idle);
395    }
396
397    fn start_read(&self) {
398        self.rx_position.set(0);
399        self.registers
400            .cr2
401            .modify(CR2::ITEVTEN::SET + CR2::ITERREN::SET + CR2::ITBUFEN::SET);
402        self.registers.cr1.modify(CR1::ACK::SET);
403        self.registers.cr1.modify(CR1::START::SET);
404    }
405}
406
407impl<'a> i2c::I2CMaster<'a> for I2C<'a> {
408    fn set_master_client(&self, master_client: &'a dyn I2CHwMasterClient) {
409        self.master_client.replace(master_client);
410    }
411    fn enable(&self) {
412        self.registers.cr1.modify(CR1::PE::SET);
413    }
414    fn disable(&self) {
415        self.registers.cr1.modify(CR1::PE::CLEAR);
416    }
417    fn write_read(
418        &self,
419        addr: u8,
420        data: &'static mut [u8],
421        write_len: usize,
422        read_len: usize,
423    ) -> Result<(), (Error, &'static mut [u8])> {
424        if self.status.get() == I2CStatus::Idle {
425            self.reset();
426            self.status.set(I2CStatus::WritingReading);
427            self.slave_address.set(addr);
428            self.buffer.replace(data);
429            self.tx_len.set(write_len);
430            self.rx_len.set(read_len);
431            self.start_write();
432            Ok(())
433        } else {
434            Err((Error::Busy, data))
435        }
436    }
437    fn write(
438        &self,
439        addr: u8,
440        data: &'static mut [u8],
441        len: usize,
442    ) -> Result<(), (Error, &'static mut [u8])> {
443        if self.status.get() == I2CStatus::Idle {
444            self.reset();
445            self.status.set(I2CStatus::Writing);
446            self.slave_address.set(addr);
447            self.buffer.replace(data);
448            self.tx_len.set(len);
449            self.start_write();
450            Ok(())
451        } else {
452            Err((Error::Busy, data))
453        }
454    }
455    fn read(
456        &self,
457        addr: u8,
458        buffer: &'static mut [u8],
459        len: usize,
460    ) -> Result<(), (Error, &'static mut [u8])> {
461        if self.status.get() == I2CStatus::Idle {
462            self.reset();
463            self.status.set(I2CStatus::Reading);
464            self.slave_address.set(addr);
465            self.buffer.replace(buffer);
466            self.rx_len.set(len);
467            self.start_read();
468            Ok(())
469        } else {
470            Err((Error::ArbitrationLost, buffer))
471        }
472    }
473}
474
475struct I2CClock<'a>(phclk::PeripheralClock<'a>);
476
477impl ClockInterface for I2CClock<'_> {
478    fn is_enabled(&self) -> bool {
479        self.0.is_enabled()
480    }
481
482    fn enable(&self) {
483        self.0.enable();
484    }
485
486    fn disable(&self) {
487        self.0.disable();
488    }
489}