There are currently two ways in AVR-Ada to control the timing.
See Tero's blog for comparing the accuracy of the two methods.
The package AVR.Wait provides three functions allowing delays in the order of a few cycles.
procedure Wait_3_Cycles (Count : Unsigned_8); -- can wait up to 2^8 x 3 cycles procedure Wait_4_Cycles (Count : Unsigned_16); -- can wait up to 2^16 x 4 cycles procedure Wait_Cycles (Count : Unsigned_32); -- can wait up to 2^32 cycles
The generic function AVR.Wait.Generic_Wait_USecs takes the processor speed in Hertz and the microseconds (10-6 seconds) to be delayed as generic parameters. It internally calculates at compile time the number of cycles to wait. It leads to only a few instructions at assembler level.
Example of generic instantiation from the 1-Wire package:
procedure Wait_70us is new Generic_Wait_Usecs (Crystal_Hertz => 8_000_000, Micro_Seconds => 70); pragma Inline_Always (Wait_70us);
The system of busy waits counting cycles only works correctly if you disable all interrupts. You should therefor limit it to less than one millisecond. All other timing are usually better achieved by the second method using a timer.
In order to obtain accurate timing the compiler has to know at what speed the processor works. If you set the processor speed in AVR.Config you can also use
on the primary MCUs.
The above standard Ada delay works if you have applied the corresponding patch when building the cross compiler and when using AVR.Real_Time.Clock. If you don't need any of the other timing routines you have to "with" at least that package in the main procedure.
with AVR.Real_Time.Clock; pragma Unreferenced (AVR.Real_Time.Clock);