# HG changeset patch # User ideenmodellierer # Date 1563396135 -7200 # Node ID 4fe5400567e7aea73d716ec7f1b10df417af29ef # Parent abec171c2c4bda1a5dc9388d4bbc4fca7cce4bbc Set I2C speed to 88kHz, use digital filter only and reworked idle clock recovery The errata describes a possible problem in operation between 88kHz and 100kHz => Set speed as recommended as work around. Based on reference implementation only one filter should be use. Choice was digital because only drawback is lag of wakeup functionality which is not used I2C communication may be randomly interrupted e.g. by a RTE reset or firmware update => reworked recovery function to get I2C devices in idle state again (Clk and SDA HIGH) diff -r abec171c2c4b -r 4fe5400567e7 Small_CPU/Src/i2c.c --- a/Small_CPU/Src/i2c.c Wed Jul 17 22:41:31 2019 +0200 +++ b/Small_CPU/Src/i2c.c Wed Jul 17 22:42:15 2019 +0200 @@ -31,39 +31,51 @@ void HAL_I2C_Send_One_CLOCK(void) { HAL_GPIO_WritePin(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_PIN, GPIO_PIN_RESET); - HAL_Delay(10); + HAL_Delay(1); HAL_GPIO_WritePin(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_PIN, GPIO_PIN_SET); - HAL_Delay(10); + HAL_Delay(1); } GPIO_PinState MX_I2C1_TestAndClear(void) { + GPIO_PinState retval; + uint8_t repeatcnt = 3; + I2C_DeInit(); HAL_I2C_ManualControl_MspInit(); - for(int i=0; i<9;i++) + +/* The SDA line is expected to be HIGH if no com is pending => send dummy clock signals if that is not the case */ + do { - if(HAL_I2C_Read_Data_PIN() == GPIO_PIN_RESET) - HAL_I2C_Send_One_CLOCK(); - else - break; - } - return HAL_I2C_Read_Data_PIN(); + for(int i=0; i<20;i++) + { + if(HAL_I2C_Read_Data_PIN() == GPIO_PIN_RESET) + HAL_I2C_Send_One_CLOCK(); + else + break; + } + retval = HAL_I2C_Read_Data_PIN(); + }while ((repeatcnt-- > 0) && (retval != GPIO_PIN_SET)); + + return retval; } HAL_StatusTypeDef MX_I2C1_Init(void) { - I2cHandle.Instance = I2Cx; + I2cHandle.Instance = I2Cx; I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; - I2cHandle.Init.ClockSpeed = 100000;//400000; REDUCED for compatibility with HMC5583L + MMA8452Q - I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED; - I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_2; + I2cHandle.Init.ClockSpeed = 88000; /* Reduced to avoid behavior described in errata: Mismatch on the “Setup time for a repeated Start condition” */ + I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_2; /* don't care if not in fast mode */ I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED; I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED; - I2cHandle.Init.OwnAddress1 = 0x01; + I2cHandle.Init.OwnAddress1 = 0x01; /* don't care because of master mode */ + +/* According to documentation setting filters before I2C initialization is recommended */ + /* HAL_I2CEx_AnalogFilter_Config(&I2cHandle, I2C_ANALOGFILTER_ENABLED); */ + HAL_I2CEx_ConfigDigitalFilter(&I2cHandle,0x0F); global.I2C_SystemStatus = HAL_I2C_Init(&I2cHandle); - HAL_I2CEx_AnalogFilter_Config(&I2cHandle, I2C_ANALOGFILTER_ENABLED); - HAL_I2CEx_ConfigDigitalFilter(&I2cHandle,0x0F); if(global.dataSendToSlavePending) { @@ -85,12 +97,13 @@ i2c_errors++; } + HAL_StatusTypeDef I2C_Master_Transmit( uint16_t DevAddress, uint8_t *pData, uint16_t Size) { if(global.I2C_SystemStatus != HAL_OK) return global.I2C_SystemStatus; - global.I2C_SystemStatus = HAL_I2C_Master_Transmit(&I2cHandle, DevAddress, pData, Size, 2); + global.I2C_SystemStatus = HAL_I2C_Master_Transmit(&I2cHandle, DevAddress, pData, Size, 10); if(global.I2C_SystemStatus != HAL_OK) { I2C_Error_count();