Для электронщиков и радиолюбителей

Как работает загрузчик Arduino и что происходит в первые миллисекунды после сброса

Как работает загрузчик Arduino и что происходит в первые миллисекунды после сброса

Когда вы нажимаете кнопку Reset или загружаете скетч через USB, на плате происходит гораздо больше, чем кажется. В первые миллисекунды после сброса выполняется строго определённая последовательность аппаратных и программных событий. Разберём её на примере Arduino Uno с микроконтроллером ATmega328P.


1. Причины сброса: откуда всё начинается

Сброс может быть вызван:

  • нажатием кнопки Reset (низкий уровень на выводе RESET),
  • автосбросом через USB-UART при открытии порта,
  • сторожевым таймером (Watchdog),
  • просадкой питания (Brown-Out Detection),
  • включением питания (Power-On Reset).

Внутри ATmega328P есть схема детектирования сброса, которая формирует внутренний сигнал Reset и удерживает его, пока напряжение и тактирование не стабилизируются.


2. Тактирование: запуск кварца

На Arduino Uno используется внешний кварцевый резонатор 16 МГц. После сброса:

  1. Микроконтроллер запускает генератор.
  2. Ждёт стабилизации колебаний.
  3. Только после этого начинает выполнение кода.

Время ожидания задаётся fuse-битами. Это важно: если стартовать слишком рано, код начнёт выполняться при нестабильной частоте.


3. Fuse-биты: невидимая конфигурация

Fuse-биты — это конфигурационные флаги, записанные во внутреннюю память микроконтроллера. Они определяют:

  • источник тактирования,
  • включён ли делитель частоты,
  • активен ли bootloader,
  • включён ли Brown-Out Detection,
  • размер области загрузчика.

На Arduino Uno область bootloader занимает верхние 512 байт Flash-памяти. Именно туда передаётся управление после сброса.


4. Вектор сброса и переход к загрузчику

У AVR есть таблица векторов прерываний. Первый адрес — это вектор сброса.

Но если в fuse-битах установлен флаг BOOTRST, процессор после Reset переходит не к адресу 0x0000, а в область загрузчика — в верхнюю часть Flash.

Таким образом последовательность выглядит так:

Reset → запуск генератора → чтение fuse → переход в bootloader.


5. Что делает загрузчик

На Arduino Uno используется загрузчик Optiboot. Его задача:

  1. Инициализировать UART.
  2. Подождать короткое время (обычно около 500 мс).
  3. Проверить, пришла ли команда прошивки.
  4. Если команда есть — начать программирование Flash.
  5. Если нет — передать управление пользовательскому коду.

Загрузчик работает по протоколу STK500. Когда вы нажимаете «Загрузить» в IDE, компьютер:

  • открывает последовательный порт,
  • подаёт импульс DTR,
  • через конденсатор формируется кратковременный Reset,
  • микроконтроллер перезапускается и попадает в bootloader.

6. Автосброс через USB

На Uno установлен USB-UART преобразователь (ATmega16U2). Когда IDE открывает COM-порт, линия DTR опускается в ноль.

Через конденсатор 100 нФ этот импульс передаётся на RESET ATmega328P.

Это элегантное аппаратное решение позволяет:

  • автоматически входить в bootloader,
  • не нажимать кнопку вручную.

7. Если прошивки нет

Если в течение окна ожидания загрузчик не получает команду STK500, он выполняет прыжок по адресу 0x0000 — к пользовательской программе.

Этот переход обычно реализован как:

asm("jmp 0x0000");

После этого начинается выполнение уже вашего кода.


8. Что происходит перед вызовом setup()

До того как выполнится setup(), происходит ещё один этап — инициализация среды Arduino.

Компилятор добавляет служебный код, который:

  1. Инициализирует стек.
  2. Копирует глобальные переменные из Flash в SRAM.
  3. Обнуляет секцию BSS.
  4. Настраивает таймер 0 для millis() и delay().
  5. Настраивает прерывания.

Только после этого вызывается:

setup();

А затем в бесконечном цикле:

loop();

9. Временная диаграмма первых миллисекунд

Упрощённо процесс выглядит так:

0 мс — Reset
0–2 мс — стабилизация питания
2–5 мс — запуск кварца
5–10 мс — переход в bootloader
10–500 мс — ожидание команды прошивки
≈500 мс — переход к пользовательской программе

Поэтому при перезагрузке Arduino есть характерная пауза перед стартом скетча.


10. Почему это важно понимать

Понимание работы загрузчика помогает:

  • убрать задержку старта (записав код без bootloader через ISP),
  • реализовать собственный загрузчик,
  • диагностировать проблемы прошивки,
  • понять причины «мигания» светодиода при старте,
  • избежать ложных срабатываний устройств при Reset.

В критических системах иногда bootloader полностью отключают, чтобы старт происходил мгновенно.


11. Можно ли обойти загрузчик

Да. Если прошивать микроконтроллер через ISP-программатор:

  • bootloader не используется,
  • старт происходит сразу после Reset,
  • освобождаются 512 байт Flash,
  • исчезает задержка 0.5 секунды.

Это часто применяют в законченных устройствах.


Итог

В первые миллисекунды после сброса Arduino выполняет строго определённую цепочку:

  • аппаратная инициализация,
  • запуск тактирования,
  • анализ fuse-битов,
  • выполнение загрузчика,
  • проверка запроса на прошивку,
  • переход к пользовательскому коду,
  • инициализация среды Arduino,
  • вызов setup().

Эти процессы занимают доли секунды, но именно они определяют, насколько стабильно, быстро и предсказуемо стартует устройство.