AnsweredAssumed Answered

Unstable I2C on STM32F746 Discovery

Question asked by johann3s on Jul 31, 2016
Latest reply on Aug 5, 2016 by johann3s

I've been struggling with this problem for weeks now. Basically I am trying to read out a sensor via I2C. The L3SD20. I am reading out the sensor in FreeRTOS, but the sensor readout task has the highest priority of all tasks.

Communcation is very unstable. I sometimes had it working for longer periods of time. But now the communication just stops almost instantly. I did a very ugly thing to reinitialize the I2C upon communication failure, and that seems to work to a degree. But then after a few seconds of doing that the communication dies completely. Once I restart the device, I again have these few seconds seconds it is working (reinitalizing probably half of the time steps, so still very ugly).

Unfortunatly I don't have access to a logic analyzer, making debugging more difficult. I am quite new to this board, and did not work a lot with the I2C protocol yet. So am I missing something obvious? Are there specific required settings for initialization of the clock/I2C that I am missing?

Some code snippets can be found here:

Starting the communication


01.//Enable the accelerometer
02.uint8_t gyro_data=0b11001111;
03.uint8_t imu_data=0b01110111;
04. 
05.HAL_I2C_Init(&hi2c1);
06. 
07.while (HAL_I2C_Mem_Write(&hi2c1,I2C_GYRO_ADDR,0x20,1,&gyro_data,1,I2C_TIMEOUT) != HAL_OK ||
08.     HAL_I2C_Mem_Write(&hi2c1,I2C_IMU_ADDR,0x20,1,&imu_data,1,I2C_TIMEOUT) != HAL_OK)
09.{
10.  HAL_I2C_DeInit(&hi2c1);
11.  HAL_I2C_Init(&hi2c1);
12.}

Communcation each 30ms

01.if(HAL_I2C_Mem_Read(&hi2c1,I2C_GYRO_ADDR,0x28,1,(uint8_t *)&gyro_data[0],1,I2C_TIMEOUT) != HAL_OK ||
02.                  HAL_I2C_Mem_Read(&hi2c1,I2C_GYRO_ADDR,0x29,1,(uint8_t *)&gyro_data[1],1,I2C_TIMEOUT) != HAL_OK ||
03.                  HAL_I2C_Mem_Read(&hi2c1,I2C_GYRO_ADDR,0x2A,1,(uint8_t *)&gyro_data[2],1,I2C_TIMEOUT) != HAL_OK ||
04.                  HAL_I2C_Mem_Read(&hi2c1,I2C_GYRO_ADDR,0x2B,1,(uint8_t *)&gyro_data[3],1,I2C_TIMEOUT) != HAL_OK ||
05.                  HAL_I2C_Mem_Read(&hi2c1,I2C_GYRO_ADDR,0x2C,1,(uint8_t *)&gyro_data[4],1,I2C_TIMEOUT) != HAL_OK ||
06.                  HAL_I2C_Mem_Read(&hi2c1,I2C_GYRO_ADDR,0x2D,1,(uint8_t *)&gyro_data[5],1,I2C_TIMEOUT) != HAL_OK)
07.            {
08.                  error_counter_sensor++;
09. 
10.                  HAL_I2C_DeInit(&hi2c1);
11.                  HAL_I2C_Init(&hi2c1);
12. 
13.//                Error_Handler((uint8_t *)"Error reading out I2C");
14.            }

My I2C initialization

01.hi2c1.Instance = I2C1;
02.hi2c1.Init.Timing = 0x00401959;
03.hi2c1.Init.OwnAddress1 = 0;
04.hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
05.hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
06.hi2c1.Init.OwnAddress2 = 0;
07.hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
08.hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
09.hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

My HAL_I2C_Mspinit

01.GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
02.GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
03.GPIO_InitStruct.Pull = GPIO_PULLUP;
04.GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
05.GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
06.HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
07. 
08./* Peripheral clock enable */
09.__HAL_RCC_I2C1_CLK_ENABLE();

My clock initialization

01.RCC_ClkInitTypeDef RCC_ClkInitStruct;
02.RCC_OscInitTypeDef RCC_OscInitStruct;
03.HAL_StatusTypeDef ret = HAL_OK;
04. 
05./* Enable HSE Oscillator and activate PLL with HSE as source */
06.RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
07.RCC_OscInitStruct.HSEState = RCC_HSE_ON;
08.RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
09.RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
10.RCC_OscInitStruct.PLL.PLLM = 25;
11.RCC_OscInitStruct.PLL.PLLN = 400;
12.RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
13.RCC_OscInitStruct.PLL.PLLQ = 8;
14. 
15.ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
16.if(ret != HAL_OK)
17.{
18.  while(1) { ; }
19.}
20. 
21./* Activate the OverDrive to reach the 200 MHz Frequency */
22.ret = HAL_PWREx_EnableOverDrive();
23.if(ret != HAL_OK)
24.{
25.  while(1) { ; }
26.}
27. 
28./* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
29.RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
30.RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
31.RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
32.RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
33.RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
34. 
35.ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_6);
36.if(ret != HAL_OK)
37.{
38.  while(1) { ; }
39.}

Outcomes