Чип приехал в мягком конверте за 130 рублей: ATmega328P-PU, заводской, в антистатике. Я воткнул его в макетку, подал 5 вольт, подключил USB-UART адаптер к TX и RX, выбрал порт — и попытался залить мигалку. avrdude ответил stk500_recv(): programmer is not responding. Три попытки, две смены проводов, полчаса форумов. Чип не был бракованным: в нём не было загрузчика — той крошечной программы, через которую среда разговаривает с платой по UART.
Через неделю тем же способом молчать начала и моя рабочая Uno — после неудачного эксперимента с питанием. Светодиод L при этом честно мигал старой программой: flash цела, чип жив, а канал прошивки мёртв. Обе истории лечатся одной операцией — записью загрузчика заново. Ниже — что это за программа, как одна Uno прошивает другую или голый чип по шести проводам и какие ошибки я поймал за тот вечер, чтобы вы поймали меньше.
Загрузчик: 512 байт, на которых держится всё
Загрузчик — маленькая программа в самом конце flash-памяти, которая первой получает управление после ресета. На Uno это optiboot: 512 байт из 32 768. Меньше секунды после включения он слушает UART: если среда прислала команду — принимает прошивку и записывает её во flash; если тишина — передаёт управление скетчу, который уже лежит в памяти. Пауза примерно в секунду между подачей питания и первым миганием — это окно ожидания загрузчика, а не задумчивость платы.
Цена удобства видна из арифметики: из 32 768 байт скетчу остаётся около 32 256 — мелочь, и только проекты, упёршиеся в потолок, спасают заливкой через ISP, со всеми 32 килобайтами. Есть и обратный тест: нажмите RESET на Uno — с живым optiboot светодиод L мигнёт три раза подряд, загрузчик коротко представляется. Если тройки нет, а при заливке не мелькают огоньки TX и RX, канал разорван именно в месте загрузчика.
Чаще всего загрузчик не умирает — его там просто нет. Чипы, купленные отдельно для макеток, приходят с завода пустыми, и это норма, а не брак: завод не стал тратить место на optiboot. Второй типичный случай — чип прошивали через ISP целиком, поверх загрузчика: flash занята скетчем от первого до последнего байта.
Чтобы операция не выглядела магией, вспомним, как проходит обычная заливка — та, что мы разобрали в уроке про загрузку скетча. Среда дёргает линию DTR на USB-чипе, тот коротким импульсом роняет RESET, просыпается загрузчик, и по UART на 115200 бод в него летит прошивка. Если загрузчика нет, импульсу не на что отвечать — вот и not in sync вместо живых огоньков TX и RX.
Прежде чем объявлять загрузчик мёртвым, проверьте банальности: порт выбран, плата та самая — мы это проходили в уроке про плату и порт. Дальше — путь в обход: ISP-программирование по шине SPI, тем же способом, каким чип прошивают на заводе.
Arduino as ISP: одна Uno шьёт другую
Идея Arduino as ISP простая: одна Uno берёт на себя роль заводского программатора и шьёт чип-цель напрямую по SPI, минуя загрузчик. Сначала готовим программатора: Файл → Примеры → 11.ArduinoISP → ArduinoISP, заливаем на Uno обычной загрузкой — этот скетч и есть её новая профессия. Он ждёт команды по USB от среды и переводит их в сигналы SPI на пинах 11, 12 и 13.
Второй шаг, который я в первый раз пропустил: конденсатор 10 мкФ между RESET и GND на программаторе. Ставится он ПОСЛЕ заливки ArduinoISP, и вот почему: при открытии порта Uno авто-ресетится и сессия ISP срывается. Конденсатор этот импульс гасит. Но с конденсатором обычная загрузка на программатора тоже перестанет работать — поэтому строгий порядок: сначала скетч, потом конденсатор, потом сессия.
Дальше провода. От программатора к цели идут шесть линий: RESET, MOSI, MISO, SCK, 5V и GND — на Uno им соответствуют пины 10, 11, 12, 13. Если цель — вторая Uno, соединяйте пин с пином; для голого чипа сверяйтесь с распиновкой DIP-28. Шлейф из разноцветных перемычек, чтобы не путать линии, я описывал в уроке про провода и перемычки, а питание голого чипа с кварцем — в уроке про полярность и рельсы питания.
// Uno (программатор) -> цель: вторая Uno / голый ATmega328P// пин 10 -> RESET// пин 11 (MOSI) -> MOSI (ножка 17 чипа в DIP-28)// пин 12 (MISO) -> MISO (ножка 18)// пин 13 (SCK) -> SCK (ножка 19)// 5V и GND -> питание цели; на голом чипе — плюс кварц 16 МГц// и две керамики 22 пФ от кварца к GND// На программаторе после заливки ArduinoISP:// конденсатор 10 мкФ между RESET и GND, минусом к GND.Кнопки нажимаются в таком порядке. Инструменты → Плата: выбираете плату ЦЕЛИ, не программатора — для голого ATmega328P с кварцем 16 МГц это Arduino Uno. Инструменты → Программатор: Arduino as ISP — не перепутайте с Arduino as ISP for Mega, рядом лежит. Инструменты → Записать загрузчик.
Не перепутайте «Записать загрузчик» с «Загрузить через программатор»: вторая команда шьёт скетч поверх существующего загрузчика, первая — пишет сам загрузчик и заодно настраивает фьюзы чипа под выбранную плату. Для голого чипа профиль Uno означает внешний кристалл 16 МГц — кварц должен стоять ДО записи, иначе чип останется без тактирования, об этом отдельная история в плашке ниже. После успеха — ресет, заливаем Blink обычным способом из урока про мигалку и смотрим на L целевой платы.
| Симптом | Что происходит | Что проверить первым |
|---|---|---|
| stk500_recv(): not in sync | программатор не ответил среде | залит ли на Uno пример ArduinoISP; стоит ли конденсатор; не занят ли порт монитором |
| Yikes! Invalid device signature | цель ответила мусором | MOSI и MISO не перепутаны; кварц и 22 пФ на месте; контакты макетки дожаты |
| Expected signature … got 0x000000 | цель молчит совсем | питание 5V и GND; RESET идёт на пин 10; не оборван SCK |
| Пункт «Программатор» сбрасывается | среда не знает, чем шить | Инструменты → Программатор → Arduino as ISP выбран уже ПОСЛЕ выбора платы |
| Загрузчик записался, скетч по UART не едет | профиль цели не совпал с реальностью | что записали: плата в Инструментах должна отвечать тому чипу, который перед вами |
После успешной записи чип снова полноценная Arduino: скетчи едут по UART, RESET работает; повторная операция понадобится, только если вы снова что-то сломаете или соберёте партию чипов. Про партию — отдельный разговор: перекидывать шесть проводов на каждый чип быстро надоедает, для этого придуман внешний программатор, которому посвящён урок про USBasp.
Если же вы шли сюда, чтобы оживить собранный на макетке «почти-Uno» из голого чипа — поздравляю: дома теперь мини-завод. Следующая дверь — ATtiny85: тот же ISP и та же механика, но с сюрпризом в виде фьюзов, о котором расскажет соседний урок.
- 1. Светодиод L мигает старой программой, но новый скетч не заливается: not in sync. Что вероятнее всего?
- 2. В каком порядке ставить конденсатор 10 мкФ на RESET программатора?
- 3. avrdude пишет Yikes! Invalid device signature. С чего начать поиск?
- 4. Что делает «Записать загрузчик» на голый чип при профиле Arduino Uno?
- 5. Сколько flash остаётся скетчу на Uno с optiboot?
- Загрузчик — программа в конце flash: optiboot занимает 512 байт и слушает UART меньше секунды после ресета; без команды отдаёт управление скетчу
- Чипы из конверта приходят с завода без загрузчика — это норма, а не брак; тест живости: RESET на Uno мигает L три раза
- Arduino as ISP: сначала заливаем на Uno пример ArduinoISP, потом ставим конденсатор 10 мкФ на RESET, потом шесть проводов: 10-RESET, 11-MOSI, 12-MISO, 13-SCK, питание, земля
- «Записать загрузчик» = прошивка цели с её профилем: Uno ставит фьюзы на 16 МГц, поэтому кварц на голом чипе стоит до записи, а не после
- not in sync ищется по списку: нет скетча-программатора, нет конденсатора, занят порт; invalid device signature — провода SPI и тактирование цели
Частые вопросы по теме урока
- Светодиод L мигает старой программой, но новый скетч не заливается: not in sync. Что вероятнее всего?
- Мигающая старая прошивка — доказательство, что чип и flash живы: выходит из строя именно канал прошивки через загрузчик. Зарядный кабель проявлялся бы раньше: плата вообще не появилась бы в списке портов. Повреждён или отсутствует загрузчик при живом чипе и flash
- В каком порядке ставить конденсатор 10 мкФ на RESET программатора?
- Конденсатор гасит авто-ресет при открытии порта, но блокирует и обычную загрузку скетча на программатора. Поэтому строгий порядок: скетч — потом конденсатор — потом сессия ISP. После заливки ArduinoISP, перед сессией ISP
- avrdude пишет Yikes! Invalid device signature. С чего начать поиск?
- Сигнатура — ответ чипа на запрос по SPI: мусор в ответе означает проводку и тактирование. Драйвер и порт ни при чём: среда уже дошла до диалога с программатором, он отвечает за чип. Проверить, не перепутаны ли MOSI и MISO, и есть ли тактирование цели
- Что делает «Записать загрузчик» на голый чип при профиле Arduino Uno?
- Запись загрузчика прошивает цель целиком: и код optiboot, и конфигурацию фьюзов. Для профиля Uno это внешний кристалл 16 МГц — кварц обязан стоять до записи, иначе чип останется без тактирования. Записывает optiboot и настраивает фьюзы под внешний кристалл 16 МГц
- Сколько flash остаётся скетчу на Uno с optiboot?
- optiboot занимает 512 байт: 32 768 минус 512 — около 32 256. Полный размер достаётся только при прошивке через ISP, когда загрузчик не резервирует своё место. Около 32 256 байт