CARME-M4 BSP  V1.5
i2c.c
Go to the documentation of this file.
1 
77 #ifdef __cplusplus
78 extern "C" {
79 #endif /* __cplusplus */
80 
81 /*----- Header-Files -------------------------------------------------------*/
82 #include <stm32f4xx.h> /* Processor STM32F407IG */
83 #include <carme.h> /* CARME Module */
84 #include <i2c.h>
85 
86 /*----- Macros -------------------------------------------------------------*/
87 #define TIMEOUT_MAX 0x3000
89 /*----- Data types ---------------------------------------------------------*/
90 
91 /*----- Function prototypes ------------------------------------------------*/
92 static void CARME_I2C_Settings(I2C_TypeDef *I2Cx);
93 static ERROR_CODES CARME_I2C_Timeout(I2C_TypeDef* I2Cx);
94 
95 /*----- Data ---------------------------------------------------------------*/
100  /* CARME I2C Board */
101  { GPIOH, GPIO_Pin_4, GPIO_Mode_AF, GPIO_AF_I2C2 },
102  { GPIOH, GPIO_Pin_5, GPIO_Mode_AF, GPIO_AF_I2C2 },
103  /* CARME I2C Audio Codec */
104  { GPIOH, GPIO_Pin_7, GPIO_Mode_AF, GPIO_AF_I2C3 },
105  { GPIOH, GPIO_Pin_8, GPIO_Mode_AF, GPIO_AF_I2C3 }
106 };
107 
113 
114 /*----- Implementation -----------------------------------------------------*/
124 void CARME_I2C_Init(I2C_TypeDef *I2Cx) {
125 
126  GPIO_InitTypeDef GPIO_InitStruct;
127 
128  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
129  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C3, ENABLE);
130 
131  /* Configure the GPIO */
132  GPIO_StructInit(&GPIO_InitStruct);
133  GPIO_InitStruct.GPIO_Speed = GPIO_Fast_Speed;
134  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
135  GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
136  CARME_GPIO_Init(CARME_I2C_Port_Pin, &GPIO_InitStruct,
137  sizeof(CARME_I2C_Port_Pin) / sizeof(CARME_Port_Pin_t));
138 
139  /* Configure the I2C */
140  if (I2Cx == CARME_I2C_BOARD ) {
141 
142  I2C_StructInit(&I2C_InitStruct[0]);
143  I2C_InitStruct[0].I2C_ClockSpeed = CARME_I2C_SPEED;
144  I2C_InitStruct[0].I2C_OwnAddress1 = CARME_I2C_ADDR_BOARD;
145  I2C_InitStruct[0].I2C_Ack = I2C_Ack_Enable;
146  } else if (I2Cx == CARME_I2C_AUDIO ) {
147 
148  I2C_StructInit(&I2C_InitStruct[1]);
149  I2C_InitStruct[1].I2C_ClockSpeed = CARME_I2C_SPEED;
150  I2C_InitStruct[1].I2C_OwnAddress1 = CARME_I2C_ADDR_AUDIO;
151  I2C_InitStruct[1].I2C_Ack = I2C_Ack_Enable;
152  }
153  CARME_I2C_Settings(I2Cx);
154 }
155 
165 static void CARME_I2C_Settings(I2C_TypeDef *I2Cx) {
166 
167  uint8_t i;
168 
169  if (I2Cx == CARME_I2C_BOARD ) {
170  I2C_Cmd(CARME_I2C_BOARD, DISABLE);
172  I2C_Init(I2Cx, &I2C_InitStruct[0]);
173  I2C_Cmd(I2Cx, ENABLE);
174  } else if (I2Cx == CARME_I2C_AUDIO ) {
175  I2C_Cmd(CARME_I2C_AUDIO, DISABLE);
177  I2C_Init(I2Cx, &I2C_InitStruct[1]);
178  I2C_Cmd(I2Cx, ENABLE);
179  }
180 
181  i = 0xFF;
182  while (i--)
183  /* Wait until hardware is running */
184  ;
185 }
186 
198 static ERROR_CODES CARME_I2C_Timeout(I2C_TypeDef* I2Cx) {
199 
200  I2C_GenerateSTOP(I2Cx, ENABLE);
201  I2C_SoftwareResetCmd(I2Cx, ENABLE);
202  I2C_SoftwareResetCmd(I2Cx, DISABLE);
203  CARME_I2C_Settings(I2Cx);
204 
206 }
207 
226 ERROR_CODES CARME_I2C_Write(I2C_TypeDef *I2Cx, uint8_t addr, uint16_t reg,
227  uint8_t twoByte, uint8_t *pdata, uint16_t count) {
228 
229  uint32_t timeout = TIMEOUT_MAX;
230  uint16_t i;
231 
232  while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY )) {
233  if (--timeout == 0) {
234  return CARME_I2C_Timeout(I2Cx);
235  }
236  }
237 
238  I2C_GenerateSTART(I2Cx, ENABLE);
239  timeout = TIMEOUT_MAX;
241  if (--timeout == 0) {
242  return CARME_I2C_Timeout(I2Cx);
243  }
244  }
245 
246  I2C_Send7bitAddress(I2Cx, addr, I2C_Direction_Transmitter );
247  timeout = TIMEOUT_MAX;
249  if (--timeout == 0) {
250  return CARME_I2C_Timeout(I2Cx);
251  }
252  }
253 
254  if (twoByte == 1) {
255  I2C_SendData(I2Cx, (uint8_t) (reg >> 8));
256  timeout = TIMEOUT_MAX;
257  while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTING )) {
258  if (--timeout == 0) {
259  return CARME_I2C_Timeout(I2Cx);
260  }
261  }
262 
263  I2C_SendData(I2Cx, (uint8_t) reg);
264  timeout = TIMEOUT_MAX;
265  while (!I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF )) {
266  if (--timeout == 0) {
267  CARME_I2C_Timeout(I2Cx);
268  }
269  }
270  } else {
271  I2C_SendData(I2Cx, (uint8_t) reg);
272  timeout = TIMEOUT_MAX;
273  while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTING )) {
274  if (--timeout == 0) {
275  return CARME_I2C_Timeout(I2Cx);
276  }
277  }
278  }
279 
280  for (i = 0; i < count; i++) {
281  I2C_SendData(I2Cx, pdata[i]);
282  timeout = TIMEOUT_MAX;
283  while (!I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF )) {
284  if (--timeout == 0) {
285  CARME_I2C_Timeout(I2Cx);
286  }
287  }
288  }
289 
290  I2C_GenerateSTOP(I2Cx, ENABLE);
291  return CARME_NO_ERROR;
292 }
293 
312 ERROR_CODES CARME_I2C_Read(I2C_TypeDef *I2Cx, uint8_t addr, uint16_t reg,
313  uint8_t twoByte, uint8_t *pdata, uint16_t count) {
314 
315  uint32_t timeout = TIMEOUT_MAX;
316  uint16_t i;
317 
318  while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_BUSY )) {
319  if (--timeout == 0) {
320  return CARME_I2C_Timeout(I2Cx);
321  }
322  }
323 
324  I2C_GenerateSTART(I2Cx, ENABLE);
325  timeout = TIMEOUT_MAX;
327  if (--timeout == 0) {
328  return CARME_I2C_Timeout(I2Cx);
329  }
330  }
331 
332  I2C_Send7bitAddress(I2Cx, addr, I2C_Direction_Transmitter );
333  timeout = TIMEOUT_MAX;
335  if (--timeout == 0) {
336  return CARME_I2C_Timeout(I2Cx);
337  }
338  }
339 
340  if (twoByte == 1) {
341  I2C_SendData(I2Cx, (uint8_t) (reg >> 8));
342  timeout = TIMEOUT_MAX;
343  while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTING )) {
344  if (--timeout == 0) {
345  return CARME_I2C_Timeout(I2Cx);
346  }
347  }
348 
349  I2C_SendData(I2Cx, (uint8_t) reg);
350  timeout = TIMEOUT_MAX;
351  while (!I2C_GetFlagStatus(I2Cx, I2C_FLAG_BTF )) {
352  if (--timeout == 0) {
353  CARME_I2C_Timeout(I2Cx);
354  }
355  }
356  } else {
357  I2C_SendData(I2Cx, (uint8_t) reg);
358  timeout = TIMEOUT_MAX;
359  while (!I2C_CheckEvent(I2Cx, I2C_EVENT_MASTER_BYTE_TRANSMITTING )) {
360  if (--timeout == 0) {
361  return CARME_I2C_Timeout(I2Cx);
362  }
363  }
364  }
365 
366  I2C_GenerateSTART(I2Cx, ENABLE);
367  timeout = TIMEOUT_MAX;
369  if (--timeout == 0) {
370  return CARME_I2C_Timeout(I2Cx);
371  }
372  }
373 
374  I2C_Send7bitAddress(I2Cx, addr, I2C_Direction_Receiver );
375  timeout = TIMEOUT_MAX;
376  while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_ADDR ) == RESET) {
377  if (--timeout == 0) {
378  return CARME_I2C_Timeout(I2Cx);
379  }
380  }
381 
382  for (i = 0; i < count - 1; i++) {
383  timeout = TIMEOUT_MAX;
385  if (--timeout == 0) {
386  return CARME_I2C_Timeout(I2Cx);
387  }
388  }
389  pdata[i] = I2C_ReceiveData(I2Cx);
390  }
391 
392  I2C_AcknowledgeConfig(I2Cx, DISABLE);
393  (void) I2Cx->SR2;
394 
395  I2C_GenerateSTOP(I2Cx, ENABLE);
396  timeout = TIMEOUT_MAX;
397  while (I2C_GetFlagStatus(I2Cx, I2C_FLAG_RXNE ) == RESET) {
398  if (--timeout == 0) {
399  return CARME_I2C_Timeout(I2Cx);
400  }
401  }
402 
403  pdata[count - 1] = I2C_ReceiveData(I2Cx);
404  timeout = TIMEOUT_MAX;
405  while (I2Cx->CR1 & I2C_CR1_STOP ) {
406  if (--timeout == 0) {
407  return CARME_I2C_Timeout(I2Cx);
408  }
409  }
410 
411  I2C_AcknowledgeConfig(I2Cx, ENABLE);
412  I2C_ClearFlag(I2Cx, I2C_FLAG_AF );
413 
414  return CARME_NO_ERROR;
415 }
416 
417 #ifdef __cplusplus
418 }
419 #endif /* __cplusplus */
420 
static ERROR_CODES CARME_I2C_Timeout(I2C_TypeDef *I2Cx)
Restart the I2C periph if a timeout has occurred.
Definition: i2c.c:198
uint8_t ERROR_CODES
Error variable.
Definition: carme.h:255
void I2C_Send7bitAddress(I2C_TypeDef *I2Cx, uint8_t Address, uint8_t I2C_Direction)
Transmits the address byte to select the slave device.
GPIOOType_TypeDef GPIO_OType
#define I2C_EVENT_MASTER_MODE_SELECT
Communication start.
#define CARME_I2C_BOARD
Definition: i2c.h:81
uint16_t I2C_OwnAddress1
Definition: stm32f4xx_i2c.h:65
ErrorStatus I2C_CheckEvent(I2C_TypeDef *I2Cx, uint32_t I2C_EVENT)
Checks whether the last I2Cx Event is equal to the one passed as parameter.
void I2C_Init(I2C_TypeDef *I2Cx, I2C_InitTypeDef *I2C_InitStruct)
Initializes the I2Cx peripheral according to the specified parameters in the I2C_InitStruct.
#define CARME_I2C_ADDR_BOARD
Definition: i2c.h:85
GPIOSpeed_TypeDef GPIO_Speed
GPIOPuPd_TypeDef GPIO_PuPd
void CARME_GPIO_Init(CARME_Port_Pin_t *pPortPinAssociation, GPIO_InitTypeDef *pGPIO_InitStruct, uint8_t size)
Initialize GPIO ports with a CARME_Port_Pin_t table.
Definition: carme.c:540
void I2C_GenerateSTOP(I2C_TypeDef *I2Cx, FunctionalState NewState)
Generates I2Cx communication STOP condition.
void GPIO_StructInit(GPIO_InitTypeDef *GPIO_InitStruct)
Fills each GPIO_InitStruct member with its default value.
ERROR_CODES CARME_I2C_Read(I2C_TypeDef *I2Cx, uint8_t addr, uint16_t reg, uint8_t twoByte, uint8_t *pdata, uint16_t count)
Read data from an I2C slave device on a specific register address.
Definition: i2c.c:312
#define CARME_I2C_ADDR_AUDIO
Definition: i2c.h:88
CARME port and pin association structure.
Definition: carme.h:245
#define TIMEOUT_MAX
Definition: i2c.c:87
void I2C_DeInit(I2C_TypeDef *I2Cx)
Deinitialize the I2Cx peripheral registers to their default reset values.
#define CARME_ERROR_I2C_TIMEOUT
Definition: i2c.h:92
void I2C_Cmd(I2C_TypeDef *I2Cx, FunctionalState NewState)
Enables or disables the specified I2C peripheral.
FlagStatus I2C_GetFlagStatus(I2C_TypeDef *I2Cx, uint32_t I2C_FLAG)
Checks whether the specified I2C flag is set or not.
#define CARME_I2C_AUDIO
Definition: i2c.h:82
static CARME_Port_Pin_t CARME_I2C_Port_Pin[]
I2C Port and Pin association.
Definition: i2c.c:99
GPIO Init structure definition.
void I2C_SoftwareResetCmd(I2C_TypeDef *I2Cx, FunctionalState NewState)
Enables or disables the specified I2C software reset.
void CARME_I2C_Init(I2C_TypeDef *I2Cx)
I2C initialization.
Definition: i2c.c:124
#define CARME_NO_ERROR
Definition: carme.h:135
static I2C_InitTypeDef I2C_InitStruct[2]
I2C init structures to reinitialize the interface, if it is crashed.
Definition: i2c.c:112
void I2C_AcknowledgeConfig(I2C_TypeDef *I2Cx, FunctionalState NewState)
Enables or disables the specified I2C acknowledge feature.
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState)
Enables or disables the Low Speed APB (APB1) peripheral clock.
void I2C_ClearFlag(I2C_TypeDef *I2Cx, uint32_t I2C_FLAG)
Clears the I2Cx's pending flags.
#define CARME_I2C_SPEED
Definition: i2c.h:84
#define I2C_EVENT_MASTER_BYTE_RECEIVED
Communication events.
ERROR_CODES CARME_I2C_Write(I2C_TypeDef *I2Cx, uint8_t addr, uint16_t reg, uint8_t twoByte, uint8_t *pdata, uint16_t count)
Write data to an I2C slave device on a specific register address.
Definition: i2c.c:226
uint8_t I2C_ReceiveData(I2C_TypeDef *I2Cx)
Returns the most recent received data by the I2Cx peripheral.
void I2C_StructInit(I2C_InitTypeDef *I2C_InitStruct)
Fills each I2C_InitStruct member with its default value.
I2C Init structure definition.
Definition: stm32f4xx_i2c.h:54
#define I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED
Address Acknowledge.
uint32_t I2C_ClockSpeed
Definition: stm32f4xx_i2c.h:56
uint16_t I2C_Ack
Definition: stm32f4xx_i2c.h:68
static void CARME_I2C_Settings(I2C_TypeDef *I2Cx)
I2C interface initialization.
Definition: i2c.c:165
void I2C_SendData(I2C_TypeDef *I2Cx, uint8_t Data)
Sends a data byte through the I2Cx peripheral.
void I2C_GenerateSTART(I2C_TypeDef *I2Cx, FunctionalState NewState)
Generates I2Cx communication START condition.
I2C board support package for the CARME module.