Mercurial > public > ostc4
comparison Small_CPU/Src/i2c.c @ 328:4fe5400567e7 I2C_Improvment
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)
author | ideenmodellierer |
---|---|
date | Wed, 17 Jul 2019 22:42:15 +0200 |
parents | 2b9775f71e30 |
children |
comparison
equal
deleted
inserted
replaced
327:abec171c2c4b | 328:4fe5400567e7 |
---|---|
29 } | 29 } |
30 | 30 |
31 void HAL_I2C_Send_One_CLOCK(void) | 31 void HAL_I2C_Send_One_CLOCK(void) |
32 { | 32 { |
33 HAL_GPIO_WritePin(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_PIN, GPIO_PIN_RESET); | 33 HAL_GPIO_WritePin(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_PIN, GPIO_PIN_RESET); |
34 HAL_Delay(10); | 34 HAL_Delay(1); |
35 HAL_GPIO_WritePin(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_PIN, GPIO_PIN_SET); | 35 HAL_GPIO_WritePin(I2Cx_SCL_GPIO_PORT, I2Cx_SCL_PIN, GPIO_PIN_SET); |
36 HAL_Delay(10); | 36 HAL_Delay(1); |
37 } | 37 } |
38 | 38 |
39 GPIO_PinState MX_I2C1_TestAndClear(void) | 39 GPIO_PinState MX_I2C1_TestAndClear(void) |
40 { | 40 { |
41 GPIO_PinState retval; | |
42 uint8_t repeatcnt = 3; | |
43 | |
41 I2C_DeInit(); | 44 I2C_DeInit(); |
42 HAL_I2C_ManualControl_MspInit(); | 45 HAL_I2C_ManualControl_MspInit(); |
43 for(int i=0; i<9;i++) | 46 |
47 /* The SDA line is expected to be HIGH if no com is pending => send dummy clock signals if that is not the case */ | |
48 do | |
44 { | 49 { |
45 if(HAL_I2C_Read_Data_PIN() == GPIO_PIN_RESET) | 50 for(int i=0; i<20;i++) |
46 HAL_I2C_Send_One_CLOCK(); | 51 { |
47 else | 52 if(HAL_I2C_Read_Data_PIN() == GPIO_PIN_RESET) |
48 break; | 53 HAL_I2C_Send_One_CLOCK(); |
49 } | 54 else |
50 return HAL_I2C_Read_Data_PIN(); | 55 break; |
56 } | |
57 retval = HAL_I2C_Read_Data_PIN(); | |
58 }while ((repeatcnt-- > 0) && (retval != GPIO_PIN_SET)); | |
59 | |
60 return retval; | |
51 } | 61 } |
52 | 62 |
53 HAL_StatusTypeDef MX_I2C1_Init(void) | 63 HAL_StatusTypeDef MX_I2C1_Init(void) |
54 { | 64 { |
55 I2cHandle.Instance = I2Cx; | 65 I2cHandle.Instance = I2Cx; |
56 I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; | 66 I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; |
57 I2cHandle.Init.ClockSpeed = 100000;//400000; REDUCED for compatibility with HMC5583L + MMA8452Q | 67 I2cHandle.Init.ClockSpeed = 88000; /* Reduced to avoid behavior described in errata: Mismatch on the “Setup time for a repeated Start condition” */ |
58 I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED; | 68 I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; |
59 I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_2; | 69 I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_2; /* don't care if not in fast mode */ |
60 I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED; | 70 I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED; |
61 I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED; | 71 I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED; |
62 I2cHandle.Init.OwnAddress1 = 0x01; | 72 I2cHandle.Init.OwnAddress1 = 0x01; /* don't care because of master mode */ |
73 | |
74 /* According to documentation setting filters before I2C initialization is recommended */ | |
75 /* HAL_I2CEx_AnalogFilter_Config(&I2cHandle, I2C_ANALOGFILTER_ENABLED); */ | |
76 HAL_I2CEx_ConfigDigitalFilter(&I2cHandle,0x0F); | |
63 | 77 |
64 global.I2C_SystemStatus = HAL_I2C_Init(&I2cHandle); | 78 global.I2C_SystemStatus = HAL_I2C_Init(&I2cHandle); |
65 HAL_I2CEx_AnalogFilter_Config(&I2cHandle, I2C_ANALOGFILTER_ENABLED); | |
66 HAL_I2CEx_ConfigDigitalFilter(&I2cHandle,0x0F); | |
67 | 79 |
68 if(global.dataSendToSlavePending) | 80 if(global.dataSendToSlavePending) |
69 { | 81 { |
70 scheduleSpecial_Evaluate_DataSendToSlave(); | 82 scheduleSpecial_Evaluate_DataSendToSlave(); |
71 } | 83 } |
83 void I2C_Error_count(void) | 95 void I2C_Error_count(void) |
84 { | 96 { |
85 i2c_errors++; | 97 i2c_errors++; |
86 } | 98 } |
87 | 99 |
100 | |
88 HAL_StatusTypeDef I2C_Master_Transmit( uint16_t DevAddress, uint8_t *pData, uint16_t Size) | 101 HAL_StatusTypeDef I2C_Master_Transmit( uint16_t DevAddress, uint8_t *pData, uint16_t Size) |
89 { | 102 { |
90 if(global.I2C_SystemStatus != HAL_OK) | 103 if(global.I2C_SystemStatus != HAL_OK) |
91 return global.I2C_SystemStatus; | 104 return global.I2C_SystemStatus; |
92 | 105 |
93 global.I2C_SystemStatus = HAL_I2C_Master_Transmit(&I2cHandle, DevAddress, pData, Size, 2); | 106 global.I2C_SystemStatus = HAL_I2C_Master_Transmit(&I2cHandle, DevAddress, pData, Size, 10); |
94 if(global.I2C_SystemStatus != HAL_OK) | 107 if(global.I2C_SystemStatus != HAL_OK) |
95 { | 108 { |
96 I2C_Error_count(); | 109 I2C_Error_count(); |
97 } | 110 } |
98 | 111 |