Blackbox device type 'file' (SITL) considered working when file handler is available
[inav.git] / src / main / drivers / bus_i2c_hal.c
blob3b1459ab1fb1a9cf37343c9ff0fb09081de20d93
1 /*
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/>.
18 #include <stdbool.h>
19 #include <stdint.h>
21 #include <platform.h>
23 #include "drivers/io.h"
24 #include "drivers/time.h"
26 #include "drivers/bus_i2c.h"
27 #include "drivers/nvic.h"
28 #include "io_impl.h"
29 #include "rcc.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)
39 #else
40 #define IOCFG_I2C IOCFG_AF_OD
41 #endif
43 #ifndef I2C1_SCL
44 #define I2C1_SCL PB6
45 #endif
47 #ifndef I2C1_SDA
48 #define I2C1_SDA PB7
49 #endif
51 #ifndef I2C2_SCL
52 #define I2C2_SCL PB10
53 #endif
54 #ifndef I2C2_SDA
55 #define I2C2_SDA PB11
56 #endif
58 #ifndef I2C3_SCL
59 #define I2C3_SCL PA8
60 #endif
61 #ifndef I2C3_SDA
62 #define I2C3_SDA PB4
63 #endif
65 #if defined(USE_I2C_DEVICE_4)
66 #ifndef I2C4_SCL
67 #define I2C4_SCL PD12
68 #endif
69 #ifndef I2C4_SDA
70 #define I2C4_SDA PD13
71 #endif
72 #endif
74 static i2cDevice_t i2cHardwareMap[I2CDEV_COUNT] = {
76 #if defined(STM32F7)
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 }
82 #endif
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 }
89 #endif
90 #endif
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
98 // tick equals 1ms.
99 #define I2C_DEFAULT_TIMEOUT (I2C_TIMEOUT / 1000)
101 typedef struct {
102 bool initialised;
103 I2C_HandleTypeDef handle;
104 } i2cState_t;
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);
155 #endif
158 static bool i2cHandleHardwareFailure(I2CDevice device)
160 i2cErrorCount++;
161 i2cInit(device);
162 return false;
165 bool i2cWriteBuffer(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len_, const uint8_t *data, bool allowRawAccess)
167 if (device == I2CINVALID)
168 return false;
170 i2cState_t * state = &(i2cState[device]);
172 if (!state->initialised)
173 return false;
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);
180 else {
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);
187 return true;
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)
198 return false;
200 i2cState_t * state = &(i2cState[device]);
202 if (!state->initialised)
203 return false;
205 HAL_StatusTypeDef status;
207 if (reg_ == 0xFF && allowRawAccess) {
208 status = HAL_I2C_Master_Receive(&state->handle, addr_ << 1,buf, len, I2C_DEFAULT_TIMEOUT);
210 else {
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);
217 return true;
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)
243 trmax = 120;
244 tfmax = 120;
245 tsuDATmin = 50;
246 thdDATmin = 0;
247 } else {
248 // Fm (Fast mode)
249 trmax = 300;
250 tfmax = 300;
251 tsuDATmin = 100;
252 thdDATmin = 0;
255 tAFmin = 50;
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;
277 *scldel = SCLDELmin;
278 *sdadel = SDADELmin;
279 *sclh = SCLH - 1;
280 *scll = SCLL - 1;
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))
288 uint8_t scldel;
289 uint8_t sdadel;
290 uint16_t sclh;
291 uint16_t scll;
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)
313 return;
316 if (state->initialised)
317 return;
320 // Enable RCC
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);
331 // Init pins
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:
341 default:
342 pHandle->Init.Timing = 0x00A01B5B; // 400kHz, Rise 100ns, Fall 10ns 0x00500B6A
343 break;
345 case I2C_SPEED_800KHZ:
346 pHandle->Init.Timing = 0x00401B1B; // 800khz, Rise 40, Fall 4
347 break;
349 case I2C_SPEED_100KHZ:
350 pHandle->Init.Timing = 0x60100544; // 100kHz, Rise 100ns, Fall 10ns
351 break;
353 case I2C_SPEED_200KHZ:
354 pHandle->Init.Timing = 0x00A01EDF; // 200kHz, Rise 100ns, Fall 10ns
355 break;
359 // Compute TIMINGR value based on peripheral clock for this device instance
361 uint32_t i2cPclk;
363 #if defined(STM32F7) || defined(STM32G4)
364 // F7 Clock source configured in startup/system_stm32f7xx.c as:
365 // I2C1234 : PCLK1
366 // G4 Clock source configured in startup/system_stm32g4xx.c as:
367 // I2C1234 : PCLK1
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();
374 #else
375 #error Unknown MCU type
376 #endif
378 switch (hardware->speed) {
379 case I2C_SPEED_400KHZ:
380 default:
381 pHandle->Init.Timing = i2cClockTIMINGR(i2cPclk, 400, 0); // 400kHz, Rise 100ns, Fall 10ns 0x00500B6A
382 break;
384 case I2C_SPEED_800KHZ:
385 pHandle->Init.Timing = i2cClockTIMINGR(i2cPclk, 800, 0); // 800khz, Rise 40, Fall 4
386 break;
388 case I2C_SPEED_100KHZ:
389 pHandle->Init.Timing = i2cClockTIMINGR(i2cPclk, 100, 0); // 100kHz, Rise 100ns, Fall 10ns
390 break;
392 case I2C_SPEED_200KHZ:
393 pHandle->Init.Timing = i2cClockTIMINGR(i2cPclk, 200, 0); // 200kHz, Rise 100ns, Fall 10ns
394 break;
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)
425 int i;
427 IOHi(scl);
428 IOHi(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
437 int timeout = 100;
438 while (!IORead(scl) && timeout) {
439 delayMicroseconds(5);
440 timeout--;
443 // Pull low
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
451 IOLo(scl);
452 delayMicroseconds(5);
453 IOLo(sda);
454 delayMicroseconds(5);
456 IOHi(scl); // Set bus scl high
457 delayMicroseconds(5);
458 IOHi(sda); // Set bus sda high
461 #endif