Старт/инициализация процессора
Процессоры разных семейств и/или архитектуры (Z80, MOS 6502, Motorola 68000, x86) инициализацию организовывали по-разному. Это поведение уже "зашито" в сам процессор.
Важно: кроме упоминаемых регистров часто при сбросе обнуляются или выставляются с особыми значениями дополнительные регистры (например,
указатель стека-Stack Pointer), которые я не упоминаю для простоты. При проектировании систем, конечно, это учитывается тоже.
По поведению на старте процессоры можно разделить на два типа.
Первый тип. Исполняем с этого места
По стартовому адресу лежит первая инструкция, и процессор просто начинает её выполнять.
Z80 - самый простой. После сброса счётчик команд PC (Program Counter) выставляется на адрес 0x0000, и
процессор исполняет то, что лежит с нулевого адреса.
8086 - та же идея, только стартовый адрес находится почти в самом конце адресного пространства. У первых 8086
это 0xFFFF0 (16 байт до конца мегабайта), у современных x86 (начиная с 386) - 0xFFFFFFF0 (16 байт до конца уже
4-гигабайтного пространства). Но принцип тот же: по этому адресу лежит инструкция (как правило - сразу переход куда
надо), и процессор её исполняет.
Классический ARM (ARM7/ARM9) - по адресу 0x00000000 лежит таблица векторов, и первая её ячейка (вектор
сброса) - это тоже инструкция, обычно переход на настоящий стартовый код (он же - reset_handler). При этом,
расположение таблицы можно переключить на high vectors по адресу 0xFFFF0000 - но это опция конфигурации.
Второй тип. Читаем, с какого места исполнять
По стартовому адресу лежит не инструкция, а указатель - адрес, по которому уже находится настоящий код. Процессор сначала читает этот указатель, а потом переходит (или, как говорят, "прыгает") по нему. Дополнительный шаг, который даёт возможность менять точку входа.
MOS 6502 (в Famicom/NES/"Денди", кстати, стояла его версия - Ricoh 2A03, тот же 6502, но с
отключённым десятичным режимом (не работает коррекция BCD) и со встроенным звуком) - при сбросе читает 16-битный
указатель (он же - вектор сброса), из адресов 0xFFFC–0xFFFD, и переходит по нему - то есть по вектору лежит адрес,
ведущий к коду. То есть в конце памяти лежит не код, а "адрес, где лежит код".
Motorola 68000 (центральный процессор Sega Mega Drive/Genesis) - читает при сбросе два 32-битных
значения: из 0x000000 - начальное значение указателя стека, из 0x000004 - стартовый адрес программы. Вычитав оба,
процессор начинает работу.
ARM Cortex-M - устроен "идейно" так же, как 68000: из 0x00000000 читает начальный SP (он же - указатель
стека, Stack Pointer), из 0x00000004 - начальный PC. Это отличие от классического ARM (ARM7/ARM9): там по вектору лежала
инструкция, а у Cortex-M - адрес.
То есть, разница сводится к одному вопросу: что находится по стартовому адресу - код, который сразу исполняют, или адрес, по которому этот код искать.
Первая программа
В обоих случаях возникает одна и та же проблема-рекурсия: при старте процессор так или иначе узнает, как и откуда ему выполнять программу, но самой программы ещё нет. И загрузить её может только какая-то другая программа, которая сама должна быть тоже уже загружена. То есть, как-то нужно сделать так, чтобы минимальная программа в памяти была уже при включении - в самом начале, которая будет работать автономно "сама по себе" и (или) позволит загрузиться, например, с дискеты, жёсткого (или твёрдотельного) диска и так далее.
В основе своей эта идея существует и применяется и сейчас, например, во всех современных x86-совместимых компьютерах.
Времена ZX Spectrum, C64 и других подобных домашних компьютеров
В основе использовалась память из комбинации двух типов (и, соответственно, микросхем): ROM (ПЗУ) + RAM (
ОЗУ).
Идея: ROM (ПЗУ, постоянное запоминающее устройство, read-only memory) записывается ещё при
изготовлении на заводе (масочное ПЗУ - то есть, на этапе изготовления кремния) или отдельным программатором один раз
после изготовления - на другом компьютере. В самом ZX Spectrum ROM-микросхема была как раз масочная.
Чтобы не углубляться в схемотехнические детали, управляющие линии на рисунке остались без изменений (хотя в реальном ZX Spectrum, конечно, теперь появляется зависимость от того, какой адрес выставлен на шине адреса). Также от ROM -микросхемы шина данных - однонаправленная, то есть, только чтение из памяти (что логично, ведь она уже записана и данные стереть нельзя) и сама микросхема не имеет управляющего вывода для записи данных.
Ещё добавился декодер адреса (Address Decoder), который, в зависимости от того, к какому адресу происходит обращение
к памяти, перенаправляет обращение на ROM или RAM так, что первые 16КБ адресного пространства отводятся под
ROM (диапазон адресов 0x0000-0x3FFF). В саму же ROM записывают (или "прошивают") какую-то управляющую
программу.
В ZX Spectrum 48K памяти поделены на 16КБ ROM и 32КБ RAM. В ROM содержится полноценный
интерпретатор языка BASIC (диалект Sinclair BASIC) и встроенные процедуры загрузки и сохранения (на
ZX Spectrum - на обычнуюаудиокассету), то есть, ROM выполняет роль своего рода "прошивки" (firmware) или
операционной системы и среды разработки.
Теперь, при включении процессор сразу начинает выполнять программу с адреса 0x0000 - она записана в ROM.
Оставшиеся 32КБ оперативной памяти используются под нужды программы.
В Z-Frame
Такой подход с использованием ROM накладывает сразу несколько ограничений как на функциональность, так и на удобство
разработки и программ, и самого "железа". Во-первых, программа всегда должна начинаться с того же адреса 0x0000 для
старта. Во-вторых, чтобы отладить программу "вживую", нужно использовать перепрограммируемую ROM (ведь обычная
ROM, напомню, записывается только один раз), то есть, нужна EEPROM (электрически стираемое перепрограммируемое запоминающее устройство, electrically erasable programmable ROM) - с возможностью стереть то, что было записано
до этого, записать программатором новую программу (или новую версию), посмотреть, как она себя ведёт и повторять до
достижения результата. В-третьих, всегда нужно будет учитывать, даже если пойти по примеру ZX Spectrum, что
стартовый диапазон адресов (необязательно 16К) всегда будет фиксированным. Во всех случаях для компьютера с
произвольным набором программного обеспечения (ПО), такой вариант реализации - крайне неудобен.
Поэтому нужно устройство, которое при включении, во-первых, запускается первым и может работать автономно само (без внешних процессора и оперативной памяти), во-вторых, сможет загрузить уже в эту внешнюю (по отношению к себе) память нужную программу, которую уже будет исполнять центральный процессор.
С такой задачей справится отдельный микроконтроллер, как обособленный вычислитель содержащий внутри себя и "процессор",
и свою память и "прошивку" - свою программу, которая уже сможет загрузить нужную программу в RAM, например, прочитав
её с подключённой SD-карты. Я выбрал для этой цели микроконтроллер STM32F407VGT6. Достаточное количество внутренней
памяти для программы-"прошивки" (1МБ, flash-память), оперативной памяти (192КБ) и скорости (168МГц) позволят
получить, забегая вперёд, много удобств и возможностей в дальнейшем.