Зачем нам нужен загрузчик отдельно от нашей прикладной программы в микроконтроллерах?

28

Зачем нам нужна отдельная программа в той же флэш-памяти программ микроконтроллера, в частности STM32F103, которая называется загрузчиком?

Что особенного в этом, чтобы отделить его от основной прикладной программы?

Вообще говоря, выполняет ли загрузчик системы на основе микропроцессора (скажем, PowerPC MPC8270) ту же работу, что и микроконтроллер (скажем, ARM STM32F103), или они выполняют принципиально разные задачи друг от друга, и оба они называются «загрузчиками»? ?

альт-роза
источник
2
по той же причине, по которой у вас есть отдельные микросхемы и детали, а не одна гигантская монолитная структура
Эмоб
Вы не Просто введите вашу программу с помощью переключателей и индикаторов на консоли компьютера.
Hot Licks
1
Строго говоря, вам не нужна отдельная программа загрузчика на микроконтроллере. Но мы чаще всего выбираем один для дополнительных функций полезности, которые он предлагает. Если эти функции не нужны, не нужны, то вы можете удалить загрузчик. Загрузчик микроконтроллера обычно используется для записи новой программы во флэш-память. Иногда его можно использовать для отладки функций, некоторых точек останова поддержки и других полезных функций. На микрокомпьютере, как правило, загрузчик загружает программы из массовой памяти и будет там необходим.
ghellquist

Ответы:

55

Загрузчик на микроконтроллере отвечает за обновление основной прошивки по каналу связи, отличному от заголовка программы. Это полезно для обновления встроенного программного обеспечения в полевых условиях через BLE, UART, I2C, SD-карты, USB и т. Д. Было бы крайне неудобно требовать от покупателей приобретать программаторы только для обновления встроенного программного обеспечения на своих устройствах.

Причина, по которой загрузчик хранится отдельно, заключается в надежности. Загрузчик и код приложения размещены в отдельных разделах флэш-памяти, поэтому код приложения может быть удален и перезаписан загрузчиком без изменения чего-либо, связанного с кодом загрузчика.

Если загрузчик и приложение были сохранены вместе, то код загрузчика должен быть скопирован в ОЗУ, прежде чем он сможет работать, так как любое обновление прошивки удалит код загрузчика во флэш-памяти. Если отключить питание с помощью кода загрузчика в ОЗУ и очистить флэш-память, устройство будет заблокировано.

CurtisHx
источник
3
У нас та же причина. Они находятся в одной и той же флэш-памяти, но загрузчик выровнен по границе стирания флэш-памяти и достаточно умен, чтобы стирать флэш-память только выше ее собственных адресов.
Джошуа
3
В некоторых случаях программный заголовок микропроцессора может быть фактически недоступен без разборки шасси продукта, поэтому возможность перепрограммировать его по шине связи без дополнительного оборудования является ключевым фактором для надежности.
Джон Го-Соко
6
@ alt-rose Загрузчик и прикладная программа - это отдельно скомпилированные программы, каждая из которых имеет свой собственный код запуска и main()функцию. При включении питания загрузочный код запускается и вызывает загрузчик main(). Программа начального загрузчика проверяет правильность прикладной программы и затем переходит к коду запуска прикладной программы, который вызывает прикладную программу main(). Код запуска каждой программы инициализирует среду выполнения C для соответствующей программы (т. Е. Инициализирует переменные, стек и т. Д.) И, как правило, ни одна из программ main()никогда не возвращается к коду запуска.
Ккрамбо
1
@ alt-rose: Точно так же, как процессор получает начальный адрес загрузчика - это не так. Вместо этого ЦП указывает, что он будет использовать в качестве начального адреса загрузчика, а загрузчик указывает, что он будет использовать в качестве начального адреса прикладной программы.
MSalters
4
@kkrambo Несмотря на то, что обычно это правда, не существует требования (и не является общепринятым фактом), что загрузчик должен быть написан на C или языке, производном от C, с буквой a main.
Якк
26
  1. Так что процесс загрузки может восстановиться после ошибок. Предположим, что произошла ошибка связи или отключение питания во время обновления. Если бы загрузчик был частью приложения, которое вы обновляли, то пользователь не смог бы повторить попытку без использования специального оборудования для перепрошивки на загрузчик.

  2. Некоторые микроконтроллеры не могут выполнять код из оперативной памяти. Если загрузчик был смешан с остальной частью программного обеспечения, вы фактически не смогли бы обновить свое программное обеспечение, потому что вы не можете стереть страницы флэш-памяти, из которых вы сейчас выполняете. Обходной путь - сначала записать новый код во вторую половину флеш-памяти, а затем перейти к нему. Новый код затем копирует себя в первую половину флеш-памяти. Конечно, недостатком является то, что горение флэш-памяти обычно происходит медленно, и теперь, когда вам приходится делать это дважды, процесс загрузки может занять вдвое больше времени. Кроме того, этот обходной путь ограничивает размер вашего приложения, чтобы он не превышал половины вашей общей флэш-памяти.

  3. Хорошо написанные загрузчики пытаются проверить, что на устройстве существует действительный код, прежде чем пытаться его выполнить. Если загрузчик и другой код были смешаны вместе, то как вы могли быть уверены, что ваша подпрограмма проверки будет работать, если весь код не загрузится?

  4. Аутентификация. Безопасные загрузчики перед выполнением пытаются проверить, что загруженное приложение соответствует цифровой подписи. Но если загрузчик и другой код были смешаны вместе, вы не можете контролировать то, что выполняется на устройстве, потому что, как только пользователь загружает новый код, вы не можете контролировать то, что происходит при запуске.

user4574
источник
4
Как пример пункта 2, некоторые микроконтроллеры могут даже не иметь доступной оперативной памяти при запуске: например, Raspberry Pi использует свой графический процессор для загрузки загрузчика с SD-карты, которая затем включает процессор ARM и память.
ErikF
11

Они обычно там, чтобы позволить вам обновить вашу основную прикладную программу.

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

Colin
источник
9

Загрузчик позволяет MCU взаимодействовать с чем-то другим, чтобы принять новую программу, сохранить ее и запустить после сброса. Если у вас не было загрузчика, то нужен программист для доступа к памяти и установки программы на место.

CrossRoads
источник
2
Вот и все. MCU может получать код только через специальную программную подсистему (например, AVRICE или JTAG) или уже имея флэш-загрузчик. Это решение приложения о том, насколько сложен загрузчик, например, некоторые системы могут загружать код из WiFi. На очень низкоуровневых микроконтроллерах, таких как ATTiny, загрузчик (и последовательные выводы) являются большими накладными расходами, поэтому вы всегда используете программиста.
Богатое
7

В дополнение к другим правильным ответам о разрешении перепрограммирования основной прошивки из загрузчика, другое преимущество наличия отдельного загрузчика состоит в том, что вы можете логически отделить задачи «сделать один раз при загрузке» от кода, который вам нужен во время выполнения. Затем, после того, как загрузчик завершит свои начальные задачи по настройке, основная микропрограмма может вытеснить загрузчик со всем его ненужным кодом из памяти, экономя значительное пространство ОЗУ. Этого можно достичь и другими способами, но разделение загрузчика и встроенного ПО значительно упрощает работу на многих архитектурах.

Nate S - Восстановить Монику
источник
1
На микроконтроллере код, скорее всего, никогда не находится в оперативной памяти, поэтому его нельзя удалить. Конечно, вы можете сбросить данные загрузчика из ОЗУ.
Бен Фойгт
@ BenVoigt, это зависит от микроконтроллера. Некоторые (в основном те, которые имеют NOR flash) позволят вам выполнять напрямую без флеш-памяти, но другие (обычно с NAND flash, который становится все более распространенным) требуют, чтобы вы выполняли из ОЗУ. Иногда нет даже встроенной флэш-памяти, и вам необходимо скопировать код с внешней флэш-микросхемы в локальную память SRAM, прежде чем вы сможете выполнить что-либо.
Nate S - Восстановить Монику
2

Короткий ответ, потому что программное обеспечение является удивительным.

Вы можете иметь все, что загрузчик делает «чисто аппаратным». Но гораздо, намного, намного проще иметь задачи, которые загрузчик действительно записывает как программный, а затем интерпретировать аппаратно.

Эти задачи могут включать настройку аппаратного обеспечения для запуска «настоящего» программного обеспечения (например, на Raspberry Pi (через @ErikF)), наличия протокола для замены «настоящей» программы перед ее запуском (проверьте вывод, если этот пин-код устанавливается, затем перепрошивается реальная программа) или даже настраивается программная среда для «настоящей» программы.

В менее микромасштабном программном обеспечении, когда вы запускаете исполняемый файл, который перемещает загрузчик приложения, выполняет такие вещи, как загрузка частей ваших данных в память, иногда фиксирует адреса, устанавливает аргументы для основных или других глобальных вещей, раскручивает библиотеки, предоставляемые вашей ОС, и затем переходит к началу _mainкода. Некоторые из этих вещей могут быть выполнены загрузчиком.

В микроконтроллере некоторые задачи, которые выполняет загрузчик, могут быть разделены на программы. Компилятор для вашей платформы может автоматически вставлять «установочный» код в каждый исполняемый файл.

Но наличие его в загрузчике означает, что один и тот же компилятор может работать на другом оборудовании, поскольку загрузчик может «скрыть» разницу между платформами.

Завершите это тем, что флэш-память основной программы не рискует загрузчиком (и возможностью перепрошивки основной программы), и наличие нетривиального загрузчика - довольно хорошая вещь.

Yakk
источник
-1

Один из ответов, который не был рассмотрен, - это необходимость разделения проблем из-за ограничений языка Си.

Обычно загрузчики написаны на смеси ассемблера и C, с самого раннего этапа загрузки в ассемблере.

Это сделано для настройки некоторых вещей, таких как:

  • выделение стека C
  • чтение указателя стека в регистр
  • чтение счетчика программ в регистр
  • объявляя векторы сброса
  • загрузка второго этапа (initramfs) в оперативную память.

Это очень грубая аппроксимация предпринятых шагов, и я описываю процесс загрузки ARM, он снова отличается для x86 и других архитектур.

Тем не менее, основная причина остается той же: выделение стека C должно выполняться из сборки.

BitShift
источник
Почему отрицательный голос? Это актуально и точно.
BitShift
-1

Одна часть вопроса, на которую до сих пор не было ответа, - это различие между загрузчиками на микроконтроллерах и микропроцессорных системах.

микроконтроллер

Большинство микроконтроллеров имеют встроенную память ПЗУ, в которой содержится их программный код. Для изменения этого кода обычно требуется устройство программиста, которое подключается к интерфейсу программирования микроконтроллера (например, ISP на ATMega). Но эти программные интерфейсы обычно не очень удобны в использовании по сравнению с другими интерфейсами, поскольку они могут быть недоступны в данном контексте. Так, например, хотя почти каждый компьютер имеет порты USB, SPI-интерфейс, необходимый для ISP, гораздо реже, а другие интерфейсы, такие как PID-интерфейс, используемый в ATXMega, поддерживаются только специальным программным обеспечением.

Так, например, если вы хотите обновить программное обеспечение с обычного компьютера без какого-либо внешнего оборудования, вы можете использовать загрузчик, который считывает данные с интерфейса другого типа (например, RS232, USB или RS232 через USB, как на Arduino), чтобы запрограммировать устройство через общие интерфейсы.

Тем не менее, если вам не нужны эти функции, загрузчик является полностью необязательным. Микроконтроллер по-прежнему может запускать свой код полностью без загрузчика.

Микропроцессор

На микропроцессоре дела обстоят немного иначе. В то время как большинство микропроцессоров имеют ПЗУ, достаточно большое для загрузчика, эти ПЗУ не достаточно велики, чтобы вместить полную ОС. Таким образом, цель загрузчика - инициализировать оборудование, найти загрузочную ОС, загрузить и запустить ее. Таким образом, загрузчик имеет решающее значение для каждой загрузки.

В системах x86 / x64 этот загрузчик является либо BIOS, либо UEFI (в основном, более новой версией BIOS).

Иногда вы можете даже запустить несколько загрузчиков в цепочке. Например, если у вас есть система двойной загрузки с Windows и Linux, вы можете получить следующее:

  • BIOS / UEFI загружается и находит установленный GRUB. Затем он загружает GRUB (= Grand Unified Bootloader)
  • GRUB находит какой-то Linux и загрузчик Windows. Пользователь выбирает загрузчик Windows.
  • Загрузчик Windows запускается и находит установленные Windows 7 и Windows 10. Пользователь выбирает Windows 10.
  • Windows 10 наконец загружается.

Таким образом, в этом случае было три части программного обеспечения, которые можно считать загрузчиком. Как GRUB, так и Windows Bootloader в основном предназначены для того, чтобы предоставить пользователю более удобный вариант выбора загрузки, чем тот, который им предоставляет BIOS / UEFI. Он также позволяет запускать несколько ОС с одного жесткого диска или даже с одного раздела.

TLDR

Таким образом, хотя в обеих системах загрузчик выполняет похожие действия (помогая пользователю выбрать, какой код загружать), они оба сильно отличаются друг от друга тем, как они выполняют это и что именно они делают.

Dakkaron
источник
Хотя полезно отличать системы с достаточным энергонезависимым хранилищем с произвольным доступом (ПЗУ или флэш-память) для хранения всей программы от тех, которые должны выполнять код из ОЗУ, существуют микроконтроллеры обоих типов и микропроцессоры обоих типов.
суперкат
Конечно, разница между микроконтроллером и микропроцессором не является жесткой границей, и некоторые микроконтроллеры ведут себя больше как микропроцессор, и наоборот. Вот почему я взял AtMega / Arduino и x86 / x64 в качестве примеров, потому что они ведут себя таким образом.
Даккарон
«Микропроцессоры имеют ПЗУ, достаточно большое для загрузчика ... В системах x86 / x64 этот загрузчик является либо BIOS, либо UEFI» Нет. BIOS или UEFI хранятся во флэш-памяти вне чипа. Встроенное ПЗУ предназначено для функций еще более низкого уровня, таких как инициализация микрокода.
Бен Фойгт
@Dakkaron: я бы нарисовал грань между микропроцессором и микроконтроллером, основываясь на том, предназначен ли чип для использования в нетривиальных целях, без чего-либо еще на адресной шине. 8031 не подходит, за исключением того, что это функционально 8051 (который определенно является микроконтроллером), который не определен как имеющий что-либо полезное во внутреннем ПЗУ, но в противном случае был бы разработан для использования полностью из внутреннего хранилища). Нечто подобное RCA / CDP 1802 не подходит, даже если его можно использовать для управления светодиодной табличкой ...
биркой с именами суперкат
... без внешней ОЗУ и ПЗУ, поскольку конструкции без ОЗУ / без ПЗУ ограничены тривиальными задачами. Что-то вроде TMS 32050, который, если я помню, имеет загрузчик и несколько тысяч слов 16-разрядных слов оперативной памяти внутри, однако, будет считаться микроконтроллером; хотя многим приложениям потребуется больше добавления ОЗУ, при подключении через UART к другой системе оно может служить многим целям без какой-либо информации на шине памяти.
суперкат