2025-06-04 2:03 PM
I am dealing with an I2C lockup issue where the I2C bus is locked up periodically and I need to toggle the SCL pin to free up the bus. To test my theory and make sure that the fix works I just used an osDelay(1) call. I know this is a 1ms delay but it was enough to prove that if I do that it fixes my problem. However, there is no reason to take up an entire 20 ms to complete this operation (from what I've read it's recommended to toggle 10 times to reliably unlock the bus) when 20us is enough. How would I implement a 1us delay function or is there one already available to use?
2025-06-04 2:15 PM
Could perhaps use a 32-bit TIM (2 or 5) as a free-running counter, at 1 MHz or higher tick count, mark some time arbitrarily in the future via TIM->CCRx register vs CNT, and get a CCx interrupt. Probably don't want to be interrupting at 1 MHz, but a few 100 KHz ticker wouldn't hurt briefly.
Not sure if you have a scheduler implemented.
Could also have the recovery in it's own thread/task, spinning on the 32-bit free-runner, it wouldn't preclude other tasks running
2025-06-05 4:26 PM
Perhaps just a brute force approach and loop to suck up the 1uSec. I had to delay the time between two I2C commands of 200uS during initialization. So this was the only thing I had going on. I measured the delay and it was close enough to what was required:
//wait 200uSec todo this was when XIP from flash (~250uSec measured), but from RAM will be faster
uint32_t count =0;
do {
count++;
} while (count < 20000);
2025-06-05 6:00 PM
I recently implemented a one wire interface to the old Dallas Semi temperature sensors (DS18B20). It required precise microsecond timing. I don't use HAL, but used the following simple/efficient timing functions -
#define zero_usec_counter TIM6->CNT = 0
#define get_usec_counter ( TIM6->CNT )
#define delay_to_usec_count(x) while ( get_usec_counter < x )
eg.
one_wire_line_low;
zero_usec_counter;
delay_to_usec_count ( 960 );
one_wire_line_release;
zero_usec_counter;
delay_to_usec_count ( 70 );
out = one_wire_line_value;
delay_to_usec_count ( 480 );
2025-06-06 11:04 AM
Very nice Gregstm. I will be using this in the future!