Skip to content

Commit d974b47

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 d974b47

33 files changed

+1856
-668
lines changed

targets/TARGET_STM/TARGET_STM32F0/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ target_sources(mbed-stm32f0
2121
cmsis_nvic.c
2222
flash_api.c
2323
gpio_irq_device.c
24+
i2c_device.c
2425
pwmout_device.c
2526
serial_device.c
2627
spi_api.c
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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_get_pclk(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+
} else {
45+
// should not happend
46+
error("I2C: unknown instance");
47+
}
48+
return pclk;
49+
}
50+
51+
/**
52+
* @brief Provide the suitable timing depending on requested frequency
53+
* @param hz Required I2C clock in Hz.
54+
* @retval I2C timing or 0 in case of error.
55+
*/
56+
uint32_t i2c_get_timing(I2CName i2c, int hz)
57+
{
58+
uint32_t tim;
59+
uint32_t pclk;
60+
61+
pclk = i2c_get_pclk(i2c);
62+
63+
if (pclk == I2C_PCLK_DEF) {
64+
switch (hz) {
65+
case 100000:
66+
tim = TIMING_VAL_DEFAULT_CLK_100KHZ;
67+
break;
68+
case 400000:
69+
tim = TIMING_VAL_DEFAULT_CLK_400KHZ;
70+
break;
71+
case 1000000:
72+
tim = TIMING_VAL_DEFAULT_CLK_1MHZ;
73+
break;
74+
default:
75+
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
76+
break;
77+
}
78+
}
79+
80+
else {
81+
tim = i2c_compute_timing(pclk, hz);
82+
}
83+
return tim;
84+
}
85+
86+
/**
87+
* @}
88+
*/
89+
90+
#endif // DEVICE_I2C

targets/TARGET_STM/TARGET_STM32F0/i2c_device.h

Lines changed: 17 additions & 29 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
@@ -32,41 +33,28 @@ extern "C" {
3233
#define I2C2_EV_IRQn I2C2_IRQn
3334
#define I2C2_ER_IRQn I2C2_IRQn
3435
#endif
35-
#if defined I2C3_BASE
36-
#define I2C3_EV_IRQn I2C3_IRQn
37-
#define I2C3_ER_IRQn I2C3_IRQn
38-
#endif
39-
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-
4236

4337
/* Define IP version */
4438
#define I2C_IP_VERSION_V2
4539

40+
#define TIMING_VAL_DEFAULT_CLK_100KHZ 0x10805E89 // Standard mode with Rise Time = 400ns and Fall Time = 100ns
41+
#define TIMING_VAL_DEFAULT_CLK_400KHZ 0x00901850 // Fast mode with Rise Time = 250ns and Fall Time = 100ns
42+
#define TIMING_VAL_DEFAULT_CLK_1MHZ 0x00700818 // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
43+
#define I2C_PCLK_DEF 48000000 // 48 MHz
44+
45+
#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)
46+
4647
/* Family specifc settings for clock source */
4748
#define I2CAPI_I2C1_CLKSRC RCC_I2C1CLKSOURCE_SYSCLK
4849

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;
50+
uint32_t i2c_get_pclk(I2CName i2c);
51+
uint32_t i2c_compute_timing(uint32_t clock_src_freq, uint32_t i2c_freq);
52+
uint32_t i2c_get_timing(I2CName i2c, int hz);
53+
void i2c_compute_presc_scldel_sdadel(uint32_t clock_src_freq, uint32_t I2C_speed);
54+
uint32_t i2c_compute_scll_sclh(uint32_t clock_src_freq, uint32_t I2C_speed);
5355

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;
56+
#ifdef __cplusplus
6857
}
69-
58+
#endif
7059
#endif // DEVICE_I2C
71-
7260
#endif

targets/TARGET_STM/TARGET_STM32F3/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ target_sources(mbed-stm32f3
2121
analogout_device.c
2222
flash_api.c
2323
gpio_irq_device.c
24+
i2c_device.c
2425
pwmout_device.c
2526
serial_device.c
2627
spi_api.c
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
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_get_pclk(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+
#if defined I2C2_BASE
46+
else if (i2c == I2C_2) {
47+
clocksource = __HAL_RCC_GET_I2C2_SOURCE();
48+
switch (clocksource) {
49+
case RCC_I2C2CLKSOURCE_SYSCLK:
50+
pclk = HAL_RCC_GetSysClockFreq();
51+
break;
52+
53+
case RCC_I2C2CLKSOURCE_HSI:
54+
pclk = HSI_VALUE;
55+
break;
56+
}
57+
}
58+
#endif
59+
#if defined I2C3_BASE
60+
else if (i2c == I2C_3) {
61+
clocksource = __HAL_RCC_GET_I2C3_SOURCE();
62+
switch (clocksource) {
63+
case RCC_I2C3CLKSOURCE_SYSCLK:
64+
pclk = HAL_RCC_GetSysClockFreq();
65+
break;
66+
67+
case RCC_I2C3CLKSOURCE_HSI:
68+
pclk = HSI_VALUE;
69+
break;
70+
}
71+
}
72+
#endif
73+
else {
74+
// should not happend
75+
error("I2C: unknown instance");
76+
}
77+
return pclk;
78+
}
79+
80+
/**
81+
* @brief Provide the suitable timing depending on requested frequency
82+
* @param hz Required I2C clock in Hz.
83+
* @retval I2C timing or 0 in case of error.
84+
*/
85+
uint32_t i2c_get_timing(I2CName i2c, int hz)
86+
{
87+
uint32_t tim;
88+
uint32_t pclk;
89+
90+
pclk = i2c_get_pclk(i2c);
91+
92+
if (pclk == I2C_PCLK_HSI) {
93+
switch (hz) {
94+
case 100000:
95+
tim = TIMING_VAL_64M_CLK_100KHZ;
96+
break;
97+
case 400000:
98+
tim = TIMING_VAL_64M_CLK_400KHZ;
99+
break;
100+
case 1000000:
101+
tim = TIMING_VAL_64M_CLK_1MHZ;
102+
break;
103+
default:
104+
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
105+
break;
106+
}
107+
} else if (pclk == I2C_PCLK_HSE) {
108+
switch (hz) {
109+
case 100000:
110+
tim = TIMING_VAL_72M_CLK_100KHZ;
111+
break;
112+
case 400000:
113+
tim = TIMING_VAL_72M_CLK_400KHZ;
114+
break;
115+
case 1000000:
116+
tim = TIMING_VAL_72M_CLK_1MHZ;
117+
break;
118+
default:
119+
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
120+
break;
121+
}
122+
}
123+
124+
else {
125+
tim = i2c_compute_timing(pclk, hz);
126+
}
127+
return tim;
128+
}
129+
130+
/**
131+
* @}
132+
*/
133+
134+
#endif // DEVICE_I2C

0 commit comments

Comments
 (0)