Merge pull request #10558 from iNavFlight/MrD_Correct-comments-on-OSD-symbols
[inav.git] / src / main / drivers / bus_i2c_at32f43x.c
blob98fdd9424689905bcb887fc2ea72c61bda00c840
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>
22 #include "io_impl.h"
23 #include "drivers/io.h"
24 #include "drivers/time.h"
25 #include "rcc.h"
26 #include "drivers/bus_i2c.h"
27 #include "drivers/nvic.h"
28 #include "drivers/i2c_application.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 #define I2Cx_ADDRESS 0x00
36 // Clock period in us during unstick transfer
37 #define UNSTICK_CLK_US 10
38 // Allow 500us for clock strech to complete during unstick
39 #define UNSTICK_CLK_STRETCH (500/UNSTICK_CLK_US)
41 static void i2cUnstick(IO_t scl, IO_t sda);
43 #if defined(USE_I2C_PULLUP)
44 #define IOCFG_I2C IOCFG_AF_OD_UP
45 #else
46 #define IOCFG_I2C IOCFG_AF_OD
47 #endif
49 #ifndef I2C1_SCL
50 #define I2C1_SCL PA9
51 #endif
53 #ifndef I2C1_SDA
54 #define I2C1_SDA PA10
55 #endif
57 #ifndef I2C2_SCL
58 #define I2C2_SCL PD12
59 #endif
60 #ifndef I2C2_SDA
61 #define I2C2_SDA PD13
62 #endif
64 #ifndef I2C3_SCL
65 #define I2C3_SCL PC0
66 #endif
67 #ifndef I2C3_SDA
68 #define I2C3_SDA PC1
69 #endif
71 //Define thi I2C hardware map
72 static i2cDevice_t i2cHardwareMap[I2CDEV_COUNT] = {
73 { .dev = I2C1, .scl = IO_TAG(I2C1_SCL), .sda = IO_TAG(I2C1_SDA), .rcc = RCC_APB1(I2C1), .speed = I2C_SPEED_400KHZ, .ev_irq = I2C1_EVT_IRQn, .er_irq = I2C1_ERR_IRQn, .af = GPIO_MUX_4 },
74 { .dev = I2C2, .scl = IO_TAG(I2C2_SCL), .sda = IO_TAG(I2C2_SDA), .rcc = RCC_APB1(I2C2), .speed = I2C_SPEED_400KHZ, .ev_irq = I2C2_EVT_IRQn, .er_irq = I2C2_ERR_IRQn, .af = GPIO_MUX_4 },
75 { .dev = I2C3, .scl = IO_TAG(I2C3_SCL), .sda = IO_TAG(I2C3_SDA), .rcc = RCC_APB1(I2C3), .speed = I2C_SPEED_400KHZ, .ev_irq = I2C3_EVT_IRQn, .er_irq = I2C3_ERR_IRQn, .af = GPIO_MUX_4 },
78 static volatile uint16_t i2cErrorCount = 0;
80 // Note that I2C_TIMEOUT is in us, while the HAL
81 // functions expect the timeout to be in ticks.
82 // Since we're setting up the ticks a 1khz, each
83 // tick equals 1ms.
84 // AT32F4 i2c TIMEOUT USING loop times
85 #define I2C_DEFAULT_TIMEOUT (I2C_TIMEOUT*288 / 1000 )
86 //#define I2C_DEFAULT_TIMEOUT (0xD80)
88 typedef struct {
89 bool initialised;
90 i2c_handle_type handle;
91 } i2cState_t;
93 static i2cState_t i2cState[I2CDEV_COUNT];
95 void i2cSetSpeed(uint8_t speed)
97 for (unsigned int i = 0; i < ARRAYLEN(i2cHardwareMap); i++) {
98 i2cHardwareMap[i].speed = speed;
102 //I2C1_ERR_IRQHandler
103 void I2C1_ERR_IRQHandler(void)
105 i2c_err_irq_handler(&i2cState[I2CDEV_1].handle);
108 void I2C1_EVT_IRQHandler(void)
110 i2c_evt_irq_handler(&i2cState[I2CDEV_1].handle);
113 void I2C2_ERR_IRQHandler(void)
115 i2c_err_irq_handler(&i2cState[I2CDEV_2].handle);
118 void I2C2_EVT_IRQHandler(void)
120 i2c_evt_irq_handler(&i2cState[I2CDEV_2].handle);
123 void I2C3_ERR_IRQHandler(void)
125 i2c_err_irq_handler(&i2cState[I2CDEV_3].handle);
128 void I2C3_EVT_IRQHandler(void)
130 i2c_evt_irq_handler(&i2cState[I2CDEV_3].handle);
133 static bool i2cHandleHardwareFailure(I2CDevice device)
135 (void)device;
136 i2cErrorCount++;
137 i2cInit(device);
138 return false;
141 bool i2cWriteBuffer(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len_, const uint8_t *data, bool allowRawAccess)
143 if (device == I2CINVALID)
144 return false;
146 i2cState_t * state = &(i2cState[device]);
148 if (!state->initialised)
149 return false;
151 i2c_status_type status;
153 if ((reg_ == 0xFF || len_ == 0) && allowRawAccess) {
154 status = i2c_master_transmit(&state->handle, addr_ << 1, CONST_CAST(uint8_t*, data), len_, I2C_DEFAULT_TIMEOUT);
155 if(status != I2C_OK)
157 /* wait for the stop flag to be set */
158 i2c_wait_flag(&state->handle, I2C_STOPF_FLAG, I2C_EVENT_CHECK_NONE, I2C_DEFAULT_TIMEOUT);
160 /* clear stop flag */
161 i2c_flag_clear(state->handle.i2cx, I2C_STOPF_FLAG);
164 else {
165 status = i2c_memory_write(&state->handle,I2C_MEM_ADDR_WIDIH_8, addr_ << 1, reg_, CONST_CAST(uint8_t*, data), len_, I2C_DEFAULT_TIMEOUT);
166 //status = i2c_memory_write_int(&state->handle,I2C_MEM_ADDR_WIDIH_8, addr_ << 1, reg_, data, len_, I2C_DEFAULT_TIMEOUT);
168 if(status != I2C_OK)
170 /* wait for the stop flag to be set */
171 i2c_wait_flag(&state->handle, I2C_STOPF_FLAG, I2C_EVENT_CHECK_NONE, I2C_DEFAULT_TIMEOUT);
173 /* clear stop flag */
174 i2c_flag_clear(state->handle.i2cx, I2C_STOPF_FLAG);
178 if (status == I2C_ERR_STEP_1) {//BUSY
179 return false;
182 if (status != I2C_OK)
183 return i2cHandleHardwareFailure(device);
185 return true;
188 bool i2cWrite(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t data, bool allowRawAccess)
190 return i2cWriteBuffer(device, addr_, reg_, 1, &data, allowRawAccess);
193 bool i2cRead(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len, uint8_t* buf, bool allowRawAccess)
195 if (device == I2CINVALID)
196 return false;
198 i2cState_t * state = &(i2cState[device]);
200 if (!state->initialised)
201 return false;
203 //HAL_StatusTypeDef status;
204 i2c_status_type status;
205 if (reg_ == 0xFF && allowRawAccess) {
206 status = i2c_master_receive(&state->handle, addr_ << 1,buf, len, I2C_DEFAULT_TIMEOUT);
207 if(status != I2C_OK)
209 /* wait for the stop flag to be set */
210 i2c_wait_flag(&state->handle, I2C_STOPF_FLAG, I2C_EVENT_CHECK_NONE, I2C_DEFAULT_TIMEOUT);
212 /* clear stop flag */
213 i2c_flag_clear(state->handle.i2cx, I2C_STOPF_FLAG);
217 else {
218 status = i2c_memory_read(&state->handle, I2C_MEM_ADDR_WIDIH_8,addr_ << 1, reg_, buf, len, I2C_DEFAULT_TIMEOUT);
220 if(status != I2C_OK)
222 /* wait for the stop flag to be set */
223 i2c_wait_flag(&state->handle, I2C_STOPF_FLAG, I2C_EVENT_CHECK_NONE, I2C_DEFAULT_TIMEOUT);
225 /* clear stop flag */
226 i2c_flag_clear(state->handle.i2cx, I2C_STOPF_FLAG);
231 if (status != I2C_OK)
232 return i2cHandleHardwareFailure(device);
234 return true;
238 * Compute SCLDEL, SDADEL, SCLH and SCLL for TIMINGR register according to reference manuals.
240 static void i2cClockComputeRaw(uint32_t pclkFreq, int i2cFreqKhz, int presc, int dfcoeff,
241 uint8_t *scldel, uint8_t *sdadel, uint16_t *sclh, uint16_t *scll)
243 // Values from I2C-SMBus specification
244 uint16_t trmax; // Rise time (max)
245 uint16_t tfmax; // Fall time (max)
246 uint8_t tsuDATmin; // SDA setup time (min)
247 uint8_t thdDATmin; // SDA hold time (min)
248 uint16_t tHIGHmin; // High period of SCL clock (min)
249 uint16_t tLOWmin; // Low period of SCL clock (min)
251 // Silicon specific values, from datasheet
252 uint8_t tAFmin = 50; // Analog filter delay (min)
254 // Actual (estimated) values
255 uint8_t tr = 100; // Rise time
256 uint8_t tf = 10; // Fall time
258 if (i2cFreqKhz > 400) {
259 // Fm+ (Fast mode plus)
260 trmax = 120;
261 tfmax = 120;
262 tsuDATmin = 50;
263 thdDATmin = 0;
264 tHIGHmin = 260;
265 tLOWmin = 500;
266 } else {
267 // Fm (Fast mode)
268 trmax = 300;
269 tfmax = 300;
270 tsuDATmin = 100;
271 thdDATmin = 0;
272 tHIGHmin = 600;
273 tLOWmin = 1300;
276 // Convert pclkFreq into nsec
277 float tI2cclk = 1000000000.0f / pclkFreq;
279 // Convert target i2cFreq into cycle time (nsec)
280 float tSCL = 1000000.0f / i2cFreqKhz;
282 uint32_t SCLDELmin = (trmax + tsuDATmin) / ((presc + 1) * tI2cclk) - 1;
283 uint32_t SDADELmin = (tfmax + thdDATmin - tAFmin - ((dfcoeff + 3) * tI2cclk)) / ((presc + 1) * tI2cclk);
285 float tsync1 = tf + tAFmin + dfcoeff * tI2cclk + 2 * tI2cclk;
286 float tsync2 = tr + tAFmin + dfcoeff * tI2cclk + 2 * tI2cclk;
288 float tSCLH = tHIGHmin * tSCL / (tHIGHmin + tLOWmin) - tsync2;
289 float tSCLL = tSCL - tSCLH - tsync1 - tsync2;
291 uint32_t SCLH = tSCLH / ((presc + 1) * tI2cclk) - 1;
292 uint32_t SCLL = tSCLL / ((presc + 1) * tI2cclk) - 1;
294 while (tsync1 + tsync2 + ((SCLH + 1) + (SCLL + 1)) * ((presc + 1) * tI2cclk) < tSCL) {
295 SCLH++;
298 *scldel = SCLDELmin;
299 *sdadel = SDADELmin;
300 *sclh = SCLH;
301 *scll = SCLL;
304 static uint32_t i2cClockTIMINGR(uint32_t pclkFreq, int i2cFreqKhz, int dfcoeff)
306 #define TIMINGR(presc, scldel, sdadel, sclh, scll) \
307 ((presc << 28)|(scldel << 20)|(sdadel << 16)|(sclh << 8)|(scll << 0))
309 uint8_t scldel;
310 uint8_t sdadel;
311 uint16_t sclh;
312 uint16_t scll;
314 for (int presc = 1; presc < 15; presc++) {
315 i2cClockComputeRaw(pclkFreq, i2cFreqKhz, presc, dfcoeff, &scldel, &sdadel, &sclh, &scll);
317 // If all fields are not overflowing, return TIMINGR.
318 // Otherwise, increase prescaler and try again.
319 if ((scldel < 16) && (sdadel < 16) && (sclh < 256) && (scll < 256)) {
320 return TIMINGR(presc, scldel, sdadel, sclh, scll);
323 return 0; // Shouldn't reach here
326 void i2cInit(I2CDevice device)
328 i2cDevice_t * hardware = &(i2cHardwareMap[device]);
329 i2cState_t * state = &(i2cState[device]);
331 //I2C_HandleTypeDef * pHandle = &state->handle;
332 i2c_handle_type * pHandle = &state->handle;
334 if (hardware->dev == NULL)
335 return;
337 IO_t scl = IOGetByTag(hardware->scl);
338 IO_t sda = IOGetByTag(hardware->sda);
340 IOInit(scl, OWNER_I2C, RESOURCE_I2C_SCL, RESOURCE_INDEX(device));
341 IOInit(sda, OWNER_I2C, RESOURCE_I2C_SDA, RESOURCE_INDEX(device));
342 // Enable RCC
343 RCC_ClockCmd(hardware->rcc, ENABLE);
345 i2cUnstick(scl, sda);
347 // Init pins
348 IOConfigGPIOAF(scl, IOCFG_I2C, hardware->af);
349 IOConfigGPIOAF(sda, IOCFG_I2C, hardware->af);
351 // Init I2C peripheral
352 pHandle->i2cx = hardware->dev;
353 i2c_reset(pHandle->i2cx);
354 // Compute TIMINGR value based on peripheral clock for this device instance
355 uint32_t i2cPclk;
357 #if defined(AT32F43x)
358 crm_clocks_freq_type clocks_struct;
359 crm_clocks_freq_get(&clocks_struct);
360 i2cPclk = clocks_struct.apb1_freq;
362 #else
363 #error Unknown MCU type
364 #endif
367 // switch (hardware->speed) {
368 // case I2C_SPEED_400KHZ:
369 // default:
370 // i2c_init(pHandle->i2cx, 15, 0x10F03863); // 400kHz, Rise 100ns, Fall 10ns 0x10C03863
371 // break;
373 // case I2C_SPEED_800KHZ:
374 // i2c_init(pHandle->i2cx, 15, 0x00E03259); // 800khz, Rise 40, Fall 4
375 // break;
377 // case I2C_SPEED_100KHZ:
378 // i2c_init(pHandle->i2cx, 15, 0x30E0AEAE); // 100kHz, Rise 100ns, Fall 10ns 0x30607EE0 0x30607DDE
379 // break;
381 // case I2C_SPEED_200KHZ:
382 // i2c_init(pHandle->i2cx, 15, 0x10F078D6); // 200kHz, Rise 100ns, Fall 10ns 0x10C078D6
383 // break;
384 // }
387 switch (hardware->speed) {
388 case I2C_SPEED_400KHZ:
389 default:
390 i2c_init(pHandle->i2cx, 0x0f, i2cClockTIMINGR(i2cPclk, 400, 0));
391 break;
393 case I2C_SPEED_800KHZ:
394 i2c_init(pHandle->i2cx, 0x0f, i2cClockTIMINGR(i2cPclk, 800, 0));
395 break;
397 case I2C_SPEED_100KHZ:
398 i2c_init(pHandle->i2cx, 0x0f, i2cClockTIMINGR(i2cPclk, 100, 0));
399 break;
401 case I2C_SPEED_200KHZ:
402 i2c_init(pHandle->i2cx, 0x0f, i2cClockTIMINGR(i2cPclk, 200, 0));
403 break;
406 i2c_own_address1_set(pHandle->i2cx, I2C_ADDRESS_MODE_7BIT, 0x0);
407 //i2c_own_address2_enable(pHandle->i2cx, false); // enable or disable own address 2
408 //i2c_own_address2_set(pHandle->i2cx, I2C_ADDRESS_MODE_7BIT, 0x0);
409 //i2c_general_call_enable(pHandle->i2cx, false); // enable or disable general call mode
410 //i2c_clock_stretch_enable(pHandle->i2cx, true); // enable or disable clock stretch
412 nvic_irq_enable(hardware->er_irq,NVIC_PRIO_I2C_ER, 0);
413 nvic_irq_enable(hardware->ev_irq, NVIC_PRIO_I2C_EV,0);
415 i2c_enable(pHandle->i2cx, TRUE);
417 state->initialised = true;
420 uint16_t i2cGetErrorCounter(void)
422 return i2cErrorCount;
425 static void i2cUnstick(IO_t scl, IO_t sda)
427 int i;
429 IOHi(scl);
430 IOHi(sda);
432 IOConfigGPIO(scl, IOCFG_OUT_OD);
433 IOConfigGPIO(sda, IOCFG_OUT_OD);
435 // Analog Devices AN-686
436 // We need 9 clock pulses + STOP condition
437 for (i = 0; i < 9; i++) {
438 // Wait for any clock stretching to finish
439 int timeout = UNSTICK_CLK_STRETCH;
440 while (!IORead(scl) && timeout) {
441 delayMicroseconds(UNSTICK_CLK_US);
442 timeout--;
445 // Pull low
446 IOLo(scl); // Set bus low
447 delayMicroseconds(UNSTICK_CLK_US/2);
448 IOHi(scl); // Set bus high
449 delayMicroseconds(UNSTICK_CLK_US/2);
452 // Generate a stop condition in case there was none
453 IOLo(scl);
454 delayMicroseconds(UNSTICK_CLK_US/2);
455 IOLo(sda);
456 delayMicroseconds(UNSTICK_CLK_US/2);
458 IOHi(scl); // Set bus scl high
459 delayMicroseconds(UNSTICK_CLK_US/2);
460 IOHi(sda); // Set bus sda high
463 bool i2cBusy(I2CDevice device, bool *error)
465 if (device == I2CINVALID)
466 return true;
468 i2cState_t * state = &(i2cState[device]);
470 if (error) {
471 *error = state->handle.error_code==I2C_OK?false:true;
474 if(state->handle.error_code ==I2C_OK){
476 if (i2c_flag_get(state->handle.i2cx, I2C_BUSYF_FLAG) == SET)
478 return true;
480 return false;
483 return true;
486 #endif