stm32_rust_template/driver/i2c/
stm32f407.rs

1#[cfg(feature = "stm32f407")]
2extern crate alloc;
3use super::{BusSpeed, Event, I2c, Result, Status};
4use crate::mcu::stm32f407::{self, i2c::*};
5use crate::utils;
6use alloc::boxed::Box;
7use core::ops::FnMut;
8use core::ptr;
9
10/// The APB1 peripheral clock frequency in Hz.
11/// This value is used for timing calculations in the I2C peripheral.
12///
13/// # Note
14/// This should be updated to match the actual clock configuration of your MCU.
15const PCLK1_HZ: u32 = 16_000_000;
16
17/// Configuration for the I2C driver.
18#[derive(Clone, Copy)]
19pub struct I2cConfig {
20    pub bus_speed: BusSpeed,
21    pub own_address: u32,
22}
23
24impl Default for I2cConfig {
25    fn default() -> Self {
26        Self {
27            bus_speed: BusSpeed::Standard,
28            own_address: 0,
29        }
30    }
31}
32
33impl Default for BusSpeed {
34    fn default() -> Self {
35        BusSpeed::Standard
36    }
37}
38
39/// A polling-based I2C driver for STM32F407.
40pub struct I2cDriver<'a> {
41    regs: *mut RegisterBlock,
42    _callback: Option<Box<dyn FnMut(Event) + 'a>>,
43    config: I2cConfig,
44    data_count: u32,
45}
46
47impl<'a> I2cDriver<'a> {
48    pub fn new(i2c_base_addr: u32, config: I2cConfig) -> Self {
49        Self {
50            regs: i2c_base_addr as *mut RegisterBlock,
51            _callback: None,
52            config,
53            data_count: 0,
54        }
55    }
56
57    /// Create a new I2C1 driver instance
58    pub fn new_i2c1(config: I2cConfig) -> Self {
59        Self::new(stm32f407::I2C1_BASEADDR, config)
60    }
61
62    /// Create a new I2C2 driver instance
63    pub fn new_i2c2(config: I2cConfig) -> Self {
64        Self::new(stm32f407::I2C2_BASEADDR, config)
65    }
66
67    /// Create a new I2C3 driver instance
68    pub fn new_i2c3(config: I2cConfig) -> Self {
69        Self::new(stm32f407::I2C3_BASEADDR, config)
70    }
71
72    fn regs(&self) -> &mut RegisterBlock {
73        unsafe { &mut *self.regs }
74    }
75
76    fn generate_start_condition(&mut self) {
77        let mut cr1 = unsafe { ptr::read_volatile(&self.regs().cr1) };
78        cr1 = utils::set_bit(cr1, CR1_START_POS, true);
79        unsafe { ptr::write_volatile(&mut self.regs().cr1, cr1) };
80    }
81
82    fn generate_stop_condition(&mut self) {
83        let mut cr1 = unsafe { ptr::read_volatile(&self.regs().cr1) };
84        cr1 = utils::set_bit(cr1, CR1_STOP_POS, true);
85        unsafe { ptr::write_volatile(&mut self.regs().cr1, cr1) };
86    }
87
88    fn execute_address_phase_write(&mut self, slave_addr: u32) {
89        let mut addr = slave_addr << 1;
90        addr &= !1; // Clear R/W bit for write
91        unsafe { ptr::write_volatile(&mut self.regs().dr, addr) };
92    }
93
94    fn execute_address_phase_read(&mut self, slave_addr: u32) {
95        let mut addr = slave_addr << 1;
96        addr |= 1; // Set R/W bit for read
97        unsafe { ptr::write_volatile(&mut self.regs().dr, addr) };
98    }
99
100    fn get_flag_status(&self, flag_bit: u32) -> bool {
101        let sr1 = unsafe { ptr::read_volatile(&self.regs().sr1) };
102        utils::read_bit(sr1, flag_bit)
103    }
104
105    fn clear_addr_flag(&mut self) {
106        let _ = unsafe { ptr::read_volatile(&self.regs().sr1) };
107        let _ = unsafe { ptr::read_volatile(&self.regs().sr2) };
108    }
109
110    fn manage_acking(&mut self, enable: bool) {
111        let mut cr1 = unsafe { ptr::read_volatile(&self.regs().cr1) };
112        cr1 = utils::set_bit(cr1, CR1_ACK_POS, enable);
113        unsafe { ptr::write_volatile(&mut self.regs().cr1, cr1) };
114    }
115}
116
117impl<'a> I2c<'a> for I2cDriver<'a> {
118    fn initialize(&mut self, callback: impl FnMut(Event) + 'a) -> Result<()> {
119        self._callback = Some(Box::new(callback));
120
121        // Note: The peripheral clock must be enabled before calling this function.
122
123        // Disable peripheral for configuration.
124        let mut cr1 = unsafe { ptr::read_volatile(&self.regs().cr1) };
125        cr1 = utils::set_bit(cr1, CR1_PE_POS, false);
126        unsafe { ptr::write_volatile(&mut self.regs().cr1, cr1) };
127
128        // Configure CR1: Ack control - always enable for master.
129        cr1 = unsafe { ptr::read_volatile(&self.regs().cr1) };
130        cr1 = utils::set_bit(cr1, CR1_ACK_POS, true);
131        unsafe { ptr::write_volatile(&mut self.regs().cr1, cr1) };
132
133        // Configure CR2: Peripheral clock frequency.
134        let mut cr2 = unsafe { ptr::read_volatile(&self.regs().cr2) };
135        let freq_mhz = PCLK1_HZ / 1_000_000;
136        cr2 = utils::set_bits(cr2, freq_mhz, 0, 6);
137        unsafe { ptr::write_volatile(&mut self.regs().cr2, cr2) };
138
139        // Configure OAR1: Own address.
140        let mut oar1 = unsafe { ptr::read_volatile(&self.regs().oar1) };
141        oar1 = utils::set_bits(oar1, self.config.own_address, 1, 7);
142        oar1 = utils::set_bit(oar1, 14, true); // This bit must be kept at 1.
143        unsafe { ptr::write_volatile(&mut self.regs().oar1, oar1) };
144
145        // Configure CCR: Clock control register.
146        let ccr_val;
147        let mut ccr_reg = 0;
148        match self.config.bus_speed {
149            BusSpeed::Standard => {
150                ccr_val = PCLK1_HZ / (2 * 100_000); // 100kHz
151            }
152            BusSpeed::Fast => {
153                ccr_reg = utils::set_bit(ccr_reg, 15, true); // F/S mode
154                // I2C_FM_DUTY_2 = 0
155                ccr_val = PCLK1_HZ / (3 * 400_000); // 400kHz
156            }
157            _ => return Err(-1),
158        }
159        ccr_reg |= ccr_val & 0xFFF;
160        unsafe { ptr::write_volatile(&mut self.regs().ccr, ccr_reg) };
161
162        // Configure TRISE: Rise time.
163        let trise_val = match self.config.bus_speed {
164            BusSpeed::Standard => (PCLK1_HZ / 1_000_000) + 1,
165            BusSpeed::Fast => (PCLK1_HZ / 1_000_000 * 300 / 1000) + 1,
166            _ => return Err(-1),
167        };
168        unsafe { ptr::write_volatile(&mut self.regs().trise, trise_val & 0x3F) };
169
170        // Enable the peripheral.
171        cr1 = unsafe { ptr::read_volatile(&self.regs().cr1) };
172        cr1 = utils::set_bit(cr1, CR1_PE_POS, true);
173        unsafe { ptr::write_volatile(&mut self.regs().cr1, cr1) };
174
175        Ok(())
176    }
177
178    fn uninitialize(&mut self) -> Result<()> {
179        let mut cr1 = unsafe { ptr::read_volatile(&self.regs().cr1) };
180        cr1 = utils::set_bit(cr1, CR1_PE_POS, false);
181        unsafe { ptr::write_volatile(&mut self.regs().cr1, cr1) };
182        self._callback = None;
183        Ok(())
184    }
185
186    fn master_transmit(&mut self, addr: u32, data: &[u8], xfer_pending: bool) -> Result<()> {
187        self.data_count = 0;
188        self.generate_start_condition();
189        while !self.get_flag_status(SR1_SB_POS) {}
190
191        self.execute_address_phase_write(addr);
192        while !self.get_flag_status(SR1_ADDR_POS) {}
193        self.clear_addr_flag();
194
195        for byte in data {
196            while !self.get_flag_status(SR1_TXE_POS) {}
197            unsafe { ptr::write_volatile(&mut self.regs().dr, *byte as u32) };
198            self.data_count += 1;
199        }
200
201        while !self.get_flag_status(SR1_TXE_POS) {}
202        while !self.get_flag_status(SR1_BTF_POS) {}
203
204        if !xfer_pending {
205            self.generate_stop_condition();
206        }
207        Ok(())
208    }
209
210    fn master_receive(&mut self, addr: u32, data: &mut [u8], xfer_pending: bool) -> Result<()> {
211        self.data_count = 0;
212        let len = data.len();
213        if len == 0 {
214            return Ok(());
215        }
216
217        self.generate_start_condition();
218        while !self.get_flag_status(SR1_SB_POS) {}
219
220        self.execute_address_phase_read(addr);
221        while !self.get_flag_status(SR1_ADDR_POS) {}
222
223        if len == 1 {
224            self.manage_acking(false);
225            self.clear_addr_flag();
226            if !xfer_pending {
227                self.generate_stop_condition();
228            }
229            while !self.get_flag_status(SR1_RXNE_POS) {}
230            data[0] = unsafe { ptr::read_volatile(&self.regs().dr) as u8 };
231            self.data_count = 1;
232        } else {
233            self.clear_addr_flag();
234            for i in (1..=len).rev() {
235                while !self.get_flag_status(SR1_RXNE_POS) {}
236                if i == 2 {
237                    self.manage_acking(false);
238                    if !xfer_pending {
239                        self.generate_stop_condition();
240                    }
241                }
242                data[len - i] = unsafe { ptr::read_volatile(&self.regs().dr) as u8 };
243                self.data_count += 1;
244            }
245        }
246
247        self.manage_acking(true);
248        Ok(())
249    }
250
251    fn slave_transmit(&mut self, _data: &[u8]) -> Result<()> {
252        todo!("Polling slave transmit not implemented")
253    }
254
255    fn slave_receive(&mut self, _data: &mut [u8]) -> Result<()> {
256        todo!("Polling slave receive not implemented")
257    }
258
259    fn get_data_count(&self) -> Result<u32> {
260        Ok(self.data_count)
261    }
262
263    fn set_bus_speed(&mut self, _speed: BusSpeed) -> Result<()> {
264        todo!("Changing bus speed requires re-initialization")
265    }
266
267    fn set_own_address(&mut self, _address: u32) -> Result<()> {
268        todo!("Changing own address requires re-initialization")
269    }
270
271    fn clear_bus(&mut self) -> Result<()> {
272        todo!("Bus clear is not implemented")
273    }
274
275    fn abort_transfer(&mut self) -> Result<()> {
276        self.generate_stop_condition();
277        Ok(())
278    }
279
280    fn get_status(&self) -> Status {
281        let sr1 = unsafe { ptr::read_volatile(&self.regs().sr1) };
282        let sr2 = unsafe { ptr::read_volatile(&self.regs().sr2) };
283
284        Status {
285            busy: utils::read_bit(sr2, SR2_BUSY_POS),
286            master_mode: utils::read_bit(sr2, SR2_MSL_POS),
287            receiving: !utils::read_bit(sr2, SR2_TRA_POS),
288            general_call: utils::read_bit(sr2, SR2_GENCALL_POS),
289            arbitration_lost: utils::read_bit(sr1, SR1_ARLO_POS),
290            bus_error: utils::read_bit(sr1, SR1_BERR_POS),
291        }
292    }
293}