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:
Zim Kalinowski 2022-08-20 03:51:44 +08:00
commit 662b6c9ad3
3 changed files with 54 additions and 56 deletions

View File

@ -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;

View File

@ -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;
} }

View File

@ -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;
} }