mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/i2c_incorrect_speed_v4.3' into 'release/v4.3'
I2C: Fix SCL period timings on ESP targets (backport v4.3) See merge request espressif/esp-idf!18272
This commit is contained in:
commit
662b6c9ad3
@ -1,16 +1,8 @@
|
|||||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// The LL layer for I2C register operations
|
// The LL layer for I2C register operations
|
||||||
|
|
||||||
@ -121,9 +113,29 @@ static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2
|
|||||||
*/
|
*/
|
||||||
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg)
|
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg)
|
||||||
{
|
{
|
||||||
//scl period
|
/* SCL period. According to the TRM, we should always subtract 1 to SCL low period */
|
||||||
hw->scl_low_period.period = bus_cfg->scl_low;
|
assert(bus_cfg->scl_low > 0);
|
||||||
hw->scl_high_period.period = bus_cfg->scl_high;
|
hw->scl_low_period.period = bus_cfg->scl_low - 1;
|
||||||
|
/* Still according to the TRM, if filter is not enbled, we have to subtract 7,
|
||||||
|
* if SCL filter is enabled, we have to subtract:
|
||||||
|
* 8 if SCL filter is between 0 and 2 (included)
|
||||||
|
* 6 + SCL threshold if SCL filter is between 3 and 7 (included)
|
||||||
|
* to SCL high period */
|
||||||
|
uint16_t scl_high = bus_cfg->scl_high;
|
||||||
|
/* In the "worst" case, we will subtract 13, make sure the result will still be correct */
|
||||||
|
assert(scl_high > 13);
|
||||||
|
if (hw->scl_filter_cfg.en) {
|
||||||
|
if (hw->scl_filter_cfg.thres <= 2) {
|
||||||
|
scl_high -= 8;
|
||||||
|
} else if (hw->scl_filter_cfg.thres <= 7) {
|
||||||
|
scl_high -= hw->scl_filter_cfg.thres + 6;
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scl_high -= 7;
|
||||||
|
}
|
||||||
|
hw->scl_high_period.period = scl_high;
|
||||||
//sda sample
|
//sda sample
|
||||||
hw->sda_hold.time = bus_cfg->sda_hold;
|
hw->sda_hold.time = bus_cfg->sda_hold;
|
||||||
hw->sda_sample.time = bus_cfg->sda_sample;
|
hw->sda_sample.time = bus_cfg->sda_sample;
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// The LL layer for I2C register operations
|
// The LL layer for I2C register operations
|
||||||
|
|
||||||
@ -156,17 +148,17 @@ static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg)
|
|||||||
{
|
{
|
||||||
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, bus_cfg->clkm_div - 1);
|
HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, bus_cfg->clkm_div - 1);
|
||||||
//scl period
|
//scl period
|
||||||
hw->scl_low_period.period = bus_cfg->scl_low - 1;
|
hw->scl_low_period.period = bus_cfg->scl_low - 2;
|
||||||
hw->scl_high_period.period = bus_cfg->scl_high;
|
hw->scl_high_period.period = bus_cfg->scl_high - 3;
|
||||||
//sda sample
|
//sda sample
|
||||||
hw->sda_hold.time = bus_cfg->sda_hold;
|
hw->sda_hold.time = bus_cfg->sda_hold - 1;
|
||||||
hw->sda_sample.time = bus_cfg->sda_sample;
|
hw->sda_sample.time = bus_cfg->sda_sample - 1;
|
||||||
//setup
|
//setup
|
||||||
hw->scl_rstart_setup.time = bus_cfg->setup;
|
hw->scl_rstart_setup.time = bus_cfg->setup - 1;
|
||||||
hw->scl_stop_setup.time = bus_cfg->setup;
|
hw->scl_stop_setup.time = bus_cfg->setup - 1;
|
||||||
//hold
|
//hold
|
||||||
hw->scl_start_hold.time = bus_cfg->hold - 1;
|
hw->scl_start_hold.time = bus_cfg->hold - 1;
|
||||||
hw->scl_stop_hold.time = bus_cfg->hold;
|
hw->scl_stop_hold.time = bus_cfg->hold - 1;
|
||||||
hw->timeout.time_out_value = bus_cfg->tout;
|
hw->timeout.time_out_value = bus_cfg->tout;
|
||||||
hw->timeout.time_out_en = 1;
|
hw->timeout.time_out_en = 1;
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,8 @@
|
|||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
// The LL layer for I2C register operations
|
// The LL layer for I2C register operations
|
||||||
|
|
||||||
@ -147,18 +139,20 @@ static inline void i2c_ll_update(i2c_dev_t *hw)
|
|||||||
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg)
|
static inline void i2c_ll_set_bus_timing(i2c_dev_t *hw, i2c_clk_cal_t *bus_cfg)
|
||||||
{
|
{
|
||||||
hw->clk_conf.sclk_div_num = bus_cfg->clkm_div - 1;
|
hw->clk_conf.sclk_div_num = bus_cfg->clkm_div - 1;
|
||||||
|
/* According to the Technical Reference Manual, the following timings must be subtracted by 1.
|
||||||
|
* Moreover, the frequency calculation also shows that we must subtract 3 to the total SCL */
|
||||||
//scl period
|
//scl period
|
||||||
hw->scl_low_period.period = bus_cfg->scl_low - 1;
|
hw->scl_low_period.period = bus_cfg->scl_low - 1 - 2;
|
||||||
hw->scl_high_period.period = bus_cfg->scl_high;
|
hw->scl_high_period.period = bus_cfg->scl_high - 1 - 1;
|
||||||
//sda sample
|
//sda sample
|
||||||
hw->sda_hold.time = bus_cfg->sda_hold;
|
hw->sda_hold.time = bus_cfg->sda_hold - 1;
|
||||||
hw->sda_sample.time = bus_cfg->sda_sample;
|
hw->sda_sample.time = bus_cfg->sda_sample - 1;
|
||||||
//setup
|
//setup
|
||||||
hw->scl_rstart_setup.time = bus_cfg->setup;
|
hw->scl_rstart_setup.time = bus_cfg->setup - 1;
|
||||||
hw->scl_stop_setup.time = bus_cfg->setup;
|
hw->scl_stop_setup.time = bus_cfg->setup - 1;
|
||||||
//hold
|
//hold
|
||||||
hw->scl_start_hold.time = bus_cfg->hold - 1;
|
hw->scl_start_hold.time = bus_cfg->hold - 1;
|
||||||
hw->scl_stop_hold.time = bus_cfg->hold;
|
hw->scl_stop_hold.time = bus_cfg->hold - 1;
|
||||||
hw->timeout.time_out_value = bus_cfg->tout;
|
hw->timeout.time_out_value = bus_cfg->tout;
|
||||||
hw->timeout.time_out_en = 1;
|
hw->timeout.time_out_en = 1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user