Какие действия происходят, когда мы включаем встроенную плату? - PullRequest
1 голос
/ 18 сентября 2010

Сейчас, После долгих обсуждений в этой теме с dwelch мое сомнение изменилось к точному.

«Если вам интересно, как процессор готов к выполнению первой инструкции. Как устроена логика» КАК ПРОЕКТИРОВАНА ЛОГИКА? Можете ли вы дать мне больше идей по этому поводу? Есть ли какой-нибудь документ, дайте мне больше деталей? Является ли алгоритм позади всей архитектуры одинаковыми?

Ответы [ 5 ]

4 голосов
/ 19 сентября 2010

Какой адрес в пространстве памяти процессоров, где он начинает выполняться, описан в документации к чипу / процессору. Процесс запуска исполнения по этому адресу является верным для этого чипа, независимо от того, к какому размеру или назначению платы он припаивается. Встраиваемый, одноплатный компьютер, материнская плата ноутбука, настольная материнская плата, тостер и т. Д.

Схема для платы покажет, откуда происходит включение питания. Если сброс при включении питания управляется программируемым устройством, то у вас может не быть доступа ко всем подробным сведениям, чтобы выяснить, что происходит, но для встроенной платы разработки поставщик должен был предоставить достаточно информации о времени, чтобы вы могли выполнить свою работу. Некоторым устройствам, например флэш-памяти, может потребоваться минимальный период времени, в течение которого мощность достигает некоторого процента от полной мощности (например, 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, чтобы найти загрузочный код для различных поддерживаемых процессоров (обычно в ассемблере, и в результате будет файл для каждого типа процессора, поддерживаемого этот компилятор / библиотека).

2 голосов
/ 20 сентября 2010

"Если вам интересно, как процессор готовится выполнить первый инструкция. его путь логика разработан "- КАК ПРОИЗВЕДЕНА ЛОГИКА? Можете ли вы дать мне больше идей по этому поводу? Является там любой документ, дайте мне больше подробности? Алгоритм позади всех архитектура одинакова?

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

if (RESET)         //reset pin input is asserted
    PC = 0x0000;   // or any other predetermined value
else
    PC = PC + length(currentInstruction);

для простоты понимания подумайте о процессоре, который выполняет 1 инструкцию в каждом такте. Кроме того, считайте, что все инстанции имеют одинаковый размер (4 байта как в arm).

тогда логика становится еще проще

if (RESET)
    PC = 0x0000;
else
    PC = PC + 4;

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

пока устанавливается RESET, на ПК загружается адрес перезагрузки.

теперь ответственность за утверждение и отпускание сигнала RESET лежит на схеме сброса, которая может сделать это только после получения сигнала POWERGOOD и / или сигнала CLOCKSTABLE.

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

Сигнал POWERGOOD подается силовой цепью после стабилизации напряжения.

все эти сигналы могут отсутствовать или использоваться на конкретной платформе. сигнал RESET обычно находится на всех процессорах.

как только сигнал RESET сбрасывается, конвейер выполнения включается и логика выполнения инициирует FETCH с этого адреса.

Книги по дизайну цифровой логики обычно содержат такую ​​информацию. и некоторый пример, чтобы показать, как спроектировать ALU. Алгоритм приращения ПК, стоящий за каждой архитектурой, будет аналогичным (по концепции), но должен учитывать особенности конструкции процессора.

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

теперь логика приращения ПК становится

if (RESET)
    if(RESETADDRESSJUMPER)
         PC = 0x0000;
    else
         PC = 0xfff0;
else
    PC = PC + 4;

аналогично, можно определить любую сложную логику для сброса процессора, требуемого архитектурой процессора.

1 голос
/ 18 сентября 2010

Невозможно сказать, как будет запускаться система (т.е. ЦП), поскольку это может зависеть от конкретной реализации и варьироваться в зависимости от ЦП.Однако обычно это выглядит примерно так:

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

Если у вас есть приложение, написанное на языке более высокого уровня, таком как c, то среда c должна бытьнастроить.То есть необходимо настроить различные сегменты памяти: .bss необходимо обнулить, .data нужно инициализировать с данными переменных и, возможно, даже больше.Система, скорее всего, также должна выполнить некоторые настройки оборудования, особенно часы.Эта часть запуска обычно написана на ассемблере (обычно «crt0.S», по крайней мере, части этого вида запуска также требуются для запуска приложения переменного тока на ПК).После этого устанавливается среда c, и основное приложение может запускаться, вызывая функцию main.Тем не менее, в автономной среде (которая обычно является встроенной системой, если вы не используете встроенный linux на ней или что-то в этом роде), есть некоторые важные отличия от размещенных сред.Наиболее важным здесь является то, что автономная среда не должна иметь функцию main и не должна иметь обычный прототип int main(int argc, char* argv[]).То, как именно это выглядит в вашей системе, зависит от конкретной реализации, но функция ввода для основной программы void main(void) является общей.

0 голосов
/ 20 сентября 2010

Большинство ЦП будут запускаться с вектора сброса (0x0, 0x100, 0x80000000, 0xfffff100, 0xfffffffc), как только сброс будет выполнен.В зависимости от CPu, но обычно первое, что нужно сделать, - это запустить и запустить память (MMU, SDRAM, ECC и контроллеры шины).Затем вы можете выполнить некоторые дополнительные настройки оборудования, такие как тактирование, управление питанием, сторожевые таймеры или что-то еще, но большая часть этого может быть выполнена после того, как вы попали в свою ОС или основное приложение.Теперь вы начнете с настройки времени выполнения, которая копирует вашу программу из Flash в RAM.Вы должны быть готовы запустить ваше приложение.На небольших платформах вам может потребоваться только скопировать инициализированные данные перед запуском.

0 голосов
/ 18 сентября 2010

Это зависит от процессора на плате - и что находится в памяти (ПЗУ или один из вариантов СППЗУ).

Один из сценариев состоит в том, что процессор выполняет код по адресу 0, поэтому аппаратное обеспечение должно обеспечить наличие некоторого допустимого кода для процессора для выполнения по этому адресу, например JMP os_start, чтобы перейти к началу работы. реальный код системы.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...