Перейти к содержанию

Биты защиты AVR (lock bits)

У AVR кроме фьюзов есть ещё один байт конфигурации — байт защиты. Он решает, можно ли считать прошивку программатором и может ли загрузчик переписать сам себя. Arduino Uno поставляется с запрещённой записью в область загрузчика.

Обновлено Редакция GAW

Биты защиты (lock bits) — байт конфигурации AVR, который ограничивает доступ к памяти программ. Биты LB1 и LB2 запрещают программатору перезаписывать или читать флеш-память и EEPROM, а биты BLB0x и BLB1x у кристаллов с загрузчиком ограничивают, что команды SPM и LPM могут делать с разделами приложения и загрузчика. Как и у фьюзов, «0» означает «запрограммирован» (включён), «1» — «нет»; вернуть биты в 1 можно только полным стиранием кристалла (DS40002061B, разд. 28.1).

Байт защиты ATmega328P

БитИмяЧто защищает
5:4BLB12, BLB11раздел загрузчика (режимы BLB1)
3:2BLB02, BLB01раздел приложения (режимы BLB0)
1:0LB2, LB1вся память от программатора

Биты 7:6 не используются. У ATmega48A/48PA отдельного раздела загрузчика нет, и битов всего два — LB1 и LB2.

Режимы

РежимLB2 LB1Действие
11 1защиты нет
21 0программирование флеш и EEPROM запрещено, фьюзы заблокированы
30 0запрещены программирование и проверка (чтение), заблокированы фьюзы и BLB

Режимы BLB по табл. 28-3: в режиме 2 команда SPM не может писать в раздел, в режиме 3 к этому добавляется запрет LPM читать раздел из другого раздела, в режиме 4 — только запрет LPM. В режимах 3 и 4 действует и правило для прерываний: если векторы лежат в другом разделе, то при выполнении кода из защищённого раздела прерывания запрещены (DS40002061B, табл. 28-3). Так загрузчик защищает себя от случайной перезаписи прошивкой.

На практике

Arduino Uno: перед записью загрузчика ставится unlock_bits = 0x3F, после — lock_bits = 0x0F (boards.txt ArduinoCore-avr): загрузчик защищён от записи, а для программатора ограничений нет. Сигнатура кристалла читается и при включённой защите (разд. 28.3). Читают и пишут байт защиты как память lock в avrdude; соседние фьюзы удобно разбирать в калькуляторе фьюзов AVR.

Частые вопросы

Можно ли снять защиту и прочитать прошивку?

Снять — да, прочитать — нет. Биты защиты возвращаются в 1 только командой Chip Erase, которая стирает флеш-память и EEPROM; EEPROM уцелеет, только если запрограммирован фьюз EESAVE (DS40002061B, разд. 28.1, 28.7.3). После этого кристалл снова можно программировать, но исходная прошивка уже потеряна. В режиме LB 3 проверка (чтение) флеш программатором запрещена.

Что значит байт 0x0F у Arduino Uno?

В boards.txt для Uno указан lock_bits = 0x0F, то есть 0000 1111. Наш разбор по табл. 28-1–28-3 DS40002061B: BLB12 = BLB11 = 0 — режим BLB1 3, SPM не может писать в раздел загрузчика, а LPM из приложения не читает его; BLB02 = BLB01 = 1 и LB2 = LB1 = 1 — для приложения и для программатора ограничений нет. Перед записью загрузчика Arduino ставит unlock_bits = 0x3F.

Почему после записи битов защиты фьюзы не меняются?

В режимах LB 2 и 3 фьюзы заблокированы для последовательного и параллельного программирования (DS40002061B, табл. 28-2). Поэтому Microchip требует программировать фьюзы и биты BLB до битов LB, а изменить их потом можно только после Chip Erase.

Источники

  1. Microchip. ATmega48A/PA/88A/PA/168A/PA/328/P Data Sheet, DS40002061B — разд. 28.1 — у ATmega48A/48PA два бита защиты, у ATmega88A…328P шесть; «1» — не запрограммирован, «0» — запрограммирован; стираются в 1 только командой Chip Erase; табл. 28-1 — байт защиты: биты 5:4 BLB12/BLB11, 3:2 BLB02/BLB01, 1:0 LB2/LB1, биты 7:6 не используются; табл. 28-2 — режим LB 2 (LB = 10): дальнейшее программирование флеш и EEPROM запрещено, фьюзы заблокированы; режим 3 (LB = 00): запрещены и программирование, и проверка (чтение), заблокированы фьюзы и BLB; фьюзы и BLB программируют до LB; табл. 28-3 — режимы BLB0 (раздел приложения) и BLB1 (раздел загрузчика) 1–4: SPM не пишет, LPM не читает, прерывания из чужого раздела запрещены; разд. 28.3 — сигнатура читается и у защищённого кристалла; 28.7.3 — Chip Erase стирает флеш, EEPROM (кроме случая с запрограммированным EESAVE) и биты защиты, фьюзы не меняет
  2. Arduino. ArduinoCore-avr, boards.txt (commit 11b9130) — uno.bootloader.unlock_bits=0x3F, uno.bootloader.lock_bits=0x0F, загрузчик optiboot_atmega328.hex
  3. AVRDUDE v8.3, man-страница avrdude.1 — память lock (lockbits): один или четыре байта, обычно задаёт, разрешены ли внешнее чтение и запись флеш-памяти или её частей

Нашли ошибку?