Какой адрес в пространстве памяти процессоров, где он начинает выполняться, описан в документации к чипу / процессору. Процесс запуска исполнения по этому адресу является верным для этого чипа, независимо от того, к какому размеру или назначению платы он припаивается. Встраиваемый, одноплатный компьютер, материнская плата ноутбука, настольная материнская плата, тостер и т. Д.
Схема для платы покажет, откуда происходит включение питания. Если сброс при включении питания управляется программируемым устройством, то у вас может не быть доступа ко всем подробным сведениям, чтобы выяснить, что происходит, но для встроенной платы разработки поставщик должен был предоставить достаточно информации о времени, чтобы вы могли выполнить свою работу. Некоторым устройствам, например флэш-памяти, может потребоваться минимальный период времени, в течение которого мощность достигает некоторого процента от полной мощности (например, 75% от 3,3 В) и время, когда может произойти первое чтение. Или некоторым устройствам требуется X количество тактов на входе тактовой частоты перед сбросом, вот так. Fpga и другие подобные устройства, которые загружают свои аппаратные конструкции с какого-то променада, нуждаются в часах, перезагрузке при включении питания, периоде времени для загрузки дизайна и т. Д. И эта fpga может быть контроллером памяти для процессора, например Поэтому, прежде чем вы сможете загрузить процессор, вам может потребоваться, чтобы эта fpga была запущена и запущена для маршрутизации ваших запросов flash или ram, вы можете зайти так далеко, чтобы эта fpga инициализировала dram, чтобы он выглядел как sram для процессора. Сброс процессора придется отложить, пока все это не произойдет. Некоторые регуляторы напряжения или другие устройства имеют выходную мощность, которая указывает на то, что мощность регулируется до требуемого напряжения и готова к использованию. Устройство, которое управляет сбросом, может ожидать этого включения, прежде чем оно сбросит сброс на процессоре. Все, что мне нужно, это то, что должно произойти, прежде чем процессор сможет загрузиться.
После сброса сброса микросхемы / процессора, как описано в других ответах.
В зависимости от процессора на выводах процессора могут быть варианты ремешков, описывающие конфигурацию загрузки, которые могут повлиять на начальный адрес для выполнения, что будет описано в документации по процессорам. Процессор может всегда загружаться с известного адреса или из таблицы адресов (векторной таблицы, таблицы исключений и т. Д. Под многими именами) в зависимости от произошедшего события, сброса, прерывания, пробуждения из режима пониженного энергопотребления / спящего режима и т. Д. В документации по процессору / микросхеме будет описан процесс загрузки и / или как вы узнаете, что или где выполняются первые инструкции.
Как только процессор, наконец, начинает выполнять инструкции, в зависимости от системы, вам может потребоваться включить USB-интерфейс, чтобы хост мог перечислить устройство, вам может потребоваться быстро включить интерфейс PCI, чтобы хост мог перечислить устройство. / доска. Если у вас есть драм, вам, вероятно, придется инициализировать контроллер драм на микросхеме или выключить, где-то между процессором и драмом. Если этот драм или другие воспоминания имеют какое-то обнаружение или исправление ошибок, вам, вероятно, придется инициализировать эту память, чтобы инициализировать теги ECC. Этот RAM должен быть запущен и запущен, прежде чем вы сможете использовать его для своего стека или для инициализации .bss и .data. Некоторые устройства загружаются с отключенными периферийными устройствами внутри чипа (например, порты rs232, usb и т. Д.), И в зависимости от вашего приложения вы можете просто включить их в загрузочном коде перед вызовом main (). На доске могут быть светодиоды, указывающие определенные вещи, иногда для этого есть код.
Если ваш компилятор генерирует сегменты .data или .bss, которые, к слову, относятся к программному обеспечению, аппаратное обеспечение не имеет представления об этом, большинство программистов предпочли бы инициализировать эти разделы памяти (без сомнения, это указано в стандарте для языка).Для .bss это означает обнуление, для .data это означает заполнение начальными значениями.Это обычно для C или других языков высокого уровня, для ассемблера вы можете управлять этим самостоятельно, компоновщику может быть все равно, если объекты, которые связаны, были C или ассемблером и могут создавать разделы памяти .data, .bss и т.д. независимо отисходный язык.
например:
const int a=27;
int b=28;
int c;
Переменная a будет помещена в исполняемый код или сегмент .text.Переменная b будет помещена в .data, потому что перед вызовом main () вы, как программист, ожидаете, что в ячейке памяти будет находиться это значение.И c будет в сегменте .bss, потому что как программист вы надеетесь / ожидаете, что область памяти будет нулевой, прежде чем вызывается main ().
Код запуска также инициализирует указатель или указатели стека в зависимости от ситуации.может быть, он может включить кэш и делать различные другие вещи.
Многое может произойти между reset и main (), и кажется, что мы предполагаем, что это корень вашего вопроса.
Поскольку вы упомянули встроенный, вы можете захотеть взять на себякод запускаИнструменты компилятора обычно имеют код запуска для целевого процессора, но шансы его соответствия карте памяти встроенных процессоров маловероятны, по крайней мере, при использовании универсального компилятора, такого как gcc.Например, PIC c-компилятор, или кролик-полупроводник, или какой-то другой компилятор, предназначенный специально для одного семейства микросхем, где вы должны указывать микросхему при компиляции, что хорошо указывает компилятору карту памяти, чтобы он мог управлять инициализацией этих областей.,Gcc / binutils поддерживает сценарии компоновщика и имеет множество предварительно встроенных модулей запуска кода для различных процессоров, в зависимости от природы целевого процессора и лица, создавшего этот открытый исходный код, вы можете управлять некоторыми из этих вещей, не имеянаписать свой собственный или изменить код запуска.Вы можете сделать это в любом случае, так как это может быть проще изменить / написать, чем вычислить все ручки, которые вы должны повернуть, чтобы заставить универсальный сделать то, что вы хотите.
Вы можете сделатьВаш код запуска проще и создайте правила программирования для проекта или, по крайней мере, для загрузчика, чтобы все переменные были инициализированы перед использованием.
, например, вместо:
const int a=27;
int b=28;
int c;
примерно так:
const int a=27;
int b;
int c;
void embedded_main ( void )
{
b = 27;
c = 0;
...
}
Если вы сделаете это, код запуска больше не будет обнулять .bss или копировать.данные от rom до ram перед вызовом embedded_main ().Обратите внимание, что некоторые компиляторы добавляют дополнительный (иногда) неиспользуемый код в двоичный файл, если он видит функцию с именем main (), если вы понимаете, что делает компилятор и что это за код, и если вам это нужно или нет, вы можете переименовать main () вчто-либо еще, чтобы избежать раздувания вашего двоичного файла и использования flash / rom.
Не инициализировать переменную c в приведенном выше примере перед ее использованием (предполагая, что она равна нулю) - это плохая форма, и некоторые компиляторы предупреждают вас об использовании возможно неинициализированнойпеременная.Так что вы все равно должны его инициализировать.
Вы можете получить довольно хороший прирост производительности при загрузке, не подготавливая .bss и .data, и, например, скажите, что если вы являетесь PCI-мишенью, вам может понадобиться каждая миллисекунда, которую вы можете запустить и запустить, прежде чем хост начнет перечислить. Вы не сохраняете ни один выпускной вечер, инициализируя переменные во время выполнения, сегмент .data заменяется кодом в сегменте .text, и в зависимости от процессора он, вероятно, потребляет больше флэш-памяти, чтобы сделать это таким образом. таким образом, вы можете повысить производительность и переносимость кода запуска, избавить от множества головных болей в этом коде запуска и компоновщиках, но если вы не разработчик высокоуровневого кода, который вы называете, вы можете получить горе от этих разработчиков. это компромисс, который сильно зависит от системы и того, что вы планируете с ней делать.
Код запуска моей руки часто выглядит следующим образом:
.globl _start
_start:
b reset
b hang
b hang
b hang
b hang
b hang
b hang
b hang
b hang
b hang
b hang
b hang
b hang
b hang
b hang
b hang
b hang
reset:
ldr sp,=0x2000C000
bl notmain
hang: b hang
для cortex-m3, где указатель стека находится по адресу нуля непосредственно перед таблицей векторов исключений, тогда вы можете сделать что-то вроде этого:
.cpu cortex-m3
.thumb
.word 0x40080000
.word _start
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.thumb_func
hang: b .
.thumb_func
.global _start
_start:
bl notmain
b hang
.end
Найдите в исходном коде файлы newlib или glibc для файлов с именем crt0.S или Start.S, чтобы найти загрузочный код для различных поддерживаемых процессоров (обычно в ассемблере, и в результате будет файл для каждого типа процессора, поддерживаемого этот компилятор / библиотека).