Как избежать случайной перезаписи прошивки - PullRequest
5 голосов
/ 17 февраля 2012

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

Как насчет того, когда у нас есть код, который записывает на флэш-память (например, загрузчик)?Теперь может случиться так, что мы случайно прыгнем прямо в код записи флэш-памяти - пропуская все проверки.Прежде чем сторожевой таймер начнет лаять, вы получите поврежденную прошивку.Это именно то, что происходило со мной.

Теперь некоторые могут сказать - исправить ошибку root, из-за которой мы даже запрыгнули в код записи.Ну, когда вы разрабатываете, вы постоянно меняете код.Даже если сейчас нет такой ошибки, завтра может быть.Кроме того, ни один код не содержит ошибок - или, по крайней мере, не мой.

Так что теперь я делаю какую-то перекрестную проверку.У меня есть переменная с именем 'wen', которую я устанавливаю в 0xa5 перед обычными проверками (например, проверяю, чтобы убедиться, что пункт назначения действителен).Затем, перед тем как приступить к фактическому стиранию или записи, я проверяю, действительно ли значение 'wen' равно 0xa5.В противном случае это означает, что мы как-то случайно запрыгнули в код написания.После успешной записи 'Вен' очищается.Я сделал это в C, и это сработало хорошо.Но теоретическая вероятность того, что произойдет повреждение, все еще незначительна, потому что от последней проверки 'wen' до записи в регистр SPMCR осталось немного инструкций.

Теперь я хочу улучшить это, поместив эту проверку в сборку, междуинструкция записи в SPMCR и spm.

__asm__ __volatile__
(   
    "lds __zero_reg__, %0\n\t"
    "out %1, %2\n\t"
    "ldi r25, %3\n\t"
    "add __zero_reg__, r25\n\t"
    "brne spm_fail\n\t"
    "spm\n\t"
    "rjmp spm_done\n\t"
    "spm_fail: clr __zero_reg__\n\t"
    "call __assert\n\t"
    "spm_done:"
    :
    : "i" ((uint16_t)(&wen)),
      "I" (_SFR_IO_ADDR(__SPM_REG)),
      "r" ((uint8_t)(__BOOT_PAGE_ERASE)),
      "M" ((uint8_t)(-ACK)),
      "z" ((uint16_t)(adr))
   : "r25"
);

Код еще не пробовал, сделаем это завтра.Вы видите какие-либо проблемы?Как вы решите такую ​​проблему?

Ответы [ 2 ]

3 голосов
/ 17 февраля 2012

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

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

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

2 голосов
/ 17 февраля 2012

Я не уверен, почему у вас должна быть возможность записи на флэш-память в вашем загрузчике.Наш загрузчик делает, потому что он может обновить прикладную программу через последовательный порт.Таким образом, мы исключаем возможность непреднамеренной записи, гарантируя, что загрузчик не содержит никакого кода, который записывает на флэш-память.Этот загружаемый код является заголовком в том же пакете, который содержит изображение для записи.Встроенное изображение хранит контрольную сумму алгоритма программирования и проверяет ее перед запуском.

Если вы пишете вещи, которые сгенерированы внутри, тогда я бы посмотрел на аппаратные блокировки.Разрешить запись только в том случае, если вы ранее установили конкретный вывод дискретного вывода в положение ON.Чтобы ответить на вопрос «что если IP перепрыгнет через чеки»?Вы можете сделать это в 2 частях.Сначала установите некоторые критические переменные для алгоритма.(например, адрес для записи - оставьте его инициализированным в недопустимую память и установите его правильно только в отдельном вызове, выполненном перед записью. Затем попросите функцию записи проверить вашу HW-блокировку. Выполните один из шагов включения в прерывании,или в ответ на таймер, что вряд ли удастся выполнить в правильной последовательности, если у вас есть мошеннический IP-адрес.

Если ваш IP-адрес действительно может куда-то перейти, возможно, будет невозможно предотвратить случайную запись.лучшее, на что вы можете надеяться, это то, что вы обеспечиваете единственный путь к нему и настраиваете все остальное, необходимое для успешной записи.

...