1
+ /* mbed Microcontroller Library
2
+ * SPDX-License-Identifier: BSD-3-Clause
3
+ ******************************************************************************
4
+ *
5
+ * Copyright (c) 2015-2020 STMicroelectronics.
6
+ * Copyright (c) 2020, Arduino SA.
7
+ * All rights reserved.
8
+ *
9
+ * This software component is licensed by ST under BSD 3-Clause license,
10
+ * the "License"; You may not use this file except in compliance with the
11
+ * License. You may obtain a copy of the License at:
12
+ * opensource.org/licenses/BSD-3-Clause
13
+ *
14
+ ******************************************************************************
15
+ */
16
+
17
+ #include "i2c_device.h"
18
+ #include "mbed_assert.h"
19
+ #include "stm32h7xx_ll_rcc.h"
20
+
21
+ #if DEVICE_I2C
22
+
23
+ /** @defgroup I2C_DEVICE_Private_Constants I2C_DEVICE Private Constants
24
+ * @{
25
+ */
26
+ #ifndef I2C_VALID_TIMING_NBR
27
+ #define I2C_VALID_TIMING_NBR 128U
28
+ #endif
29
+ #define I2C_SPEED_FREQ_STANDARD 0U /* 100 kHz */
30
+ #define I2C_SPEED_FREQ_FAST 1U /* 400 kHz */
31
+ #define I2C_SPEED_FREQ_FAST_PLUS 2U /* 1 MHz */
32
+ #define I2C_ANALOG_FILTER_DELAY_MIN 50U /* ns */
33
+ #define I2C_ANALOG_FILTER_DELAY_MAX 260U /* ns */
34
+ #define I2C_USE_ANALOG_FILTER 1U
35
+ #define I2C_DIGITAL_FILTER_COEF 0U
36
+ #define I2C_PRESC_MAX 16U
37
+ #define I2C_SCLDEL_MAX 16U
38
+ #define I2C_SDADEL_MAX 16U
39
+ #define I2C_SCLH_MAX 256U
40
+ #define I2C_SCLL_MAX 256U
41
+ #define SEC2NSEC 1000000000UL
42
+ /**
43
+ * @}
44
+ */
45
+
46
+ /** @defgroup I2C_DEVICE_Private_Types I2C_DEVICE Private Types
47
+ * @{
48
+ */
49
+ typedef struct
50
+ {
51
+ uint32_t freq ; /* Frequency in Hz */
52
+ uint32_t freq_min ; /* Minimum frequency in Hz */
53
+ uint32_t freq_max ; /* Maximum frequency in Hz */
54
+ uint32_t hddat_min ; /* Minimum data hold time in ns */
55
+ uint32_t vddat_max ; /* Maximum data valid time in ns */
56
+ uint32_t sudat_min ; /* Minimum data setup time in ns */
57
+ uint32_t lscl_min ; /* Minimum low period of the SCL clock in ns */
58
+ uint32_t hscl_min ; /* Minimum high period of SCL clock in ns */
59
+ uint32_t trise ; /* Rise time in ns */
60
+ uint32_t tfall ; /* Fall time in ns */
61
+ uint32_t dnf ; /* Digital noise filter coefficient */
62
+ } I2C_Charac_t ;
63
+
64
+ typedef struct
65
+ {
66
+ uint32_t presc ; /* Timing prescaler */
67
+ uint32_t tscldel ; /* SCL delay */
68
+ uint32_t tsdadel ; /* SDA delay */
69
+ uint32_t sclh ; /* SCL high period */
70
+ uint32_t scll ; /* SCL low period */
71
+ } I2C_Timings_t ;
72
+ /**
73
+ * @}
74
+ */
75
+
76
+ /** @defgroup I2C_DEVICE_Private_Constants I2C_DEVICE Private Constants
77
+ * @{
78
+ */
79
+ static const I2C_Charac_t I2C_Charac [] =
80
+ {
81
+ [I2C_SPEED_FREQ_STANDARD ] =
82
+ {
83
+ .freq = 100000 ,
84
+ .freq_min = 80000 ,
85
+ .freq_max = 120000 ,
86
+ .hddat_min = 0 ,
87
+ .vddat_max = 3450 ,
88
+ .sudat_min = 250 ,
89
+ .lscl_min = 4700 ,
90
+ .hscl_min = 4000 ,
91
+ .trise = 640 ,
92
+ .tfall = 20 ,
93
+ .dnf = I2C_DIGITAL_FILTER_COEF ,
94
+ },
95
+ [I2C_SPEED_FREQ_FAST ] =
96
+ {
97
+ .freq = 400000 ,
98
+ .freq_min = 320000 ,
99
+ .freq_max = 480000 ,
100
+ .hddat_min = 0 ,
101
+ .vddat_max = 900 ,
102
+ .sudat_min = 100 ,
103
+ .lscl_min = 1300 ,
104
+ .hscl_min = 600 ,
105
+ .trise = 250 ,
106
+ .tfall = 100 ,
107
+ .dnf = I2C_DIGITAL_FILTER_COEF ,
108
+ },
109
+ [I2C_SPEED_FREQ_FAST_PLUS ] =
110
+ {
111
+ .freq = 1000000 ,
112
+ .freq_min = 800000 ,
113
+ .freq_max = 1200000 ,
114
+ .hddat_min = 0 ,
115
+ .vddat_max = 450 ,
116
+ .sudat_min = 50 ,
117
+ .lscl_min = 500 ,
118
+ .hscl_min = 260 ,
119
+ .trise = 60 ,
120
+ .tfall = 100 ,
121
+ .dnf = I2C_DIGITAL_FILTER_COEF ,
122
+ },
123
+ };
124
+ /**
125
+ * @}
126
+ */
127
+
128
+ /** @defgroup I2C_DEVICE_Private_Variables I2C_DEVICE Private Variables
129
+ * @{
130
+ */
131
+ static I2C_Timings_t I2c_valid_timing [I2C_VALID_TIMING_NBR ];
132
+ static uint32_t I2c_valid_timing_nbr = 0 ;
133
+ /**
134
+ * @}
135
+ */
136
+
137
+ /** @defgroup I2C_DEVICE_Private_Functions I2C_DEVICE Private Functions
138
+ * @{
139
+ */
140
+ /**
141
+ * @brief Compute PRESC, SCLDEL and SDADEL.
142
+ * @param clock_src_freq I2C source clock in HZ.
143
+ * @param I2C_speed I2C frequency (index).
144
+ * @retval None.
145
+ */
146
+ static void I2C_Compute_PRESC_SCLDEL_SDADEL (uint32_t clock_src_freq , uint32_t I2C_speed )
147
+ {
148
+ uint32_t prev_presc = I2C_PRESC_MAX ;
149
+ uint32_t ti2cclk ;
150
+ int32_t tsdadel_min , tsdadel_max ;
151
+ int32_t tscldel_min ;
152
+ uint32_t presc , scldel , sdadel ;
153
+ uint32_t tafdel_min , tafdel_max ;
154
+
155
+ ti2cclk = (SEC2NSEC + (clock_src_freq / 2U ))/ clock_src_freq ;
156
+
157
+ tafdel_min = (I2C_USE_ANALOG_FILTER == 1U ) ? I2C_ANALOG_FILTER_DELAY_MIN : 0U ;
158
+ tafdel_max = (I2C_USE_ANALOG_FILTER == 1U ) ? I2C_ANALOG_FILTER_DELAY_MAX : 0U ;
159
+
160
+ /* tDNF = DNF x tI2CCLK
161
+ tPRESC = (PRESC+1) x tI2CCLK
162
+ SDADEL >= {tf +tHD;DAT(min) - tAF(min) - tDNF - [3 x tI2CCLK]} / {tPRESC}
163
+ SDADEL <= {tVD;DAT(max) - tr - tAF(max) - tDNF- [4 x tI2CCLK]} / {tPRESC} */
164
+
165
+ tsdadel_min = (int32_t )I2C_Charac [I2C_speed ].tfall + (int32_t )I2C_Charac [I2C_speed ].hddat_min -
166
+ (int32_t )tafdel_min - (int32_t )(((int32_t )I2C_Charac [I2C_speed ].dnf + 3 ) * (int32_t )ti2cclk );
167
+
168
+ tsdadel_max = (int32_t )I2C_Charac [I2C_speed ].vddat_max - (int32_t )I2C_Charac [I2C_speed ].trise -
169
+ (int32_t )tafdel_max - (int32_t )(((int32_t )I2C_Charac [I2C_speed ].dnf + 4 ) * (int32_t )ti2cclk );
170
+
171
+
172
+ /* {[tr+ tSU;DAT(min)] / [tPRESC]} - 1 <= SCLDEL */
173
+ tscldel_min = (int32_t )I2C_Charac [I2C_speed ].trise + (int32_t )I2C_Charac [I2C_speed ].sudat_min ;
174
+
175
+ if (tsdadel_min <= 0 )
176
+ {
177
+ tsdadel_min = 0 ;
178
+ }
179
+
180
+ if (tsdadel_max <= 0 )
181
+ {
182
+ tsdadel_max = 0 ;
183
+ }
184
+
185
+ for (presc = 0 ; presc < I2C_PRESC_MAX ; presc ++ )
186
+ {
187
+ for (scldel = 0 ; scldel < I2C_SCLDEL_MAX ; scldel ++ )
188
+ {
189
+ /* TSCLDEL = (SCLDEL+1) * (PRESC+1) * TI2CCLK */
190
+ uint32_t tscldel = (scldel + 1U ) * (presc + 1U ) * ti2cclk ;
191
+
192
+ if (tscldel >= (uint32_t )tscldel_min )
193
+ {
194
+ for (sdadel = 0 ; sdadel < I2C_SDADEL_MAX ; sdadel ++ )
195
+ {
196
+ /* TSDADEL = SDADEL * (PRESC+1) * TI2CCLK */
197
+ uint32_t tsdadel = (sdadel * (presc + 1U )) * ti2cclk ;
198
+
199
+ if ((tsdadel >= (uint32_t )tsdadel_min ) && (tsdadel <= (uint32_t )tsdadel_max ))
200
+ {
201
+ if (presc != prev_presc )
202
+ {
203
+ I2c_valid_timing [I2c_valid_timing_nbr ].presc = presc ;
204
+ I2c_valid_timing [I2c_valid_timing_nbr ].tscldel = scldel ;
205
+ I2c_valid_timing [I2c_valid_timing_nbr ].tsdadel = sdadel ;
206
+ prev_presc = presc ;
207
+ I2c_valid_timing_nbr ++ ;
208
+
209
+ if (I2c_valid_timing_nbr >= I2C_VALID_TIMING_NBR )
210
+ {
211
+ return ;
212
+ }
213
+ }
214
+ }
215
+ }
216
+ }
217
+ }
218
+ }
219
+ }
220
+
221
+ /**
222
+ * @brief Calculate SCLL and SCLH and find best configuration.
223
+ * @param clock_src_freq I2C source clock in HZ.
224
+ * @param I2C_speed I2C frequency (index).
225
+ * @retval config index (0 to I2C_VALID_TIMING_NBR], 0xFFFFFFFF for no valid config.
226
+ */
227
+ static uint32_t I2C_Compute_SCLL_SCLH (uint32_t clock_src_freq , uint32_t I2C_speed )
228
+ {
229
+ uint32_t ret = 0xFFFFFFFFU ;
230
+ uint32_t ti2cclk ;
231
+ uint32_t ti2cspeed ;
232
+ uint32_t prev_error ;
233
+ uint32_t dnf_delay ;
234
+ uint32_t clk_min , clk_max ;
235
+ uint32_t scll , sclh ;
236
+ uint32_t tafdel_min ;
237
+
238
+ ti2cclk = (SEC2NSEC + (clock_src_freq / 2U ))/ clock_src_freq ;
239
+ ti2cspeed = (SEC2NSEC + (I2C_Charac [I2C_speed ].freq / 2U ))/ I2C_Charac [I2C_speed ].freq ;
240
+
241
+ tafdel_min = (I2C_USE_ANALOG_FILTER == 1U ) ? I2C_ANALOG_FILTER_DELAY_MIN : 0U ;
242
+
243
+ /* tDNF = DNF x tI2CCLK */
244
+ dnf_delay = I2C_Charac [I2C_speed ].dnf * ti2cclk ;
245
+
246
+ clk_max = SEC2NSEC / I2C_Charac [I2C_speed ].freq_min ;
247
+ clk_min = SEC2NSEC / I2C_Charac [I2C_speed ].freq_max ;
248
+
249
+ prev_error = ti2cspeed ;
250
+
251
+ for (uint32_t count = 0 ; count < I2c_valid_timing_nbr ; count ++ )
252
+ {
253
+ /* tPRESC = (PRESC+1) x tI2CCLK*/
254
+ uint32_t tpresc = (I2c_valid_timing [count ].presc + 1U ) * ti2cclk ;
255
+
256
+ for (scll = 0 ; scll < I2C_SCLL_MAX ; scll ++ )
257
+ {
258
+ /* tLOW(min) <= tAF(min) + tDNF + 2 x tI2CCLK + [(SCLL+1) x tPRESC ] */
259
+ uint32_t tscl_l = tafdel_min + dnf_delay + (2U * ti2cclk ) + ((scll + 1U ) * tpresc );
260
+
261
+
262
+ /* The I2CCLK period tI2CCLK must respect the following conditions:
263
+ tI2CCLK < (tLOW - tfilters) / 4 and tI2CCLK < tHIGH */
264
+ if ((tscl_l > I2C_Charac [I2C_speed ].lscl_min ) && (ti2cclk < ((tscl_l - tafdel_min - dnf_delay ) / 4U )))
265
+ {
266
+ for (sclh = 0 ; sclh < I2C_SCLH_MAX ; sclh ++ )
267
+ {
268
+ /* tHIGH(min) <= tAF(min) + tDNF + 2 x tI2CCLK + [(SCLH+1) x tPRESC] */
269
+ uint32_t tscl_h = tafdel_min + dnf_delay + (2U * ti2cclk ) + ((sclh + 1U ) * tpresc );
270
+
271
+ /* tSCL = tf + tLOW + tr + tHIGH */
272
+ uint32_t tscl = tscl_l + tscl_h + I2C_Charac [I2C_speed ].trise + I2C_Charac [I2C_speed ].tfall ;
273
+
274
+ if ((tscl >= clk_min ) && (tscl <= clk_max ) && (tscl_h >= I2C_Charac [I2C_speed ].hscl_min ) && (ti2cclk < tscl_h ))
275
+ {
276
+ int32_t error = (int32_t )tscl - (int32_t )ti2cspeed ;
277
+
278
+ if (error < 0 )
279
+ {
280
+ error = - error ;
281
+ }
282
+
283
+ /* look for the timings with the lowest clock error */
284
+ if ((uint32_t )error < prev_error )
285
+ {
286
+ prev_error = (uint32_t )error ;
287
+ I2c_valid_timing [count ].scll = scll ;
288
+ I2c_valid_timing [count ].sclh = sclh ;
289
+ ret = count ;
290
+ }
291
+ }
292
+ }
293
+ }
294
+ }
295
+ }
296
+
297
+ return ret ;
298
+ }
299
+
300
+ /**
301
+ * @brief Compute I2C timing according current I2C clock source and required I2C clock.
302
+ * @param clock_src_freq I2C clock source in Hz.
303
+ * @param i2c_freq Required I2C clock in Hz.
304
+ * @retval I2C timing or 0 in case of error.
305
+ */
306
+ static uint32_t I2C_ComputeTiming (uint32_t clock_src_freq , uint32_t i2c_freq )
307
+ {
308
+ uint32_t ret = 0 ;
309
+ uint32_t speed ;
310
+ uint32_t idx ;
311
+
312
+
313
+ if ((clock_src_freq != 0U ) && (i2c_freq != 0U ))
314
+ {
315
+ for ( speed = 0 ; speed <= (uint32_t )I2C_SPEED_FREQ_FAST_PLUS ; speed ++ )
316
+ {
317
+ if ((i2c_freq >= I2C_Charac [speed ].freq_min ) &&
318
+ (i2c_freq <= I2C_Charac [speed ].freq_max ))
319
+ {
320
+ I2C_Compute_PRESC_SCLDEL_SDADEL (clock_src_freq , speed );
321
+ idx = I2C_Compute_SCLL_SCLH (clock_src_freq , speed );
322
+
323
+ if (idx < I2C_VALID_TIMING_NBR )
324
+ {
325
+ ret = ((I2c_valid_timing [idx ].presc & 0x0FU ) << 28 ) |\
326
+ ((I2c_valid_timing [idx ].tscldel & 0x0FU ) << 20 ) |\
327
+ ((I2c_valid_timing [idx ].tsdadel & 0x0FU ) << 16 ) |\
328
+ ((I2c_valid_timing [idx ].sclh & 0xFFU ) << 8 ) |\
329
+ ((I2c_valid_timing [idx ].scll & 0xFFU ) << 0 );
330
+ }
331
+ break ;
332
+ }
333
+ }
334
+ }
335
+
336
+ return ret ;
337
+ }
338
+ /**
339
+ * @}
340
+ */
341
+
342
+ /** @defgroup I2C_DEVICE_Exported_Functions I2C_DEVICE Exported Functions
343
+ * @{
344
+ */
345
+ /**
346
+ * @brief Provide the suitable timing depending on requested frequency
347
+ * @param hz Required I2C clock in Hz.
348
+ * @retval I2C timing or 0 in case of error.
349
+ */
350
+ uint32_t get_i2c_timing (int hz )
351
+ {
352
+ uint32_t clock_src_freq ;
353
+ uint32_t tim ;
354
+
355
+ /* we will use D2PCLK1 to calculate I2C timings */
356
+ MBED_ASSERT (RCC_I2C1CLKSOURCE_D2PCLK1 == __HAL_RCC_GET_I2C1_SOURCE ());
357
+
358
+ LL_RCC_ClocksTypeDef rcc_clocks ;
359
+ LL_RCC_GetSystemClocksFreq (& rcc_clocks );
360
+
361
+ tim = I2C_ComputeTiming (rcc_clocks .PCLK1_Frequency , hz );
362
+
363
+ return tim ;
364
+ }
365
+ /**
366
+ * @}
367
+ */
368
+
369
+ #endif // DEVICE_I2C
0 commit comments