Skip to content

Commit

Permalink
i2c: fix a bug in sda sample timing
Browse files Browse the repository at this point in the history
* Closes #9777

This bug prevented SCL line to work properly after a NACK was received in master mode.
  • Loading branch information
o-marshmallow committed Apr 13, 2023
1 parent 7d41c5b commit a0f8434
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 7 deletions.
7 changes: 6 additions & 1 deletion components/hal/esp32c2/include/hal/i2c_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <stdbool.h>
#include "hal/misc.h"
#include "hal/assert.h"
#include "soc/i2c_periph.h"
#include "soc/soc_caps.h"
#include "soc/i2c_struct.h"
Expand Down Expand Up @@ -92,12 +93,16 @@ static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2
clk_cal->scl_wait_high = (bus_freq >= 80*1000) ? (half_cycle / 2 - 2) : (half_cycle / 4);
clk_cal->scl_high = half_cycle - clk_cal->scl_wait_high;
clk_cal->sda_hold = half_cycle / 4;
clk_cal->sda_sample = half_cycle / 2 + clk_cal->scl_wait_high;
clk_cal->sda_sample = half_cycle / 2;
clk_cal->setup = half_cycle;
clk_cal->hold = half_cycle;
//default we set the timeout value to about 10 bus cycles
// log(20*half_cycle)/log(2) = log(half_cycle)/log(2) + log(20)/log(2)
clk_cal->tout = (int)(sizeof(half_cycle) * 8 - __builtin_clz(5 * half_cycle)) + 2;

/* Verify the assumptions made by the hardware */
HAL_ASSERT(clk_cal->scl_wait_high < clk_cal->sda_sample &&
clk_cal->sda_sample < clk_cal->scl_high);
}

/**
Expand Down
7 changes: 6 additions & 1 deletion components/hal/esp32c3/include/hal/i2c_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "stdbool.h"
#include "hal/misc.h"
#include "hal/assert.h"
#include "soc/i2c_periph.h"
#include "soc/soc_caps.h"
#include "soc/i2c_struct.h"
Expand Down Expand Up @@ -93,12 +94,16 @@ static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2
clk_cal->scl_wait_high = (bus_freq >= 80*1000) ? (half_cycle / 2 - 2) : (half_cycle / 4);
clk_cal->scl_high = half_cycle - clk_cal->scl_wait_high;
clk_cal->sda_hold = half_cycle / 4;
clk_cal->sda_sample = half_cycle / 2 + clk_cal->scl_wait_high;
clk_cal->sda_sample = half_cycle / 2;
clk_cal->setup = half_cycle;
clk_cal->hold = half_cycle;
//default we set the timeout value to about 10 bus cycles
// log(20*half_cycle)/log(2) = log(half_cycle)/log(2) + log(20)/log(2)
clk_cal->tout = (int)(sizeof(half_cycle) * 8 - __builtin_clz(5 * half_cycle)) + 2;

/* Verify the assumptions made by the hardware */
HAL_ASSERT(clk_cal->scl_wait_high < clk_cal->sda_sample &&
clk_cal->sda_sample < clk_cal->scl_high);
}

/**
Expand Down
9 changes: 7 additions & 2 deletions components/hal/esp32c6/include/hal/i2c_ll.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -10,6 +10,7 @@

#include <stdbool.h>
#include "hal/misc.h"
#include "hal/assert.h"
#include "soc/i2c_periph.h"
#include "soc/soc_caps.h"
#include "soc/i2c_struct.h"
Expand Down Expand Up @@ -91,12 +92,16 @@ static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2
clk_cal->scl_wait_high = (bus_freq >= 80*1000) ? (half_cycle / 2 - 2) : (half_cycle / 4);
clk_cal->scl_high = half_cycle - clk_cal->scl_wait_high;
clk_cal->sda_hold = half_cycle / 4;
clk_cal->sda_sample = half_cycle / 2 + clk_cal->scl_wait_high;
clk_cal->sda_sample = half_cycle / 2;
clk_cal->setup = half_cycle;
clk_cal->hold = half_cycle;
//default we set the timeout value to about 10 bus cycles
// log(20*half_cycle)/log(2) = log(half_cycle)/log(2) + log(20)/log(2)
clk_cal->tout = (int)(sizeof(half_cycle) * 8 - __builtin_clz(5 * half_cycle)) + 2;

/* Verify the assumptions made by the hardware */
HAL_ASSERT(clk_cal->scl_wait_high < clk_cal->sda_sample &&
clk_cal->sda_sample < clk_cal->scl_high);
}

/**
Expand Down
7 changes: 6 additions & 1 deletion components/hal/esp32h2/include/hal/i2c_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include <stdbool.h>
#include "hal/misc.h"
#include "hal/assert.h"
#include "soc/i2c_periph.h"
#include "soc/soc_caps.h"
#include "soc/i2c_struct.h"
Expand Down Expand Up @@ -92,12 +93,16 @@ static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2
clk_cal->scl_wait_high = (bus_freq >= 80*1000) ? (half_cycle / 2 - 2) : (half_cycle / 4);
clk_cal->scl_high = half_cycle - clk_cal->scl_wait_high;
clk_cal->sda_hold = half_cycle / 4;
clk_cal->sda_sample = half_cycle / 2 + clk_cal->scl_wait_high;
clk_cal->sda_sample = half_cycle / 2;
clk_cal->setup = half_cycle;
clk_cal->hold = half_cycle;
//default we set the timeout value to about 10 bus cycles
// log(20*half_cycle)/log(2) = log(half_cycle)/log(2) + log(20)/log(2)
clk_cal->tout = (int)(sizeof(half_cycle) * 8 - __builtin_clz(5 * half_cycle)) + 2;

/* Verify the assumptions made by the hardware */
HAL_ASSERT(clk_cal->scl_wait_high < clk_cal->sda_sample &&
clk_cal->sda_sample < clk_cal->scl_high);
}

/**
Expand Down
7 changes: 6 additions & 1 deletion components/hal/esp32h4/include/hal/i2c_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "stdbool.h"
#include "hal/misc.h"
#include "hal/assert.h"
#include "soc/i2c_periph.h"
#include "soc/soc_caps.h"
#include "soc/i2c_struct.h"
Expand Down Expand Up @@ -95,12 +96,16 @@ static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2
clk_cal->scl_wait_high = (bus_freq >= 80*1000) ? (half_cycle / 2 - 2) : (half_cycle / 4);
clk_cal->scl_high = half_cycle - clk_cal->scl_wait_high;
clk_cal->sda_hold = half_cycle / 4;
clk_cal->sda_sample = half_cycle / 2 + clk_cal->scl_wait_high;
clk_cal->sda_sample = half_cycle / 2;
clk_cal->setup = half_cycle;
clk_cal->hold = half_cycle;
//default we set the timeout value to about 10 bus cycles
// log(20*half_cycle)/log(2) = log(half_cycle)/log(2) + log(20)/log(2)
clk_cal->tout = (int)(sizeof(half_cycle) * 8 - __builtin_clz(5 * half_cycle)) + 2;

/* Verify the assumptions made by the hardware */
HAL_ASSERT(clk_cal->scl_wait_high < clk_cal->sda_sample &&
clk_cal->sda_sample < clk_cal->scl_high);
}

/**
Expand Down
7 changes: 6 additions & 1 deletion components/hal/esp32s3/include/hal/i2c_ll.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

#include "stdbool.h"
#include "hal/misc.h"
#include "hal/assert.h"
#include "soc/i2c_periph.h"
#include "soc/soc_caps.h"
#include "soc/i2c_struct.h"
Expand Down Expand Up @@ -92,12 +93,16 @@ static inline void i2c_ll_cal_bus_clk(uint32_t source_clk, uint32_t bus_freq, i2
clk_cal->scl_wait_high = (bus_freq >= 80*1000) ? (half_cycle / 2 - 2) : (half_cycle / 4);
clk_cal->scl_high = half_cycle - clk_cal->scl_wait_high;
clk_cal->sda_hold = half_cycle / 4;
clk_cal->sda_sample = half_cycle / 2 + clk_cal->scl_wait_high;
clk_cal->sda_sample = half_cycle / 2;
clk_cal->setup = half_cycle;
clk_cal->hold = half_cycle;
//default we set the timeout value to about 10 bus cycles
// log(20*half_cycle)/log(2) = log(half_cycle)/log(2) + log(20)/log(2)
clk_cal->tout = (int)(sizeof(half_cycle) * 8 - __builtin_clz(5 * half_cycle)) + 2;

/* Verify the assumptions made by the hardware */
HAL_ASSERT(clk_cal->scl_wait_high < clk_cal->sda_sample &&
clk_cal->sda_sample < clk_cal->scl_high);
}

/**
Expand Down

0 comments on commit a0f8434

Please sign in to comment.