Есть ли способ заставить функцию взять точное количество тактов?

c++ loop

Можно ли использовать что-то вроде директивы компилятора для заполнения функции инструкциями do nothing, чтобы при добавлении строк кода или их удалении она всегда выполнялась за одно и то же время? Я знаю, что существует без промедления стиль написания цикла, но я хочу что-то немного более точное.

, 👍0

Обсуждение

Пожалуйста, возьмите [тур] и прочитайте "[ask]", затем вернитесь и предоставьте еще несколько бит информации, по крайней мере, какой компилятор в какой системе вы используете. Некоторая предыстория *зачем* вам это нужно, тоже было бы неплохо. О, и, пожалуйста, [отредактируйте] свой вопрос, не добавляйте комментарии, это не форум. -- Я не знаю ни одного компилятора, у которого есть такая опция; и я знаю несколько совершенно разных компиляторов. Скорее всего, вам нужно будет закодировать это на уровне сборки вручную., @the busybee

В *avr-gcc* вы можете добавить один такт с помощью asm volatile ("nop"); Но вы не можете измерить кодом, сколько тактов контроллер уже провел в каком-то другом ISR., @DataFiddler

Для меня это звучит так, как будто вы пытаетесь стрелять воробьев из пушек. Почему вам нужно, чтобы функция всегда выполнялась за одно и то же время, но при этом меняла свой код? Существуют и другие точные методы запуска регулярного выполнения функции (с помощью таймеров)., @chrisl

вы можете просто сделать снимок времени сверху и еще один, когда ваш код будет завершен, а затем "задержать" или "пока" перед возвратом, пока продолжительность не станет приемлемой., @dandavis

(оффтопик, извините) Извините за удаление вашего [this](https://hardwarerecs.stackexchange.com/questions/13454/can-i-use-my-laptop-with-external-everything) пост. Я предлагаю переспросить его, но сделать более ясным, что вы хотите сделать. Я полагаю, что вы хотите преобразовать свой ноутбук во внешний жесткий диск SATA (возможно, во внешний USB), что является очень интересной проблемой. Забавно, что вы все еще можете использовать свой ноутбук, пока не смонтируете один раздел несколько раз., @peterh

@peterh IDK какой стек обмена спросить на, @bob mcgrath


2 ответа


1

Насколько мне известно, такого нет. То, о чем вы говорите, возможно, но это должно быть сделано вручную путем подсчета циклов, и я подозреваю, что на самом деле это вам не поможет. (И затем вы сталкиваетесь с проблемами CISC, когда выполнение инструкций может занять разное время, потенциально зависящее от аргументов. Arduino (фактический) в некотором роде безопасен от этого, но, например, инструкции ветви по-прежнему занимают несколько циклов. Это ничего не говорит обо всех платах, которые работают с ардуино, но не являются ими.)

Для этого есть два потенциальных пути.

  1. Если это для криптографии, где вы хотите избежать атак по боковым каналам, определяя длину функции аутентификации или хеширования, это не очень хорошая идея. Использовать известные библиотеки, чтобы сделать это вместо этого, поскольку на практике это не является хорошим или безопасным идея написать свой собственный (хотя если это для домашней дверной замок или безопасный замок, это наверное не актуально, так как есть более крупные и более важные проблемы безопасности, которые могут быть найдены во-первых, несмотря на все усилия).
  2. Если, как я подозреваю, вы просто хотите, чтобы фрагмент кода выполнялся с очень точными временными интервалами, я предлагаю вам поискать что-то вроде порта FreeRTOS для Arduino. Это позволит вам запланировать упреждающее выполнение задачи, чтобы она всегда выполнялась с интервалами. Имейте в виду, что скетч BWOD по-прежнему довольно точен, и ниже приведена самокорректирующаяся версия, которая компенсирует любые случаи, когда он может запускаться с небольшим опозданием (это означает, что он ВСЕГДА должен выполняться с точностью до миллисекунды, повторяясь):
  unsigned long currentMillis = millis();//и вы всегда можете использовать micros()

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis += interval;//регулировка для дополнительной точности

    //Задача, которую вы хотите выполнить, будет описана ниже:
    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // установите индикатор со значением состояния переменной:
    digitalWrite(ledPin, ledState);
  }

Оговорка в вашей заявленной цели заключается в том, что любой микропроцессор НЕ БУДЕТ выполнять код именно тогда, когда вы хотите. Arduino тоже не способен на это, так как даже пустой скетч запускает несколько прерываний, которые на короткое время захватят процессор, что приведет к задержке вашего гипотетического скетча. Вы ДОЛЖНЫ использовать справочный метод, такой как BWOD, или планировщик, такой как FreeRTOS. Они используют ссылку или настраивают свои собственные прерывания, чтобы убедиться, что они выполняются вовремя, причем единственными прерываниями, которые могут быть проблемой, являются те, которые выполняются во время этого экземпляра задачи.

Это означает, что у них есть немного накладных расходов на добавление интервалов между задачами, так что, если одна из них задержится, это не приведет к опозданию следующей. Поэтому имейте в виду, что вы потеряете довольно небольшой процент процессорного времени для своего планировщика, но если это действительно проблема, найдите плату получше (например, TI TIVA/Energia IDE).

,

0

Вы можете использовать таймер с прескалером, установленным на 1, в сочетании с модулем счетчика. Прикрепите прерывания к событиям сравнения и переполнения. В соответствующих ISR вы ведете подсчет... У меня нет примера для вас, и это может быть немного сложнее, как реализовать ISR, но это наверняка возможно, если вы считаете разумное количество тактовых циклов (например, прерывание каждого цикла не будет работать, так как вычисления в ISR занимают некоторое время).

,