Клон «Уно», купленный на распродаже, оказался не совсем Уно: чип жил от внутреннего генератора на 8 МГц, без кварца, — производитель сэкономил две копеечные детали. Скетчи заливались, но вели себя странно: мигалка шла вдвое медленнее ожидаемого, Serial печатал кашу, задержка «на 500 мс» тянула секунду. В меню «Процессор» варианта про 8 МГц не было и в помине — платформа о таком чип-варианте просто не знала.
Ситуация решается за пятнадцать минут, если знать, где нарисовано меню плат. А нарисовано оно текстовым файлом boards.txt: каждая карточка в «Инструменты → Плата» читается из него построчно. Дописать свой вариант, вылезти за заводской список процессоров, дать клону собственное имя в меню — работа с одним текстовым файлом, без единой строчки C++.
Этот урок — про то, как файл устроен, зачем свои варианты нужны (нестандартные клоны, свои фьюзы, флаги оптимизации) и как заводить их так, чтобы обновление платформы через месяц не стёрло работу. Если у вас голый чип на макетке, минимальную обвязку вы уже проходили в уроке про ATmega328P на макетке; здесь следующий шаг — научить среду видеть этот чип в меню.
Где лежит файл и как он читается
Адрес файла: внутри каталога настроек Arduino15 — на Windows это AppData\Local\Arduino15, на Linux ~/.arduino15, на macOS ~/Library/Arduino15 — дальше packages/<вендор>/hardware/<архитектура>/<версия>/boards.txt; для штатного AVR-ядра путь выглядит как packages/arduino/hardware/avr/1.8.6/boards.txt. Там же лежат platform.txt с рецептами сборки и programmers.txt — тройка файлов описывает платформу целиком, но меню плат рисует именно boards.txt.
Формат простой: одна строка — одно свойство, читается как имя_платы.свойство=значение. У заводской Uno: uno.build.mcu=atmega328p задаёт чип, uno.build.f_cpu=16000000L — тактовую частоту в герцах, uno.upload.maximum_size=32256 — потолок скетча во flash, uno.bootloader.low_fuses=0xFF — нижний байт фьюзов. Подменю «Процессор» собирается из секций menu.cpu: именно оттуда у Nano берутся «Old Bootloader» и новый — то самое меню, что спасало в уроке про старый загрузчик Nano.
Версий платформы обычно несколько: рядом с 1.8.6 лежит 1.8.13, а у ESP-пакетов — ещё и подпапки по вендору. Среда читает ту папку версии, что выбрана в Boards Manager, и правка «не той» папки невидима: файл редактировался, меню не изменилось, вина списана на «сломанную IDE». Я держу закладку файлового менеджера прямо на packages/arduino/hardware/avr и перед правкой смотрю версию в менеджере: две секунды против часа слепых правок не в ту папку.
Из свойств собирается вся сборка: компилятор получает частоту, макросы и размеры памяти, avrdude — скорость порта и фьюзы при записи загрузчика. Поменяете одну строку — среда соберёт иначе; допишете блок строк с новым именем — в меню встанет новая карточка. Никакой магии: меню плат — текстовый конфиг, как и всё остальное в платформе, путь к которой открывал урок про URL пакета.
Зачем свои варианты
Первый случай — нестандартное железо. Мой клон на внутреннем 8 МГц требует собственного пункта: build.f_cpu=8000000L, и скорость загрузчика 57600 вместо 115200, потому что загрузчик тактируется от той же частоты; не поменяли — получаете not in sync, только причина не в загрузчике, а в тактах. Скульптурный тест после смены пункта меню — мигалка: на верной конфигурации она идёт в реальном времени, на неверной — вдвое медленнее.
Второй случай — свои фьюзы. Запись загрузчика берёт их из того же файла: uno.bootloader.low_fuses=0xFF означает тактирование от внешнего кварца, для внутреннего генератора 8 МГц нижний байт — 0xE2; через перезапись загрузчика эти байты уезжают в чип. Свой блок строк — способ держать под рукой целую карту вариантов: кварц, внутренний генератор, пониженное питание — по пункту меню на каждый, без реестра статей в закладках.
Третий случай — флаги оптимизации. Заводские сборки идут с -Os, компактно; ради скорости крутят -O2 и -O3, а ядра на GCC 12 и новее понимают и -Oz — размер ещё агрессивнее. AVR-пакет с компилятором avr-gcc 7.3 про -Oz не знает: флаг уедет только в текст жалобы компилятора. Условие честное — сначала версия компилятора, потом флаги; разовый эксперимент удобнее вести через сборку в терминале Arduino CLI, меняя свойства одним параметром и не трогая файлы.
Экономика вопроса смешная: вариант — пять строк, три варианта — сорок строк с комментариями, а закрывают они всё нестандартное железо в ящике. У меня в local-файле три карточки: клон на внутреннем 8 МГц, голый чип на макетке и «учебная медленная» для воркшопов — на ней я нарочно показываю, что происходит при неверной частоте: мигалка тягучая, Serial в каше, а причина в одной строке f_cpu. Префикс свойств тоже свой — my-uno8.build.board=UNO_LOCAL: в подробном выводе сборки и во временных папках видно, какой вариант ехал, и чужой вопрос «а что у тебя собралось» решается одним взглядом в лог.
| Свойство | Заводская Uno | Мой вариант на внутреннем 8 МГц |
|---|---|---|
| build.mcu | atmega328p | atmega328p — чип тот же |
| build.f_cpu | 16000000L, внешний кварц | 8000000L, внутренний RC-генератор |
| bootloader.low_fuses | 0xFF | 0xE2 |
| upload.speed | 115200 | 57600 |
Правило: оригинал не трогаем
Соблазн вписать свой вариант прямо в заводской boards.txt велик и дорог: Boards Manager обновляет платформу, подменяя папку версии целиком, и правки исчезают вместе с ней. Я так потерял свой первый вариант в 2023 году: апдейт AVR-ядра — и в меню снова заводской список, а файл о потере не предупредил. Правило с тех пор одно: оригинал не трогаем, свои определения держим отдельными файлами.
Первый инструмент — boards.local.txt, соседний файл в той же папке версии. Строки из него перекрывают одноимённые строки boards.txt, а пункты меню, описанные только в нём, встают в «Инструменты» как родные. Две оговорки. Он живёт в той же папке версии, значит, обновление платформы снесёт и его — копия в git-репозитории проекта возвращает работу за минуту. И после любых правок среде нужен перезапуск: IDE 2 кэширует меню плат и без перезапуска честно показывает старое.
Второй инструмент — своя платформа в скетчбуке: папка Documents/Arduino/hardware/<бренд>/<архитектура>/, куда переносится полный набор из пакетной платформы — boards.txt, platform.txt, programmers.txt и папки bootloaders и variants; устройство скетчбука я разбирал раньше. Такая платформа переживает любые обновления менеджера: он про неё не знает и трогать не может, а в меню появляется карточка с вашим брендом. Настройка дольше, зато это дом для постоянных вариантов, а не съёмная квартира.
Проверка, что вариант встал, занимает минуту. Пункт появился в «Инструменты → Плата» — но только после перезапуска среды; напротив имени в подменю «Процессор» стоит ваш выбор. Финальный судья — подробный вывод сборки: строка с флагами компилятора печатает вашу частоту и ваши оптимизации, и по ней видно, что подхватилось именно из local-файла. Я смотрю на build.f_cpu в выводе: если там 16000000L, а чип живёт от внутреннего генератора, дальше собирать бессмысленно — правьте строки, перезапускайте, пересобирайте.
// Proverka svoyego varianta platy: migay LED i pechatay millis.// Esli f_cpu v konfige sovpadaet s realnoy chastotoy - period 500 ms tochen.// Esli konfig govorit 16 MHz, a chip zhivet na 8 - migalka v dva raza medlennee,// a Serial pechataet kashu: skorost zagruzchika tozhe ne sovpala. const int LED = 13;unsigned long tLed = 0;unsigned long t0 = 0;int migi = 0; void setup() { Serial.begin(9600); pinMode(LED, OUTPUT); Serial.println("proverka chastoty: zhdu 10 migov");} void loop() { if (millis() - tLed > 500) { tLed = millis(); if (digitalRead(LED) == HIGH) { digitalWrite(LED, LOW); } else { digitalWrite(LED, HIGH); } migi = migi + 1; if (migi == 10) { Serial.print("10 migov za "); Serial.print((millis() - t0) / 1000); Serial.println(" s - sovpalo s 5 sekundami? znachit, chastota iz konfiga vernaya"); t0 = millis(); migi = 0; } }}Разводка по инструментам, чтобы вечером не перебирать наугад. Разовый эксперимент с флагами и свойствами — через Arduino CLI в терминале: параметр --build-property меняет значение на один прогон, файлы остаются нетронутыми. Постоянный вариант своей платы — boards.local.txt для быстрого прототипа и своя платформа в скетчбуке для того, что живёт годами. Поддержка чужого семейства целиком — по-прежнему Boards Manager с URL пакета: расширения и местные файлы тут бессильны.
Мой итог той истории с клоном: пятнадцать минут на boards.local.txt, свой пункт в меню с честным названием «328P 8 MHz internal», и клон собирается без сюрпризов уже третий год. Файл с правками пережил два апдейта платформы и один переезд на новый ноутбук — потому что жил в git, а не в папке версии. В симуляторе выше — модель чтения того же файла: команды печатают путь, заводские строки и мой блок, кнопка переключает применённый вариант, а светодиод отыгрывает мигалку с периодом из конфигурации.
- 1. Что рисует пункты меню «Инструменты → Плата»?
- 2. Где лежит boards.txt штатного AVR-ядра?
- 3. Что происходит с правками boards.txt при обновлении платформы через менеджер?
- 4. Что делает boards.local.txt?
- 5. Флаг -Oz для AVR-ядра — что выйдет?
- Меню «Инструменты → Плата» читается из boards.txt: Arduino15/packages/<вендор>/hardware/<арх>/<версия>/.
- Свой вариант — свой блок строк: частота f_cpu, фьюзы для записи загрузчика, скорость порта, флаги оптимизации.
- Заводской boards.txt не правим: обновление платформы подменяет папку версии целиком.
- boards.local.txt перекрывает строки и добавляет пункты меню, но живёт в той же папке — копия в git обязательна.
- Дом для постоянных вариантов — своя платформа в скетчбуке: hardware/<бренд>/<арх>/ переживает любые обновления.
Частые вопросы по теме урока
- Что рисует пункты меню «Инструменты → Плата»?
- Каждая карточка в меню читается построчно из boards.txt платформы; подменю «Процессор» — из секций menu.cpu. boards.txt платформы
- Где лежит boards.txt штатного AVR-ядра?
- Путь: Arduino15 → packages → вендор → hardware → архитектура → версия. Windows: AppData\Local\Arduino15; Linux: ~/.arduino15. Arduino15/packages/arduino/hardware/avr/<версия>/
- Что происходит с правками boards.txt при обновлении платформы через менеджер?
- Обновление заменяет папку версии целиком. Поэтому правят не оригинал, а local-файл или свою платформу, с копией в git. папка версии подменяется целиком, правки исчезают
- Что делает boards.local.txt?
- Соседний файл рядом с boards.txt: одноимённые строки перекрывает, свои пункты меню ставит в «Инструменты». Живёт в той же папке версии — берегите копию. переопределяет строки boards.txt и добавляет свои пункты меню
- Флаг -Oz для AVR-ядра — что выйдет?
- -Oz понимают компиляторы от GCC 12; в AVR-пакете avr-gcc 7.3, доступны -Os, -O2, -O3. Сначала версия компилятора, потом флаги. avr-gcc 7.3 его не знает — компилятор ответит жалобой