AVRdude неправильно считывает значения байтов предохранителя

Я изучаю микроконтроллер ATmega328P через стандартный Arduino UNO, с помощью avr-gcc toolchain и AVRdude (все в пакете WINAVR). Я успешно запрограммировал с его помощью плату несколько раз. Однако, когда я пытаюсь прочитать значения предохранителей через AVRdude, я получаю 0x0 для lfuse, hfuse и efuse.

Я использую следующую команду (или ее варианты) для чтения:
avrdude -c arduino -p ATmega328P -P com3 -b 115200 -v -F -U hfuse:r:hi_fuse_val.hex:h

Ниже приведен результат, который я получаю:

avrdude.exe: safemode: lfuse reads as 0
avrdude.exe: safemode: hfuse reads as 0
avrdude.exe: safemode: efuse reads as 0
avrdude.exe: safemode: lfuse reads as 0
avrdude.exe: safemode: hfuse reads as 0
avrdude.exe: safemode: efuse reads as 0

В файле hi_fuse_val.hex также записано 0.
Что я делаю не так?

, 👍1


1 ответ


Лучший ответ:

2

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

Нет самопрограммирования предохранителей

Загрузчик вообще не может писать предохранители. Чип просто не позволяет самопрограммировать предохранители. Если вы хотите изменить предохранители, вам нужно будет прибегнуть к внешнему программированию (обычно используя протокол ISP) с помощью программатора AVR (или другого Arduino, настроенного на работу как один).

Optiboot и чтение предохранителей

Optiboot не сообщает о предохранителях, по крайней мере, не так, как скомпилировано для UNO.

Протокол загрузчика "arduino", используемый опцией arduino avrdude -c, является модифицированной версией протокола STK500(v1). Это две команды, которые должны быть реализованы для чтения предохранителей, Cmnd_STK_READ_FUSE и Cmnd_STK_READ_FUSE_EXT. Они имеют соответствующие определения в копии источника optiboot ядра AVR Arduino. Но места, где они были бы реализованы в серии if-elses, отсутствуют. В отличие от записи предохранителей, чтение предохранителей возможно из кода AVR. Так что это не ограничение чипа, кода для этого просто нет.

Sidenote: Вы можете заметить, что есть также определения для команд, которые пишут ПРЕДОХРАНИТЕЛИ. Они существуют для программаторов STK500v1, а не для загрузчиков, которые могут реализовать их для поддержки записи предохранителей.

Для чего это стоит, optiboot на самом деле не читает подпись чипа. Он просто сообщает, какие значения были запечены во время компиляции. И это, и не читающие предохранители выше, вероятно, сделаны, чтобы держать optiboot как можно меньше, что и является его целью.

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

Текущие значения предохранителей

Если вам интересны ваши фактические значения предохранителей, вы запускаете sketch, который считывает их и печатает по последовательному каналу, используя #include <avr/boot.h><avr/boot.h> и

Serial.print('E');
Serial.print(':');
Serial.println(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS), HEX);

Serial.print('H');
Serial.print(':');
Serial.println(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS), HEX);

Serial.print('L');
Serial.print(':');
Serial.println(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS), HEX);
,

Большое спасибо за подробный ответ. Очень признателен., @Kraken