3232//!
3333//! For non-blocking slave operations, see `openprot-hal-nb::i2c_hardware`.
3434
35- use crate :: system_control:: { ErrorType , SystemControl } ;
3635use embedded_hal:: i2c:: { AddressMode , Operation , SevenBitAddress } ;
3736
3837/// Core I2C hardware interface providing basic operations
@@ -55,225 +54,6 @@ pub trait I2cHardwareCore {
5554 /// Initialize the I2C hardware with the given configuration
5655 fn init ( & mut self , config : & mut Self :: Config ) -> Result < ( ) , Self :: Error > ;
5756
58- /// Initialize the I2C hardware with external system control configuration
59- ///
60- /// This method provides a flexible way to initialize I2C hardware while allowing
61- /// external system control configuration through a closure. The closure receives a mutable
62- /// reference to a system controller implementing the `SystemControl` trait, enabling
63- /// platform-specific clock and reset setup operations.
64- ///
65- /// This approach supports dependency injection patterns while maintaining zero-cost
66- /// abstractions through compile-time monomorphization of the closure.
67- ///
68- /// # Arguments
69- ///
70- /// * `config` - Mutable reference to I2C-specific configuration parameters
71- /// * `system_setup` - Closure that configures the system controller for I2C operation.
72- /// The closure receives a mutable reference to the system controller and should
73- /// perform all necessary clock and reset configuration operations (enable clocks,
74- /// set frequency, release from reset, etc.)
75- ///
76- /// # Generic Parameters
77- ///
78- /// * `F` - Closure type that takes a mutable system controller reference and returns
79- /// a Result. The closure is called exactly once during initialization.
80- /// * `S` - System controller type that implements the `SystemControl` trait, providing
81- /// methods for enabling, disabling, and configuring peripheral clocks and resets.
82- ///
83- /// # Returns
84- ///
85- /// * `Ok(())` - I2C hardware initialization completed successfully
86- /// * `Err(Self::Error)` - Initialization failed due to either I2C hardware error
87- /// or system control error (automatically converted via `From<<S as ErrorType>::Error>`)
88- ///
89- /// # Errors
90- ///
91- /// This method can return errors from two sources:
92- /// - **System control errors**: Any error returned by the system controller
93- /// operations within the closure will be automatically converted to `Self::Error`
94- /// - **I2C hardware errors**: Errors from I2C-specific initialization operations.
95- /// # Examples
96- ///
97- /// ## Basic System Setup
98- /// ```text
99- /// use openprot_hal_blocking::i2c_hardware::I2cHardwareCore;
100- /// use openprot_hal_blocking::system_control::SystemControl;
101- ///
102- /// fn initialize_i2c<T: I2cHardwareCore>(
103- /// mut i2c: T,
104- /// mut system_controller: impl SystemControl
105- /// ) -> Result<(), T::Error> {
106- /// let mut config = create_i2c_config();
107- ///
108- /// i2c.init_with_system_control(&mut config, |system| {
109- /// // Release I2C peripheral from reset
110- /// system.reset_deassert(&ResetId::I2c1)?;
111- ///
112- /// // Enable I2C peripheral clock
113- /// system.enable(&ClockId::I2c1)?;
114- ///
115- /// // Set desired frequency (400kHz)
116- /// system.set_frequency(&ClockId::I2c1, 400_000)?;
117- ///
118- /// Ok(())
119- /// })?;
120- ///
121- /// Ok(())
122- /// }
123- /// ```
124- fn init_with_system_control < F , S > (
125- & mut self ,
126- config : & mut Self :: Config ,
127- system_setup : F ,
128- ) -> Result < ( ) , Self :: Error >
129- where
130- F : FnOnce ( & mut S ) -> Result < ( ) , <S as ErrorType >:: Error > ,
131- S : SystemControl ,
132- Self :: Error : From < <S as ErrorType >:: Error > ; // Let the I2C error type handle conversion
133-
134- /// Configure I2C timing parameters with external system control
135- ///
136- /// This method provides flexible timing configuration by accepting a closure
137- /// that can interact with a system controller implementing the `SystemControl` trait.
138- /// This enables runtime clock adjustments, reset management, frequency validation,
139- /// and platform-specific system configuration during timing setup.
140- ///
141- /// Unlike the basic `configure_timing` method, this version allows the timing
142- /// configuration process to interact with comprehensive system-level management,
143- /// enabling more sophisticated timing calculations and hardware optimization.
144- ///
145- /// # Arguments
146- ///
147- /// * `speed` - Target I2C bus speed (e.g., 100_000 for 100kHz, 400_000 for 400kHz)
148- /// * `timing` - Platform-specific timing configuration parameters
149- /// * `system_config` - Closure that configures the system controller for optimal I2C timing.
150- /// The closure receives a mutable reference to the system controller and should
151- /// perform any necessary clock and reset adjustments for the specified speed.
152- ///
153- /// # Generic Parameters
154- ///
155- /// * `F` - Closure type that takes a mutable system controller reference and returns
156- /// a Result with the actual configured frequency. Called once during timing setup.
157- /// * `S` - System controller type implementing the `SystemControl` trait, providing
158- /// methods for clock frequency management, reset control, and configuration.
159- ///
160- /// # Returns
161- ///
162- /// * `Ok(actual_frequency)` - Timing configuration successful, returns the actual
163- /// frequency achieved after system and timing adjustments
164- /// * `Err(Self::Error)` - Configuration failed due to either I2C timing error
165- /// or system control error (automatically converted via `From<S::Error>`)
166- ///
167- /// # Errors
168- ///
169- /// This method can return errors from multiple sources:
170- /// - **System control errors**: Any error from system controller operations
171- /// within the closure will be automatically converted to `Self::Error`
172- /// - **Timing calculation errors**: Errors from I2C-specific timing calculations
173- /// - **Hardware constraint errors**: When requested speed cannot be achieved
174- /// with current system configuration
175- /// - **Validation errors**: When the configured timing parameters are invalid
176- ///
177- /// # Examples
178- ///
179- /// ## Basic System-Aware Timing Configuration
180- /// ```text
181- /// use openprot_hal_blocking::i2c_hardware::I2cHardwareCore;
182- /// use openprot_hal_blocking::system_control::SystemControl;
183- ///
184- /// fn configure_i2c_timing<T: I2cHardwareCore>(
185- /// mut i2c: T,
186- /// mut system_controller: impl SystemControl
187- /// ) -> Result<u32, T::Error> {
188- /// let timing_config = create_timing_config();
189- ///
190- /// let actual_freq = i2c.configure_timing_with_system_control(
191- /// 400_000, // 400kHz target
192- /// &timing_config,
193- /// |system| {
194- /// // Release from reset if needed
195- /// system.reset_deassert(&ResetId::I2c1)?;
196- ///
197- /// // Optimize clock for I2C timing
198- /// system.enable(&ClockId::I2c1)?;
199- ///
200- /// // Set optimal source frequency for I2C timing calculations
201- /// system.set_frequency(&ClockId::I2c1, 48_000_000)?; // 48MHz source
202- ///
203- /// // Return the actual source frequency for timing calculations
204- /// system.get_frequency(&ClockId::I2c1)
205- /// }
206- /// )?;
207- ///
208- /// Ok(actual_freq)
209- /// }
210- /// ```
211- ///
212- /// ## Platform with Comprehensive System Setup
213- /// ```text
214- /// # use openprot_hal_blocking::i2c_hardware::I2cHardwareCore;
215- /// # use openprot_hal_blocking::system_control::SystemControl;
216- ///
217- /// fn platform_precise_timing_config(
218- /// mut i2c: PlatformI2c
219- /// ) -> Result<u32, PlatformI2cError> {
220- /// let mut system_controller = PlatformSystemController::new();
221- ///
222- /// let timing_config = PlatformTimingConfig {
223- /// prescaler: 1,
224- /// scl_delay: 4,
225- /// sda_delay: 2,
226- /// scl_high_period: 15,
227- /// scl_low_period: 19,
228- /// };
229- ///
230- /// let actual_freq = i2c.configure_timing_with_system_control(
231- /// 400_000,
232- /// &timing_config,
233- /// |system: &mut PlatformSystemController| {
234- /// // Ensure clean reset state
235- /// system.reset_pulse(&ResetId::I2c1, Duration::from_micros(10))?;
236- ///
237- /// // Configure I2C clock source for precise timing
238- /// let clock_config = PlatformClockConfig {
239- /// source: ClockSource::Sysclk, // Use SYSCLK for precision
240- /// prescaler: 1,
241- /// };
242- /// system.configure(&ClockId::I2c1, clock_config)?;
243- ///
244- /// // Set the optimal frequency for timing calculations
245- /// system.set_frequency(&ClockId::I2c1, 48_000_000)?;
246- ///
247- /// // Verify the frequency is stable
248- /// let freq = system.get_frequency(&ClockId::I2c1)?;
249- /// if freq < 45_000_000 || freq > 50_000_000 {
250- /// return Err(SystemError::FrequencyOutOfRange);
251- /// }
252- ///
253- /// Ok(freq)
254- /// }
255- /// )?;
256- ///
257- /// Ok(actual_freq)
258- /// }
259- /// ```
260- ///
261- /// # Design Notes
262- ///
263- /// The integration with `SystemControl` allows the I2C timing configuration to be
264- /// aware of and coordinate with comprehensive system-level management (clocks and resets),
265- /// resulting in more accurate timing and better hardware utilization.
266- fn configure_timing_with_system_control < F , S > (
267- & mut self ,
268- speed : Self :: I2cSpeed ,
269- timing : & Self :: TimingConfig ,
270- system_config : F ,
271- ) -> Result < u32 , Self :: Error >
272- where
273- F : FnOnce ( & mut S ) -> Result < u64 , <S as ErrorType >:: Error > ,
274- S : SystemControl ,
275- Self :: Error : From < <S as ErrorType >:: Error > ;
276-
27757 /// Configure timing parameters (clock speed, setup/hold times)
27858 ///
27959 /// Takes timing parameters as input and returns the calculated clock source frequency.
0 commit comments