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)
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/>.
27 #if defined(USE_I2C) && !defined(SOFT_I2C)
29 #include "build/debug.h"
31 #include "drivers/system.h"
32 #include "drivers/io.h"
33 #include "drivers/io_impl.h"
34 #include "drivers/rcc.h"
35 #include "drivers/time.h"
37 #include "drivers/bus_i2c.h"
38 #include "drivers/bus_i2c_impl.h"
39 #include "drivers/bus_i2c_timing.h"
41 #define IOCFG_I2C_PU IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_OD, GPIO_PuPd_UP)
42 #define IOCFG_I2C IO_CONFIG(GPIO_Mode_AF, GPIO_Speed_50MHz, GPIO_OType_OD, GPIO_PuPd_NOPULL)
44 #define I2C_GPIO_AF GPIO_AF_4
46 static volatile uint16_t i2cErrorCount
= 0;
48 const i2cHardware_t i2cHardware
[I2CDEV_COUNT
] = {
49 #ifdef USE_I2C_DEVICE_1
53 .sclPins
= { I2CPINDEF(PA15
), I2CPINDEF(PB6
), I2CPINDEF(PB8
) },
54 .sdaPins
= { I2CPINDEF(PA14
), I2CPINDEF(PB7
), I2CPINDEF(PB9
) },
55 .rcc
= RCC_APB1(I2C1
),
58 #ifdef USE_I2C_DEVICE_2
62 .sclPins
= { I2CPINDEF(PA9
), I2CPINDEF(PF6
) },
63 .sdaPins
= { I2CPINDEF(PA10
) },
64 .rcc
= RCC_APB1(I2C2
),
69 i2cDevice_t i2cDevice
[I2CDEV_COUNT
];
71 ///////////////////////////////////////////////////////////////////////////////
72 // I2C TimeoutUserCallback
73 ///////////////////////////////////////////////////////////////////////////////
75 uint32_t i2cTimeoutUserCallback(void)
81 void i2cInit(I2CDevice device
)
83 if (device
== I2CINVALID
|| device
>= I2CDEV_COUNT
) {
87 i2cDevice_t
*pDev
= &i2cDevice
[device
];
88 const i2cHardware_t
*hw
= pDev
->hardware
;
94 I2C_TypeDef
*I2Cx
= pDev
->reg
;
99 RCC_ClockCmd(hw
->rcc
, ENABLE
);
100 RCC_I2CCLKConfig(I2Cx
== I2C2
? RCC_I2C2CLK_SYSCLK
: RCC_I2C1CLK_SYSCLK
);
102 IOInit(scl
, OWNER_I2C_SCL
, RESOURCE_INDEX(device
));
103 IOConfigGPIOAF(scl
, pDev
->pullUp
? IOCFG_I2C_PU
: IOCFG_I2C
, GPIO_AF_4
);
105 IOInit(sda
, OWNER_I2C_SDA
, RESOURCE_INDEX(device
));
106 IOConfigGPIOAF(sda
, pDev
->pullUp
? IOCFG_I2C_PU
: IOCFG_I2C
, GPIO_AF_4
);
108 I2C_InitTypeDef i2cInit
= {
109 .I2C_Mode
= I2C_Mode_I2C
,
110 .I2C_AnalogFilter
= I2C_AnalogFilter_Enable
,
111 .I2C_DigitalFilter
= 0x00,
112 .I2C_OwnAddress1
= 0x00,
113 .I2C_Ack
= I2C_Ack_Enable
,
114 .I2C_AcknowledgedAddress
= I2C_AcknowledgedAddress_7bit
,
115 .I2C_Timing
= i2cClockTIMINGR(SystemCoreClock
, pDev
->clockSpeed
, 0)
118 I2C_Init(I2Cx
, &i2cInit
);
120 I2C_StretchClockCmd(I2Cx
, ENABLE
);
122 I2C_Cmd(I2Cx
, ENABLE
);
125 uint16_t i2cGetErrorCounter(void)
127 return i2cErrorCount
;
130 bool i2cWrite(I2CDevice device
, uint8_t addr_
, uint8_t reg
, uint8_t data
)
132 if (device
== I2CINVALID
|| device
>= I2CDEV_COUNT
) {
136 I2C_TypeDef
*I2Cx
= i2cDevice
[device
].reg
;
144 timeUs_t timeoutStartUs
;
146 /* Test on BUSY Flag */
147 timeoutStartUs
= microsISR();
148 while (I2C_GetFlagStatus(I2Cx
, I2C_ISR_BUSY
) != RESET
) {
149 if (cmpTimeUs(microsISR(), timeoutStartUs
) >= I2C_TIMEOUT_US
) {
150 return i2cTimeoutUserCallback();
154 /* Configure slave address, nbytes, reload, end mode and start or stop generation */
155 I2C_TransferHandling(I2Cx
, addr_
, 1, I2C_Reload_Mode
, I2C_Generate_Start_Write
);
157 /* Wait until TXIS flag is set */
158 timeoutStartUs
= microsISR();
159 while (I2C_GetFlagStatus(I2Cx
, I2C_ISR_TXIS
) == RESET
) {
160 if (cmpTimeUs(microsISR(), timeoutStartUs
) >= I2C_TIMEOUT_US
) {
161 return i2cTimeoutUserCallback();
165 /* Send Register address */
166 I2C_SendData(I2Cx
, (uint8_t) reg
);
168 /* Wait until TCR flag is set */
169 timeoutStartUs
= microsISR();
170 while (I2C_GetFlagStatus(I2Cx
, I2C_ISR_TCR
) == RESET
) {
171 if (cmpTimeUs(microsISR(), timeoutStartUs
) >= I2C_TIMEOUT_US
) {
172 return i2cTimeoutUserCallback();
176 /* Configure slave address, nbytes, reload, end mode and start or stop generation */
177 I2C_TransferHandling(I2Cx
, addr_
, 1, I2C_AutoEnd_Mode
, I2C_No_StartStop
);
179 /* Wait until TXIS flag is set */
180 timeoutStartUs
= microsISR();
181 while (I2C_GetFlagStatus(I2Cx
, I2C_ISR_TXIS
) == RESET
) {
182 if (cmpTimeUs(microsISR(), timeoutStartUs
) >= I2C_TIMEOUT_US
) {
183 return i2cTimeoutUserCallback();
187 /* Write data to TXDR */
188 I2C_SendData(I2Cx
, data
);
190 /* Wait until STOPF flag is set */
191 timeoutStartUs
= microsISR();
192 while (I2C_GetFlagStatus(I2Cx
, I2C_ISR_STOPF
) == RESET
) {
193 if (cmpTimeUs(microsISR(), timeoutStartUs
) >= I2C_TIMEOUT_US
) {
194 return i2cTimeoutUserCallback();
198 /* Clear STOPF flag */
199 I2C_ClearFlag(I2Cx
, I2C_ICR_STOPCF
);
204 bool i2cRead(I2CDevice device
, uint8_t addr_
, uint8_t reg
, uint8_t len
, uint8_t* buf
)
206 if (device
== I2CINVALID
|| device
>= I2CDEV_COUNT
) {
210 I2C_TypeDef
*I2Cx
= i2cDevice
[device
].reg
;
218 timeUs_t timeoutStartUs
;
220 /* Test on BUSY Flag */
221 timeoutStartUs
= microsISR();
222 while (I2C_GetFlagStatus(I2Cx
, I2C_ISR_BUSY
) != RESET
) {
223 if (cmpTimeUs(microsISR(), timeoutStartUs
) >= I2C_TIMEOUT_US
) {
224 return i2cTimeoutUserCallback();
228 /* Configure slave address, nbytes, reload, end mode and start or stop generation */
229 I2C_TransferHandling(I2Cx
, addr_
, 1, I2C_SoftEnd_Mode
, I2C_Generate_Start_Write
);
231 /* Wait until TXIS flag is set */
232 timeoutStartUs
= microsISR();
233 while (I2C_GetFlagStatus(I2Cx
, I2C_ISR_TXIS
) == RESET
) {
234 if (cmpTimeUs(microsISR(), timeoutStartUs
) >= I2C_TIMEOUT_US
) {
235 return i2cTimeoutUserCallback();
239 /* Send Register address */
240 I2C_SendData(I2Cx
, (uint8_t) reg
);
242 /* Wait until TC flag is set */
243 timeoutStartUs
= microsISR();
244 while (I2C_GetFlagStatus(I2Cx
, I2C_ISR_TC
) == RESET
) {
245 if (cmpTimeUs(microsISR(), timeoutStartUs
) >= I2C_TIMEOUT_US
) {
246 return i2cTimeoutUserCallback();
250 /* Configure slave address, nbytes, reload, end mode and start or stop generation */
251 I2C_TransferHandling(I2Cx
, addr_
, len
, I2C_AutoEnd_Mode
, I2C_Generate_Start_Read
);
253 /* Wait until all data are received */
255 /* Wait until RXNE flag is set */
256 timeoutStartUs
= microsISR();
257 while (I2C_GetFlagStatus(I2Cx
, I2C_ISR_RXNE
) == RESET
) {
258 if (cmpTimeUs(microsISR(), timeoutStartUs
) >= I2C_TIMEOUT_US
) {
259 return i2cTimeoutUserCallback();
263 /* Read data from RXDR */
264 *buf
= I2C_ReceiveData(I2Cx
);
265 /* Point to the next location where the byte read will be saved */
268 /* Decrement the read bytes counter */
272 /* Wait until STOPF flag is set */
273 timeoutStartUs
= microsISR();
274 while (I2C_GetFlagStatus(I2Cx
, I2C_ISR_STOPF
) == RESET
) {
275 if (cmpTimeUs(microsISR(), timeoutStartUs
) >= I2C_TIMEOUT_US
) {
276 return i2cTimeoutUserCallback();
280 /* Clear STOPF flag */
281 I2C_ClearFlag(I2Cx
, I2C_ICR_STOPCF
);
283 /* If all operations OK */
287 bool i2cWriteBuffer(I2CDevice device
, uint8_t addr_
, uint8_t reg_
, uint8_t len_
, uint8_t *data
)
291 for (uint8_t i
= 0; i
< len_
; i
++) {
292 status
&= i2cWrite(device
, addr_
, reg_
+ i
, data
[i
]);
298 bool i2cReadBuffer(I2CDevice device
, uint8_t addr_
, uint8_t reg
, uint8_t len
, uint8_t* buf
)
300 return i2cRead(device
, addr_
, reg
, len
, buf
);
303 bool i2cBusy(I2CDevice device
, bool *error
)