[ell-i-developers] Re: ELL-i-Arduino Delay functions and interrupt disable

  • From: Félix Halcartegaray V. <felix@xxxxxxxx>
  • To: ell-i-developers@xxxxxxxxxxxxx
  • Date: Sat, 22 Feb 2014 16:37:57 +0200

Hello,

I tested the delays with the oscilloscope, and the ASM section on
function delayMicroseconds that performs the delays below 20
microseconds works perfectly in wiring_time.h:

asm volatile(
            "L_%=_delayMicroseconds:"       "\n\t"
            "sub    %0, #1"                 "\n\t"
            "bge    L_%=_delayMicroseconds" "\n"
            : /* no outputs */ : "r" (cycles4)
            );

doing 12 loops for each microsecond @48 Mhz.

The next section, for delays equal or over 20 microsecond that
compares the current micros() with the micros() the function started
works well for delays over 1000 microseconds, so the delay and
delayMilisecond functions work fine.

The problem is with delay times between 20 and 1000 microseconds, and
then strange things happen on the oscilloscope, with what appear to be
random delays appearing, sometimes too small and sometimes too big.
Might be because the call to micros() function and the while loop
takes more time than the delay, and then there are problems. The
library for the DHT22 sensors uses a call to delayMicroseconds of 40
microseconds, so it was definitely not working.

I would like to know if there are problems of extending the ASM loop
that currently works with less than 20 microseconds into more than 20
microseconds, and how much more is reasonable? Currently it does 240
iterations of the code above for 20 microseconds.

Another issues is that if I change the call of 40 microseconds to:
delayMicroseconds(15);
delayMicroseconds(15);
delayMicroseconds(10);

It gives a 25 microsecond delay. After several tests, I noticed that
if I call twice the delayMicroseconds function with the same argument
in consecutive lines, the second calls gets ignored. So if I do:
delayMicroseconds(15);
delayMicroseconds(10);
delayMicroseconds(15);

It gives the 40 microseconds delay I expect. I don't know the internal
working of the compiler and/or optimizations, so if an explanation to
this issue could be provided it would be great. And if there is a way
to call the function twice without ignoring the second call, even
better.

The sensor is still not working, but at least the delays are working
now. The library for the sensor first sets the pin as output, takes it
to LOW to signal the sensor to start sending data and sets the pin as
input to listen. I don't know how long this change takes, but if it is
more than a few microseconds, the problem with the reading might be
there. I will test it, but if someone has done it before, I am glad to
know.

Thanks!
Felix.


2014-02-21 8:24 GMT+02:00 Pekka Nikander <pekka.nikander@xxxxxx>:
>> [...] so it uses the function delayMicroseconds() from
>> Arduino to read fast but not continuously, and this function is not be
>> tested in our environment according to Pekka. Can someone test if this
>> function is doing what it should? Probably the problem is here.
>
> I think it is best that if you check it, with oscilloscope.  Just create a 
> simple sketch that toggles an I/O with delayMicroseconds in between, and 
> measure if the time is right with different values.
>
> It is also a good idea to have a look at the source code in 
> Ell-i/Arduino.git, in hardware/ell-i/stm32/cores/arduino/wiring_time.h.  
> (Grep is your friend.)  Based on my quick look, it is no wonder if it does 
> not work correctly.
>
>> I don´t know if that works in our environment, if it does, please tell
>> me how many nanoseconds each nop should take. They say that one cycle
>> at 16 Mhz is 62.5 nanoseconds. I don´t know what is the frequency of
>> our processor at the moment, so it would be interesting to know.
>
> Relying on nops is a very bad practise.  The compile time frequency is 
> available in F_CPU define.  However, on the ST Cortex-M0 it is possible to 
> change the frequency on the fly...
>
> A much better approach would be to use one of the timer/counters to read the 
> pin at fixed periods, independent of the CPU.  For that there is the Arduino 
> shiftIn API.  I seem to have implemented it using delay(), but it has never 
> been tested.  A good exercise would be to rewrite the shiftIn API with a 
> timer/counter.
>
>> noInterrupts() and interrupts() that is a more portable version
>
> They are defined in wiring_constants.h.  They should work.
>
> In general, at this staged of the development it is always a good idea to 
> read the source code.
>
> --Pekka
>
>

Other related posts: