Запускать код один раз в жизни встроенной C-программы

8

Как сделать так, чтобы фрагмент кода запускался только один раз за время существования программы? Его можно выключить и включить много раз. Единственная возможность снова запустить фрагмент кода - это снова мигать.

Код - это раздел калибровки, который я не хочу запускать снова. Если я использую EEPROM или Flash, мы установим для флага значение true или false. Итак, когда мы впервые прочитаем эту область памяти, что будет случайным значением в этой области памяти?

Каков наилучший способ реализовать это во встроенном Си?

ganeshredcobra
источник
5
Используйте флаг и сохраните этот флаг в eeprom (или на вспышке). В каждое мгновение читайте флаг с EEPROM. В самый первый момент времени значение флага заставит функцию выполняться. После этого вы можете изменить значение флага и снова сохранить его в eeprom. Все остальное время значение флага не приведет к исключению функции.
hoo2
2
непонятно что ты спрашиваешь.
old_timer
2
Какова ваша мотивация для предотвращения запуска кода во второй раз? Важно ли, чтобы код нельзя было перепроектировать, и в этом случае установка флага для его обхода может быть недостаточно безопасной? Повторил ли бы запуск кода во второй раз, повредил бы аппарат? Является ли это UX-вещью, например, отображать учебное сообщение при первом использовании системы, и в этом случае может быть желательно, чтобы функция «возврата к заводским настройкам» (если имеется) инициировала повторный запуск кода?
Майкл Джонсон
5
Как правило, целесообразно предусмотреть повторную калибровку в случае, если что-то испортилось в первый раз, или если система нуждается в повторной калибровке для другой настройки или для компенсации старения оборудования и т. Д. Я, например, склонен сбивать калибровку в первый раз, потому что я не знаю, что я должен делать.
Майкл Джонсон
3
Как насчет того, чтобы настроить код так, чтобы был способ дать команду на его выполнение (т.е. отправить что-то через последовательный порт). Таким образом, нет необходимости беспокоиться о энергонезависимой памяти, и вы можете запускать калибровку во время производства контролируемым образом.
alex.forencich

Ответы:

18

Ваш микроконтроллер может иметь EEPROM, память OTP, биты пользовательских предохранителей, где вы можете установить флаг.

Не существует «лучшего метода во встроенном C», запись энергонезависимой памяти различна в каждом микроконтроллере.

редактировать:

ВСПЫШКА

Содержимое флэш-памяти стирается при программировании устройства. После программирования все не записанные байты содержат 0xFF. Обратитесь к таблице данных, чтобы найти область, которая может быть безопасно запрограммирована из запущенной прошивки.

EEPROM

Хотя это не гарантируется в таблицах данных, все EEPROM, которые я видел до сих пор, содержали 0xFF: s при поставке с завода (кроме тех, которые запрограммированы с уникальным MAC-адресом, но это явно задокументировано). Некоторые устройства программирования / программы также могут стирать или программировать содержимое EEPROM. Некоторые могут быть защищены от записи, постоянно или обратимо.

OTP

Программируемая однократная память всегда содержит четко определенные начальные значения, документированные в таблице данных.

Всегда полезно включать в записанные данные хорошую контрольную сумму, такую ​​как CRC32, для защиты от повреждения данных, вызванного неисправными деталями, ошибками передачи, космическими лучами и т. Д.

Беренди - протестующий
источник
Если я использую EEPROM или Flash, мы установим для флага значение true или False. Так что, когда мы впервые прочитаем эту ячейку памяти, какое будет случайное значение в этой области памяти.
Ганешредобра
2
Во время производства перезагрузите EEPROM (либо с помощью программатора, если это возможно, либо с помощью немой маленькой программы очистки, прошейте ее, включите ее в течение нескольких секунд, а затем загрузите в производственную программу).
Ник Т
13

Вы сказали:

Единственный вариант запуска этого кода должен снова мигать на плате.

Другие говорят, что используют EEPROM для хранения флага, чтобы указать, когда была запущена функция run_once (). Однако у этого есть недостаток, заключающийся в том, что если вы перепрошиваете микроконтроллер, флаг ran_it_once в EEPROM уже установлен, и функция run_once () не будет выполнена. Если ваш микроконтроллер имеет встроенную ЭСППЗУ, возможно, можно сбросить флаг ran_it_once при перепрошивке микроконтроллера, если программист поддерживает это.

Лучший способ - иметь номера версий как в EEPROM, так и в коде. Когда код запускается при включении питания, он должен прочитать номер версии из EEPROM и сравнить его с номером версии, хранящимся в коде. Если они не совпадают, то вызывается функция run_once (), и последним действием кода run_once () является запись номера версии прошивки в EEPROM. Каждый раз, когда вы изменяете исходный код прошивки, вы должны увеличивать номер версии, встроенный в него.

Стив Г
источник
1
Это на самом деле будет иметь ту же проблему, что и логический флаг, если все, что пользователь сделал, это перепрошит микроконтроллер, и его нужно будет снова запустить (в этом сценарии). Это определенно решило бы проблему, если бы микропрограмма была обновлена, и это должно было быть перезапущено.
Taegost
8

Выберите микроконтроллер, который может записывать / стирать собственную память программы. После выполнения рассматриваемого кода попросите последнюю часть указанного кода заменить первую инструкцию переходом, который ее обходит. При желании вы также можете стереть оставшуюся часть (возможно, заменить на nop), так что вероятность того, что она когда-либо снова будет выполнена, абсолютно отсутствует.

Это сообщение самоуничтожится в 5..4 ...

apalopohapa
источник
1
Каким бы умным ни был этот ответ, я думаю, что он излишне сложен. Возможно, он мог бы использовать примечание, указывающее, что его следует использовать только в том случае, если постоянная память вне памяти кода недоступна?
skrrgwasme
Даже если возможны другие решения, я думаю, что это легче понять, чем другие.
Джошуа
1
Даже если бы были возможны другие решения, я думаю, что это было бы очень трудно понять на уровне исходного кода.
CVn
Большинство PIC имеют только 35 инструкций ... что может пойти не так? ;)
rdtsc
5

Поскольку вы используете этот код для калибровки, я бы предложил создать процесс взрыва, который запускает код калибровки в качестве первого этапа и даже не помещать его в готовую рабочую версию платы. Это похоже на ответ от apalopohapa, за исключением того, что у вас будет две отдельные загрузки программы: начните процесс загрузки, который мигает при первой загрузке программы, которая выполняет все калибровки и выплевывает данные из этого. Затем возьмите эти данные и включите их в данные второй загрузки программы.

Одним из преимуществ этого подхода является то, что вы абсолютно минимизируете необходимый объем дискового пространства - вам не нужно хранить только один код, а только данные, которые он генерирует. Имея процесс взрыва, который загружает две отдельные программы, вы также немного изолируете себя от ошибок в коде инициализации, которые в противном случае могут остаться. У вас также есть некоторая дополнительная гибкость, если вы хотите перезапустить свой калибровочный код: вместо того, чтобы писать дополнительный код, чтобы очистить любой бит, обозначающий, что ваш код был запущен (который может быть случайно уже очищен), вы просто перезапускаете свой код. процесс взрыва.

Майкл
источник