Skip to content

Commit 5ef56cc

Browse files
authored
Merge pull request #14557 from affrinpinhero-2356/feature_i2cTiming_Calculation
STM32: driver/Added I2C timing calculation algorithm
2 parents dcd6dc3 + d974b47 commit 5ef56cc

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)