Почему первое выполнение процедуры Ады занимает больше времени, чем другие выполнения?

Пытаюсь написать процедуру задержки для микроконтроллера FE310. Мне нужно написать эту процедуру, потому что я использую среду выполнения с нулевым объемом памяти (ZFP), которая не обеспечивает собственных задержек Ады.

Процедура основана на 64-битном аппаратном таймере. Таймер увеличивается 32768 раз в секунду. Процедура считывает показания таймера, вычисляет конечное значение, добавляя значение к считанному значению, а затем считывает значение таймера, пока оно не достигнет своего конечного значения.

Я переключаю пин до и после выполнения и проверяю задержку с помощью логического анализатора. Задержки довольно точны, за исключением первого выполнения, где они на 400–600 мкс длиннее, чем запрошено.

Вот моя процедура:

procedure Delay_Ms (Ms : Positive)
is
  Start_Time : Machine_Time_Value;
  End_Time : Machine_Time_Value;
begin
  Start_Time := Machine_Time;
  End_Time := Start_Time + (Machine_Time_Value (Ms) * Machine_Time_Value (LF_Clock_Frequency)) / 1_000;

  loop
     exit when Machine_Time >= End_Time;
  end loop;
end Delay_Ms;

Machine_Time — это функция чтения аппаратного таймера. Machine_Time_Value — это 64-битное целое число без знака.

Я уверен, что аппаратный аспект верен, потому что я написал тот же алгоритм на C, и он ведет себя именно так, как ожидалось.

Я думаю, что GNAT добавляет некоторый код, который выполняется только в первый раз. Я искал в Интернете упоминания о подобном поведении, но не нашел ничего подходящего. Я нашел некоторую информацию о коде уточнения и о том, как его можно удалить, но после некоторых исследований я понял, что код уточнения выполняется перед основным и не должен быть причиной моей проблемы.

Вы знаете, почему первое выполнение такой процедуры, как моя, может занять больше времени? Можно ли избежать такого поведения?


person elbric0    schedule 14.04.2018    source источник
comment
Ваша реализация выглядит нормально. Одна вещь, которую вы можете попробовать, это посмотреть на соответствующий ассемблерный код. IIRC вы передаете gcc/gnatmake аргумент -S, чтобы получить дамп ассемблера скомпилированного исходного текста.   -  person Jacob Sparre Andersen    schedule 14.04.2018
comment
Кэш, наверное?   -  person Simon Wright    schedule 14.04.2018
comment
Любые проверки во время выполнения?   -  person Timur Samkharadze    schedule 15.04.2018


Ответы (1)


Как предположил Саймон Райт, разное время первого выполнения связано с тем, что MCU считывает код из флэш-памяти SPI при первом выполнении, но считывает его из кэша инструкций при последующих выполнениях.

По умолчанию тактовая частота SPI FE310 равна тактовой частоте ядра процессора, деленной на 8. Когда я устанавливаю делитель тактовой частоты SPI на 2, разница во времени выполнения делится на 4.

person elbric0    schedule 20.04.2018