mcci-catena / arduino-boards

Arduino board-support packages for MCCI-Catena
6 stars 3 forks source link

delayMicroseconds() is grossly inaccurate in STM32 port #5

Closed terrillmoore closed 6 years ago

terrillmoore commented 6 years ago

Although the code looks right, empirical measurements show that delayMicroseconds() is wrong for values in the sub 1ms range (much too long).

The following routine, if substituted in the OneWire library, makes the OneWire library work better -- but short delays (at least with 1.0.5) are still too long. [Anything less than 30 us is too long, and the OneWire protocol requires that we be accurate for 16 us (max) delays.]

#define delayMicroseconds(usec) my_delayMicroseconds(usec)

static void inline my_delayMicroseconds(uint32_t usec)
{
  const uint32_t now = SysTick->VAL;
  const uint32_t tickmax = SysTick->LOAD;
  const uint32_t ticks = (usec * tickmax + 500) / 1000;
  uint32_t val, lastVal;
  uint32_t dt;

  for (dt = 0, lastVal = now; 
       dt < ticks;
       lastVal = val)
  {
    val = SysTick->VAL;
    if (val >= lastVal)
    {
      dt += tickmax + lastVal - val;
    }
    else
    {
      dt += lastVal - val;
    }
  }
}

A key difference is that this routine converts usec to ticks, and then counts ticks. It assumes that interrupts don't take longer than 1ms, but that doesn't seem to be an issue in practice -- if interrupted for longer than a millisecond, it will wait too long, but the delay will be too long anyway.

terrillmoore commented 6 years ago

With the 1.0.6 BSP, this suffices to make the OneWire library work (along with the other speedups for direct I/O). Can we please update the delayMicroseconds() in the core?

terrillmoore commented 6 years ago

If we get the BSP repo forked and posted, I will send a pull request with this change.

terrillmoore commented 6 years ago

Now that we have the STM32 repo forked and posted, I've moved this issue there. Closing this. Replaced by https://github.com/mcci-catena/Arduino_Core_STM32/issues/8.