Finally rename flight.c/.h to pid.c/.h. Cleanup some dependencies.
[betaflight.git] / src / main / drivers / bus_i2c_stm32f30x.c
blob80141ac6361db565b19139dc24f6011732897186
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>
20 #include <stdlib.h>
22 #include <platform.h>
24 #include "build_config.h"
26 #include "gpio.h"
27 #include "system.h"
29 #include "bus_i2c.h"
31 #ifndef SOFT_I2C
33 #define I2C_SHORT_TIMEOUT ((uint32_t)0x1000)
34 #define I2C_LONG_TIMEOUT ((uint32_t)(10 * I2C_SHORT_TIMEOUT))
36 #define I2C1_SCL_GPIO GPIOB
37 #define I2C1_SCL_GPIO_AF GPIO_AF_4
38 #define I2C1_SCL_PIN GPIO_Pin_6
39 #define I2C1_SCL_PIN_SOURCE GPIO_PinSource6
40 #define I2C1_SCL_CLK_SOURCE RCC_AHBPeriph_GPIOB
41 #define I2C1_SDA_GPIO GPIOB
42 #define I2C1_SDA_GPIO_AF GPIO_AF_4
43 #define I2C1_SDA_PIN GPIO_Pin_7
44 #define I2C1_SDA_PIN_SOURCE GPIO_PinSource7
45 #define I2C1_SDA_CLK_SOURCE RCC_AHBPeriph_GPIOB
47 #if !defined(I2C2_SCL_GPIO)
48 #define I2C2_SCL_GPIO GPIOF
49 #define I2C2_SCL_GPIO_AF GPIO_AF_4
50 #define I2C2_SCL_PIN GPIO_Pin_6
51 #define I2C2_SCL_PIN_SOURCE GPIO_PinSource6
52 #define I2C2_SCL_CLK_SOURCE RCC_AHBPeriph_GPIOF
53 #define I2C2_SDA_GPIO GPIOA
54 #define I2C2_SDA_GPIO_AF GPIO_AF_4
55 #define I2C2_SDA_PIN GPIO_Pin_10
56 #define I2C2_SDA_PIN_SOURCE GPIO_PinSource10
57 #define I2C2_SDA_CLK_SOURCE RCC_AHBPeriph_GPIOA
59 #endif
61 static uint32_t i2cTimeout;
63 static volatile uint16_t i2c1ErrorCount = 0;
64 static volatile uint16_t i2c2ErrorCount = 0;
66 static I2C_TypeDef *I2Cx = NULL;
68 ///////////////////////////////////////////////////////////////////////////////
69 // I2C TimeoutUserCallback
70 ///////////////////////////////////////////////////////////////////////////////
72 uint32_t i2cTimeoutUserCallback(I2C_TypeDef *I2Cx)
74 if (I2Cx == I2C1) {
75 i2c1ErrorCount++;
76 } else {
77 i2c2ErrorCount++;
79 return false;
82 void i2cInitPort(I2C_TypeDef *I2Cx)
84 GPIO_InitTypeDef GPIO_InitStructure;
85 I2C_InitTypeDef I2C_InitStructure;
87 if (I2Cx == I2C1) {
88 RCC_AHBPeriphClockCmd(I2C1_SCL_CLK_SOURCE | I2C1_SDA_CLK_SOURCE, ENABLE);
89 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
90 RCC_I2CCLKConfig(RCC_I2C1CLK_SYSCLK);
92 //i2cUnstick(I2Cx); // Clock out stuff to make sure slaves arent stuck
94 GPIO_PinAFConfig(I2C1_SCL_GPIO, I2C1_SCL_PIN_SOURCE, I2C1_SCL_GPIO_AF);
95 GPIO_PinAFConfig(I2C1_SDA_GPIO, I2C1_SDA_PIN_SOURCE, I2C1_SDA_GPIO_AF);
97 GPIO_StructInit(&GPIO_InitStructure);
98 I2C_StructInit(&I2C_InitStructure);
100 // Init pins
102 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
103 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
104 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
105 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
107 GPIO_InitStructure.GPIO_Pin = I2C1_SCL_PIN;
108 GPIO_Init(I2C1_SCL_GPIO, &GPIO_InitStructure);
110 GPIO_InitStructure.GPIO_Pin = I2C1_SDA_PIN;
111 GPIO_Init(I2C1_SDA_GPIO, &GPIO_InitStructure);
113 I2C_StructInit(&I2C_InitStructure);
115 I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
116 I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
117 I2C_InitStructure.I2C_DigitalFilter = 0x00;
118 I2C_InitStructure.I2C_OwnAddress1 = 0x00;
119 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
120 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
121 I2C_InitStructure.I2C_Timing = 0x00E0257A; // 400 Khz, 72Mhz Clock, Analog Filter Delay ON, Rise 100, Fall 10.
122 //I2C_InitStructure.I2C_Timing = 0x8000050B;
124 I2C_Init(I2C1, &I2C_InitStructure);
126 I2C_Cmd(I2C1, ENABLE);
129 if (I2Cx == I2C2) {
130 RCC_AHBPeriphClockCmd(I2C2_SCL_CLK_SOURCE | I2C2_SDA_CLK_SOURCE, ENABLE);
131 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
132 RCC_I2CCLKConfig(RCC_I2C2CLK_SYSCLK);
134 //i2cUnstick(I2Cx); // Clock out stuff to make sure slaves arent stuck
136 GPIO_PinAFConfig(I2C2_SCL_GPIO, I2C2_SCL_PIN_SOURCE, I2C2_SCL_GPIO_AF);
137 GPIO_PinAFConfig(I2C2_SDA_GPIO, I2C2_SDA_PIN_SOURCE, I2C2_SDA_GPIO_AF);
139 GPIO_StructInit(&GPIO_InitStructure);
140 I2C_StructInit(&I2C_InitStructure);
142 // Init pins
143 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
144 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
145 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
146 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
148 GPIO_InitStructure.GPIO_Pin = I2C2_SCL_PIN;
149 GPIO_Init(I2C2_SCL_GPIO, &GPIO_InitStructure);
151 GPIO_InitStructure.GPIO_Pin = I2C2_SDA_PIN;
152 GPIO_Init(I2C2_SDA_GPIO, &GPIO_InitStructure);
154 I2C_StructInit(&I2C_InitStructure);
156 I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
157 I2C_InitStructure.I2C_AnalogFilter = I2C_AnalogFilter_Enable;
158 I2C_InitStructure.I2C_DigitalFilter = 0x00;
159 I2C_InitStructure.I2C_OwnAddress1 = 0x00;
160 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
161 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
163 // FIXME timing is board specific
164 //I2C_InitStructure.I2C_Timing = 0x00310309; // //400kHz I2C @ 8MHz input -> PRESC=0x0, SCLDEL=0x3, SDADEL=0x1, SCLH=0x03, SCLL=0x09 - value from TauLabs/Sparky
165 // ^ when using this setting and after a few seconds of a scope probe being attached to the I2C bus it was observed that the bus enters
166 // a busy state and does not recover.
168 I2C_InitStructure.I2C_Timing = 0x00E0257A; // 400 Khz, 72Mhz Clock, Analog Filter Delay ON, Rise 100, Fall 10.
170 //I2C_InitStructure.I2C_Timing = 0x8000050B;
172 I2C_Init(I2C2, &I2C_InitStructure);
174 I2C_Cmd(I2C2, ENABLE);
178 void i2cInit(I2CDevice index)
180 if (index == I2CDEV_1) {
181 I2Cx = I2C1;
182 } else {
183 I2Cx = I2C2;
185 i2cInitPort(I2Cx);
188 uint16_t i2cGetErrorCounter(void)
190 if (I2Cx == I2C1) {
191 return i2c1ErrorCount;
194 return i2c2ErrorCount;
198 bool i2cWrite(uint8_t addr_, uint8_t reg, uint8_t data)
200 addr_ <<= 1;
202 /* Test on BUSY Flag */
203 i2cTimeout = I2C_LONG_TIMEOUT;
204 while (I2C_GetFlagStatus(I2Cx, I2C_ISR_BUSY) != RESET) {
205 if ((i2cTimeout--) == 0) {
206 return i2cTimeoutUserCallback(I2Cx);
210 /* Configure slave address, nbytes, reload, end mode and start or stop generation */
211 I2C_TransferHandling(I2Cx, addr_, 1, I2C_Reload_Mode, I2C_Generate_Start_Write);
213 /* Wait until TXIS flag is set */
214 i2cTimeout = I2C_LONG_TIMEOUT;
215 while (I2C_GetFlagStatus(I2Cx, I2C_ISR_TXIS) == RESET) {
216 if ((i2cTimeout--) == 0) {
217 return i2cTimeoutUserCallback(I2Cx);
221 /* Send Register address */
222 I2C_SendData(I2Cx, (uint8_t) reg);
224 /* Wait until TCR flag is set */
225 i2cTimeout = I2C_LONG_TIMEOUT;
226 while (I2C_GetFlagStatus(I2Cx, I2C_ISR_TCR) == RESET)
228 if ((i2cTimeout--) == 0) {
229 return i2cTimeoutUserCallback(I2Cx);
233 /* Configure slave address, nbytes, reload, end mode and start or stop generation */
234 I2C_TransferHandling(I2Cx, addr_, 1, I2C_AutoEnd_Mode, I2C_No_StartStop);
236 /* Wait until TXIS flag is set */
237 i2cTimeout = I2C_LONG_TIMEOUT;
238 while (I2C_GetFlagStatus(I2Cx, I2C_ISR_TXIS) == RESET) {
239 if ((i2cTimeout--) == 0) {
240 return i2cTimeoutUserCallback(I2Cx);
244 /* Write data to TXDR */
245 I2C_SendData(I2Cx, data);
247 /* Wait until STOPF flag is set */
248 i2cTimeout = I2C_LONG_TIMEOUT;
249 while (I2C_GetFlagStatus(I2Cx, I2C_ISR_STOPF) == RESET) {
250 if ((i2cTimeout--) == 0) {
251 return i2cTimeoutUserCallback(I2Cx);
255 /* Clear STOPF flag */
256 I2C_ClearFlag(I2Cx, I2C_ICR_STOPCF);
258 return true;
261 bool i2cRead(uint8_t addr_, uint8_t reg, uint8_t len, uint8_t* buf)
263 addr_ <<= 1;
265 /* Test on BUSY Flag */
266 i2cTimeout = I2C_LONG_TIMEOUT;
267 while (I2C_GetFlagStatus(I2Cx, I2C_ISR_BUSY) != RESET) {
268 if ((i2cTimeout--) == 0) {
269 return i2cTimeoutUserCallback(I2Cx);
273 /* Configure slave address, nbytes, reload, end mode and start or stop generation */
274 I2C_TransferHandling(I2Cx, addr_, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
276 /* Wait until TXIS flag is set */
277 i2cTimeout = I2C_LONG_TIMEOUT;
278 while (I2C_GetFlagStatus(I2Cx, I2C_ISR_TXIS) == RESET) {
279 if ((i2cTimeout--) == 0) {
280 return i2cTimeoutUserCallback(I2Cx);
284 /* Send Register address */
285 I2C_SendData(I2Cx, (uint8_t) reg);
287 /* Wait until TC flag is set */
288 i2cTimeout = I2C_LONG_TIMEOUT;
289 while (I2C_GetFlagStatus(I2Cx, I2C_ISR_TC) == RESET) {
290 if ((i2cTimeout--) == 0) {
291 return i2cTimeoutUserCallback(I2Cx);
295 /* Configure slave address, nbytes, reload, end mode and start or stop generation */
296 I2C_TransferHandling(I2Cx, addr_, len, I2C_AutoEnd_Mode, I2C_Generate_Start_Read);
298 /* Wait until all data are received */
299 while (len) {
300 /* Wait until RXNE flag is set */
301 i2cTimeout = I2C_LONG_TIMEOUT;
302 while (I2C_GetFlagStatus(I2Cx, I2C_ISR_RXNE) == RESET) {
303 if ((i2cTimeout--) == 0) {
304 return i2cTimeoutUserCallback(I2Cx);
308 /* Read data from RXDR */
309 *buf = I2C_ReceiveData(I2Cx);
310 /* Point to the next location where the byte read will be saved */
311 buf++;
313 /* Decrement the read bytes counter */
314 len--;
317 /* Wait until STOPF flag is set */
318 i2cTimeout = I2C_LONG_TIMEOUT;
319 while (I2C_GetFlagStatus(I2Cx, I2C_ISR_STOPF) == RESET) {
320 if ((i2cTimeout--) == 0) {
321 return i2cTimeoutUserCallback(I2Cx);
325 /* Clear STOPF flag */
326 I2C_ClearFlag(I2Cx, I2C_ICR_STOPCF);
328 /* If all operations OK */
329 return true;
332 #endif