2012-02-09 4 views
2

Я столкнулся с чем-то очень похожим на следующее, когда вы ищете базовую информацию о программировании Cortex-M3 с незащищенным металлическим корпусом (о которой здесь говорится в большом ответе, который я попытаюсь найти позже).Как линкер ARM знает, где остановлена ​​таблица исключений?

/* vectors.s */ 
.cpu cortex-m3 
.thumb 

.word 0x20002000 /* stack top address */ 
.word _start  /* 1 Reset */ 
.word hang  /* 2 NMI */ 
.word hang  /* 3 HardFault */ 
.word hang  /* 4 MemManage */ 
.word hang  /* 5 BusFault */ 
.word hang  /* 6 UsageFault */ 
.word hang  /* 7 RESERVED */ 
.word hang  /* 8 RESERVED */ 
.word hang  /* 9 RESERVED*/ 
.word hang  /* 10 RESERVED */ 
.word hang  /* 11 SVCall */ 
.word hang  /* 12 Debug Monitor */ 
.word hang  /* 13 RESERVED */ 
.word hang  /* 14 PendSV */ 
.word hang  /* 15 SysTick */ 
.word hang  /* 16 External Interrupt(0) */ 
.word hang  /* 17 External Interrupt(1) */ 
.word hang  /* 18 External Interrupt(2) */ 
.word hang  /* 19 ... */ 

.thumb_func 
.global _start 
_start: 
    bl notmain 
    b hang 

.thumb_func 
hang: b . 

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

Как это работает и что я должен прочитать, чтобы узнать?

ответ

2

Это мой код, и программист не является компоновщиком, который должен знать, что происходит. Кортекс-м имеет разные векторные таблицы, и они могут быть довольно длинными, многими индивидуальными векторами прерывания. Выше было просто быстро от одного аромата в один прекрасный день. Если вы никогда не будете использовать ничего, кроме вектора сброса, вам нужно записать больше мест памяти, создавая целую таблицу? возможно нет. Возможно, вы захотите сделать достаточно глубоким, чтобы покрыть неопределенные исключения и прерывания и т. Д., Чтобы вы могли захватить их под контролем. Если вам нужно только сбросить и одно прерывание, но это прерывание довольно глубоко в таблице, вы можете сделать огромную таблицу, чтобы покрыть оба, или если достаточно храбрый, поместите некоторый код между ними, чтобы восстановить потерянное пространство.

Чтобы узнать/прочитать больше, вам необходимо обратиться к техническому справочному руководству TRM для конкретных коры коры головного мозга cortex-m0, cortex-m3 и cortex-m4, а также, возможно, ARM ARM для armv7- м (коры головного мозга - все члены семейства arm-7-м). ARM ARM означает ARM Architectural Reference Manual, в котором говорится о целом в целом семействе, но не покрывает основные конкретные детали до какой-либо большой длины, вам необходимо ARM ARM и правильное TRM, как правило, при программировании ARM (если вам нужно попасть в что-то низкое как ASM или конкретные регистры). Все можно найти на веб-сайте arm infocenter.arm.com слева, ищите архитектуру или посмотрите на процессоры серии Cortex-M.

Эти сердечники являются достаточно новыми, они, вероятно, не имеют больше, чем исходное число оборотов. Для некоторых старых ядер лучше всего получить TRM для конкретного ядра. Возьмите ARM11 Mpcore, например, если поставщик использовал rev 1.0 (r1p0) ядра, несмотря на устаревшую маркировку в руководстве, по которой вы, по крайней мере, пытаетесь использовать руководство rev 1.0 по руководству rev 2.0, если есть различия. Поставщики не всегда говорят вам, какой оборот они купили/использовали, поэтому это может быть проблемой при сортировке, как программировать вещь или какие ошибки применяются к вам, а что нет. (Linux - ПОЛНОСТЬЮ ошибок, связанных с ARM, из-за того, что они не понимают этого, ошибки, применяемые неправильно вообще или применяются к неправильному ядру, инструкции, используемые на неправильном ядре или в неподходящее время и т. Д.).

Я, вероятно, написал этот обработчик для кортика-м3, когда я впервые получил его, а затем вырезал и вставил здесь и там, чтобы не исправлять/изменять его.

Ядро (CPU, logic) определенно знает, сколько прерываний поддерживается, и знает полный состав таблицы векторов. На краю ядра могут быть сигналы управления, которые могут изменить такие вещи, и поставщик, возможно, связал их одним способом или сделал их программируемыми и т. Д. Независимо от того, что логика для этого ядра определенно знает, что выглядит векторная таблица так как программист должен сделать код соответствующим аппаратным средствам по мере необходимости. Все это будет описано в TRM для этого ядра.

EDIT

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

Это всего лишь банк флэш-памяти, вы подаете ему адрес, щелкая строкой чтения, и некоторые данные выходят. Эти биты не означают ничего, пока вы не разместите их в контексте. Вы можете вызвать цикл памяти по адресу 0x10, если вы создаете какой-то код, который выполняет команду загрузки по этому адресу, или вы можете перейти на этот адрес, а цикл выборки читает это местоположение, надеясь найти инструкцию, и если событие имеет этот жесткий код адрес и чтение происходит по этому адресу, он надеется найти адрес для обработчика. но это всего лишь память. Так же, как файл в файловой системе, его просто байты на диске. Если это jpeg, то конкретный байт может быть пикселем, если файл на диске является программой, тогда байт при смещении может быть инструкцией. его просто байт.

Эти адреса генерируются непосредственно из логики. В наши дни логика написана с использованием языков программирования (обычно verilog или vhdl или какой-то более высокий уровень языка, который производит verilog или vhdl в качестве вывода). Не иначе, чем если бы вы написать программу в вашем любимом языке вы можете выбрать в буквальном смысле жёстко некоторому адресу

x = (unsigned int *)0x1234; 

или вы можете выбрать, чтобы использовать структуру или массив или какой-то другой стиль программирования, но когда-то составлен он по-прежнему заканчивает производить некоторый фиксированный адрес или смещение:

unsigned int vector_table[256]; 
... 
handler_address = vector_table[interrupt_base+interrupt_number]; 
... 

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

.cpu cortex-m3 
.thumb 

.word 0x20002000 /* stack top address */ 
.word _start  /* 1 Reset */ 

.thumb_func 
.global _start 
_start: 
    bl notmain 
    b hang 

.thumb_func 
hang: b . 

И да, совсем я поместил два слова инструкции бла notmain в ячейке памяти для ОГО. если NMI должен был произойти, тогда процессор прочитает это местоположение, предположим, что это адрес для обработчика, попробуйте извлечь инструкцию по этому адресу, и у кого будет кто-нибудь знает. Возможно, он даже узнал, что он является недопустимым адресом и вызывает прерывание данных, которое в приведенном выше случае будет еще одним адресом, и может превратиться в бесконечный цикл прерываний данных. Или, если случайно одна из этих инструкций появляется как адрес в нашей программе, тогда в основном она будет прыгать прямо в середину программы, что нередко окажется в каком-то крахе. что такое авария? действительно? CPU делает свою работу по чтению байтов из памяти и интерпретирует их в качестве инструкций, если эти инструкции говорят о том, что они выполняют неровные обращения или эти байты не являются допустимыми инструкциями или вы должны считать неверный адрес памяти, который вы возвращаете обратно в векторную таблицу. Или вам может быть так повезло, что испорченные адреса, написанные или прочитанные с помощью прыжка в середине пространства кода, вызывают удаление банка вспышки или байт, чтобы выплюнуть uart или входной порт gpio, который будет изменен на выходной порт (если вам повезет, вы пытаетесь прогнать землю или что-то еще, и вы расплавляете чип).

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

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

+0

Я понимаю, что это таблица векторов прерываний, и я понимаю, что она может быть такой же разреженной/полной, как она может быть, но я не понимаю, как процессор или что-то еще знает, что это конкретный кусок строк - таблица векторов прерываний, а строки, следующие за ней, - нет. Что разделяет разделы? Должна ли таблица векторов быть первой в файле? Определяется ли это как «все, что предшествует первой директиве .thumb_func»? – Mark

+0

Или мы просто заканчиваем векторную таблицу и используем ее как пространство для кода? И.Е. если мы закончили таблицу после прерывания NMI, например, и, скажем, произошло прерывание BusFault, переместимся ли мы в какое-то странное место, потому что какая-то инструкция или данные заняли этот слот в векторной таблице? – Mark

1

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