2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
23 #include "drivers/io.h"
24 #include "drivers/time.h"
26 #include "drivers/bus_i2c.h"
27 #include "drivers/nvic.h"
31 #if !defined(SOFT_I2C) && defined(USE_I2C)
33 #define CLOCKSPEED 800000 // i2c clockspeed 400kHz default (conform specs), 800kHz and 1200kHz (Betaflight default)
35 static void i2cUnstick(IO_t scl
, IO_t sda
);
37 #if defined(USE_I2C_PULLUP)
38 #define IOCFG_I2C IO_CONFIG(GPIO_MODE_AF_OD, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP)
40 #define IOCFG_I2C IOCFG_AF_OD
65 #if defined(USE_I2C_DEVICE_4)
74 static i2cDevice_t i2cHardwareMap
[I2CDEV_COUNT
] = {
77 { .dev
= I2C1
, .scl
= IO_TAG(I2C1_SCL
), .sda
= IO_TAG(I2C1_SDA
), .rcc
= RCC_APB1(I2C1
), .speed
= I2C_SPEED_400KHZ
, .ev_irq
= I2C1_EV_IRQn
, .er_irq
= I2C1_ER_IRQn
, .af
= GPIO_AF4_I2C1
},
78 { .dev
= I2C2
, .scl
= IO_TAG(I2C2_SCL
), .sda
= IO_TAG(I2C2_SDA
), .rcc
= RCC_APB1(I2C2
), .speed
= I2C_SPEED_400KHZ
, .ev_irq
= I2C2_EV_IRQn
, .er_irq
= I2C2_ER_IRQn
, .af
= GPIO_AF4_I2C2
},
79 { .dev
= I2C3
, .scl
= IO_TAG(I2C3_SCL
), .sda
= IO_TAG(I2C3_SDA
), .rcc
= RCC_APB1(I2C3
), .speed
= I2C_SPEED_400KHZ
, .ev_irq
= I2C3_EV_IRQn
, .er_irq
= I2C3_ER_IRQn
, .af
= GPIO_AF4_I2C3
},
80 #if defined(USE_I2C_DEVICE_4)
81 { .dev
= I2C4
, .scl
= IO_TAG(I2C4_SCL
), .sda
= IO_TAG(I2C4_SDA
), .rcc
= RCC_APB1(I2C4
), .speed
= I2C_SPEED_400KHZ
, .ev_irq
= I2C4_EV_IRQn
, .er_irq
= I2C4_ER_IRQn
, .af
= GPIO_AF4_I2C4
}
83 #elif defined(STM32H7)
84 { .dev
= I2C1
, .scl
= IO_TAG(I2C1_SCL
), .sda
= IO_TAG(I2C1_SDA
), .rcc
= RCC_APB1L(I2C1
), .speed
= I2C_SPEED_400KHZ
, .ev_irq
= I2C1_EV_IRQn
, .er_irq
= I2C1_ER_IRQn
, .af
= GPIO_AF4_I2C1
},
85 { .dev
= I2C2
, .scl
= IO_TAG(I2C2_SCL
), .sda
= IO_TAG(I2C2_SDA
), .rcc
= RCC_APB1L(I2C2
), .speed
= I2C_SPEED_400KHZ
, .ev_irq
= I2C2_EV_IRQn
, .er_irq
= I2C2_ER_IRQn
, .af
= GPIO_AF4_I2C2
},
86 { .dev
= I2C3
, .scl
= IO_TAG(I2C3_SCL
), .sda
= IO_TAG(I2C3_SDA
), .rcc
= RCC_APB1L(I2C3
), .speed
= I2C_SPEED_400KHZ
, .ev_irq
= I2C3_EV_IRQn
, .er_irq
= I2C3_ER_IRQn
, .af
= GPIO_AF4_I2C3
},
87 #if defined(USE_I2C_DEVICE_4)
88 { .dev
= I2C4
, .scl
= IO_TAG(I2C4_SCL
), .sda
= IO_TAG(I2C4_SDA
), .rcc
= RCC_APB4(I2C4
), .speed
= I2C_SPEED_400KHZ
, .ev_irq
= I2C4_EV_IRQn
, .er_irq
= I2C4_ER_IRQn
, .af
= GPIO_AF4_I2C4
}
93 static volatile uint16_t i2cErrorCount
= 0;
95 // Note that I2C_TIMEOUT is in us, while the HAL
96 // functions expect the timeout to be in ticks.
97 // Since we're setting up the ticks a 1khz, each
99 #define I2C_DEFAULT_TIMEOUT (I2C_TIMEOUT / 1000)
103 I2C_HandleTypeDef handle
;
106 static i2cState_t i2cState
[I2CDEV_COUNT
];
108 void i2cSetSpeed(uint8_t speed
)
110 for (unsigned int i
= 0; i
< ARRAYLEN(i2cHardwareMap
); i
++) {
111 i2cHardwareMap
[i
].speed
= speed
;
115 void I2C1_ER_IRQHandler(void)
117 HAL_I2C_ER_IRQHandler(&i2cState
[I2CDEV_1
].handle
);
120 void I2C1_EV_IRQHandler(void)
122 HAL_I2C_EV_IRQHandler(&i2cState
[I2CDEV_1
].handle
);
125 void I2C2_ER_IRQHandler(void)
127 HAL_I2C_ER_IRQHandler(&i2cState
[I2CDEV_2
].handle
);
130 void I2C2_EV_IRQHandler(void)
132 HAL_I2C_EV_IRQHandler(&i2cState
[I2CDEV_2
].handle
);
135 void I2C3_ER_IRQHandler(void)
137 HAL_I2C_ER_IRQHandler(&i2cState
[I2CDEV_3
].handle
);
140 void I2C3_EV_IRQHandler(void)
142 HAL_I2C_EV_IRQHandler(&i2cState
[I2CDEV_3
].handle
);
145 #ifdef USE_I2C_DEVICE_4
146 void I2C4_ER_IRQHandler(void)
148 HAL_I2C_ER_IRQHandler(&i2cState
[I2CDEV_4
].handle
);
151 void I2C4_EV_IRQHandler(void)
153 HAL_I2C_EV_IRQHandler(&i2cState
[I2CDEV_4
].handle
);
158 static bool i2cHandleHardwareFailure(I2CDevice device
)
165 bool i2cWriteBuffer(I2CDevice device
, uint8_t addr_
, uint8_t reg_
, uint8_t len_
, const uint8_t *data
, bool allowRawAccess
)
167 if (device
== I2CINVALID
)
170 i2cState_t
* state
= &(i2cState
[device
]);
172 if (!state
->initialised
)
175 HAL_StatusTypeDef status
;
177 if ((reg_
== 0xFF || len_
== 0) && allowRawAccess
) {
178 status
= HAL_I2C_Master_Transmit(&state
->handle
, addr_
<< 1, (uint8_t *)data
, len_
, I2C_DEFAULT_TIMEOUT
);
181 status
= HAL_I2C_Mem_Write(&state
->handle
, addr_
<< 1, reg_
, I2C_MEMADD_SIZE_8BIT
, (uint8_t *)data
, len_
, I2C_DEFAULT_TIMEOUT
);
184 if (status
!= HAL_OK
)
185 return i2cHandleHardwareFailure(device
);
190 bool i2cWrite(I2CDevice device
, uint8_t addr_
, uint8_t reg_
, uint8_t data
, bool allowRawAccess
)
192 return i2cWriteBuffer(device
, addr_
, reg_
, 1, &data
, allowRawAccess
);
195 bool i2cRead(I2CDevice device
, uint8_t addr_
, uint8_t reg_
, uint8_t len
, uint8_t* buf
, bool allowRawAccess
)
197 if (device
== I2CINVALID
)
200 i2cState_t
* state
= &(i2cState
[device
]);
202 if (!state
->initialised
)
205 HAL_StatusTypeDef status
;
207 if (reg_
== 0xFF && allowRawAccess
) {
208 status
= HAL_I2C_Master_Receive(&state
->handle
, addr_
<< 1,buf
, len
, I2C_DEFAULT_TIMEOUT
);
211 status
= HAL_I2C_Mem_Read(&state
->handle
, addr_
<< 1, reg_
, I2C_MEMADD_SIZE_8BIT
,buf
, len
, I2C_DEFAULT_TIMEOUT
);
214 if (status
!= HAL_OK
)
215 return i2cHandleHardwareFailure(device
);
221 * Compute SCLDEL, SDADEL, SCLH and SCLL for TIMINGR register according to reference manuals.
223 static void i2cClockComputeRaw(uint32_t pclkFreq
, int i2cFreqKhz
, int presc
, int dfcoeff
,
224 uint8_t *scldel
, uint8_t *sdadel
, uint16_t *sclh
, uint16_t *scll
)
226 // Values from I2C-SMBus specification
227 uint16_t trmax
; // Raise time (max)
228 uint16_t tfmax
; // Fall time (max)
229 uint8_t tsuDATmin
; // SDA setup time (min)
230 uint8_t thdDATmin
; // SDA hold time (min)
232 // Silicon specific values, from datasheet
233 uint8_t tAFmin
; // Analog filter delay (min)
234 //uint8_t tAFmax; // Analog filter delay (max)
236 // Actual (estimated) values
237 uint16_t tr
= 100; // Raise time
238 uint16_t tf
= 100; // Fall time
239 uint8_t tAF
= 70; // Analog filter delay
241 if (i2cFreqKhz
> 400) {
242 // Fm+ (Fast mode plus)
256 //tAFmax = 90; // Unused
258 // Convert pclkFreq into nsec
259 float tI2cclk
= 1000000000.0f
/ pclkFreq
;
261 // Convert target i2cFreq into cycle time (nsec)
262 float tSCL
= 1000000.0f
/ i2cFreqKhz
;
264 uint32_t SCLDELmin
= (trmax
+ tsuDATmin
)/((presc
+ 1) * tI2cclk
) - 1;
266 uint32_t SDADELmin
= (tfmax
+ thdDATmin
- tAFmin
- ((dfcoeff
+ 3) * tI2cclk
)) / ((presc
+ 1) * tI2cclk
);
268 float tsync1
= tf
+ tAF
+ dfcoeff
* tI2cclk
+ 3 * tI2cclk
;
269 float tsync2
= tr
+ tAF
+ dfcoeff
* tI2cclk
+ 3 * tI2cclk
;
271 float tSCLHL
= tSCL
- tsync1
- tsync2
;
272 float SCLHL
= tSCLHL
/ ((presc
+ 1) * tI2cclk
) - 1;
274 uint32_t SCLH
= SCLHL
/ 4.75; // STM32CubeMX seems to use a value like this
275 uint32_t SCLL
= (uint32_t)(SCLHL
+ 0.5f
) - SCLH
;
283 static uint32_t i2cClockTIMINGR(uint32_t pclkFreq
, int i2cFreqKhz
, int dfcoeff
)
285 #define TIMINGR(presc, scldel, sdadel, sclh, scll) \
286 ((presc << 28)|(scldel << 20)|(sdadel << 16)|(sclh << 8)|(scll << 0))
293 for (int presc
= 1; presc
< 15; presc
++) {
294 i2cClockComputeRaw(pclkFreq
, i2cFreqKhz
, presc
, dfcoeff
, &scldel
, &sdadel
, &sclh
, &scll
);
296 // If all fields are not overflowing, return TIMINGR.
297 // Otherwise, increase prescaler and try again.
298 if ((scldel
< 16) && (sdadel
< 16) && (sclh
< 256) && (scll
< 256)) {
299 return TIMINGR(presc
, scldel
, sdadel
, sclh
, scll
);
302 return 0; // Shouldn't reach here
305 void i2cInit(I2CDevice device
)
307 i2cDevice_t
* hardware
= &(i2cHardwareMap
[device
]);
308 i2cState_t
* state
= &(i2cState
[device
]);
309 I2C_HandleTypeDef
* pHandle
= &state
->handle
;
312 if (hardware
->dev
== NULL
)
316 if (state->initialised)
321 RCC_ClockCmd(hardware
->rcc
, ENABLE
);
323 IO_t scl
= IOGetByTag(hardware
->scl
);
324 IO_t sda
= IOGetByTag(hardware
->sda
);
326 IOInit(scl
, OWNER_I2C
, RESOURCE_I2C_SCL
, RESOURCE_INDEX(device
));
327 IOInit(sda
, OWNER_I2C
, RESOURCE_I2C_SDA
, RESOURCE_INDEX(device
));
329 i2cUnstick(scl
, sda
);
332 IOConfigGPIOAF(scl
, IOCFG_I2C
, hardware
->af
);
333 IOConfigGPIOAF(sda
, IOCFG_I2C
, hardware
->af
);
335 // Init I2C peripheral
336 pHandle
->Instance
= hardware
->dev
;
339 switch (i2c->speed) {
340 case I2C_SPEED_400KHZ:
342 pHandle->Init.Timing = 0x00A01B5B; // 400kHz, Rise 100ns, Fall 10ns 0x00500B6A
345 case I2C_SPEED_800KHZ:
346 pHandle->Init.Timing = 0x00401B1B; // 800khz, Rise 40, Fall 4
349 case I2C_SPEED_100KHZ:
350 pHandle->Init.Timing = 0x60100544; // 100kHz, Rise 100ns, Fall 10ns
353 case I2C_SPEED_200KHZ:
354 pHandle->Init.Timing = 0x00A01EDF; // 200kHz, Rise 100ns, Fall 10ns
359 // Compute TIMINGR value based on peripheral clock for this device instance
363 #if defined(STM32F7) || defined(STM32G4)
364 // F7 Clock source configured in startup/system_stm32f7xx.c as:
366 // G4 Clock source configured in startup/system_stm32g4xx.c as:
368 i2cPclk
= HAL_RCC_GetPCLK1Freq();
369 #elif defined(STM32H7)
370 // Clock sources configured in startup/system_stm32h7xx.c as:
371 // I2C123 : D2PCLK1 (rcc_pclk1 for APB1)
372 // I2C4 : D3PCLK1 (rcc_pclk4 for APB4)
373 i2cPclk
= (hardware
->dev
== I2C4
) ? HAL_RCCEx_GetD3PCLK1Freq() : HAL_RCC_GetPCLK1Freq();
375 #error Unknown MCU type
378 switch (hardware
->speed
) {
379 case I2C_SPEED_400KHZ
:
381 pHandle
->Init
.Timing
= i2cClockTIMINGR(i2cPclk
, 400, 0); // 400kHz, Rise 100ns, Fall 10ns 0x00500B6A
384 case I2C_SPEED_800KHZ
:
385 pHandle
->Init
.Timing
= i2cClockTIMINGR(i2cPclk
, 800, 0); // 800khz, Rise 40, Fall 4
388 case I2C_SPEED_100KHZ
:
389 pHandle
->Init
.Timing
= i2cClockTIMINGR(i2cPclk
, 100, 0); // 100kHz, Rise 100ns, Fall 10ns
392 case I2C_SPEED_200KHZ
:
393 pHandle
->Init
.Timing
= i2cClockTIMINGR(i2cPclk
, 200, 0); // 200kHz, Rise 100ns, Fall 10ns
397 pHandle
->Init
.OwnAddress1
= 0x0;
398 pHandle
->Init
.AddressingMode
= I2C_ADDRESSINGMODE_7BIT
;
399 pHandle
->Init
.DualAddressMode
= I2C_DUALADDRESS_DISABLE
;
400 pHandle
->Init
.OwnAddress2
= 0x0;
401 pHandle
->Init
.GeneralCallMode
= I2C_GENERALCALL_DISABLE
;
402 pHandle
->Init
.NoStretchMode
= I2C_NOSTRETCH_DISABLE
;
405 HAL_I2C_Init(pHandle
);
406 /* Enable the Analog I2C Filter */
407 HAL_I2CEx_ConfigAnalogFilter(pHandle
, I2C_ANALOGFILTER_ENABLE
);
409 HAL_NVIC_SetPriority(hardware
->er_irq
, NVIC_PRIO_I2C_ER
, 0);
410 HAL_NVIC_EnableIRQ(hardware
->er_irq
);
412 HAL_NVIC_SetPriority(hardware
->ev_irq
, NVIC_PRIO_I2C_EV
, 0);
413 HAL_NVIC_EnableIRQ(hardware
->ev_irq
);
415 state
->initialised
= true;
418 uint16_t i2cGetErrorCounter(void)
420 return i2cErrorCount
;
423 static void i2cUnstick(IO_t scl
, IO_t sda
)
430 IOConfigGPIO(scl
, IOCFG_OUT_OD
);
431 IOConfigGPIO(sda
, IOCFG_OUT_OD
);
433 // Analog Devices AN-686
434 // We need 9 clock pulses + STOP condition
435 for (i
= 0; i
< 9; i
++) {
436 // Wait for any clock stretching to finish
438 while (!IORead(scl
) && timeout
) {
439 delayMicroseconds(5);
444 IOLo(scl
); // Set bus low
445 delayMicroseconds(5);
446 IOHi(scl
); // Set bus high
447 delayMicroseconds(5);
450 // Generate a stop condition in case there was none
452 delayMicroseconds(5);
454 delayMicroseconds(5);
456 IOHi(scl
); // Set bus scl high
457 delayMicroseconds(5);
458 IOHi(sda
); // Set bus sda high