cancel
Showing results for 
Search instead for 
Did you mean: 

Unstable I2C on STM32F746 Discovery

johannesvg
Associate II
Posted on July 31, 2016 at 16:04

I've been struggling with this problem for weeks now. Basically I am trying to read out a sensor via I2C. The L3SD 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


//Enable the accelerometer

uint8_t gyro_data=0b11001111;

uint8_t imu_data=0b01110111;


HAL_I2C_Init(&hi2c1);


while
(HAL_I2C_Mem_Write(&hi2c1,I2C_GYRO_ADDR,0x20,1,&gyro_data,1,I2C_TIMEOUT) != HAL_OK ||

HAL_I2C_Mem_Write(&hi2c1,I2C_IMU_ADDR,0x20,1,&imu_data,1,I2C_TIMEOUT) != HAL_OK)

{

HAL_I2C_DeInit(&hi2c1);

HAL_I2C_Init(&hi2c1);

}

Communcation each 30ms


if
(HAL_I2C_Mem_Read(&hi2c1,I2C_GYRO_ADDR,0x28,1,(uint8_t *)&gyro_data[0],1,I2C_TIMEOUT) != HAL_OK ||

HAL_I2C_Mem_Read(&hi2c1,I2C_GYRO_ADDR,0x29,1,(uint8_t *)&gyro_data[1],1,I2C_TIMEOUT) != HAL_OK ||

HAL_I2C_Mem_Read(&hi2c1,I2C_GYRO_ADDR,0x2A,1,(uint8_t *)&gyro_data[2],1,I2C_TIMEOUT) != HAL_OK ||

HAL_I2C_Mem_Read(&hi2c1,I2C_GYRO_ADDR,0x2B,1,(uint8_t *)&gyro_data[3],1,I2C_TIMEOUT) != HAL_OK ||

HAL_I2C_Mem_Read(&hi2c1,I2C_GYRO_ADDR,0x2C,1,(uint8_t *)&gyro_data[4],1,I2C_TIMEOUT) != HAL_OK ||

HAL_I2C_Mem_Read(&hi2c1,I2C_GYRO_ADDR,0x2D,1,(uint8_t *)&gyro_data[5],1,I2C_TIMEOUT) != HAL_OK)

{

error_counter_sensor++;


HAL_I2C_DeInit(&hi2c1);

HAL_I2C_Init(&hi2c1);


// Error_Handler((uint8_t *)''Error reading out I2C'');

}

My I2C initialization


hi2c1.Instance = I2C1;

hi2c1.Init.Timing = 0x00401959;

hi2c1.Init.OwnAddress1 = 0;

hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;

hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;

hi2c1.Init.OwnAddress2 = 0;

hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;

hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;

hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

My HAL_I2C_Mspinit


GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;

GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;

GPIO_InitStruct.Pull = GPIO_PULLUP;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;

HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);


/* Peripheral clock enable */

__HAL_RCC_I2C1_CLK_ENABLE();

My clock initialization


RCC_ClkInitTypeDef RCC_ClkInitStruct;

RCC_OscInitTypeDef RCC_OscInitStruct;

HAL_StatusTypeDef ret = HAL_OK;


/* Enable HSE Oscillator and activate PLL with HSE as source */

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;

RCC_OscInitStruct.HSEState = RCC_HSE_ON;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

RCC_OscInitStruct.PLL.PLLM = 25;

RCC_OscInitStruct.PLL.PLLN = 400;

RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;

RCC_OscInitStruct.PLL.PLLQ = 8;


ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);

if
(ret != HAL_OK)

{

while
(1) { ; }

}


/* Activate the OverDrive to reach the 200 MHz Frequency */

ret = HAL_PWREx_EnableOverDrive();

if
(ret != HAL_OK)

{

while
(1) { ; }

}


/* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */

RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;


ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_6);

if
(ret != HAL_OK)

{

while
(1) { ; }

}

3 REPLIES 3
Nesrine M_O
Lead II
Posted on August 01, 2016 at 15:41

Hi johann3s,

 ''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?''

I suggest you to have a look to I2C examples under the STM32F7 cube firmware package it may be helpful:

STM32Cube_FW_F7_V1.4.0\Projects\STM32746G-Discovery\Examples\I2C

-Syrine-

johannesvg
Associate II
Posted on August 01, 2016 at 15:54

Thank you. I am aware of the examples, in fact I copied several parts of the initialization code specifically from there to prevent myself from making errors.

johannesvg
Associate II
Posted on August 05, 2016 at 08:05

Issue resolved. There was a hardware issue with the I2C slave. Now everything works perfectly