Что такое Fuse и Lock биты в AVR микроконтроллере, как с ними работать
В этой статье постараюсь кратко изложить суть того, чем являются конфигурационные (Fuse) и блокировочные (Lock) биты в AVR микроконтроллерах (МК) производства фирмы ATMEL.
Вы узнаете что такое Fuse и Lock биты, для чего они нужны, как с ними работать, приведу различные примеры из документации, а также несколько примеров работы с AVRDude.
Содержание:
- Что такое Fuse и Lock байты/биты?
- Для чего нужны биты конфигурации и блокировки
- Структура конфигурационного и блокировочного байта
- Работа с фьюзами и Lock-битами
- Пример установки Fuses с использованием AVRDude
- Пример установки Lock Bits с использованием AVRDude
- Выполняем расчет битов в байте вручную
- Заключение
Что такое Fuse и Lock байты/биты?
Слово "Fuse" (Фьюз) с английского переводится как "плавкий предохранитель". А слово "Lock" - "блокировка".
Fuse- и Lock-биты в AVR микроконтроллере содержатся в нескольких специальных байтах энергонезависимой памяти. Их можно представить себе как наборы специальных переключателей, положение каждого из которых влияет на определенный функционал и настройки в МК.
Каждый такой бит имеет специальное название и отвечает за некоторую закрепленную за ним функцию. Например установка фьюза "RSTDSBL" превратит пин для сброса (RESET) в обычный I/O-порт.
Особенность таких "переключателей" в AVR МК состоит не только в их назначении, но и в понимании микроконтроллером значений их бит:
- 1 - не активен (не установлен, не запрограммирован);
- 0 - активен (установлен, запрограммирован).
Это важно запомнить!
В общем понимании нам привычно что "1" является установкой значения (например контакты выключателя замкнуты и ток течет), а "0" - сбросом (контакты разомкнуты, ток не течет). Но в ситуации с Fuse- и Lock-битами в МК все иначе.
Почему же так сделано и зачем это нужно?
Дело в том, что установка каждого из фьюз- или лок-битов в AVR микроконтроллере - операция необратимая (как при пережигании нити плавкого предохранителя).
Например, если в каком-то МК установить (активировать, значение "0") специальный бит с названием "CKSEL0", то чип переключится на использование генератора тактовых сигналов с обязательным внешним кварцевым резонатором (кварцом). Если кварц не подключен, то генератор не заработает, не будет тактового сигнала - процессор микроконтроллера не запустится.
Вернуть обратно состояние такого бита при обычном программировании МК уже не получится. Сбросить его возможно удастся лишь используя специальный высоковольтный программатор, причем сброшены будут все данные в МК.
Вот почему такие биты называются "Fuse" (Фьюз, плавкий предохранитель)!
Давайте представим себе что Fuse-биты в одном из байтов AVR МК представляют из себя набор реальных плавких предохранителей (по английски "Fuses").
Микроконтроллер это понимает так: если нить "плавкого предохранителя" цела (преднамеренно не пережигалась) - то значение соответствующего ему бита равно "1" (не активен, не установлен).
Для установки нужных нам значений (битов) в Fuse-байте понадобится спалить соответствующие им "плавкие предохранители", то есть перевести их в состояние логического "0" (активен, уставновлен).
Рис. 1. Что такое фьюзы (fuses), пример кодирования с плавкими предохранителями.
На рисунке мы видим 8 плавких предохранителей, изменяя состояния которых можно запрограммировать 1 байт (8 бит) информации.
AVR микроконтроллер проверит состояния всех фьюз-битов и узнает что значения для номеров 1-3, 7 (отсчет справа налево) равны "0" - это соответствует состоянию "активен, установлен", что задаст некоторые параметры и включит нужный функционал.
Предохранители прожжены (по аналогии с Fuse-битами в МК значения установлены), возврат их состояний обратно электрическим способом невозможен...если конечно не запаять внутрь трубочек по кусочку проволоки (что по аналогии равно использованию специального высоковольтного программатора для МК).
Начиная работать с AVR микроконтроллерами кому-то может быть сложно понять зачем было ломать принятые и вполне логичные нормы где: 1=установлен, а 0=не установлен.
Но если исходить из названия "Fuse" и с пониманием того как такие "плавкие предохранители" работают в МК (прожигание нужных позиций для установки значений с необратимостью операции) - то все становится закономерно и вполне понятно!
Итак: Fuse- или Lock-бит в AVR MK имеющий числовое значение "0" является активным (установленным).
Для чего нужны биты конфигурации и блокировки
Итак, мы уже знаем что Fuse- и Lock-биты в AVR микроконтроллерах содержатся в специальной, независимой от питания чипа области памяти.
При помощи Fuse-битов можно установить различные режимы работы микроконтроллера, параметры подключенных к его портам пинов, задать источник тактового сигнала и его частоту, превратить пин для "Reset" в обычный порт ввода-вывода, а также многое другое.
Некоторые названия и описания часто используемых Fuse-битов в AVR МК:
- RSTDSBL (ReSeT DiSaBLe) - "запретить ресет", превращает пин для сброса МК в обычный порт ввода/вывода;
- CKSEL0..3 (ClocK SELect) - четыре бита для установки параметров и источника тактового сигнала МК (внешний кварц, внутренний RC-генератор, делитель частоты и т.п.);
- CKDIV8 (ClocK DIVision 8) - если этот бит установлен то тактовая частота от внутреннего RC-генератора будет делиться на 8;
- CKOPT (ClocK OPTimization) - задает размах сигнала (амплитуду) с выходного тактового генератора, оптимизация потребляемого тока, влияет на помехоустойчивость;
- SUT0..1 (Start Up Time) - установка временной задержки запуска программы после подачи питания или перезапуска МК;
- SPIEN (Serial Programming Interface ENable) - разрешение/запрещение программирования МК через последовательный программный интерфейс;
- JTAGEN (JTAG ENable) - разрешает/запрещает использование JTAG интерфейса;
- EESAVE (EEprom SAVE) - если этот бит установлен, то содержимое энергонезависимой памяти будет сохранено после стирания кристалла (опция -e в AVRDude);
- WDTON (Watch Dog Timer ON) - отключение программного управления сторожевым таймером, запуск таймера автоматически при подаче питания на МК;
- BODEN (Brown-Out Detection ENabled), BODLEVEL (Brown-Out Detection LEVEL) - биты для включения и настройки мониторинга за напряжением питания МК;
- BOOTRST (BOOT ReSeT) - выполнять запуск через загрузчик (Boot Loader), микроконтроллер начнет выполнение программы не с адреса 0x0000 (по умолчанию), а с адреса где расположен загрузчик.
Важно заметить что при установке фьюза RSTDSBL теряется возможность перепрошивки МК через ISP-интерфейс. Тем не менее, с использованием высоковольтного (+12В) параллельного программатора перепрошивка все же возможна.
Биты блокировки (Lock bits) позволяют установить режимы доступа (запись/чтение) к внутренней Flash-памяти и/или EEPROM, причем направление доступа можно ограничить как изнутри микроконтроллера, так и снаружи (при использовании ISP-интерфейса).
Данная возможность может быть полезна для защиты от копирования/изменения вашей программы, а также хранящихся в энергонезависимой памяти данных.
Структура конфигурационного и блокировочного байта
Фьюзы (фьюз-биты) содержатся в трех байтах:
- Fuse Low Byte - младший байт;
- Fuse High Byte - старший байт;
- Fuse Extended Byte - байт с опциями расширенных функций.
Блокировочные биты (Lock Bits) микроконтроллера расположены в отдельном блокировочном байте. Не редко можно слышать что их относят к фьюзам, но это не так, не стоит путать, тем более что названы они так чтобы можно было их четко различать.
У каждой модели микроконтроллера есть свой набор доступных к изменению фьюзов и блокировочных битов. Чтобы более детально разобраться со структурой Fuse- и Lock-байтов в интересующем вас МК - нужно обратиться к официальной документации (даташиту) по конкретной модели микроконтроллера.
Ниже приведен пример структуры Fuse-байтов для микроконтроллера ATTiny13. В первой строке идет номер бита, во второй - название, а в третьей - значение по умолчанию. Помним что значение 0 = бит установлен (запрограммирован).
Младший Fuse-байт (Fuse Low Byte):
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
SPIEN | EESAVE | WDTON | CKDIV8 | SUT1 | SUT0 | CKSEL1 | CKSEL0 |
0 | 1 | 1 | 0 | 1 | 0 | 1 | 0 |
Как видим, интерфейс последовательного программирования (SPI) по умолчанию разрешен, частота внутреннего тактового генератора делится на 8 (CKDIV8), в качестве источника тактового сигнала используется внутренний RC-генератор (CKSEL0).
Старший Fuse-байт (Fuse High Byte):
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
- | - | - | SELFPRGEN | DWEN | BODLEVEL1 | BODLEVEL0 | SRTDISBL |
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
В данном фьюз-байте все биты неактивны (не запрограммированы).
Структура блокировочного байта (Lock Byte):
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
- | - | - | - | - | - | LB2 | LB1 |
1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
Установка бита под номером "0" (LB1) в "0" (активен) запретит программирование внутренней Flash и EEPROM памяти. Если еще дополнительно установить бит под номером 1 (LB1) то это дополнительно заблокирует возможность считывания данных с памяти МК ATTiny13.
Данную информацию я легко получил, скачав даташит на ATTiny13 в формате PDF, для этого достаточно выполнить поиск в интернете в поисковой системе по запросу "ATTiny13 datasheet download".
Открыв документ ищем раздел "Memory Programming". Как правило, PDF-файл с даташитом на микроконтроллер занимет от 1 до 10МБ. Документы от ATMEL хорошо структурированы, содержат хорошую внутреннюю навигацию со ссылками и содержанием, очень удобно искать нужную информацию.
Работа с фьюзами и Lock-битами
Выполнять установку фьюз-битов и битов блокировки нужно очень и очень аккуратно, с уверенным пониманием того что и для чего выполняется!
Невнимательность и лень в изучении документации может стать причиной неработоспособности используемого AVR микроконтроллера.
Самая безопасная стратегия при записи фьюзов и блокировочных битов:
- Читаем значение нужного байта из МК;
- Устанавливаем в полученном байте нужные биты, все внимательно проверяем;
- Записываем результирующий байт в МК.
Почему именно так, а не сразу запись в МК? - потому что преследуя некоторую цель с установкой одного бита, можно нарушить состояние других битов, что может повлечь за собой, к примеру, переключение МК на источник тактового сигнала который не предусмотрен и микроконтроллер просто не запустится.
Важно помнить что в случае выполнения операции стирания (опция "-e" в AVRDUDE) все Fuse и Lock биты будут восстановлены по умолчанию, а записанная во Flash-память программа уничтожена.
Пример установки Fuses с использованием AVRDude
Допустим что нам нужно выполнить сброс фьюза CKDIV8 в младшем байте, эта операция заставит микроконтроллер ATTIny13 работать на тактовой частоте 8МГц вместо 1МГц (когда бит установлен то частота делится на 8).
Попробуем выполнить чтение байта с фьюзами, изменим один бит (установим фьюз), а потом выполним запись в МК при помощи AVRDude на примере малыша ATTiny13.
Если возникнут вопросы при работе с "дудкой" - читаем документацию по AVRDude.
Итак, изучаем документацию (даташит, datasheet) по микроконтроллеру и подключаем его к программатору.
Рис. 2. Микроконтроллер ATTiny13 подключен к программатору USB ISP.
По умолчанию, при запуске AVRDude выводит на экран значения всех трех байтов с фьюзами, достаточно подключить МК к программатору и выполнить команду с нужными настройками (в данном случае МК - ATTiny13, программатор - USB ISP):
avrdude -p t13 -c usbasp
Вывод команды:
avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e9007
avrdude: safemode: Fuses OK (E:FF, H:FF, L:6A)
avrdude done. Thank you.
Как видим, значения байтов следующие:
- E - расширенный Fuse-байт (Extended) = FF (0xFF);
- H - старший байт (High Byte) = FF (0xFF);
- L - младший байт (Low Byte) = 6A (0x6A).
Также значение любого из фьюз-байтов можно считать и сохранить в файл. К примеру, запишем значение младшего фьюз-байта (Low Fuse Byte, lfuse) в файл "lfuse.txt" и выведем его содержимое на экран:
avrdude -p t13 -c usbasp -U lfuse:r:lfuse.txt:h
cat lfuse.txt
Значение младшего байта с фьюзами сейчас - 0x6A, что в двоичном представлении равно 01101010 - именно то, что я приводил в структуре младшего фьюз-байта для ATTiny13 по умолчанию.
Теперь нам нужно изменить значение бита CKDIV8 в байте 01101010 на 1 (сбросить его), получаем двоичное число 01111010, которое равно 0x7A.
Раньше я уже описывал как работать с битами, а также как удобно переводить числа из одной системы счисления в другую. В одном из следующих разделов также опишу как выполнять расчет битов в байте простым "ручным" способом.
Итак, записываем новое значение в байт с фьюзами в микроконтроллере с помощью AVRDude:
avrdude -p t13 -c usbasp -U lfuse:w:0x7a:m
Вот расшифровка "магии" с параметрами "-U lfuse:w:0x7a:m":
- -U - опция, указание на выполнение операции с памятью;
- lfuse - область памяти, младший байт который содержит фьюзы (Low Fuse Byte);
- : - разделитель;
- w - значит что будет выполняться операция записи (write);
- 0x7a - значение байта для записи в указанную область памяти;
- m - указывает что данные (значение байта) будут указаны прямо в командной строчке.
Результат выполнения команды:
avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e9007
avrdude: reading input file "0x7a"
avrdude: writing lfuse (1 bytes):
Writing | ################################################## | 100% 0.01s
avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0x7a:
avrdude: load data lfuse data from input file 0x7a:
avrdude: input file 0x7a contains 1 bytes
avrdude: reading on-chip lfuse data:
Reading | ################################################## | 100% 0.00s
avrdude: verifying ...
avrdude: 1 bytes of lfuse verified
avrdude: safemode: Fuses OK (E:FF, H:FF, L:7A)
avrdude done. Thank you.
Как видим, все удачно записалось и прочиталось - "Fuses OK (E:FF, H:FF, L:7A)"! Теперь микроконтроллер должен работать на частоте 8МГц.
Для записи старшего или расширенного байтов нужно 'lfuse' заменить на 'hfuse' (старший байт) или на 'efuse' (байт с расширенными настройками).
Также в одном вызове команды avrdude можно указать запись сразу нескольких байтов.
Примеры команд (данные "0x.." заменены на XXXX, там должны быть ваши значения для каждого из байтов):
# Установка Младшего + Старшего байтов, две команды
avrdude -p m8 -c usbasp -U lfuse:w:XXXX:m
avrdude -p m8 -c usbasp -U hfuse:w:XXXX:m
# Установка Расширенного байта
avrdude -p m8 -c usbasp -U efuse:w:XXXX:m
# Установка Младшего + Старшего байтов, одна команда
avrdude -p m8 -c usbasp -U lfuse:w:XXXX:m -U hfuse:w:XXXX:m
# Установка Младшего + Старшего + Расширенного байтов
avrdude -p m8 -c usbasp -U lfuse:w:XXXX:m -U hfuse:w:XXXX:m -U efuse:w:XXXX:m
Важно! Перед записью байтов фьюзов в микроконтроллер:
- Считываем состояния байтов в МК;
- Сопоставляем данные с теми которые должны быть записаны с учетом уже установленных значений (заводских, по умолчанию);
- Записываем измененные и проверенные значения в МК.
Пример установки Lock Bits с использованием AVRDude
Для установки битов блокировки (Lock Bits) в микроконтроллере используем аналогичную стратегию, но есть и отличия. Для считывания значения байта, содержащего биты блокировки, понадобится указать AVRDude выполнить операцию чтения из памяти.
Считываем текущее значение байта с битами блокировки в файл "lock.txt" и выводим содержимое этого файла на экран:
avrdude -p t13 -c usbasp -U lock:r:lock.txt:h
cat lock.txt
Расшифровка параметров:
- -U - выполнение операции с памятью;
- lock - область памяти, которая содержит фьюзы блокировки (Lock Fuses);
- : - разделитель;
- r - значит что будет выполняться операция чтения (read);
- lock.txt - имя файла, в который будет записана считываемая из памяти информация;
- h - формат данных шестнадцатеричный (hexadecimal).
Результат работы команд:
avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.00s
avrdude: Device signature = 0x1e9007
avrdude: reading lock memory:
Reading | ################################################## | 100% 0.00s
avrdude: writing output file "lock.txt"
avrdude: safemode: Fuses OK (E:FF, H:FF, L:7A)
avrdude done. Thank you.
0x3f
Текущее значение байта с Lock Bits - 0x3F, что в двоичном представлении равно 00111111. В даташите на ATTiny13 указано что для изменения значимы только два бита - 00111111.
Изменив эти биты на 0 мы активируем соотвествующие биты блокировки, чем заблокируем возможность программирования и чтения внутренней Flash + EEPROM. В результате наш байт будет выглядеть вот так - 00111100, а в шестнадцатеричном представлении - 0x3C.
Для записи байта c Lock-битами в микроконтроллер ATtiny13 нужно выполнить следующую команду:
avrdude -p t13 -c usbasp -U lock:w:0x3c:m
Будьте предельно внимательны с этой командой, поскольку изменение Lock-битов может повлечь за собой необратимые последствия!
Выполняем расчет битов в байте вручную
Расчет значения байта с установленными нужными в нем битами для AVR микроконтроллера можно выполнять в различных онлайн-калькуляторах, ссылка на один из таких приведена в конце статьи.
Тем не менее, важно уметь выполнить такие расчеты "вручную", то есть изучив документацию по микроконтроллеру самому составить нужную последовательность бит и перевести состоящий из них байт в двоичный (Binary) или шестнадцатеричный (HEX) вид.
Допустим что изучив структуру фьюзов микроконтроллера ATTiny13 нам нужно в младшем Fuse-байте выполнить следующее:
- Сбросить фьюз (CKDIV8) - 4-й бит уствновить в 1;
- Активировать фьюз (EESAVE) - 6-й бит установить в 0.
Итак, у нас есть новенький микроконтроллер и значение младшего Fuse-байта по умолчанию - "0x6a" (0x - значит что значение представлено в HEX-формате, это число мы узнали считав значение байта при помощи AVRDude, а также из документации).
Теперь нам нужно число "0x6a" перевести в двоичное представление, это можно сделать используя специализированный математический калькулятор, а можно просто разделить значение на две части и воспользоваться табличкой что ниже.
Binary | 0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 |
HEX | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
Binary | 1010 | 1011 | 1100 | 1101 | 1110 | 1111 |
HEX | A | B | C | D | E | F |
Разделяем значение "6A" (0x6a) на две части - "6" и "A", ищем в табличке соответствующие бинарные представления - 0110 (6) и 1010 (А). Значение 0x6a в двоичной системе счисления - 01101010.
Теперь изменим 4-й бит в байте на 1, а 6-й бит - на 0: [7й бит->] 00111010 [<-0й бит]
Разделяем полученное бинарное представление 00111010 на две равные части: 0011 и 1010. Конвертируем эти части в HEX, используя табличку выше: 0011 = 3, 1010 = A.
Соединяем полученные цифры в шестнадцатеричном формате: 0011 1010 = 3A. Получается, для того чтобы сбросить фьюз 4 (CKDIV8), а также активировать фьюз 6 (EESAVE) - нужно в младший фьюз-байт записать значение "0x3a".
Заключение
Работа с Fuses в AVR-микроконтроллере - это относительно не сложно, но стоит проявить внимательность. Главное не спешить и не лениться сверяться с официальной документацией.
Всю рутину по записи и считывании значений берет на себя "швейцарский нож" из мира AVR по имени AVRDude, нам лишь остается только правильно выполнить расчет нужного байта с фьюзами.
Удачного и результативного программирования!
Начало цикла статей: Программирование AVR микроконтроллеров в Linux на языках Asembler и C.
Полезные ресурсы:
Спасибо за очень полезный, информативный, интересный и крутой цикл статей о программировании Avr под Линукс для чайников и самоваров
если выставил неправильно фьюзы, их потом можно исправить после неправильной прошивки ? и так же с локами ?
разобрался вроде, если стереть чип, то "предохранители" можно по новой "пережигать" ?
После ошибочной установки некоторых фьюзов, внутрисхемное программирование микроконтроллера (ISP - In System Programmable) может стать недоступным:
Чтобы выполнить сброс фьюзов в МК и вернуть возможность последовательного программирования существуют специальные высоковольтные (+12В) программаторы, работающие в режимах HVPP (High Voltage Parallel Programming) и HVSP (High Voltage Serial Programming).
Подобное устройство можно заказать в готовом виде или же изготовить самостоятельно по одной из схем, которые можно отыскать в интернете используя примерно следующие ключевые слова: "avr fuse doctor", "fusebit doctor".
Очень интересная познавательная статья, но хотелось бы кое что уточнить более конкретно.
Как установить в AVRDUDE в Fuse Extended значение HEX равное F9 вместо 01?
Приветствую, Сергей!
Установку 'расширенного' байта (Extended Fuse) можно выполнить указав название области памяти 'efuse' (от extendedfuse).
Добавил примеры в статью.
Первый раздел переработан, более подробно описана аналогия и пример с плавкими предохранителями.
К примеру, нам нужно убрать фьюз CKDIV8 в младшем.....Что такое убрать ? Есть установить , сбросить В гугле нет такого термина для битов и бойтов . Куда убрать ?
Исправил. Спасибо.
Интересно, а как-то можно одной командой прошить, верифицировать и установить lock фьюзы? При одновременной прошивке верификация не проходит(
Уважаемый ph0en1x, спасибо вам за ваш труд. Материал достойный внимания!)
Но тем не менее есть вопрос )).
Скажите как быть, если в даташите нет конкретных таблиц с базовыми значениями фьюз битов???
Точнее есть одна таблица, но там весьма странные значения и нет конкретики и четкости.
Микроконтроллер Atmel AT89S52-24AI.
На примере Tiny13 вопросов вообще нет, тут же....
Скачивал даташиты разные, но нигде так и не нашел).
Стало интересно и стал смотреть другие микроконтроллеры (даташиты) у каких - то нет таблиц с EXTENDED фьюзами, а LOW и HIGH есть...
В общем неразбериха. Не могли бы пояснить?
Здравствуйте.
В разных микроконтроллерах может быть разный набор как функционала, так и фьюзов с блокировочными битами.
Даташиты, актуальную и наиболее полную информацию по AVR МК стоит искать на официальном сайте - microchip.com (Microchip купили Atmel в 2016-м году).
Искать информацию по даташиту (PDF) можно используя ключевые слова (например "fuse"), для этого как правило достаточно в программе для просмотра PDF вызвать окно поиска (комбинация клавиш CTRL+F).
AT89S52 - недорогой, совместимый с Intel MCS-51 (8051) микроконтроллер.
Размер даташита на МК AT89S52 - примерно 500Кб, там всего 38 страниц. Чип содержит три блокировочных бита. О фьюзах нигде даже не упоминается. Функционал в целом скромный, пинов (40-44 шт.) хватает под нужные задачи, фьюзы похоже что не понадобились.
Если взять более солидный МК и з серии AT89х, например AT89LP6440 - получим более обширный функционал, также есть фьюзы, которые управляют разными полезными возможностями. Даташит тут также посолиднее - целых 200 страниц.
Если взять ATtiny13 - то тут набор периферии и пинов достаточно скромный, но введение фьюзов нужно как минимум для добавления еще одного порта ввода/вывода путем превращения в него пина "Reset" (фьюз-бит RSTDSBL).
Наличие и конфигурация фьюзов в разных МК зависит от их функционала, набора периферии и т.д.