Skip to content

Commit 60f7d05

Browse files
committed
Avoid I2C timing computation when input clock is unchanged
With U8g2 library, I2C clock is set for each transmission. With some I2C harwdware version, timings are then computed for each time. This cause very slow display on LCD.
1 parent f2ef8f2 commit 60f7d05

File tree

1 file changed

+29
-4
lines changed

1 file changed

+29
-4
lines changed

cores/arduino/stm32/twi.c

+29-4
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,6 @@ extern "C" {
6262
#ifndef I2C_VALID_TIMING_NBR
6363
#define I2C_VALID_TIMING_NBR 8U
6464
#endif
65-
#define I2C_SPEED_FREQ_STANDARD 0U /* 100 kHz */
66-
#define I2C_SPEED_FREQ_FAST 1U /* 400 kHz */
67-
#define I2C_SPEED_FREQ_FAST_PLUS 2U /* 1 MHz */
6865
#define I2C_ANALOG_FILTER_DELAY_MIN 50U /* ns */
6966
#ifndef I2C_ANALOG_FILTER_DELAY_MAX
7067
#define I2C_ANALOG_FILTER_DELAY_MAX 260U /* ns */
@@ -82,6 +79,22 @@ extern "C" {
8279
#define I2C_SCLL_MAX 256U
8380
#define SEC2NSEC 1000000000UL
8481

82+
typedef enum {
83+
I2C_SPEED_FREQ_STANDARD, /* 100 kHz */
84+
I2C_SPEED_FREQ_FAST, /* 400 kHz */
85+
I2C_SPEED_FREQ_FAST_PLUS, /* 1 MHz */
86+
I2C_SPEED_FREQ_NUMBER /* Must be the last entry */
87+
} i2c_speed_freq_t;
88+
89+
#ifdef I2C_TIMING
90+
typedef struct {
91+
uint32_t input_clock; /* I2C Input clock */
92+
uint32_t timing; /* I2C timing corresponding to Input clock */
93+
} I2C_timing_t;
94+
95+
static I2C_timing_t I2C_ClockTiming[I2C_SPEED_FREQ_NUMBER] = {0};
96+
#endif
97+
8598
typedef struct {
8699
uint32_t freq; /* Frequency in Hz */
87100
uint32_t freq_min; /* Minimum frequency in Hz */
@@ -354,6 +367,16 @@ static uint32_t i2c_computeTiming(uint32_t clkSrcFreq, uint32_t i2c_speed)
354367
uint8_t presc, scldel, sdadel;
355368
uint32_t tafdel_min, tafdel_max;
356369

370+
if (i2c_speed > I2C_SPEED_FREQ_NUMBER) {
371+
return ret;
372+
}
373+
// Don't compute timing if already available value for the requested spped with the same I2C input frequency
374+
if ((I2C_ClockTiming[i2c_speed].input_clock == clkSrcFreq) &&(I2C_ClockTiming[i2c_speed].timing != 0U)) {
375+
return I2C_ClockTiming[i2c_speed].timing;
376+
}
377+
378+
I2C_ClockTiming[i2c_speed].input_clock = clkSrcFreq; // Save the I2C input clock for which we will save timing
379+
357380
ti2cclk = (SEC2NSEC + (clkSrcFreq / 2U)) / clkSrcFreq;
358381
ti2cspeed = (SEC2NSEC + (I2C_Charac[i2c_speed].freq / 2U)) / I2C_Charac[i2c_speed].freq;
359382

@@ -437,6 +460,7 @@ static uint32_t i2c_computeTiming(uint32_t clkSrcFreq, uint32_t i2c_speed)
437460
((sclh & 0xFFU) << 8) | \
438461
((scll & 0xFFU) << 0);
439462
prev_presc = presc;
463+
I2C_ClockTiming[i2c_speed].timing = ret; // Save I2C Timing found for further reuse (and avoid to compute again)
440464
}
441465
}
442466
}
@@ -716,6 +740,7 @@ i2c_status_e i2c_master_write(i2c_t *obj, uint8_t dev_address,
716740
return i2c_IsDeviceReady(obj, dev_address, 1);
717741
}
718742

743+
// LL_GPIO_SetOutputPin(GPIOA, LL_GPIO_PIN_5);
719744
do {
720745
if (HAL_I2C_Master_Transmit_IT(&(obj->handle), dev_address, data, size) == HAL_OK) {
721746
ret = I2C_OK;
@@ -736,7 +761,7 @@ i2c_status_e i2c_master_write(i2c_t *obj, uint8_t dev_address,
736761
Master restarts communication */
737762
} while (((HAL_I2C_GetError(&(obj->handle)) & HAL_I2C_ERROR_AF) == HAL_I2C_ERROR_AF)
738763
&& (delta < I2C_TIMEOUT_TICK));
739-
764+
// LL_GPIO_ResetOutputPin(GPIOA, LL_GPIO_PIN_5);
740765
return ret;
741766
}
742767

0 commit comments

Comments
 (0)