2023-03-17 04:02 AM
I am currently using a TSC2007 to detect touchs on a screen.
When working in blocking mode this is correctly working as the TSC2007 correctly streches the clock and the HAL correctly waits for the data to be ready
When working with interrupts the HAL fails to wait as a NACK and STOP interrupt is triggered which cancels further transmissions of bytes.
I can avoid the TSC2007 doing the streching by manually waiting a specific amount of time. The probem is that depending on the waiting time the read value is incorrect.
The current solution I am using is calling my TSC2007 driver in blocking mode in a low level priority freertos task
Correct clock streching and read when using HAL_I2C_Master_Receive
Read cancelled by HAL when using HAL_I2C_Master_Receive_IT
Read correctly done with HAL_I2C_Master_Receive_IT(but incorrect values reported by device) if I wait for an amount of time that requieres
Any idea how to support clock streching in master mode with Interruptions?
Solved! Go to Solution.
2023-03-20 01:50 AM
After properly understanding the issue, the casuse was incorrect transmision of the message when using the HAL_I2C_Master_Receive_IT/HAL_I2C_Master_Transmit_IT
With blocking mode this was working
void Task_TSC2007Driver(void)
{
TSC2007_CommandByte driver_command = { 0 };
driver_command.cmd_bits.tc_function = TC_FUNCTION_MEASURE_Y_POSITION;
driver_command.cmd_bits.power_config = POWER_CONFIG_ADC_ON_IRQ_DISABLED;
driver_command.cmd_bits.adc_config = ADC_CONFIG_12_BITS_RESOLUTION;
HAL_I2C_Master_Transmit(tsc2007_i2c_handle, TSC2007_I2C_ADDR, &driver_command.cmd_byte, 1,100);
HAL_I2C_Master_Receive(tsc2007_i2c_handle, TSC2007_I2C_ADDR, &y_buffer[0], 2,100);
}
Howerver with IT based approach it is necessary to ensure that the pointer were the data is stored remains unmodified during all the transmission as the HAL driver does not make a copy of it.
In my case I have a variable that creates the data to be transmitted (TSC2007_CommandByte driver_command). Ensuring this variable maintains its value after calling HAL_I2C_Master_Transmit_IT ensures the tranmission is correct. Thus this will work erratically:
static void TSC2007_GetX(void)
{
TSC2007_CommandByte driver_command = { 0 };
fsm_tsc2007_driver_it = TSC_IT_GET_X;
driver_command.cmd_bits.tc_function = TC_FUNCTION_MEASURE_X_POSITION;
driver_command.cmd_bits.power_config = POWER_CONFIG_ADC_ON_IRQ_DISABLED;
driver_command.cmd_bits.adc_config = ADC_CONFIG_12_BITS_RESOLUTION;
HAL_I2C_Master_Transmit_IT(tsc2007_i2c_handle, TSC2007_I2C_ADDR, &driver_command.cmd_byte, 1);
}
And this will work properly:
TSC2007_CommandByte driver_command = { 0 };
static void TSC2007_GetX(void)
{
fsm_tsc2007_driver_it = TSC_IT_GET_X;
driver_command.cmd_bits.tc_function = TC_FUNCTION_MEASURE_X_POSITION;
driver_command.cmd_bits.power_config = POWER_CONFIG_ADC_ON_IRQ_DISABLED;
driver_command.cmd_bits.adc_config = ADC_CONFIG_12_BITS_RESOLUTION;
HAL_I2C_Master_Transmit_IT(tsc2007_i2c_handle, TSC2007_I2C_ADDR, &driver_command.cmd_byte, 1);
}
2023-03-17 06:00 AM
Where is the SCL clock stretching in the scope captures? SCL clock stretching means the yellow clock pusle should have missing pusles if master doesn't hold on. The "Stop/Start" bit makes a longer clock high period, it's normal. I'm puzzled.
2023-03-17 08:09 AM
you didnt show any clock stretching , as S.Ma said.
it would be like this : scl kept low by slave
2023-03-17 08:39 AM
Hello @Community member ,
Please try to debug and check registers to see the received data .
Check the error flags set in the status register or catch the error via HAL_I2C_GetError.
If you are facing some erratic behavior on STM32F7, do not forget to check Errata sheet of the device. There are few points related to I2C interface.
Foued
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2023-03-17 09:00 AM
And to be honest, this clock-stretching concept where the slave drags on SCL wasn't even a thing when I was with PHILIPS/NXP (mid/late 1980's)
If one needs to deal with really abhorrent divergence from normal behaviour you can always bit-bang the bus, and monitor the SCL attaining the desired state.
2023-03-17 12:39 PM
@AScha.3 Thank you for the clarification. I was misinterpreting the stop+start as the clock stretching. This means that what I am probably seing is the TX of a message that for some reason i failing and then a second message is started to be TX. I will further troubleshoot this issue
2023-03-20 01:50 AM
After properly understanding the issue, the casuse was incorrect transmision of the message when using the HAL_I2C_Master_Receive_IT/HAL_I2C_Master_Transmit_IT
With blocking mode this was working
void Task_TSC2007Driver(void)
{
TSC2007_CommandByte driver_command = { 0 };
driver_command.cmd_bits.tc_function = TC_FUNCTION_MEASURE_Y_POSITION;
driver_command.cmd_bits.power_config = POWER_CONFIG_ADC_ON_IRQ_DISABLED;
driver_command.cmd_bits.adc_config = ADC_CONFIG_12_BITS_RESOLUTION;
HAL_I2C_Master_Transmit(tsc2007_i2c_handle, TSC2007_I2C_ADDR, &driver_command.cmd_byte, 1,100);
HAL_I2C_Master_Receive(tsc2007_i2c_handle, TSC2007_I2C_ADDR, &y_buffer[0], 2,100);
}
Howerver with IT based approach it is necessary to ensure that the pointer were the data is stored remains unmodified during all the transmission as the HAL driver does not make a copy of it.
In my case I have a variable that creates the data to be transmitted (TSC2007_CommandByte driver_command). Ensuring this variable maintains its value after calling HAL_I2C_Master_Transmit_IT ensures the tranmission is correct. Thus this will work erratically:
static void TSC2007_GetX(void)
{
TSC2007_CommandByte driver_command = { 0 };
fsm_tsc2007_driver_it = TSC_IT_GET_X;
driver_command.cmd_bits.tc_function = TC_FUNCTION_MEASURE_X_POSITION;
driver_command.cmd_bits.power_config = POWER_CONFIG_ADC_ON_IRQ_DISABLED;
driver_command.cmd_bits.adc_config = ADC_CONFIG_12_BITS_RESOLUTION;
HAL_I2C_Master_Transmit_IT(tsc2007_i2c_handle, TSC2007_I2C_ADDR, &driver_command.cmd_byte, 1);
}
And this will work properly:
TSC2007_CommandByte driver_command = { 0 };
static void TSC2007_GetX(void)
{
fsm_tsc2007_driver_it = TSC_IT_GET_X;
driver_command.cmd_bits.tc_function = TC_FUNCTION_MEASURE_X_POSITION;
driver_command.cmd_bits.power_config = POWER_CONFIG_ADC_ON_IRQ_DISABLED;
driver_command.cmd_bits.adc_config = ADC_CONFIG_12_BITS_RESOLUTION;
HAL_I2C_Master_Transmit_IT(tsc2007_i2c_handle, TSC2007_I2C_ADDR, &driver_command.cmd_byte, 1);
}