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 <affrin.pinhero@hcl.com>
pull/14557/head
Affrin Pinhero 2021-04-19 16:57:27 +05:30
parent a3be10c976
commit d974b47439
33 changed files with 1857 additions and 669 deletions

View File

@ -21,6 +21,7 @@ target_sources(mbed-stm32f0
cmsis_nvic.c
flash_api.c
gpio_irq_device.c
i2c_device.c
pwmout_device.c
serial_device.c
spi_api.c

View File

@ -0,0 +1,90 @@
/* mbed Microcontroller Library
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#include "i2c_device.h"
#include "mbed_assert.h"
#include "mbed_error.h"
#include "stm32f0xx_ll_rcc.h"
/* Define I2C Device */
#if DEVICE_I2C
/**
* @brief Get I2C clock source frequency according I2C instance used.
* @param i2c I2C instance name.
* @retval I2C clock source frequency in Hz.
*/
uint32_t i2c_get_pclk(I2CName i2c)
{
uint32_t clocksource;
uint32_t pclk = 0;
if (i2c == I2C_1) {
clocksource = __HAL_RCC_GET_I2C1_SOURCE();
switch (clocksource) {
case RCC_I2C1CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C1CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
} else {
// should not happend
error("I2C: unknown instance");
}
return pclk;
}
/**
* @brief Provide the suitable timing depending on requested frequency
* @param hz Required I2C clock in Hz.
* @retval I2C timing or 0 in case of error.
*/
uint32_t i2c_get_timing(I2CName i2c, int hz)
{
uint32_t tim;
uint32_t pclk;
pclk = i2c_get_pclk(i2c);
if (pclk == I2C_PCLK_DEF) {
switch (hz) {
case 100000:
tim = TIMING_VAL_DEFAULT_CLK_100KHZ;
break;
case 400000:
tim = TIMING_VAL_DEFAULT_CLK_400KHZ;
break;
case 1000000:
tim = TIMING_VAL_DEFAULT_CLK_1MHZ;
break;
default:
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
break;
}
}
else {
tim = i2c_compute_timing(pclk, hz);
}
return tim;
}
/**
* @}
*/
#endif // DEVICE_I2C

View File

@ -2,7 +2,7 @@
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2015-2020 STMicroelectronics.
* Copyright (c) 2015-2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
@ -16,12 +16,13 @@
#ifndef MBED_I2C_DEVICE_H
#define MBED_I2C_DEVICE_H
#include "cmsis.h"
#include "PeripheralNames.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Define I2C Device */
#if DEVICE_I2C
#if defined I2C1_BASE
@ -32,41 +33,28 @@ extern "C" {
#define I2C2_EV_IRQn I2C2_IRQn
#define I2C2_ER_IRQn I2C2_IRQn
#endif
#if defined I2C3_BASE
#define I2C3_EV_IRQn I2C3_IRQn
#define I2C3_ER_IRQn I2C3_IRQn
#endif
#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)
/* Define IP version */
#define I2C_IP_VERSION_V2
#define TIMING_VAL_DEFAULT_CLK_100KHZ 0x10805E89 // Standard mode with Rise Time = 400ns and Fall Time = 100ns
#define TIMING_VAL_DEFAULT_CLK_400KHZ 0x00901850 // Fast mode with Rise Time = 250ns and Fall Time = 100ns
#define TIMING_VAL_DEFAULT_CLK_1MHZ 0x00700818 // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
#define I2C_PCLK_DEF 48000000 // 48 MHz
#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)
/* Family specifc settings for clock source */
#define I2CAPI_I2C1_CLKSRC RCC_I2C1CLKSOURCE_SYSCLK
/* Provide the suitable timing depending on requested frequencie */
static inline uint32_t get_i2c_timing(int hz)
{
uint32_t tim = 0;
uint32_t i2c_get_pclk(I2CName i2c);
uint32_t i2c_compute_timing(uint32_t clock_src_freq, uint32_t i2c_freq);
uint32_t i2c_get_timing(I2CName i2c, int hz);
void i2c_compute_presc_scldel_sdadel(uint32_t clock_src_freq, uint32_t I2C_speed);
uint32_t i2c_compute_scll_sclh(uint32_t clock_src_freq, uint32_t I2C_speed);
switch (hz) {
case 100000:
tim = 0x10805E89; // Standard mode with Rise Time = 400ns and Fall Time = 100ns
break;
case 400000:
tim = 0x00901850; // Fast mode with Rise Time = 250ns and Fall Time = 100ns
break;
case 1000000:
tim = 0x00700818; // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
break;
default:
break;
}
return tim;
#ifdef __cplusplus
}
#endif // DEVICE_I2C
#endif
#endif // DEVICE_I2C
#endif

View File

@ -21,6 +21,7 @@ target_sources(mbed-stm32f3
analogout_device.c
flash_api.c
gpio_irq_device.c
i2c_device.c
pwmout_device.c
serial_device.c
spi_api.c

View File

@ -0,0 +1,134 @@
/* mbed Microcontroller Library
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#include "i2c_device.h"
#include "mbed_assert.h"
#include "mbed_error.h"
#include "stm32f3xx_ll_rcc.h"
/* Define I2C Device */
#if DEVICE_I2C
/**
* @brief Get I2C clock source frequency according I2C instance used.
* @param i2c I2C instance name.
* @retval I2C clock source frequency in Hz.
*/
uint32_t i2c_get_pclk(I2CName i2c)
{
uint32_t clocksource;
uint32_t pclk = 0;
if (i2c == I2C_1) {
clocksource = __HAL_RCC_GET_I2C1_SOURCE();
switch (clocksource) {
case RCC_I2C1CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C1CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#if defined I2C2_BASE
else if (i2c == I2C_2) {
clocksource = __HAL_RCC_GET_I2C2_SOURCE();
switch (clocksource) {
case RCC_I2C2CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C2CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
#if defined I2C3_BASE
else if (i2c == I2C_3) {
clocksource = __HAL_RCC_GET_I2C3_SOURCE();
switch (clocksource) {
case RCC_I2C3CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C3CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
else {
// should not happend
error("I2C: unknown instance");
}
return pclk;
}
/**
* @brief Provide the suitable timing depending on requested frequency
* @param hz Required I2C clock in Hz.
* @retval I2C timing or 0 in case of error.
*/
uint32_t i2c_get_timing(I2CName i2c, int hz)
{
uint32_t tim;
uint32_t pclk;
pclk = i2c_get_pclk(i2c);
if (pclk == I2C_PCLK_HSI) {
switch (hz) {
case 100000:
tim = TIMING_VAL_64M_CLK_100KHZ;
break;
case 400000:
tim = TIMING_VAL_64M_CLK_400KHZ;
break;
case 1000000:
tim = TIMING_VAL_64M_CLK_1MHZ;
break;
default:
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
break;
}
} else if (pclk == I2C_PCLK_HSE) {
switch (hz) {
case 100000:
tim = TIMING_VAL_72M_CLK_100KHZ;
break;
case 400000:
tim = TIMING_VAL_72M_CLK_400KHZ;
break;
case 1000000:
tim = TIMING_VAL_72M_CLK_1MHZ;
break;
default:
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
break;
}
}
else {
tim = i2c_compute_timing(pclk, hz);
}
return tim;
}
/**
* @}
*/
#endif // DEVICE_I2C

View File

@ -1,6 +1,6 @@
/* mbed Microcontroller Library
*******************************************************************************
* Copyright (c) 2015, STMicroelectronics
* Copyright (c) 2015-2021, STMicroelectronics
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -27,76 +27,48 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************
*/
#ifndef MBED_I2C_DEVICE_H
#define MBED_I2C_DEVICE_H
#include "cmsis.h"
#include "PeripheralNames.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Define I2C Device */
#if DEVICE_I2C
#define I2C_IP_VERSION_V2
#define TIMING_VAL_64M_CLK_100KHZ 0x10B17DB4 // Standard mode with Rise time = 120ns, Fall time = 120ns
#define TIMING_VAL_64M_CLK_400KHZ 0x00E22163 // Fast Mode with Rise time = 120ns, Fall time = 120ns
#define TIMING_VAL_64M_CLK_1MHZ 0x00A00D1E // Fast Mode Plus with Rise time = 120ns, Fall time = 10ns
#define I2C_PCLK_HSI 64000000 // 64 MHz
#define TIMING_VAL_72M_CLK_100KHZ 0x10D28DCB // Standard mode with Rise time = 120ns, Fall time = 120ns
#define TIMING_VAL_72M_CLK_400KHZ 0x00F32571 // Fast Mode with Rise time = 120ns, Fall time = 120ns
#define TIMING_VAL_72M_CLK_1MHZ 0x00C00D24 // Fast Mode Plus with Rise time = 120ns, Fall time = 10ns
#define I2C_PCLK_HSE 72000000 // 72 MHz
#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)
/* Define IP version */
#define I2C_IP_VERSION_V2
/* Family specifc settings for clock source */
#define I2CAPI_I2C1_CLKSRC RCC_I2C1CLKSOURCE_SYSCLK
#define I2CAPI_I2C2_CLKSRC RCC_I2C2CLKSOURCE_SYSCLK
#define I2CAPI_I2C3_CLKSRC RCC_I2C3CLKSOURCE_SYSCLK
/* Provide the suitable timing depending on requested frequencie */
static inline uint32_t get_i2c_timing(int hz)
{
uint32_t tim = 0;
/*
Values calculated with I2C_Timing_Configuration_V1.0.1.xls file (see AN4235)
* Standard mode (up to 100 kHz)
* Fast Mode (up to 400 kHz)
* Fast Mode Plus (up to 1 MHz)
Below values obtained with:
- I2C clock source = 64 MHz (System Clock w/ HSI) or 72 (System Clock w/ HSE)
- Analog filter delay = ON
- Digital filter coefficient = 0
*/
if (SystemCoreClock == 64000000) {
switch (hz) {
case 100000:
tim = 0x10B17DB4; // Standard mode with Rise time = 120ns, Fall time = 120ns
break;
case 400000:
tim = 0x00E22163; // Fast Mode with Rise time = 120ns, Fall time = 120ns
break;
case 1000000:
tim = 0x00A00D1E; // Fast Mode Plus with Rise time = 120ns, Fall time = 10ns
break;
default:
break;
}
} else if (SystemCoreClock == 72000000) {
switch (hz) {
case 100000:
tim = 0x10D28DCB; // Standard mode with Rise time = 120ns, Fall time = 120ns
break;
case 400000:
tim = 0x00F32571; // Fast Mode with Rise time = 120ns, Fall time = 120ns
break;
case 1000000:
tim = 0x00C00D24; // Fast Mode Plus with Rise time = 120ns, Fall time = 10ns
break;
default:
break;
}
}
return tim;
}
uint32_t i2c_get_pclk(I2CName i2c);
uint32_t i2c_compute_timing(uint32_t clock_src_freq, uint32_t i2c_freq);
uint32_t i2c_get_timing(I2CName i2c, int hz);
void i2c_compute_presc_scldel_sdadel(uint32_t clock_src_freq, uint32_t I2C_speed);
uint32_t i2c_compute_scll_sclh(uint32_t clock_src_freq, uint32_t I2C_speed);
#ifdef __cplusplus
}
#endif
#endif // DEVICE_I2C
#endif

View File

@ -15,6 +15,7 @@ target_sources(mbed-stm32f7
analogout_device.c
flash_api.c
gpio_irq_device.c
i2c_device.c
pwmout_device.c
serial_device.c
spi_api.c

View File

@ -0,0 +1,144 @@
/* mbed Microcontroller Library
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#include "i2c_device.h"
#include "mbed_assert.h"
#include "mbed_error.h"
#include "stm32f7xx_ll_rcc.h"
/* Define I2C Device */
#if DEVICE_I2C
/**
* @brief Get I2C clock source frequency according I2C instance used.
* @param i2c I2C instance name.
* @retval I2C clock source frequency in Hz.
*/
uint32_t i2c_get_pclk(I2CName i2c)
{
uint32_t clocksource;
uint32_t pclk = 0;
if (i2c == I2C_1) {
clocksource = __HAL_RCC_GET_I2C1_SOURCE();
switch (clocksource) {
case RCC_I2C1CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C1CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C1CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#if defined I2C2_BASE
else if (i2c == I2C_2) {
clocksource = __HAL_RCC_GET_I2C2_SOURCE();
switch (clocksource) {
case RCC_I2C2CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C2CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C2CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
#if defined I2C3_BASE
else if (i2c == I2C_3) {
clocksource = __HAL_RCC_GET_I2C3_SOURCE();
switch (clocksource) {
case RCC_I2C3CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C3CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C3CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
#if defined I2C4_BASE
else if (i2c == I2C_4) {
clocksource = __HAL_RCC_GET_I2C4_SOURCE();
switch (clocksource) {
case RCC_I2C4CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C4CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C4CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
else {
// should not happend
error("I2C: unknown instance");
}
return pclk;
}
/**
* @brief Provide the suitable timing depending on requested frequency
* @param hz Required I2C clock in Hz.
* @retval I2C timing or 0 in case of error.
*/
uint32_t i2c_get_timing(I2CName i2c, int hz)
{
uint32_t tim;
uint32_t pclk;
pclk = i2c_get_pclk(i2c);
if (pclk == I2C_PCLK_DEF) {
switch (hz) {
case 100000:
tim = TIMING_VAL_DEFAULT_CLK_100KHZ;
break;
case 400000:
tim = TIMING_VAL_DEFAULT_CLK_400KHZ;
break;
case 1000000:
tim = TIMING_VAL_DEFAULT_CLK_1MHZ;
break;
default:
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
break;
}
} else {
tim = i2c_compute_timing(pclk, hz);
}
return tim;
}
/**
* @}
*/
#endif // DEVICE_I2C

View File

@ -1,6 +1,6 @@
/* mbed Microcontroller Library
*******************************************************************************
* Copyright (c) 2015, STMicroelectronics
* Copyright (c) 2015-2021, STMicroelectronics
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -27,17 +27,25 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************
*/
#ifndef MBED_I2C_DEVICE_H
#define MBED_I2C_DEVICE_H
#include "cmsis.h"
#include "PeripheralNames.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Define I2C Device */
#if DEVICE_I2C
#define TIMING_VAL_DEFAULT_CLK_100KHZ 0x10916998 // Standard mode with Rise time = 120ns, Fall time = 120ns
#define TIMING_VAL_DEFAULT_CLK_400KHZ 0x00B11B54 // Fast Mode with Rise time = 120ns, Fall time = 120ns
#define TIMING_VAL_DEFAULT_CLK_1MHZ 0x0090091B // Fast Mode Plus with Rise time = 120ns, Fall time = 10ns
#define I2C_PCLK_DEF 54000000 // 54 MHz
/* Define IP version */
#define I2C_IP_VERSION_V2
#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)
@ -48,40 +56,14 @@ extern "C" {
#define I2CAPI_I2C3_CLKSRC RCC_I2C3CLKSOURCE_PCLK1
#define I2CAPI_I2C4_CLKSRC RCC_I2C4CLKSOURCE_PCLK1
/* Provide the suitable timing depending on requested frequencie */
static inline uint32_t get_i2c_timing(int hz)
{
uint32_t tim = 0;
/*
Values calculated with I2C_Timing_Configuration tool (excel file)
* Standard mode (up to 100 kHz)
* Fast Mode (up to 400 kHz)
* Fast Mode Plus (up to 1 MHz)
Below values obtained with:
- I2Cx clock source = APB1CLK = 54 MHz
- Analog filter delay = ON
- Digital filter coefficient = 0
*/
switch (hz) {
case 100000:
tim = 0x10916998; // Standard mode with Rise time = 120ns, Fall time = 120ns
break;
case 400000:
tim = 0x00B11B54; // Fast Mode with Rise time = 120ns, Fall time = 120ns
break;
case 1000000:
tim = 0x0090091B; // Fast Mode Plus with Rise time = 120ns, Fall time = 10ns
break;
default:
break;
}
return tim;
}
uint32_t i2c_get_pclk(I2CName i2c);
uint32_t i2c_compute_timing(uint32_t clock_src_freq, uint32_t i2c_freq);
uint32_t i2c_get_timing(I2CName i2c, int hz);
void i2c_compute_presc_scldel_sdadel(uint32_t clock_src_freq, uint32_t I2C_speed);
uint32_t i2c_compute_scll_sclh(uint32_t clock_src_freq, uint32_t I2C_speed);
#ifdef __cplusplus
}
#endif
#endif // DEVICE_I2C
#endif

View File

@ -17,6 +17,7 @@ target_sources(mbed-stm32g0
analogout_device.c
flash_api.c
gpio_irq_device.c
i2c_device.c
pwmout_device.c
serial_device.c
spi_api.c

View File

@ -0,0 +1,90 @@
/* mbed Microcontroller Library
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#include "i2c_device.h"
#include "mbed_assert.h"
#include "mbed_error.h"
#include "stm32g0xx_ll_rcc.h"
/* Define I2C Device */
#if DEVICE_I2C
/**
* @brief Get I2C clock source frequency according I2C instance used.
* @param i2c I2C instance name.
* @retval I2C clock source frequency in Hz.
*/
uint32_t i2c_get_pclk(I2CName i2c)
{
uint32_t clocksource;
uint32_t pclk = 0;
if (i2c == I2C_1) {
clocksource = __HAL_RCC_GET_I2C1_SOURCE();
switch (clocksource) {
case RCC_I2C1CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C1CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C1CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
} else {
// should not happend
error("I2C: unknown instance");
}
return pclk;
}
/**
* @brief Provide the suitable timing depending on requested frequency
* @param hz Required I2C clock in Hz.
* @retval I2C timing or 0 in case of error.
*/
uint32_t i2c_get_timing(I2CName i2c, int hz)
{
uint32_t tim;
uint32_t pclk;
pclk = i2c_get_pclk(i2c);
if (pclk == I2C_PCLK_DEF) {
switch (hz) {
case 100000:
tim = TIMING_VAL_DEFAULT_CLK_100KHZ;
break;
case 400000:
tim = TIMING_VAL_DEFAULT_CLK_400KHZ;
break;
case 1000000:
tim = TIMING_VAL_DEFAULT_CLK_1MHZ;
break;
default:
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
break;
}
} else {
tim = i2c_compute_timing(pclk, hz);
}
return tim;
}
/**
* @}
*/
#endif // DEVICE_I2C

View File

@ -2,7 +2,7 @@
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2015 STMicroelectronics.
* Copyright (c) 2015-2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
@ -12,19 +12,27 @@
*
******************************************************************************
*/
#ifndef MBED_I2C_DEVICE_H
#define MBED_I2C_DEVICE_H
#include "cmsis.h"
#include "PeripheralNames.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Define IP version */
#if DEVICE_I2C
#define I2C_IP_VERSION_V2
// Common settings: I2C clock = 64 MHz, Analog filter = ON, Digital filter coefficient = 0
#define TIMING_VAL_DEFAULT_CLK_100KHZ 0xC0311319 // Standard mode with Rise Time = 400ns and Fall Time = 100ns
#define TIMING_VAL_DEFAULT_CLK_400KHZ 0x10B1102E // Fast mode with Rise Time = 250ns and Fall Time = 100ns
#define TIMING_VAL_DEFAULT_CLK_1MHZ 0x00710B1E // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
#define I2C_PCLK_DEF 64000000 // 64 MHz
/* Define IP version */
#define I2C_IP_VERSION_V2
#define I2C1_EV_IRQn I2C1_IRQn
#define I2C1_ER_IRQn I2C1_IRQn
@ -32,39 +40,20 @@ extern "C" {
#define I2C2_EV_IRQn I2C2_IRQn
#define I2C2_ER_IRQn I2C2_IRQn
#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)
/* Family specifc settings for clock source */
#define I2CAPI_I2C1_CLKSRC RCC_I2C1CLKSOURCE_SYSCLK
#define I2CAPI_I2C2_CLKSRC RCC_I2C2CLKSOURCE_SYSCLK
/* Provide the suitable timing depending on requested frequencie */
static inline uint32_t get_i2c_timing(int hz)
{
uint32_t tim = 0;
// Common settings: I2C clock = 64 MHz, Analog filter = ON, Digital filter coefficient = 0
switch (hz) {
case 100000:
tim = 0xC0311319; // Standard mode with Rise Time = 400ns and Fall Time = 100ns
break;
case 400000:
tim = 0x10B1102E; // Fast mode with Rise Time = 250ns and Fall Time = 100ns
break;
case 1000000:
tim = 0x00710B1E; // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
break;
default:
break;
}
return tim;
}
uint32_t i2c_get_pclk(I2CName i2c);
uint32_t i2c_compute_timing(uint32_t clock_src_freq, uint32_t i2c_freq);
uint32_t i2c_get_timing(I2CName i2c, int hz);
void i2c_compute_presc_scldel_sdadel(uint32_t clock_src_freq, uint32_t I2C_speed);
uint32_t i2c_compute_scll_sclh(uint32_t clock_src_freq, uint32_t I2C_speed);
#ifdef __cplusplus
}
#endif
#endif // DEVICE_I2C
#endif

View File

@ -18,6 +18,7 @@ target_sources(mbed-stm32g4
analogout_device.c
flash_api.c
gpio_irq_device.c
i2c_device.c
pwmout_device.c
serial_device.c
spi_api.c

View File

@ -0,0 +1,143 @@
/* mbed Microcontroller Library
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#include "i2c_device.h"
#include "mbed_assert.h"
#include "mbed_error.h"
#include "stm32g4xx_ll_rcc.h"
/* Define I2C Device */
#if DEVICE_I2C
/**
* @brief Get I2C clock source frequency according I2C instance used.
* @param i2c I2C instance name.
* @retval I2C clock source frequency in Hz.
*/
uint32_t i2c_get_pclk(I2CName i2c)
{
uint32_t clocksource;
uint32_t pclk = 0;
if (i2c == I2C_1) {
clocksource = __HAL_RCC_GET_I2C1_SOURCE();
switch (clocksource) {
case RCC_I2C1CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C1CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C1CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#if defined I2C2_BASE
else if (i2c == I2C_2) {
clocksource = __HAL_RCC_GET_I2C2_SOURCE();
switch (clocksource) {
case RCC_I2C2CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C2CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C2CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
#if defined I2C3_BASE
else if (i2c == I2C_3) {
clocksource = __HAL_RCC_GET_I2C3_SOURCE();
switch (clocksource) {
case RCC_I2C3CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C3CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C3CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
#if defined I2C4_BASE
else if (i2c == I2C_4) {
clocksource = __HAL_RCC_GET_I2C4_SOURCE();
switch (clocksource) {
case RCC_I2C4CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C4CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C4CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
else {
// should not happend
error("I2C: unknown instance");
}
return pclk;
}
/**
* @brief Provide the suitable timing depending on requested frequency
* @param hz Required I2C clock in Hz.
* @retval I2C timing or 0 in case of error.
*/
uint32_t i2c_get_timing(I2CName i2c, int hz)
{
uint32_t tim;
uint32_t pclk;
pclk = i2c_get_pclk(i2c);
if (pclk == I2C_PCLK_DEF) {
switch (hz) {
case 100000:
tim = TIMING_VAL_DEFAULT_CLK_100KHZ;
break;
case 400000:
tim = TIMING_VAL_DEFAULT_CLK_400KHZ;
break;
case 1000000:
tim = TIMING_VAL_DEFAULT_CLK_1MHZ;
break;
default:
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
break;
}
} else {
tim = i2c_compute_timing(pclk, hz);
}
return tim;
}
/**
* @}
*/
#endif // DEVICE_I2C

View File

@ -2,7 +2,7 @@
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2015-2020 STMicroelectronics.
* Copyright (c) 2015-2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
@ -16,14 +16,22 @@
#ifndef MBED_I2C_DEVICE_H
#define MBED_I2C_DEVICE_H
#include "cmsis.h"
#include "PeripheralNames.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Define I2C Device */
#if DEVICE_I2C
// Common settings: I2C clock = 64 MHz, Analog filter = ON, Digital filter coefficient = 0
#define TIMING_VAL_DEFAULT_CLK_100KHZ 0xC0311319 // Standard mode with Rise Time = 400ns and Fall Time = 100ns
#define TIMING_VAL_DEFAULT_CLK_400KHZ 0x10B1102E // Fast mode with Rise Time = 250ns and Fall Time = 100ns
#define TIMING_VAL_DEFAULT_CLK_1MHZ 0x00710B1E // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
#define I2C_PCLK_DEF 170000000 // 170 MHz
/* Define IP version */
#define I2C_IP_VERSION_V2
#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)
@ -34,31 +42,14 @@ extern "C" {
#define I2CAPI_I2C3_CLKSRC RCC_I2C3CLKSOURCE_SYSCLK
#define I2CAPI_I2C4_CLKSRC RCC_I2C4CLKSOURCE_SYSCLK
/* Provide the suitable timing depending on requested frequencie */
static inline uint32_t get_i2c_timing(int hz)
{
uint32_t tim = 0;
// Common settings: I2C clock = 64 MHz, Analog filter = ON, Digital filter coefficient = 0
switch (hz) {
case 100000:
tim = 0xC0311319; // Standard mode with Rise Time = 400ns and Fall Time = 100ns
break;
case 400000:
tim = 0x10B1102E; // Fast mode with Rise Time = 250ns and Fall Time = 100ns
break;
case 1000000:
tim = 0x00710B1E; // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
break;
default:
break;
}
return tim;
}
uint32_t i2c_get_pclk(I2CName i2c);
uint32_t i2c_compute_timing(uint32_t clock_src_freq, uint32_t i2c_freq);
uint32_t i2c_get_timing(I2CName i2c, int hz);
void i2c_compute_presc_scldel_sdadel(uint32_t clock_src_freq, uint32_t I2C_speed);
uint32_t i2c_compute_scll_sclh(uint32_t clock_src_freq, uint32_t I2C_speed);
#ifdef __cplusplus
}
#endif
#endif // DEVICE_I2C
#endif

339
targets/TARGET_STM/TARGET_STM32H7/i2c_device.c Normal file → Executable file
View File

@ -2,8 +2,7 @@
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2015-2020 STMicroelectronics.
* Copyright (c) 2020, Arduino SA.
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
@ -19,313 +18,20 @@
#include "mbed_error.h"
#include "stm32h7xx_ll_rcc.h"
/* Define I2C Device */
#if DEVICE_I2C
/** @defgroup I2C_DEVICE_Private_Constants I2C_DEVICE Private Constants
* @{
*/
#ifndef I2C_VALID_TIMING_NBR
#define I2C_VALID_TIMING_NBR 128U
#endif
#define I2C_SPEED_FREQ_STANDARD 0U /* 100 kHz */
#define I2C_SPEED_FREQ_FAST 1U /* 400 kHz */
#define I2C_SPEED_FREQ_FAST_PLUS 2U /* 1 MHz */
#define I2C_ANALOG_FILTER_DELAY_MIN 50U /* ns */
#define I2C_ANALOG_FILTER_DELAY_MAX 260U /* ns */
#define I2C_USE_ANALOG_FILTER 1U
#define I2C_DIGITAL_FILTER_COEF 0U
#define I2C_PRESC_MAX 16U
#define I2C_SCLDEL_MAX 16U
#define I2C_SDADEL_MAX 16U
#define I2C_SCLH_MAX 256U
#define I2C_SCLL_MAX 256U
#define SEC2NSEC 1000000000UL
/**
* @}
*/
/** @defgroup I2C_DEVICE_Private_Types I2C_DEVICE Private Types
* @{
*/
typedef struct {
uint32_t freq; /* Frequency in Hz */
uint32_t freq_min; /* Minimum frequency in Hz */
uint32_t freq_max; /* Maximum frequency in Hz */
uint32_t hddat_min; /* Minimum data hold time in ns */
uint32_t vddat_max; /* Maximum data valid time in ns */
uint32_t sudat_min; /* Minimum data setup time in ns */
uint32_t lscl_min; /* Minimum low period of the SCL clock in ns */
uint32_t hscl_min; /* Minimum high period of SCL clock in ns */
uint32_t trise; /* Rise time in ns */
uint32_t tfall; /* Fall time in ns */
uint32_t dnf; /* Digital noise filter coefficient */
} I2C_Charac_t;
typedef struct {
uint32_t presc; /* Timing prescaler */
uint32_t tscldel; /* SCL delay */
uint32_t tsdadel; /* SDA delay */
uint32_t sclh; /* SCL high period */
uint32_t scll; /* SCL low period */
} I2C_Timings_t;
/**
* @}
*/
/** @defgroup I2C_DEVICE_Private_Constants I2C_DEVICE Private Constants
* @{
*/
static const I2C_Charac_t I2C_Charac[] = {
[I2C_SPEED_FREQ_STANDARD] =
{
.freq = 100000,
.freq_min = 80000,
.freq_max = 120000,
.hddat_min = 0,
.vddat_max = 3450,
.sudat_min = 250,
.lscl_min = 4700,
.hscl_min = 4000,
.trise = 640,
.tfall = 20,
.dnf = I2C_DIGITAL_FILTER_COEF,
},
[I2C_SPEED_FREQ_FAST] =
{
.freq = 400000,
.freq_min = 320000,
.freq_max = 480000,
.hddat_min = 0,
.vddat_max = 900,
.sudat_min = 100,
.lscl_min = 1300,
.hscl_min = 600,
.trise = 250,
.tfall = 100,
.dnf = I2C_DIGITAL_FILTER_COEF,
},
[I2C_SPEED_FREQ_FAST_PLUS] =
{
.freq = 1000000,
.freq_min = 800000,
.freq_max = 1200000,
.hddat_min = 0,
.vddat_max = 450,
.sudat_min = 50,
.lscl_min = 500,
.hscl_min = 260,
.trise = 60,
.tfall = 100,
.dnf = I2C_DIGITAL_FILTER_COEF,
},
};
/**
* @}
*/
/** @defgroup I2C_DEVICE_Private_Variables I2C_DEVICE Private Variables
* @{
*/
static I2C_Timings_t I2c_valid_timing[I2C_VALID_TIMING_NBR];
static uint32_t I2c_valid_timing_nbr = 0;
/**
* @}
*/
/** @defgroup I2C_DEVICE_Private_Functions I2C_DEVICE Private Functions
* @{
*/
/**
* @brief Compute PRESC, SCLDEL and SDADEL.
* @param clock_src_freq I2C source clock in HZ.
* @param I2C_speed I2C frequency (index).
* @retval None.
*/
static void I2C_Compute_PRESC_SCLDEL_SDADEL(uint32_t clock_src_freq, uint32_t I2C_speed)
{
uint32_t prev_presc = I2C_PRESC_MAX;
uint32_t ti2cclk;
int32_t tsdadel_min, tsdadel_max;
int32_t tscldel_min;
uint32_t presc, scldel, sdadel;
uint32_t tafdel_min, tafdel_max;
ti2cclk = (SEC2NSEC + (clock_src_freq / 2U)) / clock_src_freq;
tafdel_min = (I2C_USE_ANALOG_FILTER == 1U) ? I2C_ANALOG_FILTER_DELAY_MIN : 0U;
tafdel_max = (I2C_USE_ANALOG_FILTER == 1U) ? I2C_ANALOG_FILTER_DELAY_MAX : 0U;
/* tDNF = DNF x tI2CCLK
tPRESC = (PRESC+1) x tI2CCLK
SDADEL >= {tf +tHD;DAT(min) - tAF(min) - tDNF - [3 x tI2CCLK]} / {tPRESC}
SDADEL <= {tVD;DAT(max) - tr - tAF(max) - tDNF- [4 x tI2CCLK]} / {tPRESC} */
tsdadel_min = (int32_t)I2C_Charac[I2C_speed].tfall + (int32_t)I2C_Charac[I2C_speed].hddat_min -
(int32_t)tafdel_min - (int32_t)(((int32_t)I2C_Charac[I2C_speed].dnf + 3) * (int32_t)ti2cclk);
tsdadel_max = (int32_t)I2C_Charac[I2C_speed].vddat_max - (int32_t)I2C_Charac[I2C_speed].trise -
(int32_t)tafdel_max - (int32_t)(((int32_t)I2C_Charac[I2C_speed].dnf + 4) * (int32_t)ti2cclk);
/* {[tr+ tSU;DAT(min)] / [tPRESC]} - 1 <= SCLDEL */
tscldel_min = (int32_t)I2C_Charac[I2C_speed].trise + (int32_t)I2C_Charac[I2C_speed].sudat_min;
if (tsdadel_min <= 0) {
tsdadel_min = 0;
}
if (tsdadel_max <= 0) {
tsdadel_max = 0;
}
for (presc = 0; presc < I2C_PRESC_MAX; presc++) {
for (scldel = 0; scldel < I2C_SCLDEL_MAX; scldel++) {
/* TSCLDEL = (SCLDEL+1) * (PRESC+1) * TI2CCLK */
uint32_t tscldel = (scldel + 1U) * (presc + 1U) * ti2cclk;
if (tscldel >= (uint32_t)tscldel_min) {
for (sdadel = 0; sdadel < I2C_SDADEL_MAX; sdadel++) {
/* TSDADEL = SDADEL * (PRESC+1) * TI2CCLK */
uint32_t tsdadel = (sdadel * (presc + 1U)) * ti2cclk;
if ((tsdadel >= (uint32_t)tsdadel_min) && (tsdadel <= (uint32_t)tsdadel_max)) {
if (presc != prev_presc) {
I2c_valid_timing[I2c_valid_timing_nbr].presc = presc;
I2c_valid_timing[I2c_valid_timing_nbr].tscldel = scldel;
I2c_valid_timing[I2c_valid_timing_nbr].tsdadel = sdadel;
prev_presc = presc;
I2c_valid_timing_nbr ++;
if (I2c_valid_timing_nbr >= I2C_VALID_TIMING_NBR) {
return;
}
}
}
}
}
}
}
}
/**
* @brief Calculate SCLL and SCLH and find best configuration.
* @param clock_src_freq I2C source clock in HZ.
* @param I2C_speed I2C frequency (index).
* @retval config index (0 to I2C_VALID_TIMING_NBR], 0xFFFFFFFF for no valid config.
*/
static uint32_t I2C_Compute_SCLL_SCLH(uint32_t clock_src_freq, uint32_t I2C_speed)
{
uint32_t ret = 0xFFFFFFFFU;
uint32_t ti2cclk;
uint32_t ti2cspeed;
uint32_t prev_error;
uint32_t dnf_delay;
uint32_t clk_min, clk_max;
uint32_t scll, sclh;
uint32_t tafdel_min;
ti2cclk = (SEC2NSEC + (clock_src_freq / 2U)) / clock_src_freq;
ti2cspeed = (SEC2NSEC + (I2C_Charac[I2C_speed].freq / 2U)) / I2C_Charac[I2C_speed].freq;
tafdel_min = (I2C_USE_ANALOG_FILTER == 1U) ? I2C_ANALOG_FILTER_DELAY_MIN : 0U;
/* tDNF = DNF x tI2CCLK */
dnf_delay = I2C_Charac[I2C_speed].dnf * ti2cclk;
clk_max = SEC2NSEC / I2C_Charac[I2C_speed].freq_min;
clk_min = SEC2NSEC / I2C_Charac[I2C_speed].freq_max;
prev_error = ti2cspeed;
for (uint32_t count = 0; count < I2c_valid_timing_nbr; count++) {
/* tPRESC = (PRESC+1) x tI2CCLK*/
uint32_t tpresc = (I2c_valid_timing[count].presc + 1U) * ti2cclk;
for (scll = 0; scll < I2C_SCLL_MAX; scll++) {
/* tLOW(min) <= tAF(min) + tDNF + 2 x tI2CCLK + [(SCLL+1) x tPRESC ] */
uint32_t tscl_l = tafdel_min + dnf_delay + (2U * ti2cclk) + ((scll + 1U) * tpresc);
/* The I2CCLK period tI2CCLK must respect the following conditions:
tI2CCLK < (tLOW - tfilters) / 4 and tI2CCLK < tHIGH */
if ((tscl_l > I2C_Charac[I2C_speed].lscl_min) && (ti2cclk < ((tscl_l - tafdel_min - dnf_delay) / 4U))) {
for (sclh = 0; sclh < I2C_SCLH_MAX; sclh++) {
/* tHIGH(min) <= tAF(min) + tDNF + 2 x tI2CCLK + [(SCLH+1) x tPRESC] */
uint32_t tscl_h = tafdel_min + dnf_delay + (2U * ti2cclk) + ((sclh + 1U) * tpresc);
/* tSCL = tf + tLOW + tr + tHIGH */
uint32_t tscl = tscl_l + tscl_h + I2C_Charac[I2C_speed].trise + I2C_Charac[I2C_speed].tfall;
if ((tscl >= clk_min) && (tscl <= clk_max) && (tscl_h >= I2C_Charac[I2C_speed].hscl_min) && (ti2cclk < tscl_h)) {
int32_t error = (int32_t)tscl - (int32_t)ti2cspeed;
if (error < 0) {
error = -error;
}
/* look for the timings with the lowest clock error */
if ((uint32_t)error < prev_error) {
prev_error = (uint32_t)error;
I2c_valid_timing[count].scll = scll;
I2c_valid_timing[count].sclh = sclh;
ret = count;
}
}
}
}
}
}
return ret;
}
/**
* @brief Compute I2C timing according current I2C clock source and required I2C clock.
* @param clock_src_freq I2C clock source in Hz.
* @param i2c_freq Required I2C clock in Hz.
* @retval I2C timing or 0 in case of error.
*/
static uint32_t I2C_ComputeTiming(uint32_t clock_src_freq, uint32_t i2c_freq)
{
uint32_t ret = 0;
uint32_t speed;
uint32_t idx;
if ((clock_src_freq != 0U) && (i2c_freq != 0U)) {
for (speed = 0 ; speed <= (uint32_t)I2C_SPEED_FREQ_FAST_PLUS ; speed++) {
if ((i2c_freq >= I2C_Charac[speed].freq_min) &&
(i2c_freq <= I2C_Charac[speed].freq_max)) {
I2C_Compute_PRESC_SCLDEL_SDADEL(clock_src_freq, speed);
idx = I2C_Compute_SCLL_SCLH(clock_src_freq, speed);
if (idx < I2C_VALID_TIMING_NBR) {
ret = ((I2c_valid_timing[idx].presc & 0x0FU) << 28) | \
((I2c_valid_timing[idx].tscldel & 0x0FU) << 20) | \
((I2c_valid_timing[idx].tsdadel & 0x0FU) << 16) | \
((I2c_valid_timing[idx].sclh & 0xFFU) << 8) | \
((I2c_valid_timing[idx].scll & 0xFFU) << 0);
}
break;
}
}
}
return ret;
}
/**
* @brief Get I2C clock source frequency according I2C instance used.
* @param i2c I2C instance name.
* @retval I2C clock source frequency in Hz.
*/
static uint32_t I2C_GetPclk(I2CName i2c)
uint32_t i2c_get_pclk(I2CName i2c)
{
uint32_t clocksource;
uint32_t pclk = 0;
PLL3_ClocksTypeDef pll3_clocks;
if (i2c == I2C_1 || i2c == I2C_2 || i2c == I2C_3) {
if ((i2c == I2C_1) || (i2c == I2C_2) || (i2c == I2C_3)) {
clocksource = __HAL_RCC_GET_I2C123_SOURCE();
switch (clocksource) {
case RCC_I2C123CLKSOURCE_D2PCLK1:
@ -346,7 +52,9 @@ static uint32_t I2C_GetPclk(I2CName i2c)
error("I2C123: Invalid clock source");
break;
}
} else if (i2c == I2C_4) {
}
#if defined I2C4_BASE
else if (i2c == I2C_4) {
clocksource = __HAL_RCC_GET_I2C4_SOURCE();
switch (clocksource) {
case RCC_I2C4CLKSOURCE_D3PCLK1:
@ -367,11 +75,12 @@ static uint32_t I2C_GetPclk(I2CName i2c)
error("I2C4: Invalid clock source");
break;
}
} else {
}
#endif
else {
// should not happend
error("I2C: unknown instance");
}
return pclk;
}
/**
@ -386,17 +95,29 @@ static uint32_t I2C_GetPclk(I2CName i2c)
* @param hz Required I2C clock in Hz.
* @retval I2C timing or 0 in case of error.
*/
uint32_t get_i2c_timing(I2CName i2c, int hz)
uint32_t i2c_get_timing(I2CName i2c, int hz)
{
uint32_t tim;
uint32_t pclk;
I2c_valid_timing_nbr = 0;
pclk = I2C_GetPclk(i2c);
tim = I2C_ComputeTiming(pclk, hz);
pclk = i2c_get_pclk(i2c);
if (pclk == I2C_PCLK_DEF) {
switch (hz) {
case 100000:
tim = TIMING_VAL_DEFAULT_CLK_100KHZ;
break;
case 400000:
tim = TIMING_VAL_DEFAULT_CLK_400KHZ;
break;
case 1000000:
tim = TIMING_VAL_DEFAULT_CLK_1MHZ;
break;
default:
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
break;
}
} else {
tim = i2c_compute_timing(pclk, hz);
}
return tim;
}
/**

View File

@ -2,7 +2,7 @@
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2015-2020 STMicroelectronics.
* Copyright (c) 2015-2021 STMicroelectronics.
* Copyright (c) 2020, Arduino SA.
* All rights reserved.
*
@ -23,10 +23,17 @@
extern "C" {
#endif
/* Define I2C Device */
#if DEVICE_I2C
/* Define IP version */
#define I2C_IP_VERSION_V2
#define TIMING_VAL_DEFAULT_CLK_100KHZ 0x40E15676 // Standard mode with Rise Time = 400ns and Fall Time = 100ns
#define TIMING_VAL_DEFAULT_CLK_400KHZ 0x20C11434 // Fast mode with Rise Time = 250ns and Fall Time = 100ns
#define TIMING_VAL_DEFAULT_CLK_1MHZ 0x00C31536 // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
#define I2C_PCLK_DEF 120000000 // 120 MHz
#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)
/* Family specifc settings for clock source */
@ -35,14 +42,14 @@ extern "C" {
#define I2CAPI_I2C3_CLKSRC RCC_I2C3CLKSOURCE_D2PCLK1
#define I2CAPI_I2C4_CLKSRC RCC_I2C4CLKSOURCE_D3PCLK1
/* Provide the suitable timing depending on requested frequency */
extern uint32_t get_i2c_timing(I2CName i2c, int hz);
uint32_t i2c_get_pclk(I2CName i2c);
uint32_t i2c_compute_timing(uint32_t clock_src_freq, uint32_t i2c_freq);
uint32_t i2c_get_timing(I2CName i2c, int hz);
void i2c_compute_presc_scldel_sdadel(uint32_t clock_src_freq, uint32_t I2C_speed);
uint32_t i2c_compute_scll_sclh(uint32_t clock_src_freq, uint32_t I2C_speed);
#ifdef __cplusplus
}
#endif
#endif // DEVICE_I2C
#endif

View File

@ -17,6 +17,7 @@ target_sources(mbed-stm32l0
analogout_device.c
flash_api.c
gpio_irq_device.c
i2c_device.c
pwmout_device.c
serial_device.c
spi_api.c

View File

@ -0,0 +1,114 @@
/* mbed Microcontroller Library
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#include "i2c_device.h"
#include "mbed_assert.h"
#include "mbed_error.h"
#include "stm32l0xx_ll_rcc.h"
/* Define I2C Device */
#if DEVICE_I2C
/**
* @brief Get I2C clock source frequency according I2C instance used.
* @param i2c I2C instance name.
* @retval I2C clock source frequency in Hz.
*/
uint32_t i2c_get_pclk(I2CName i2c)
{
uint32_t clocksource;
uint32_t pclk = 0;
if (i2c == I2C_1) {
clocksource = __HAL_RCC_GET_I2C1_SOURCE();
switch (clocksource) {
case RCC_I2C1CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C1CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C1CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#if defined I2C3_BASE
else if (i2c == I2C_3) {
clocksource = __HAL_RCC_GET_I2C3_SOURCE();
switch (clocksource) {
case RCC_I2C3CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C3CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C3CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
else {
// should not happend
error("I2C: unknown instance");
}
return pclk;
}
/**
* @}
*/
/** @defgroup I2C_DEVICE_Exported_Functions I2C_DEVICE Exported Functions
* @{
*/
/**
* @brief Provide the suitable timing depending on requested frequency
* @param hz Required I2C clock in Hz.
* @retval I2C timing or 0 in case of error.
*/
uint32_t i2c_get_timing(I2CName i2c, int hz)
{
uint32_t tim;
uint32_t pclk;
pclk = i2c_get_pclk(i2c);
if (pclk == I2C_PCLK_DEF) {
switch (hz) {
case 100000:
tim = TIMING_VAL_DEFAULT_CLK_100KHZ;
break;
case 400000:
tim = TIMING_VAL_DEFAULT_CLK_400KHZ;
break;
case 1000000:
tim = TIMING_VAL_DEFAULT_CLK_1MHZ;
break;
default:
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
break;
}
} else {
tim = i2c_compute_timing(pclk, hz);
}
return tim;
}
/**
* @}
*/
#endif // DEVICE_I2C

View File

@ -2,7 +2,7 @@
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2016-2020 STMicroelectronics.
* Copyright (c) 2016-2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
@ -12,17 +12,20 @@
*
******************************************************************************
*/
#ifndef MBED_I2C_DEVICE_H
#define MBED_I2C_DEVICE_H
#include "cmsis.h"
#include "PeripheralNames.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Define I2C Device */
#if DEVICE_I2C
/* Define IP version */
#define I2C_IP_VERSION_V2
#if defined I2C1_BASE
@ -38,6 +41,11 @@ extern "C" {
#define I2C3_ER_IRQn I2C3_IRQn
#endif
#define TIMING_VAL_DEFAULT_CLK_100KHZ 0x20602938 // Standard mode with Rise Time = 400ns and Fall Time = 100ns
#define TIMING_VAL_DEFAULT_CLK_400KHZ 0x00B0122A // Fast mode with Rise Time = 250ns and Fall Time = 100ns
#define TIMING_VAL_DEFAULT_CLK_1MHZ 0x0030040E // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
#define I2C_PCLK_DEF 32000000 // 32 MHz
#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)
/* Family specifc settings for clock source */
@ -45,31 +53,14 @@ extern "C" {
#define I2CAPI_I2C3_CLKSRC RCC_I2C3CLKSOURCE_SYSCLK
#define I2CAPI_I2C4_CLKSRC RCC_I2C4CLKSOURCE_SYSCLK
/* Provide the suitable timing depending on requested frequencie */
static inline uint32_t get_i2c_timing(int hz)
{
uint32_t tim = 0;
switch (hz) {
case 100000:
tim = 0x20602938; // Standard mode with Rise Time = 400ns and Fall Time = 100ns
break;
case 400000:
tim = 0x00B0122A; // Fast mode with Rise Time = 250ns and Fall Time = 100ns
break;
case 1000000:
tim = 0x0030040E; // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
break;
default:
break;
}
return tim;
}
uint32_t i2c_get_pclk(I2CName i2c);
uint32_t i2c_compute_timing(uint32_t clock_src_freq, uint32_t i2c_freq);
uint32_t i2c_get_timing(I2CName i2c, int hz);
void i2c_compute_presc_scldel_sdadel(uint32_t clock_src_freq, uint32_t I2C_speed);
uint32_t i2c_compute_scll_sclh(uint32_t clock_src_freq, uint32_t I2C_speed);
#ifdef __cplusplus
}
#endif
#endif // DEVICE_I2C
#endif

View File

@ -23,6 +23,7 @@ target_sources(mbed-stm32l4
analogout_device.c
flash_api.c
gpio_irq_device.c
i2c_device.c
pwmout_device.c
serial_device.c
spi_api.c

View File

@ -0,0 +1,179 @@
/* mbed Microcontroller Library
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#include "i2c_device.h"
#include "mbed_assert.h"
#include "mbed_error.h"
#include "stm32l4xx_ll_rcc.h"
/* Define I2C Device */
#if DEVICE_I2C
/**
* @brief Get I2C clock source frequency according I2C instance used.
* @param i2c I2C instance name.
* @retval I2C clock source frequency in Hz.
*/
uint32_t i2c_get_pclk(I2CName i2c)
{
uint32_t clocksource;
uint32_t pclk = 0;
if (i2c == I2C_1) {
clocksource = __HAL_RCC_GET_I2C1_SOURCE();
switch (clocksource) {
case RCC_I2C1CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C1CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C1CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#if defined I2C2_BASE
else if (i2c == I2C_2) {
clocksource = __HAL_RCC_GET_I2C2_SOURCE();
switch (clocksource) {
case RCC_I2C2CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C2CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C2CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
#if defined I2C3_BASE
else if (i2c == I2C_3) {
clocksource = __HAL_RCC_GET_I2C3_SOURCE();
switch (clocksource) {
case RCC_I2C3CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C3CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C3CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
#if defined I2C4_BASE
else if (i2c == I2C_4) {
clocksource = __HAL_RCC_GET_I2C4_SOURCE();
switch (clocksource) {
case RCC_I2C4CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C4CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C4CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
else {
// should not happend
error("I2C: unknown instance");
}
return pclk;
}
/**
* @}
*/
/** @defgroup I2C_DEVICE_Exported_Functions I2C_DEVICE Exported Functions
* @{
*/
/**
* @brief Provide the suitable timing depending on requested frequency
* @param hz Required I2C clock in Hz.
* @retval I2C timing or 0 in case of error.
*/
uint32_t i2c_get_timing(I2CName i2c, int hz)
{
uint32_t tim;
uint32_t pclk;
pclk = i2c_get_pclk(i2c);
if (pclk == I2C_PCLK_80M) {
switch (hz) {
case 100000:
tim = TIMING_VAL_80M_CLK_100KHZ;
break;
case 400000:
tim = TIMING_VAL_80M_CLK_400KHZ;
break;
case 1000000:
tim = TIMING_VAL_80M_CLK_1MHZ;
break;
default:
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
break;
}
} else if (pclk == I2C_PCLK_48M) {
switch (hz) {
case 100000:
tim = TIMING_VAL_48M_CLK_100KHZ;
break;
case 400000:
tim = TIMING_VAL_48M_CLK_400KHZ;
break;
case 1000000:
tim = TIMING_VAL_48M_CLK_1MHZ;
break;
default:
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
break;
}
} else if (pclk == I2C_PCLK_120M) {
switch (hz) {
case 100000:
tim = TIMING_VAL_120M_CLK_100KHZ;
break;
case 400000:
tim = TIMING_VAL_120M_CLK_400KHZ;
break;
case 1000000:
tim = TIMING_VAL_120M_CLK_1MHZ;
break;
default:
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
break;
}
} else {
tim = i2c_compute_timing(pclk, hz);
}
return tim;
}
/**
* @}
*/
#endif // DEVICE_I2C

View File

@ -1,5 +1,5 @@
/* mbed Microcontroller Library
* Copyright (c) 2016-2020 STMicroelectronics
* Copyright (c) 2016-2021 STMicroelectronics
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,17 +18,36 @@
#ifndef MBED_I2C_DEVICE_H
#define MBED_I2C_DEVICE_H
#include "cmsis.h"
#include "mbed_error.h"
#include "PeripheralNames.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Define I2C Device */
#if DEVICE_I2C
/* Define IP version */
#define I2C_IP_VERSION_V2
// Common settings: I2C clock = 80 MHz, Analog filter = ON, Digital filter coefficient = 0
#define TIMING_VAL_80M_CLK_100KHZ 0x30C14E6B // Standard mode with Rise Time = 400ns and Fall Time = 100ns
#define TIMING_VAL_80M_CLK_400KHZ 0x10D1143A // Fast mode with Rise Time = 250ns and Fall Time = 100ns
#define TIMING_VAL_80M_CLK_1MHZ 0x00810E27 // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
#define I2C_PCLK_80M 80000000 // 80 MHz
// Common settings: I2C clock = 48 MHz, Analog filter = ON, Digital filter coefficient = 0
#define TIMING_VAL_48M_CLK_100KHZ 0x20A03E55 // Standard mode with Rise Time = 400ns and Fall Time = 100ns
#define TIMING_VAL_48M_CLK_400KHZ 0x10800C21 // Fast mode with Rise Time = 250ns and Fall Time = 100ns
#define TIMING_VAL_48M_CLK_1MHZ 0x00500816 // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
#define I2C_PCLK_48M 48000000 // 48 MHz
// Common settings: I2C clock = 120 MHz, Analog filter = ON, Digital filter coefficient = 0
#define TIMING_VAL_120M_CLK_100KHZ 0x107075B0 // Standard mode with Rise Time = 400ns and Fall Time = 100ns
#define TIMING_VAL_120M_CLK_400KHZ 0x00501E6C // Fast mode with Rise Time = 250ns and Fall Time = 100ns
#define TIMING_VAL_120M_CLK_1MHZ 0x00200A26 // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
#define I2C_PCLK_120M 120000000 // 120 MHz
#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)
/* Family specifc settings for clock source */
@ -37,65 +56,14 @@ extern "C" {
#define I2CAPI_I2C3_CLKSRC RCC_I2C3CLKSOURCE_SYSCLK
#define I2CAPI_I2C4_CLKSRC RCC_I2C4CLKSOURCE_SYSCLK
/* Provide the suitable timing depending on requested frequencie */
static inline uint32_t get_i2c_timing(int hz)
{
uint32_t tim = 0;
if (SystemCoreClock == 80000000) {
// Common settings: I2C clock = 80 MHz, Analog filter = ON, Digital filter coefficient = 0
switch (hz) {
case 100000:
tim = 0x30C14E6B; // Standard mode with Rise Time = 400ns and Fall Time = 100ns
break;
case 400000:
tim = 0x10D1143A; // Fast mode with Rise Time = 250ns and Fall Time = 100ns
break;
case 1000000:
tim = 0x00810E27; // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
break;
default:
break;
}
} else if (SystemCoreClock == 48000000) {
// Common settings: I2C clock = 48 MHz, Analog filter = ON, Digital filter coefficient = 0
switch (hz) {
case 100000:
tim = 0x20A03E55; // Standard mode with Rise Time = 400ns and Fall Time = 100ns
break;
case 400000:
tim = 0x10800C21; // Fast mode with Rise Time = 250ns and Fall Time = 100ns
break;
case 1000000:
tim = 0x00500816; // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
break;
default:
break;
}
} else if (SystemCoreClock == 120000000) {
// Common settings: I2C clock = 120 MHz, Analog filter = ON, Digital filter coefficient = 0
switch (hz) {
case 100000:
tim = 0x107075B0; // Standard mode with Rise Time = 400ns and Fall Time = 100ns
break;
case 400000:
tim = 0x00501E6C; // Fast mode with Rise Time = 250ns and Fall Time = 100ns
break;
case 1000000:
tim = 0x00200A26; // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
break;
default:
break;
}
} else {
error("get_i2c_timing error\n");
}
return tim;
}
uint32_t i2c_get_pclk(I2CName i2c);
uint32_t i2c_compute_timing(uint32_t clock_src_freq, uint32_t i2c_freq);
uint32_t i2c_get_timing(I2CName i2c, int hz);
void i2c_compute_presc_scldel_sdadel(uint32_t clock_src_freq, uint32_t I2C_speed);
uint32_t i2c_compute_scll_sclh(uint32_t clock_src_freq, uint32_t I2C_speed);
#ifdef __cplusplus
}
#endif
#endif // DEVICE_I2C
#endif

View File

@ -14,6 +14,7 @@ target_sources(mbed-stm32l5
analogout_device.c
flash_api.c
gpio_irq_device.c
i2c_device.c
pwmout_device.c
serial_device.c
system_clock.c

View File

@ -0,0 +1,153 @@
/* mbed Microcontroller Library
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#include "i2c_device.h"
#include "mbed_assert.h"
#include "mbed_error.h"
#include "stm32l5xx_ll_rcc.h"
/* Define I2C Device */
#if DEVICE_I2C
/**
* @brief Get I2C clock source frequency according I2C instance used.
* @param i2c I2C instance name.
* @retval I2C clock source frequency in Hz.
*/
uint32_t i2c_get_pclk(I2CName i2c)
{
uint32_t clocksource;
uint32_t pclk = 0;
if (i2c == I2C_1) {
clocksource = __HAL_RCC_GET_I2C1_SOURCE();
switch (clocksource) {
case RCC_I2C1CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C1CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C1CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#if defined I2C2_BASE
else if (i2c == I2C_2) {
clocksource = __HAL_RCC_GET_I2C2_SOURCE();
switch (clocksource) {
case RCC_I2C2CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C2CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C2CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
#if defined I2C3_BASE
else if (i2c == I2C_3) {
clocksource = __HAL_RCC_GET_I2C3_SOURCE();
switch (clocksource) {
case RCC_I2C3CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C3CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C3CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
#if defined I2C4_BASE
else if (i2c == I2C_4) {
clocksource = __HAL_RCC_GET_I2C4_SOURCE();
switch (clocksource) {
case RCC_I2C4CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C4CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C4CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
else {
// should not happend
error("I2C: unknown instance");
}
return pclk;
}
/**
* @}
*/
/** @defgroup I2C_DEVICE_Exported_Functions I2C_DEVICE Exported Functions
* @{
*/
/**
* @brief Provide the suitable timing depending on requested frequency
* @param hz Required I2C clock in Hz.
* @retval I2C timing or 0 in case of error.
*/
uint32_t i2c_get_timing(I2CName i2c, int hz)
{
uint32_t tim;
uint32_t pclk;
pclk = i2c_get_pclk(i2c);
if (pclk == I2C_PCLK_DEF) {
switch (hz) {
case 100000:
tim = TIMING_VAL_DEFAULT_CLK_100KHZ;
break;
case 400000:
tim = TIMING_VAL_DEFAULT_CLK_400KHZ;
break;
case 1000000:
tim = TIMING_VAL_DEFAULT_CLK_1MHZ;
break;
default:
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
break;
}
}
else {
tim = i2c_compute_timing(pclk, hz);
}
return tim;
}
/**
* @}
*/
#endif // DEVICE_I2C

View File

@ -2,7 +2,7 @@
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2015 STMicroelectronics.
* Copyright (c) 2015-2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
@ -16,17 +16,24 @@
#ifndef MBED_I2C_DEVICE_H
#define MBED_I2C_DEVICE_H
#include "cmsis.h"
#include "mbed_error.h"
#include "PeripheralNames.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Define I2C Device */
#if DEVICE_I2C
/* Define IP version */
#define I2C_IP_VERSION_V2
// Common settings: I2C clock = 110 MHz, Analog filter = ON, Digital filter coefficient = 0
#define TIMING_VAL_DEFAULT_CLK_100KHZ 0x40E15676 // Standard mode with Rise Time = 400ns and Fall Time = 100ns
#define TIMING_VAL_DEFAULT_CLK_400KHZ 0x20C11434 // Fast mode with Rise Time = 250ns and Fall Time = 100ns
#define TIMING_VAL_DEFAULT_CLK_1MHZ 0x00C31536 // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
#define I2C_PCLK_DEF 110000000 // 110 MHz
#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)
/* Family specifc settings for clock source */
@ -35,36 +42,14 @@ extern "C" {
#define I2CAPI_I2C3_CLKSRC RCC_I2C3CLKSOURCE_SYSCLK
#define I2CAPI_I2C4_CLKSRC RCC_I2C4CLKSOURCE_SYSCLK
/* Provide the suitable timing depending on requested frequencie */
static inline uint32_t get_i2c_timing(int hz)
{
uint32_t tim = 0;
if (SystemCoreClock == 110000000) {
// Common settings: I2C clock = 80 MHz, Analog filter = ON, Digital filter coefficient = 0
switch (hz) {
case 100000:
tim = 0x40E15676; // Standard mode with Rise Time = 400ns and Fall Time = 100ns
break;
case 400000:
tim = 0x20C11434; // Fast mode with Rise Time = 250ns and Fall Time = 100ns
break;
case 1000000:
tim = 0x00C31536; // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
break;
default:
break;
}
}
else {
error("Value not provided for SystemCoreClock %u\n", SystemCoreClock);
}
return tim;
}
uint32_t i2c_get_pclk(I2CName i2c);
uint32_t i2c_compute_timing(uint32_t clock_src_freq, uint32_t i2c_freq);
uint32_t i2c_get_timing(I2CName i2c, int hz);
void i2c_compute_presc_scldel_sdadel(uint32_t clock_src_freq, uint32_t I2C_speed);
uint32_t i2c_compute_scll_sclh(uint32_t clock_src_freq, uint32_t I2C_speed);
#ifdef __cplusplus
}
#endif
#endif // DEVICE_I2C
#endif

View File

@ -12,6 +12,7 @@ target_sources(mbed-stm32wb
analogin_device.c
flash_api.c
gpio_irq_device.c
i2c_device.c
pwmout_device.c
serial_device.c
spi_api.c

View File

@ -0,0 +1,151 @@
/* mbed Microcontroller Library
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#include "i2c_device.h"
#include "mbed_assert.h"
#include "mbed_error.h"
#include "stm32wbxx_ll_rcc.h"
/* Define I2C Device */
#if DEVICE_I2C
/**
* @brief Get I2C clock source frequency according I2C instance used.
* @param i2c I2C instance name.
* @retval I2C clock source frequency in Hz.
*/
uint32_t i2c_get_pclk(I2CName i2c)
{
uint32_t clocksource;
uint32_t pclk = 0;
if (i2c == I2C_1) {
clocksource = __HAL_RCC_GET_I2C1_SOURCE();
switch (clocksource) {
case RCC_I2C1CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C1CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C1CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#if defined I2C2_BASE
if (i2c == I2C_2) {
clocksource = __HAL_RCC_GET_I2C2_SOURCE();
switch (clocksource) {
case RCC_I2C2CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C2CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C2CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
#if defined I2C3_BASE
else if (i2c == I2C_3) {
clocksource = __HAL_RCC_GET_I2C3_SOURCE();
switch (clocksource) {
case RCC_I2C3CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C3CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C3CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
else {
// should not happend
error("I2C: unknown instance");
}
return pclk;
}
/**
* @}
*/
/** @defgroup I2C_DEVICE_Exported_Functions I2C_DEVICE Exported Functions
* @{
*/
/**
* @brief Provide the suitable timing depending on requested frequency
* @param hz Required I2C clock in Hz.
* @retval I2C timing or 0 in case of error.
*/
uint32_t i2c_get_timing(I2CName i2c, int hz)
{
uint32_t tim;
uint32_t pclk;
pclk = i2c_get_pclk(i2c);
if (pclk == I2C_PCLK_64M) {
switch (hz) {
case 100000:
tim = TIMING_VAL_64M_CLK_100KHZ;
break;
case 400000:
tim = TIMING_VAL_64M_CLK_400KHZ;
break;
case 1000000:
tim = TIMING_VAL_64M_CLK_1MHZ;
break;
default:
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
break;
}
}
else if (pclk == I2C_PCLK_32M) {
switch (hz) {
case 100000:
tim = TIMING_VAL_32M_CLK_100KHZ;
break;
case 400000:
tim = TIMING_VAL_32M_CLK_400KHZ;
break;
case 1000000:
tim = TIMING_VAL_32M_CLK_1MHZ;
break;
default:
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
break;
}
}
else {
tim = i2c_compute_timing(pclk, hz);
}
return tim;
}
/**
* @}
*/
#endif // DEVICE_I2C

View File

@ -1,5 +1,5 @@
/* mbed Microcontroller Library
* Copyright (c) 2019 STMicroelectronics
* Copyright (c) 2019-2021 STMicroelectronics
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,16 +18,30 @@
#ifndef MBED_I2C_DEVICE_H
#define MBED_I2C_DEVICE_H
#include "cmsis.h"
#include "PeripheralNames.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef DEVICE_I2C
/* Define I2C Device */
#if DEVICE_I2C
/* Define IP version */
#define I2C_IP_VERSION_V2
// Common settings: I2C clock = 64 MHz, Analog filter = ON, Digital filter coefficient = 0
#define TIMING_VAL_64M_CLK_100KHZ 0x10707DBC // Standard mode with Rise Time = 400ns and Fall Time = 100ns
#define TIMING_VAL_64M_CLK_400KHZ 0x00602173 // Fast mode with Rise Time = 250ns and Fall Time = 100ns
#define TIMING_VAL_64M_CLK_1MHZ 0x00300B29 // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
#define I2C_PCLK_64M 64000000 // 64 MHz
// Common settings: I2C clock = 32 MHz, Analog filter = ON, Digital filter coefficient = 0
#define TIMING_VAL_32M_CLK_100KHZ 0x00707CBB // Standard mode with Rise Time = 400ns and Fall Time = 100ns
#define TIMING_VAL_32M_CLK_400KHZ 0x00300F38 // Fast mode with Rise Time = 250ns and Fall Time = 100ns
#define TIMING_VAL_32M_CLK_1MHZ 0x00100413 // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
#define I2C_PCLK_32M 32000000 // 32 MHz
#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)
/* Family specific settings for clock source */
@ -35,48 +49,14 @@ extern "C" {
#define I2CAPI_I2C2_CLKSRC RCC_I2C2CLKSOURCE_SYSCLK
#define I2CAPI_I2C3_CLKSRC RCC_I2C3CLKSOURCE_SYSCLK
/* Provide the suitable timing depending on requested frequency */
static inline uint32_t get_i2c_timing(int hz)
{
uint32_t tim = 0;
if (SystemCoreClock == 64000000) {
// Common settings: I2C clock = 64 MHz, Analog filter = ON, Digital filter coefficient = 0
switch (hz) {
case 100000:
tim = 0x10707DBC; // Standard mode with Rise Time = 400ns and Fall Time = 100ns
break;
case 400000:
tim = 0x00602173; // Fast mode with Rise Time = 250ns and Fall Time = 100ns
break;
case 1000000:
tim = 0x00300B29; // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
break;
default:
break;
}
} else if (SystemCoreClock == 32000000) {
// Common settings: I2C clock = 32 MHz, Analog filter = ON, Digital filter coefficient = 0
switch (hz) {
case 100000:
tim = 0x00707CBB; // Standard mode with Rise Time = 400ns and Fall Time = 100ns
break;
case 400000:
tim = 0x00300F38; // Fast mode with Rise Time = 250ns and Fall Time = 100ns
break;
case 1000000:
tim = 0x00100413; // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
break;
default:
break;
}
}
return tim;
}
uint32_t i2c_get_pclk(I2CName i2c);
uint32_t i2c_compute_timing(uint32_t clock_src_freq, uint32_t i2c_freq);
uint32_t i2c_get_timing(I2CName i2c, int hz);
void i2c_compute_presc_scldel_sdadel(uint32_t clock_src_freq, uint32_t I2C_speed);
uint32_t i2c_compute_scll_sclh(uint32_t clock_src_freq, uint32_t I2C_speed);
#ifdef __cplusplus
}
#endif
#endif // DEVICE_I2C
#endif

View File

@ -12,6 +12,7 @@ target_sources(mbed-stm32wl
analogout_device.c
flash_api.c
gpio_irq_device.c
i2c_device.c
pwmout_device.c
serial_device.c
spi_api.c

View File

@ -0,0 +1,136 @@
/* mbed Microcontroller Library
* SPDX-License-Identifier: BSD-3-Clause
******************************************************************************
*
* Copyright (c) 2021 STMicroelectronics.
* All rights reserved.
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#include "i2c_device.h"
#include "mbed_assert.h"
#include "mbed_error.h"
#include "stm32wlxx_ll_rcc.h"
/* Define I2C Device */
#if DEVICE_I2C
/**
* @brief Get I2C clock source frequency according I2C instance used.
* @param i2c I2C instance name.
* @retval I2C clock source frequency in Hz.
*/
uint32_t i2c_get_pclk(I2CName i2c)
{
uint32_t clocksource;
uint32_t pclk = 0;
if (i2c == I2C_1) {
clocksource = __HAL_RCC_GET_I2C1_SOURCE();
switch (clocksource) {
case RCC_I2C1CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C1CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C1CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#if defined I2C2_BASE
if (i2c == I2C_2) {
clocksource = __HAL_RCC_GET_I2C2_SOURCE();
switch (clocksource) {
case RCC_I2C2CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C2CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C2CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
#if defined I2C3_BASE
else if (i2c == I2C_3) {
clocksource = __HAL_RCC_GET_I2C3_SOURCE();
switch (clocksource) {
case RCC_I2C3CLKSOURCE_PCLK1:
pclk = HAL_RCC_GetPCLK1Freq();
break;
case RCC_I2C3CLKSOURCE_SYSCLK:
pclk = HAL_RCC_GetSysClockFreq();
break;
case RCC_I2C3CLKSOURCE_HSI:
pclk = HSI_VALUE;
break;
}
}
#endif
else {
// should not happend
error("I2C: unknown instance");
}
return pclk;
}
/**
* @}
*/
/** @defgroup I2C_DEVICE_Exported_Functions I2C_DEVICE Exported Functions
* @{
*/
/**
* @brief Provide the suitable timing depending on requested frequency
* @param hz Required I2C clock in Hz.
* @retval I2C timing or 0 in case of error.
*/
uint32_t i2c_get_timing(I2CName i2c, int hz)
{
uint32_t tim;
uint32_t pclk;
pclk = i2c_get_pclk(i2c);
if (pclk == I2C_PCLK_DEF) {
switch (hz) {
case 100000:
tim = TIMING_VAL_DEFAULT_CLK_100KHZ;
break;
case 400000:
tim = TIMING_VAL_DEFAULT_CLK_400KHZ;
break;
case 1000000:
tim = TIMING_VAL_DEFAULT_CLK_1MHZ;
break;
default:
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
break;
}
}
else {
tim = i2c_compute_timing(pclk, hz);
}
return tim;
}
/**
* @}
*/
#endif // DEVICE_I2C

View File

@ -16,16 +16,24 @@
#ifndef MBED_I2C_DEVICE_H
#define MBED_I2C_DEVICE_H
#include "cmsis.h"
#include "PeripheralNames.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef DEVICE_I2C
/* Define I2C Device */
#if DEVICE_I2C
/* Define IP version */
#define I2C_IP_VERSION_V2
// Common settings: I2C clock = 48 MHz, Analog filter = ON, Digital filter coefficient = 0
#define TIMING_VAL_DEFAULT_CLK_100KHZ 0x20E03F53 // Standard mode with Rise Time = 640ns and Fall Time = 20ns
#define TIMING_VAL_DEFAULT_CLK_400KHZ 0x20500817 // Fast mode with Rise Time = 250ns and Fall Time = 100ns
#define TIMING_VAL_DEFAULT_CLK_1MHZ 0x00500A18 // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
#define I2C_PCLK_DEF 48000000 // 48 MHz
#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)
/* Family specific settings for clock source */
@ -33,32 +41,14 @@ extern "C" {
#define I2CAPI_I2C2_CLKSRC RCC_I2C2CLKSOURCE_SYSCLK
#define I2CAPI_I2C3_CLKSRC RCC_I2C3CLKSOURCE_SYSCLK
/* Provide the suitable timing depending on requested frequency */
static inline uint32_t get_i2c_timing(int hz)
{
uint32_t tim = 0;
// Common settings: I2C clock = 48 MHz, Analog filter = ON, Digital filter coefficient = 0
switch (hz) {
case 100000:
tim = 0x20E03F53; // Standard mode with Rise Time = 640ns and Fall Time = 20ns
break;
case 400000:
tim = 0x20500817; // Fast mode with Rise Time = 250ns and Fall Time = 100ns
break;
case 1000000:
tim = 0x00500A18; // Fast mode Plus with Rise Time = 60ns and Fall Time = 100ns
break;
default:
break;
}
return tim;
}
uint32_t i2c_get_pclk(I2CName i2c);
uint32_t i2c_compute_timing(uint32_t clock_src_freq, uint32_t i2c_freq);
uint32_t i2c_get_timing(I2CName i2c, int hz);
void i2c_compute_presc_scldel_sdadel(uint32_t clock_src_freq, uint32_t I2C_speed);
uint32_t i2c_compute_scll_sclh(uint32_t clock_src_freq, uint32_t I2C_speed);
#ifdef __cplusplus
}
#endif
#endif // DEVICE_I2C
#endif

View File

@ -1,6 +1,6 @@
/* mbed Microcontroller Library
*******************************************************************************
* Copyright (c) 2015, STMicroelectronics
* Copyright (c) 2015-2021, STMicroelectronics
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -43,6 +43,115 @@
#include "mbed_error.h"
#include "platform/mbed_power_mgmt.h"
/** @defgroup I2C_DEVICE_Private_Constants I2C_DEVICE Private Constants
* @{
*/
#ifndef I2C_VALID_TIMING_NBR
#define I2C_VALID_TIMING_NBR 128U
#endif
#define I2C_SPEED_FREQ_STANDARD 0U /* 100 kHz */
#define I2C_SPEED_FREQ_FAST 1U /* 400 kHz */
#define I2C_SPEED_FREQ_FAST_PLUS 2U /* 1 MHz */
#define I2C_ANALOG_FILTER_DELAY_MIN 50U /* ns */
#define I2C_ANALOG_FILTER_DELAY_MAX 260U /* ns */
#define I2C_USE_ANALOG_FILTER 1U
#define I2C_DIGITAL_FILTER_COEF 0U
#define I2C_PRESC_MAX 16U
#define I2C_SCLDEL_MAX 16U
#define I2C_SDADEL_MAX 16U
#define I2C_SCLH_MAX 256U
#define I2C_SCLL_MAX 256U
#define SEC2NSEC 1000000000UL
/**
* @}
*/
/** @defgroup I2C_DEVICE_Private_Types I2C_DEVICE Private Types
* @{
*/
typedef struct {
uint32_t freq; /* Frequency in Hz */
uint32_t freq_min; /* Minimum frequency in Hz */
uint32_t freq_max; /* Maximum frequency in Hz */
uint32_t hddat_min; /* Minimum data hold time in ns */
uint32_t vddat_max; /* Maximum data valid time in ns */
uint32_t sudat_min; /* Minimum data setup time in ns */
uint32_t lscl_min; /* Minimum low period of the SCL clock in ns */
uint32_t hscl_min; /* Minimum high period of SCL clock in ns */
uint32_t trise; /* Rise time in ns */
uint32_t tfall; /* Fall time in ns */
uint32_t dnf; /* Digital noise filter coefficient */
} I2C_Charac_t;
typedef struct {
uint32_t presc; /* Timing prescaler */
uint32_t tscldel; /* SCL delay */
uint32_t tsdadel; /* SDA delay */
uint32_t sclh; /* SCL high period */
uint32_t scll; /* SCL low period */
} I2C_Timings_t;
/**
* @}
*/
/** @defgroup I2C_DEVICE_Private_Constants I2C_DEVICE Private Constants
* @{
*/
static const I2C_Charac_t I2C_Charac[] = {
[I2C_SPEED_FREQ_STANDARD] =
{
.freq = 100000,
.freq_min = 80000,
.freq_max = 120000,
.hddat_min = 0,
.vddat_max = 3450,
.sudat_min = 250,
.lscl_min = 4700,
.hscl_min = 4000,
.trise = 640,
.tfall = 20,
.dnf = I2C_DIGITAL_FILTER_COEF,
},
[I2C_SPEED_FREQ_FAST] =
{
.freq = 400000,
.freq_min = 320000,
.freq_max = 480000,
.hddat_min = 0,
.vddat_max = 900,
.sudat_min = 100,
.lscl_min = 1300,
.hscl_min = 600,
.trise = 250,
.tfall = 100,
.dnf = I2C_DIGITAL_FILTER_COEF,
},
[I2C_SPEED_FREQ_FAST_PLUS] =
{
.freq = 1000000,
.freq_min = 800000,
.freq_max = 1200000,
.hddat_min = 0,
.vddat_max = 450,
.sudat_min = 50,
.lscl_min = 500,
.hscl_min = 260,
.trise = 60,
.tfall = 100,
.dnf = I2C_DIGITAL_FILTER_COEF,
},
};
/**
* @}
*/
/** @defgroup I2C_DEVICE_Private_Variables I2C_DEVICE Private Variables
* @{
*/
static I2C_Timings_t I2c_valid_timing[I2C_VALID_TIMING_NBR];
static uint32_t I2c_valid_timing_nbr = 0;
#ifndef DEBUG_STDIO
# define DEBUG_STDIO 0
#endif
@ -482,7 +591,8 @@ void i2c_frequency(i2c_t *obj, int hz)
#ifdef I2C_IP_VERSION_V2
/* Only predefined timing for below frequencies are supported */
MBED_ASSERT((hz == 100000) || (hz == 400000) || (hz == 1000000));
/* Calculates I2C timing value with respect to I2C input clock and I2C bus frequency */
handle->Init.Timing = i2c_get_timing(obj_s->i2c, hz);
// Enable the Fast Mode Plus capability
if (hz == 1000000) {
#if defined(I2C1_BASE) && defined(I2C_FASTMODEPLUS_I2C1) // sometimes I2C_FASTMODEPLUS_I2Cx is define even if not supported by the chip
@ -550,14 +660,6 @@ void i2c_frequency(i2c_t *obj, int hz)
HAL_I2CEx_ConfigAnalogFilter(handle, I2C_ANALOGFILTER_ENABLE);
#endif
#ifdef I2C_IP_VERSION_V2
#ifdef TARGET_STM32H7
handle->Init.Timing = get_i2c_timing(obj_s->i2c, hz);
#else
handle->Init.Timing = get_i2c_timing(hz);
#endif
#endif
// I2C configuration
handle->Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
handle->Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
@ -1399,6 +1501,184 @@ void i2c_abort_asynch(i2c_t *obj)
HAL_I2C_Master_Abort_IT(handle, Dummy_DevAddress);
}
/**
* @brief Calculate SCLL and SCLH and find best configuration.
* @param clock_src_freq I2C source clock in HZ.
* @param I2C_speed I2C frequency (index).
* @retval config index (0 to I2C_VALID_TIMING_NBR], 0xFFFFFFFF for no valid config.
*/
uint32_t i2c_compute_scll_sclh(uint32_t clock_src_freq, uint32_t I2C_speed)
{
uint32_t ret = 0xFFFFFFFFU;
uint32_t ti2cclk;
uint32_t ti2cspeed;
uint32_t prev_error;
uint32_t dnf_delay;
uint32_t clk_min, clk_max;
uint32_t scll, sclh;
uint32_t tafdel_min;
ti2cclk = (SEC2NSEC + (clock_src_freq / 2U)) / clock_src_freq;
ti2cspeed = (SEC2NSEC + (I2C_Charac[I2C_speed].freq / 2U)) / I2C_Charac[I2C_speed].freq;
tafdel_min = (I2C_USE_ANALOG_FILTER == 1U) ? I2C_ANALOG_FILTER_DELAY_MIN : 0U;
/* tDNF = DNF x tI2CCLK */
dnf_delay = I2C_Charac[I2C_speed].dnf * ti2cclk;
clk_max = SEC2NSEC / I2C_Charac[I2C_speed].freq_min;
clk_min = SEC2NSEC / I2C_Charac[I2C_speed].freq_max;
prev_error = ti2cspeed;
for (uint32_t count = 0; count < I2c_valid_timing_nbr; count++) {
/* tPRESC = (PRESC+1) x tI2CCLK*/
uint32_t tpresc = (I2c_valid_timing[count].presc + 1U) * ti2cclk;
for (scll = 0; scll < I2C_SCLL_MAX; scll++) {
/* tLOW(min) <= tAF(min) + tDNF + 2 x tI2CCLK + [(SCLL+1) x tPRESC ] */
uint32_t tscl_l = tafdel_min + dnf_delay + (2U * ti2cclk) + ((scll + 1U) * tpresc);
/* The I2CCLK period tI2CCLK must respect the following conditions:
tI2CCLK < (tLOW - tfilters) / 4 and tI2CCLK < tHIGH */
if ((tscl_l > I2C_Charac[I2C_speed].lscl_min) && (ti2cclk < ((tscl_l - tafdel_min - dnf_delay) / 4U))) {
for (sclh = 0; sclh < I2C_SCLH_MAX; sclh++) {
/* tHIGH(min) <= tAF(min) + tDNF + 2 x tI2CCLK + [(SCLH+1) x tPRESC] */
uint32_t tscl_h = tafdel_min + dnf_delay + (2U * ti2cclk) + ((sclh + 1U) * tpresc);
/* tSCL = tf + tLOW + tr + tHIGH */
uint32_t tscl = tscl_l + tscl_h + I2C_Charac[I2C_speed].trise + I2C_Charac[I2C_speed].tfall;
if ((tscl >= clk_min) && (tscl <= clk_max) && (tscl_h >= I2C_Charac[I2C_speed].hscl_min) && (ti2cclk < tscl_h)) {
int32_t error = (int32_t)tscl - (int32_t)ti2cspeed;
if (error < 0) {
error = -error;
}
/* look for the timings with the lowest clock error */
if ((uint32_t)error < prev_error) {
prev_error = (uint32_t)error;
I2c_valid_timing[count].scll = scll;
I2c_valid_timing[count].sclh = sclh;
ret = count;
}
}
}
}
}
}
return ret;
}
/**
* @brief Compute PRESC, SCLDEL and SDADEL.
* @param clock_src_freq I2C source clock in HZ.
* @param I2C_speed I2C frequency (index).
* @retval None.
*/
void i2c_compute_presc_scldel_sdadel(uint32_t clock_src_freq, uint32_t I2C_speed)
{
uint32_t prev_presc = I2C_PRESC_MAX;
uint32_t ti2cclk;
int32_t tsdadel_min, tsdadel_max;
int32_t tscldel_min;
uint32_t presc, scldel, sdadel;
uint32_t tafdel_min, tafdel_max;
ti2cclk = (SEC2NSEC + (clock_src_freq / 2U)) / clock_src_freq;
tafdel_min = (I2C_USE_ANALOG_FILTER == 1U) ? I2C_ANALOG_FILTER_DELAY_MIN : 0U;
tafdel_max = (I2C_USE_ANALOG_FILTER == 1U) ? I2C_ANALOG_FILTER_DELAY_MAX : 0U;
/* tDNF = DNF x tI2CCLK
tPRESC = (PRESC+1) x tI2CCLK
SDADEL >= {tf +tHD;DAT(min) - tAF(min) - tDNF - [3 x tI2CCLK]} / {tPRESC}
SDADEL <= {tVD;DAT(max) - tr - tAF(max) - tDNF- [4 x tI2CCLK]} / {tPRESC} */
tsdadel_min = (int32_t)I2C_Charac[I2C_speed].tfall + (int32_t)I2C_Charac[I2C_speed].hddat_min -
(int32_t)tafdel_min - (int32_t)(((int32_t)I2C_Charac[I2C_speed].dnf + 3) * (int32_t)ti2cclk);
tsdadel_max = (int32_t)I2C_Charac[I2C_speed].vddat_max - (int32_t)I2C_Charac[I2C_speed].trise -
(int32_t)tafdel_max - (int32_t)(((int32_t)I2C_Charac[I2C_speed].dnf + 4) * (int32_t)ti2cclk);
/* {[tr+ tSU;DAT(min)] / [tPRESC]} - 1 <= SCLDEL */
tscldel_min = (int32_t)I2C_Charac[I2C_speed].trise + (int32_t)I2C_Charac[I2C_speed].sudat_min;
if (tsdadel_min <= 0) {
tsdadel_min = 0;
}
if (tsdadel_max <= 0) {
tsdadel_max = 0;
}
for (presc = 0; presc < I2C_PRESC_MAX; presc++) {
for (scldel = 0; scldel < I2C_SCLDEL_MAX; scldel++) {
/* TSCLDEL = (SCLDEL+1) * (PRESC+1) * TI2CCLK */
uint32_t tscldel = (scldel + 1U) * (presc + 1U) * ti2cclk;
if (tscldel >= (uint32_t)tscldel_min) {
for (sdadel = 0; sdadel < I2C_SDADEL_MAX; sdadel++) {
/* TSDADEL = SDADEL * (PRESC+1) * TI2CCLK */
uint32_t tsdadel = (sdadel * (presc + 1U)) * ti2cclk;
if ((tsdadel >= (uint32_t)tsdadel_min) && (tsdadel <= (uint32_t)tsdadel_max)) {
if (presc != prev_presc) {
I2c_valid_timing[I2c_valid_timing_nbr].presc = presc;
I2c_valid_timing[I2c_valid_timing_nbr].tscldel = scldel;
I2c_valid_timing[I2c_valid_timing_nbr].tsdadel = sdadel;
prev_presc = presc;
I2c_valid_timing_nbr ++;
if (I2c_valid_timing_nbr >= I2C_VALID_TIMING_NBR) {
return;
}
}
}
}
}
}
}
}
/**
* @brief Compute I2C timing according current I2C clock source and required I2C clock.
* @param clock_src_freq I2C clock source in Hz.
* @param i2c_freq Required I2C clock in Hz.
* @retval I2C timing or 0 in case of error.
*/
uint32_t i2c_compute_timing(uint32_t clock_src_freq, uint32_t i2c_freq)
{
uint32_t ret = 0;
uint32_t speed;
uint32_t idx;
if ((clock_src_freq != 0U) && (i2c_freq != 0U)) {
for (speed = 0 ; speed <= (uint32_t)I2C_SPEED_FREQ_FAST_PLUS ; speed++) {
if ((i2c_freq >= I2C_Charac[speed].freq_min) &&
(i2c_freq <= I2C_Charac[speed].freq_max)) {
i2c_compute_presc_scldel_sdadel(clock_src_freq, speed);
idx = i2c_compute_scll_sclh(clock_src_freq, speed);
if (idx < I2C_VALID_TIMING_NBR) {
ret = ((I2c_valid_timing[idx].presc & 0x0FU) << 28) | \
((I2c_valid_timing[idx].tscldel & 0x0FU) << 20) | \
((I2c_valid_timing[idx].tsdadel & 0x0FU) << 16) | \
((I2c_valid_timing[idx].sclh & 0xFFU) << 8) | \
((I2c_valid_timing[idx].scll & 0xFFU) << 0);
}
break;
}
}
}
return ret;
}
#endif // DEVICE_I2C_ASYNCH
#endif // DEVICE_I2C