Skip to content

Commit 7544f7e

Browse files
committed
Use the proper clock source for any I2C instance
1 parent 28a3475 commit 7544f7e

File tree

3 files changed

+78
-10
lines changed

3 files changed

+78
-10
lines changed

targets/TARGET_STM/TARGET_STM32H7/i2c_device.c

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "i2c_device.h"
1818
#include "mbed_assert.h"
19+
#include "mbed_error.h"
1920
#include "stm32h7xx_ll_rcc.h"
2021

2122
#if DEVICE_I2C
@@ -335,6 +336,71 @@ static uint32_t I2C_ComputeTiming(uint32_t clock_src_freq, uint32_t i2c_freq)
335336

336337
return ret;
337338
}
339+
340+
/**
341+
* @brief Get I2C clock source frequency according I2C instance used.
342+
* @param i2c I2C instance name.
343+
* @retval I2C clock source frequency in Hz.
344+
*/
345+
static uint32_t I2C_GetPclk(I2CName i2c)
346+
{
347+
uint32_t clocksource;
348+
uint32_t pclk = 0;
349+
PLL3_ClocksTypeDef pll3_clocks;
350+
351+
if(i2c == I2C_1 || i2c == I2C_2 || i2c == I2C_3) {
352+
clocksource = __HAL_RCC_GET_I2C123_SOURCE();
353+
switch(clocksource)
354+
{
355+
case RCC_I2C123CLKSOURCE_D2PCLK1:
356+
pclk = HAL_RCC_GetPCLK1Freq();
357+
break;
358+
case RCC_I2C123CLKSOURCE_PLL3:
359+
HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
360+
pclk = pll3_clocks.PLL3_R_Frequency;
361+
break;
362+
case RCC_I2C123CLKSOURCE_HSI:
363+
pclk = HSI_VALUE;
364+
break;
365+
case RCC_I2C123CLKSOURCE_CSI:
366+
pclk = CSI_VALUE;
367+
break;
368+
default:
369+
// should not happend
370+
error("I2C123: Invalid clock source");
371+
break;
372+
}
373+
}
374+
else if(i2c == I2C_4) {
375+
clocksource = __HAL_RCC_GET_I2C4_SOURCE();
376+
switch(clocksource)
377+
{
378+
case RCC_I2C4CLKSOURCE_D3PCLK1:
379+
pclk = HAL_RCCEx_GetD3PCLK1Freq();
380+
break;
381+
case RCC_I2C4CLKSOURCE_PLL3:
382+
HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
383+
pclk = pll3_clocks.PLL3_R_Frequency;
384+
break;
385+
case RCC_I2C4CLKSOURCE_HSI:
386+
pclk = HSI_VALUE;
387+
break;
388+
case RCC_I2C4CLKSOURCE_CSI:
389+
pclk = CSI_VALUE;
390+
break;
391+
default:
392+
// should not happend
393+
error("I2C4: Invalid clock source");
394+
break;
395+
}
396+
}
397+
else {
398+
// should not happend
399+
error("I2C: unknown instance");
400+
}
401+
402+
return pclk;
403+
}
338404
/**
339405
* @}
340406
*/
@@ -347,19 +413,16 @@ static uint32_t I2C_ComputeTiming(uint32_t clock_src_freq, uint32_t i2c_freq)
347413
* @param hz Required I2C clock in Hz.
348414
* @retval I2C timing or 0 in case of error.
349415
*/
350-
uint32_t get_i2c_timing(int hz)
416+
uint32_t get_i2c_timing(I2CName i2c, int hz)
351417
{
352418
uint32_t tim;
419+
uint32_t pclk;
353420

354421
I2c_valid_timing_nbr = 0;
355422

356-
/* we will use D2PCLK1 to calculate I2C timings */
357-
MBED_ASSERT(RCC_I2C1CLKSOURCE_D2PCLK1 ==__HAL_RCC_GET_I2C1_SOURCE());
358-
359-
LL_RCC_ClocksTypeDef rcc_clocks;
360-
LL_RCC_GetSystemClocksFreq(&rcc_clocks);
423+
pclk = I2C_GetPclk(i2c);
361424

362-
tim = I2C_ComputeTiming(rcc_clocks.PCLK1_Frequency, hz);
425+
tim = I2C_ComputeTiming(pclk, hz);
363426

364427
return tim;
365428
}

targets/TARGET_STM/TARGET_STM32H7/i2c_device.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#ifndef MBED_I2C_DEVICE_H
1818
#define MBED_I2C_DEVICE_H
1919

20-
#include "cmsis.h"
20+
#include "PeripheralNames.h"
2121

2222
#ifdef __cplusplus
2323
extern "C" {
@@ -36,7 +36,7 @@ extern "C" {
3636
#define I2CAPI_I2C4_CLKSRC RCC_I2C4CLKSOURCE_D3PCLK1
3737

3838
/* Provide the suitable timing depending on requested frequency */
39-
extern uint32_t get_i2c_timing(int hz);
39+
extern uint32_t get_i2c_timing(I2CName i2c, int hz);
4040

4141

4242
#ifdef __cplusplus

targets/TARGET_STM/i2c_api.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,6 @@ void i2c_frequency(i2c_t *obj, int hz)
461461
#ifdef I2C_IP_VERSION_V2
462462
/* Only predefined timing for below frequencies are supported */
463463
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
464-
handle->Init.Timing = get_i2c_timing(hz);
465464

466465
// Enable the Fast Mode Plus capability
467466
if (hz == 1000000) {
@@ -530,6 +529,12 @@ void i2c_frequency(i2c_t *obj, int hz)
530529
HAL_I2CEx_ConfigAnalogFilter(handle, I2C_ANALOGFILTER_ENABLE);
531530
#endif
532531

532+
#ifdef TARGET_STM32H7
533+
handle->Init.Timing = get_i2c_timing(obj_s->i2c, hz);
534+
#else
535+
handle->Init.Timing = get_i2c_timing(hz);
536+
#endif
537+
533538
// I2C configuration
534539
handle->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
535540
handle->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;

0 commit comments

Comments
 (0)