Merge pull request #11198 from SteveCEvans/sce_rc2
[betaflight.git] / src / main / drivers / bus_i2c_stm32f10x.c
blob743e88c53931bf904369e79f0a7e79a1e0fcffc0
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
21 #include <stdbool.h>
22 #include <stdint.h>
23 #include <stdlib.h>
24 #include <string.h>
26 #include "platform.h"
28 #if defined(USE_I2C) && !defined(SOFT_I2C)
30 #include "drivers/io.h"
31 #include "drivers/time.h"
32 #include "drivers/nvic.h"
33 #include "drivers/rcc.h"
35 #include "drivers/bus_i2c.h"
36 #include "drivers/bus_i2c_impl.h"
38 // Number of bits in I2C protocol phase
39 #define LEN_ADDR 7
40 #define LEN_RW 1
41 #define LEN_ACK 1
43 // Clock period in us during unstick transfer
44 #define UNSTICK_CLK_US 10
46 // Allow 500us for clock strech to complete during unstick
47 #define UNSTICK_CLK_STRETCH (500/UNSTICK_CLK_US)
49 static void i2c_er_handler(I2CDevice device);
50 static void i2c_ev_handler(I2CDevice device);
51 static void i2cUnstick(IO_t scl, IO_t sda);
53 #ifdef STM32F4
54 #define IOCFG_I2C_PU IO_CONFIG(GPIO_Mode_AF, 0, GPIO_OType_OD, GPIO_PuPd_UP)
55 #define IOCFG_I2C IO_CONFIG(GPIO_Mode_AF, 0, GPIO_OType_OD, GPIO_PuPd_NOPULL)
56 #else // STM32F4
57 #define IOCFG_I2C IO_CONFIG(GPIO_Mode_AF_OD, GPIO_Speed_50MHz)
58 #endif
60 const i2cHardware_t i2cHardware[I2CDEV_COUNT] = {
61 #ifdef USE_I2C_DEVICE_1
63 .device = I2CDEV_1,
64 .reg = I2C1,
65 .sclPins = {
66 I2CPINDEF(PB6, GPIO_AF_I2C1),
67 I2CPINDEF(PB8, GPIO_AF_I2C1),
69 .sdaPins = {
70 I2CPINDEF(PB7, GPIO_AF_I2C1),
71 I2CPINDEF(PB9, GPIO_AF_I2C1),
73 .rcc = RCC_APB1(I2C1),
74 .ev_irq = I2C1_EV_IRQn,
75 .er_irq = I2C1_ER_IRQn,
77 #endif
78 #ifdef USE_I2C_DEVICE_2
80 .device = I2CDEV_2,
81 .reg = I2C2,
82 .sclPins = {
83 I2CPINDEF(PB10, GPIO_AF_I2C2),
84 I2CPINDEF(PF1, GPIO_AF_I2C2),
86 .sdaPins = {
87 #if defined(STM32F446xx)
88 I2CPINDEF(PC12, GPIO_AF_I2C2),
89 #else
90 I2CPINDEF(PB11, GPIO_AF_I2C2),
91 #endif
92 I2CPINDEF(PF0, GPIO_AF_I2C2),
94 #if defined(STM32F40_41xxx) || defined (STM32F411xE)
95 // STM32F401xx/STM32F410xx/STM32F411xE/STM32F412xG
96 I2CPINDEF(PB3, GPIO_AF9_I2C2),
97 I2CPINDEF(PB9, GPIO_AF9_I2C2),
98 #endif
100 .rcc = RCC_APB1(I2C2),
101 .ev_irq = I2C2_EV_IRQn,
102 .er_irq = I2C2_ER_IRQn,
104 #endif
105 #ifdef USE_I2C_DEVICE_3
107 .device = I2CDEV_3,
108 .reg = I2C3,
109 .sclPins = {
110 I2CPINDEF(PA8, GPIO_AF_I2C3),
112 .sdaPins = {
113 I2CPINDEF(PC9, GPIO_AF_I2C3),
115 #if defined(STM32F40_41xxx) || defined (STM32F411xE)
116 // STM32F401xx/STM32F410xx/STM32F411xE/STM32F412xG
117 I2CPINDEF(PB4, GPIO_AF9_I2C3),
118 I2CPINDEF(PB8, GPIO_AF9_I2C3),
119 #endif
121 .rcc = RCC_APB1(I2C3),
122 .ev_irq = I2C3_EV_IRQn,
123 .er_irq = I2C3_ER_IRQn,
125 #endif
128 i2cDevice_t i2cDevice[I2CDEV_COUNT];
130 static volatile uint16_t i2cErrorCount = 0;
132 void I2C1_ER_IRQHandler(void) {
133 i2c_er_handler(I2CDEV_1);
136 void I2C1_EV_IRQHandler(void) {
137 i2c_ev_handler(I2CDEV_1);
140 void I2C2_ER_IRQHandler(void) {
141 i2c_er_handler(I2CDEV_2);
144 void I2C2_EV_IRQHandler(void) {
145 i2c_ev_handler(I2CDEV_2);
148 #ifdef STM32F4
149 void I2C3_ER_IRQHandler(void) {
150 i2c_er_handler(I2CDEV_3);
153 void I2C3_EV_IRQHandler(void) {
154 i2c_ev_handler(I2CDEV_3);
156 #endif
158 static bool i2cHandleHardwareFailure(I2CDevice device)
160 i2cErrorCount++;
161 // reinit peripheral + clock out garbage
162 i2cInit(device);
163 return false;
166 bool i2cWriteBuffer(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len_, uint8_t *data)
168 if (device == I2CINVALID || device > I2CDEV_COUNT) {
169 return false;
172 I2C_TypeDef *I2Cx = i2cDevice[device].reg;
174 if (!I2Cx) {
175 return false;
178 i2cState_t *state = &i2cDevice[device].state;
179 if (state->busy) {
180 return false;
183 timeUs_t timeoutStartUs = microsISR();
185 state->addr = addr_ << 1;
186 state->reg = reg_;
187 state->writing = 1;
188 state->reading = 0;
189 state->write_p = data;
190 state->read_p = data;
191 state->bytes = len_;
192 state->busy = 1;
193 state->error = false;
195 if (!(I2Cx->CR2 & I2C_IT_EVT)) { // if we are restarting the driver
196 if (!(I2Cx->CR1 & I2C_CR1_START)) { // ensure sending a start
197 while (I2Cx->CR1 & I2C_CR1_STOP) { // wait for any stop to finish sending
198 if (cmpTimeUs(microsISR(), timeoutStartUs) >= I2C_TIMEOUT_US) {
199 return i2cHandleHardwareFailure(device);
202 I2C_GenerateSTART(I2Cx, ENABLE); // send the start for the new job
204 I2C_ITConfig(I2Cx, I2C_IT_EVT | I2C_IT_ERR, ENABLE); // allow the interrupts to fire off again
207 return true;
210 bool i2cBusy(I2CDevice device, bool *error)
212 i2cState_t *state = &i2cDevice[device].state;
214 if (error) {
215 *error = state->error;
217 return state->busy;
220 bool i2cWait(I2CDevice device)
222 i2cState_t *state = &i2cDevice[device].state;
223 timeUs_t timeoutStartUs = microsISR();
225 while (state->busy) {
226 if (cmpTimeUs(microsISR(), timeoutStartUs) >= I2C_TIMEOUT_US) {
227 return i2cHandleHardwareFailure(device) && i2cWait(device);
231 return !(state->error);
234 bool i2cWrite(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t data)
236 return i2cWriteBuffer(device, addr_, reg_, 1, &data) && i2cWait(device);
239 bool i2cReadBuffer(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len, uint8_t* buf)
241 if (device == I2CINVALID || device > I2CDEV_COUNT) {
242 return false;
245 I2C_TypeDef *I2Cx = i2cDevice[device].reg;
246 if (!I2Cx) {
247 return false;
250 i2cState_t *state = &i2cDevice[device].state;
251 if (state->busy) {
252 return false;
255 timeUs_t timeoutStartUs = microsISR();
257 state->addr = addr_ << 1;
258 state->reg = reg_;
259 state->writing = 0;
260 state->reading = 1;
261 state->read_p = buf;
262 state->write_p = buf;
263 state->bytes = len;
264 state->busy = 1;
265 state->error = false;
267 if (!(I2Cx->CR2 & I2C_IT_EVT)) { // if we are restarting the driver
268 if (!(I2Cx->CR1 & I2C_CR1_START)) { // ensure sending a start
269 while (I2Cx->CR1 & I2C_CR1_STOP) { // wait for any stop to finish sending
270 if (cmpTimeUs(microsISR(), timeoutStartUs) >= I2C_TIMEOUT_US) {
271 return i2cHandleHardwareFailure(device);
274 I2C_GenerateSTART(I2Cx, ENABLE); // send the start for the new job
276 I2C_ITConfig(I2Cx, I2C_IT_EVT | I2C_IT_ERR, ENABLE); // allow the interrupts to fire off again
279 return true;
282 bool i2cRead(I2CDevice device, uint8_t addr_, uint8_t reg_, uint8_t len, uint8_t* buf)
284 return i2cReadBuffer(device, addr_, reg_, len, buf) && i2cWait(device);
287 static void i2c_er_handler(I2CDevice device) {
289 I2C_TypeDef *I2Cx = i2cDevice[device].hardware->reg;
291 i2cState_t *state = &i2cDevice[device].state;
293 // Read the I2C1 status register
294 volatile uint32_t SR1Register = I2Cx->SR1;
296 if (SR1Register & (I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_OVR)) // an error
297 state->error = true;
299 // If AF, BERR or ARLO, abandon the current job and commence new if there are jobs
300 if (SR1Register & (I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF)) {
301 (void)I2Cx->SR2; // read second status register to clear ADDR if it is set (note that BTF will not be set after a NACK)
302 I2C_ITConfig(I2Cx, I2C_IT_BUF, DISABLE); // disable the RXNE/TXE interrupt - prevent the ISR tailchaining onto the ER (hopefully)
303 if (!(SR1Register & I2C_SR1_ARLO) && !(I2Cx->CR1 & I2C_CR1_STOP)) { // if we dont have an ARLO error, ensure sending of a stop
304 if (I2Cx->CR1 & I2C_CR1_START) { // We are currently trying to send a start, this is very bad as start, stop will hang the peripheral
305 while (I2Cx->CR1 & I2C_CR1_START) {; } // wait for any start to finish sending
306 I2C_GenerateSTOP(I2Cx, ENABLE); // send stop to finalise bus transaction
307 while (I2Cx->CR1 & I2C_CR1_STOP) {; } // wait for stop to finish sending
308 i2cInit(device); // reset and configure the hardware
310 else {
311 I2C_GenerateSTOP(I2Cx, ENABLE); // stop to free up the bus
312 I2C_ITConfig(I2Cx, I2C_IT_EVT | I2C_IT_ERR, DISABLE); // Disable EVT and ERR interrupts while bus inactive
316 I2Cx->SR1 &= ~(I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_OVR); // reset all the error bits to clear the interrupt
317 state->busy = 0;
320 void i2c_ev_handler(I2CDevice device) {
322 I2C_TypeDef *I2Cx = i2cDevice[device].hardware->reg;
324 i2cState_t *state = &i2cDevice[device].state;
326 static uint8_t subaddress_sent, final_stop; // flag to indicate if subaddess sent, flag to indicate final bus condition
327 static int8_t index; // index is signed -1 == send the subaddress
328 uint8_t SReg_1 = I2Cx->SR1; // read the status register here
330 if (SReg_1 & I2C_SR1_SB) { // we just sent a start - EV5 in ref manual
331 I2Cx->CR1 &= ~I2C_CR1_POS; // reset the POS bit so ACK/NACK applied to the current byte
332 I2C_AcknowledgeConfig(I2Cx, ENABLE); // make sure ACK is on
333 index = 0; // reset the index
334 if (state->reading && (subaddress_sent || 0xFF == state->reg)) { // we have sent the subaddr
335 subaddress_sent = 1; // make sure this is set in case of no subaddress, so following code runs correctly
336 if (state->bytes == 2)
337 I2Cx->CR1 |= I2C_CR1_POS; // set the POS bit so NACK applied to the final byte in the two byte read
338 I2C_Send7bitAddress(I2Cx, state->addr, I2C_Direction_Receiver); // send the address and set hardware mode
340 else { // direction is Tx, or we havent sent the sub and rep start
341 I2C_Send7bitAddress(I2Cx, state->addr, I2C_Direction_Transmitter); // send the address and set hardware mode
342 if (state->reg != 0xFF) // 0xFF as subaddress means it will be ignored, in Tx or Rx mode
343 index = -1; // send a subaddress
346 else if (SReg_1 & I2C_SR1_ADDR) { // we just sent the address - EV6 in ref manual
347 // Read SR1,2 to clear ADDR
348 __DMB(); // memory fence to control hardware
349 if (state->bytes == 1 && state->reading && subaddress_sent) { // we are receiving 1 byte - EV6_3
350 I2C_AcknowledgeConfig(I2Cx, DISABLE); // turn off ACK
351 __DMB();
352 (void)I2Cx->SR2; // clear ADDR after ACK is turned off
353 I2C_GenerateSTOP(I2Cx, ENABLE); // program the stop
354 final_stop = 1;
355 I2C_ITConfig(I2Cx, I2C_IT_BUF, ENABLE); // allow us to have an EV7
357 else { // EV6 and EV6_1
358 (void)I2Cx->SR2; // clear the ADDR here
359 __DMB();
360 if (state->bytes == 2 && state->reading && subaddress_sent) { // rx 2 bytes - EV6_1
361 I2C_AcknowledgeConfig(I2Cx, DISABLE); // turn off ACK
362 I2C_ITConfig(I2Cx, I2C_IT_BUF, DISABLE); // disable TXE to allow the buffer to fill
364 else if (state->bytes == 3 && state->reading && subaddress_sent) // rx 3 bytes
365 I2C_ITConfig(I2Cx, I2C_IT_BUF, DISABLE); // make sure RXNE disabled so we get a BTF in two bytes time
366 else // receiving greater than three bytes, sending subaddress, or transmitting
367 I2C_ITConfig(I2Cx, I2C_IT_BUF, ENABLE);
370 else if (SReg_1 & I2C_SR1_BTF) { // Byte transfer finished - EV7_2, EV7_3 or EV8_2
371 final_stop = 1;
372 if (state->reading && subaddress_sent) { // EV7_2, EV7_3
373 if (state->bytes > 2) { // EV7_2
374 I2C_AcknowledgeConfig(I2Cx, DISABLE); // turn off ACK
375 state->read_p[index++] = (uint8_t)I2Cx->DR; // read data N-2
376 I2C_GenerateSTOP(I2Cx, ENABLE); // program the Stop
377 final_stop = 1; // required to fix hardware
378 state->read_p[index++] = (uint8_t)I2Cx->DR; // read data N - 1
379 I2C_ITConfig(I2Cx, I2C_IT_BUF, ENABLE); // enable TXE to allow the final EV7
381 else { // EV7_3
382 if (final_stop)
383 I2C_GenerateSTOP(I2Cx, ENABLE); // program the Stop
384 else
385 I2C_GenerateSTART(I2Cx, ENABLE); // program a rep start
386 state->read_p[index++] = (uint8_t)I2Cx->DR; // read data N - 1
387 state->read_p[index++] = (uint8_t)I2Cx->DR; // read data N
388 index++; // to show job completed
391 else { // EV8_2, which may be due to a subaddress sent or a write completion
392 if (subaddress_sent || (state->writing)) {
393 if (final_stop)
394 I2C_GenerateSTOP(I2Cx, ENABLE); // program the Stop
395 else
396 I2C_GenerateSTART(I2Cx, ENABLE); // program a rep start
397 index++; // to show that the job is complete
399 else { // We need to send a subaddress
400 I2C_GenerateSTART(I2Cx, ENABLE); // program the repeated Start
401 subaddress_sent = 1; // this is set back to zero upon completion of the current task
404 // we must wait for the start to clear, otherwise we get constant BTF
405 while (I2Cx->CR1 & I2C_CR1_START) {; }
407 else if (SReg_1 & I2C_SR1_RXNE) { // Byte received - EV7
408 state->read_p[index++] = (uint8_t)I2Cx->DR;
409 if (state->bytes == (index + 3))
410 I2C_ITConfig(I2Cx, I2C_IT_BUF, DISABLE); // disable TXE to allow the buffer to flush so we can get an EV7_2
411 if (state->bytes == index) // We have completed a final EV7
412 index++; // to show job is complete
414 else if (SReg_1 & I2C_SR1_TXE) { // Byte transmitted EV8 / EV8_1
415 if (index != -1) { // we dont have a subaddress to send
416 I2Cx->DR = state->write_p[index++];
417 if (state->bytes == index) // we have sent all the data
418 I2C_ITConfig(I2Cx, I2C_IT_BUF, DISABLE); // disable TXE to allow the buffer to flush
420 else {
421 index++;
422 I2Cx->DR = state->reg; // send the subaddress
423 if (state->reading || !(state->bytes)) // if receiving or sending 0 bytes, flush now
424 I2C_ITConfig(I2Cx, I2C_IT_BUF, DISABLE); // disable TXE to allow the buffer to flush
427 if (index == state->bytes + 1) { // we have completed the current job
428 subaddress_sent = 0; // reset this here
429 if (final_stop) // If there is a final stop and no more jobs, bus is inactive, disable interrupts to prevent BTF
430 I2C_ITConfig(I2Cx, I2C_IT_EVT | I2C_IT_ERR, DISABLE); // Disable EVT and ERR interrupts while bus inactive
431 state->busy = 0;
435 void i2cInit(I2CDevice device)
437 if (device == I2CINVALID)
438 return;
440 i2cDevice_t *pDev = &i2cDevice[device];
441 const i2cHardware_t *hw = pDev->hardware;
442 const IO_t scl = pDev->scl;
443 const IO_t sda = pDev->sda;
445 if (!hw || IOGetOwner(scl) || IOGetOwner(sda)) {
446 return;
449 I2C_TypeDef *I2Cx = hw->reg;
451 memset(&pDev->state, 0, sizeof(pDev->state));
453 NVIC_InitTypeDef nvic;
454 I2C_InitTypeDef i2cInit;
456 IOInit(scl, OWNER_I2C_SCL, RESOURCE_INDEX(device));
457 IOInit(sda, OWNER_I2C_SDA, RESOURCE_INDEX(device));
459 // Enable RCC
460 RCC_ClockCmd(hw->rcc, ENABLE);
462 I2C_ITConfig(I2Cx, I2C_IT_EVT | I2C_IT_ERR, DISABLE);
464 i2cUnstick(scl, sda);
466 // Init pins
467 #ifdef STM32F4
468 IOConfigGPIOAF(scl, pDev->pullUp ? IOCFG_I2C_PU : IOCFG_I2C, pDev->sclAF);
469 IOConfigGPIOAF(sda, pDev->pullUp ? IOCFG_I2C_PU : IOCFG_I2C, pDev->sdaAF);
470 #else
471 IOConfigGPIO(scl, IOCFG_I2C);
472 IOConfigGPIO(sda, IOCFG_I2C);
473 #endif
475 I2C_DeInit(I2Cx);
476 I2C_StructInit(&i2cInit);
478 I2C_ITConfig(I2Cx, I2C_IT_EVT | I2C_IT_ERR, DISABLE); // Disable EVT and ERR interrupts - they are enabled by the first request
479 i2cInit.I2C_Mode = I2C_Mode_I2C;
480 i2cInit.I2C_DutyCycle = I2C_DutyCycle_2;
481 i2cInit.I2C_OwnAddress1 = 0;
482 i2cInit.I2C_Ack = I2C_Ack_Enable;
483 i2cInit.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
484 i2cInit.I2C_ClockSpeed = pDev->clockSpeed * 1000;
486 I2C_Cmd(I2Cx, ENABLE);
487 I2C_Init(I2Cx, &i2cInit);
489 I2C_StretchClockCmd(I2Cx, ENABLE);
491 // I2C ER Interrupt
492 nvic.NVIC_IRQChannel = hw->er_irq;
493 nvic.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_I2C_ER);
494 nvic.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_I2C_ER);
495 nvic.NVIC_IRQChannelCmd = ENABLE;
496 NVIC_Init(&nvic);
498 // I2C EV Interrupt
499 nvic.NVIC_IRQChannel = hw->ev_irq;
500 nvic.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_I2C_EV);
501 nvic.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_I2C_EV);
502 NVIC_Init(&nvic);
505 uint16_t i2cGetErrorCounter(void)
507 return i2cErrorCount;
510 static void i2cUnstick(IO_t scl, IO_t sda)
512 int i;
514 IOHi(scl);
515 IOHi(sda);
517 IOConfigGPIO(scl, IOCFG_OUT_OD);
518 IOConfigGPIO(sda, IOCFG_OUT_OD);
520 // Clock out, with SDA high:
521 // 7 data bits
522 // 1 READ bit
523 // 1 cycle for the ACK
524 for (i = 0; i < (LEN_ADDR + LEN_RW + LEN_ACK); i++) {
525 // Wait for any clock stretching to finish
526 int timeout = UNSTICK_CLK_STRETCH;
527 while (!IORead(scl) && timeout) {
528 delayMicroseconds(UNSTICK_CLK_US);
529 timeout--;
532 // Pull low
533 IOLo(scl); // Set bus low
534 delayMicroseconds(UNSTICK_CLK_US/2);
535 IOHi(scl); // Set bus high
536 delayMicroseconds(UNSTICK_CLK_US/2);
539 // Generate a stop condition in case there was none
540 IOLo(scl);
541 delayMicroseconds(UNSTICK_CLK_US/2);
542 IOLo(sda);
543 delayMicroseconds(UNSTICK_CLK_US/2);
545 IOHi(scl); // Set bus scl high
546 delayMicroseconds(UNSTICK_CLK_US/2);
547 IOHi(sda); // Set bus sda high
550 #endif