Skip to content

Commit cdba4b6

Browse files
driver/i2c: Added I2C timing calculation function.
This commit adds I2C timing value automatic calculation algorithm for all supported families added. This patch improves I2C timing calculation according to I2C input clock and I2C bus speed. This commit also allows user to change the system clock and I2C input clock. Related issue: #12907 Pull request type: [x] Patch update (Bug fix / Target update / Docs update / Test update / Refactor) [] Feature update (New feature / Functionality change / New API) [] Major update (Breaking change E.g. Return code change / API behaviour change) Test results: [] No Tests required for this change (E.g docs only update) [x] Covered by existing mbed-os tests (Greentea or Unittest) [] Tests / results supplied as part of this PR Signed-off-by: Affrin Pinhero <[email protected]>
1 parent a3be10c commit cdba4b6

File tree

23 files changed

+1920
-656
lines changed

23 files changed

+1920
-656
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/* mbed Microcontroller Library
2+
* SPDX-License-Identifier: BSD-3-Clause
3+
******************************************************************************
4+
*
5+
* Copyright (c) 2021 STMicroelectronics.
6+
* All rights reserved.
7+
*
8+
* This software component is licensed by ST under BSD 3-Clause license,
9+
* the "License"; You may not use this file except in compliance with the
10+
* License. You may obtain a copy of the License at:
11+
* opensource.org/licenses/BSD-3-Clause
12+
*
13+
******************************************************************************
14+
*/
15+
16+
#include "i2c_device.h"
17+
#include "mbed_assert.h"
18+
#include "mbed_error.h"
19+
#include "stm32f0xx_ll_rcc.h"
20+
21+
/* Define I2C Device */
22+
#if DEVICE_I2C
23+
24+
/**
25+
* @brief Get I2C clock source frequency according I2C instance used.
26+
* @param i2c I2C instance name.
27+
* @retval I2C clock source frequency in Hz.
28+
*/
29+
uint32_t I2C_GetPclk(I2CName i2c)
30+
{
31+
uint32_t clocksource;
32+
uint32_t pclk = 0;
33+
if (i2c == I2C_1) {
34+
clocksource = __HAL_RCC_GET_I2C1_SOURCE();
35+
switch (clocksource) {
36+
case RCC_I2C1CLKSOURCE_SYSCLK:
37+
pclk = HAL_RCC_GetSysClockFreq();
38+
break;
39+
40+
case RCC_I2C1CLKSOURCE_HSI:
41+
pclk = HSI_VALUE;
42+
break;
43+
}
44+
}
45+
46+
#if defined(I2C_2)
47+
else if (i2c == I2C_2) {
48+
clocksource = __HAL_RCC_GET_I2C2_SOURCE();
49+
switch (clocksource) {
50+
case RCC_I2C2CLKSOURCE_SYSCLK:
51+
pclk = HAL_RCC_GetSysClockFreq();
52+
break;
53+
54+
case RCC_I2C2CLKSOURCE_HSI:
55+
pclk = HSI_VALUE;
56+
break;
57+
}
58+
}
59+
#endif
60+
61+
else {
62+
// should not happend
63+
error("I2C: unknown instance");
64+
}
65+
66+
return pclk;
67+
}
68+
69+
/**
70+
* @brief Provide the suitable timing depending on requested frequency
71+
* @param hz Required I2C clock in Hz.
72+
* @retval I2C timing or 0 in case of error.
73+
*/
74+
uint32_t get_i2c_timing(I2CName i2c, int hz)
75+
{
76+
uint32_t tim;
77+
uint32_t pclk;
78+
79+
pclk = I2C_GetPclk(i2c);
80+
81+
if (pclk == I2C_PCLK_DEF) {
82+
switch (hz) {
83+
case 100000:
84+
tim = TIMING_VAL_DEFAULT_CLK_100KHZ;
85+
break;
86+
case 400000:
87+
tim = TIMING_VAL_DEFAULT_CLK_400KHZ;
88+
break;
89+
case 1000000:
90+
tim = TIMING_VAL_DEFAULT_CLK_1MHZ;
91+
break;
92+
default:
93+
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
94+
break;
95+
}
96+
}
97+
98+
else {
99+
tim = I2C_ComputeTiming(pclk, hz);
100+
}
101+
return tim;
102+
}
103+
104+
/**
105+
* @}
106+
*/
107+
108+
#endif // DEVICE_I2C

targets/TARGET_STM/TARGET_STM32F0/i2c_device.h

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* SPDX-License-Identifier: BSD-3-Clause
33
******************************************************************************
44
*
5-
* Copyright (c) 2015-2020 STMicroelectronics.
5+
* Copyright (c) 2015-2021 STMicroelectronics.
66
* All rights reserved.
77
*
88
* This software component is licensed by ST under BSD 3-Clause license,
@@ -16,12 +16,13 @@
1616
#ifndef MBED_I2C_DEVICE_H
1717
#define MBED_I2C_DEVICE_H
1818

19-
#include "cmsis.h"
19+
#include "PeripheralNames.h"
2020

2121
#ifdef __cplusplus
2222
extern "C" {
2323
#endif
2424

25+
/* Define I2C Device */
2526
#if DEVICE_I2C
2627

2728
#if defined I2C1_BASE
@@ -37,36 +38,28 @@ extern "C" {
3738
#define I2C3_ER_IRQn I2C3_IRQn
3839
#endif
3940

40-
#define I2C_IT_ALL (I2C_IT_ERRI|I2C_IT_TCI|I2C_IT_STOPI|I2C_IT_NACKI|I2C_IT_ADDRI|I2C_IT_RXI|I2C_IT_TXI)
41-
42-
4341
/* Define IP version */
4442
#define I2C_IP_VERSION_V2
4543

44+
#define TIMING_VAL_DEFAULT_CLK_100KHZ 0x10805E89 // Standard mode with Rise Time = 400ns and Fall Time = 100ns
45+
#define TIMING_VAL_DEFAULT_CLK_400KHZ 0x00901850 // Fast mode with Rise Time = 250ns and Fall Time = 100ns
46+
#define TIMING_VAL_DEFAULT_CLK_1MHZ 0x00700818 // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
47+
#define I2C_PCLK_DEF 48000000 // 48 MHz
48+
49+
#define I2C_IT_ALL (I2C_IT_ERRI|I2C_IT_TCI|I2C_IT_STOPI|I2C_IT_NACKI|I2C_IT_ADDRI|I2C_IT_RXI|I2C_IT_TXI)
50+
4651
/* Family specifc settings for clock source */
4752
#define I2CAPI_I2C1_CLKSRC RCC_I2C1CLKSOURCE_SYSCLK
4853

49-
/* Provide the suitable timing depending on requested frequencie */
50-
static inline uint32_t get_i2c_timing(int hz)
51-
{
52-
uint32_t tim = 0;
54+
/* Provide the suitable timing depending on requested frequency */
55+
uint32_t I2C_GetPclk(I2CName i2c);
56+
uint32_t I2C_ComputeTiming(uint32_t clock_src_freq, uint32_t i2c_freq);
57+
uint32_t get_i2c_timing(I2CName i2c, int hz);
58+
void I2C_Compute_PRESC_SCLDEL_SDADEL(uint32_t clock_src_freq, uint32_t I2C_speed);
59+
uint32_t I2C_Compute_SCLL_SCLH(uint32_t clock_src_freq, uint32_t I2C_speed);
5360

54-
switch (hz) {
55-
case 100000:
56-
tim = 0x10805E89; // Standard mode with Rise Time = 400ns and Fall Time = 100ns
57-
break;
58-
case 400000:
59-
tim = 0x00901850; // Fast mode with Rise Time = 250ns and Fall Time = 100ns
60-
break;
61-
case 1000000:
62-
tim = 0x00700818; // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
63-
break;
64-
default:
65-
break;
66-
}
67-
return tim;
61+
#ifdef __cplusplus
6862
}
69-
63+
#endif
7064
#endif // DEVICE_I2C
71-
7265
#endif
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/* mbed Microcontroller Library
2+
* SPDX-License-Identifier: BSD-3-Clause
3+
******************************************************************************
4+
*
5+
* Copyright (c) 2021 STMicroelectronics.
6+
* All rights reserved.
7+
*
8+
* This software component is licensed by ST under BSD 3-Clause license,
9+
* the "License"; You may not use this file except in compliance with the
10+
* License. You may obtain a copy of the License at:
11+
* opensource.org/licenses/BSD-3-Clause
12+
*
13+
******************************************************************************
14+
*/
15+
16+
#include "i2c_device.h"
17+
#include "mbed_assert.h"
18+
#include "mbed_error.h"
19+
#include "stm32f3xx_ll_rcc.h"
20+
21+
/* Define I2C Device */
22+
#if DEVICE_I2C
23+
24+
/**
25+
* @brief Get I2C clock source frequency according I2C instance used.
26+
* @param i2c I2C instance name.
27+
* @retval I2C clock source frequency in Hz.
28+
*/
29+
uint32_t I2C_GetPclk(I2CName i2c)
30+
{
31+
uint32_t clocksource;
32+
uint32_t pclk = 0;
33+
if (i2c == I2C_1) {
34+
clocksource = __HAL_RCC_GET_I2C1_SOURCE();
35+
switch (clocksource) {
36+
case RCC_I2C1CLKSOURCE_SYSCLK:
37+
pclk = HAL_RCC_GetSysClockFreq();
38+
break;
39+
40+
case RCC_I2C1CLKSOURCE_HSI:
41+
pclk = HSI_VALUE;
42+
break;
43+
}
44+
}
45+
46+
#ifdef I2C_2
47+
else if (i2c == I2C_2) {
48+
clocksource = __HAL_RCC_GET_I2C2_SOURCE();
49+
switch (clocksource) {
50+
case RCC_I2C2CLKSOURCE_SYSCLK:
51+
pclk = HAL_RCC_GetSysClockFreq();
52+
break;
53+
54+
case RCC_I2C2CLKSOURCE_HSI:
55+
pclk = HSI_VALUE;
56+
break;
57+
}
58+
}
59+
#endif
60+
61+
#ifdef I2C_3
62+
else if (i2c == I2C_3) {
63+
clocksource = __HAL_RCC_GET_I2C3_SOURCE();
64+
switch (clocksource) {
65+
case RCC_I2C3CLKSOURCE_SYSCLK:
66+
pclk = HAL_RCC_GetSysClockFreq();
67+
break;
68+
69+
case RCC_I2C3CLKSOURCE_HSI:
70+
pclk = HSI_VALUE;
71+
break;
72+
}
73+
}
74+
#endif
75+
76+
else {
77+
// should not happend
78+
error("I2C: unknown instance");
79+
}
80+
81+
return pclk;
82+
}
83+
84+
/**
85+
* @brief Provide the suitable timing depending on requested frequency
86+
* @param hz Required I2C clock in Hz.
87+
* @retval I2C timing or 0 in case of error.
88+
*/
89+
uint32_t get_i2c_timing(I2CName i2c, int hz)
90+
{
91+
uint32_t tim;
92+
uint32_t pclk;
93+
94+
pclk = I2C_GetPclk(i2c);
95+
96+
if (pclk == I2C_PCLK_HSI) {
97+
switch (hz) {
98+
case 100000:
99+
tim = TIMING_VAL_64M_CLK_100KHZ;
100+
break;
101+
case 400000:
102+
tim = TIMING_VAL_64M_CLK_400KHZ;
103+
break;
104+
case 1000000:
105+
tim = TIMING_VAL_64M_CLK_1MHZ;
106+
break;
107+
default:
108+
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
109+
break;
110+
}
111+
} else if (pclk == I2C_PCLK_HSE) {
112+
switch (hz) {
113+
case 100000:
114+
tim = TIMING_VAL_72M_CLK_100KHZ;
115+
break;
116+
case 400000:
117+
tim = TIMING_VAL_72M_CLK_400KHZ;
118+
break;
119+
case 1000000:
120+
tim = TIMING_VAL_72M_CLK_1MHZ;
121+
break;
122+
default:
123+
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
124+
break;
125+
}
126+
}
127+
128+
else {
129+
tim = I2C_ComputeTiming(pclk, hz);
130+
}
131+
return tim;
132+
}
133+
134+
/**
135+
* @}
136+
*/
137+
138+
#endif // DEVICE_I2C

0 commit comments

Comments
 (0)