Код сборки для создания вектора прерываний на процессоре ARM LPC2148 - PullRequest
2 голосов
/ 23 марта 2011

Я только недавно начал работать с процессором ARM LPC2148.

Я пытаюсь понять некоторый код сборки, касающийся создания вектора прерываний.

вот код:

// Runtime Interrupt Vectors
// -------------------------
Vectors:
        b     _start                    // reset - _start
        ldr   pc,_undf                  // undefined - _undf
        ldr   pc,_swi                   // SWI - _swi
        ldr   pc,_pabt                  // program abort - _pabt
        ldr   pc,_dabt                  // data abort - _dabt
        nop                             // reserved
        ldr   pc,[pc,#-0xFF0]           // IRQ - read the VIC
        ldr   pc,_fiq                   // FIQ - _fiq

#if 0
// Use this group for production
_undf:  .word _reset                    // undefined - _reset
_swi:   .word _reset                    // SWI - _reset
_pabt:  .word _reset                    // program abort - _reset
_dabt:  .word _reset                    // data abort - _reset
_irq:   .word _reset                    // IRQ - _reset
_fiq:   .word _reset                    // FIQ - _reset

#else
// Use this group for development
_undf:  .word __undf                    // undefined
_swi:   .word __swi                     // SWI
_pabt:  .word __pabt                    // program abort
_dabt:  .word __dabt                    // data abort
_irq:   .word __irq                     // IRQ
_fiq:   .word __fiq                     // FIQ

__undf: b     .                         // undefined
__swi:  b     .                         // SWI
__pabt: b     .                         // program abort
__dabt: b     .                         // data abort
__irq:  b     .                         // IRQ
__fiq:  b     .                         // FIQ
#endif
        .size _boot, . - _boot
        .endfunc

Я вообще не понимаю, что здесь происходит.Если бы кто-то мог объяснить мне этот процесс, особенно то, как здесь используется инструкция ldr, я был бы признателен за это.

Tal

Ответы [ 3 ]

9 голосов
/ 23 марта 2011

Я собираюсь удалить условный код, поскольку он просто усложняет вещи:

// Runtime Interrupt Vectors
// -------------------------
Vectors:
        b     _start                    // reset - _start
        ldr   pc,_undf                  // undefined - _undf
        ldr   pc,_swi                   // SWI - _swi
        ldr   pc,_pabt                  // program abort - _pabt
        ldr   pc,_dabt                  // data abort - _dabt
        nop                             // reserved
        ldr   pc,[pc,#-0xFF0]           // IRQ - read the VIC
        ldr   pc,_fiq                   // FIQ - _fiq

_undf:  .word __undf                    // undefined
_swi:   .word __swi                     // SWI
_pabt:  .word __pabt                    // program abort
_dabt:  .word __dabt                    // data abort
_irq:   .word __irq                     // IRQ
_fiq:   .word __fiq                     // FIQ

__undf: b     .                         // undefined
__swi:  b     .                         // SWI
__pabt: b     .                         // program abort
__dabt: b     .                         // data abort
__irq:  b     .                         // IRQ
__fiq:  b     .                         // FIQ

        .size _boot, . - _boot
        .endfunc

Давайте сначала посмотрим на вектор сброса / запуска:

b   _start

Эта инструкциябезусловная ветвь (переход) к коду, помеченному "_start", который я не вижу в вашем фрагменте.По сути, это будет сборка, которая инициализирует регистры стека и процессора, возможно, некоторые области памяти затем перейдут к процедуре C, которая выполняет основную часть инициализации.

Следующим является "неопределенный" вектор, в котором ARMперейдет к выполнению недопустимой инструкции (если моя память верна):

ldr pc, _undf

Эта инструкция загружает регистр pc («программный счетчик» или указатель инструкции) с адресом на «_undf "символ.Если мы посмотрим на переменную _undf, она содержит адрес, представленный символом __undf.Таким образом, инструкция ldr pc, _undf загружает pc с адресом __undf - переходя к __undf:.

И на __undf мы видим:

__undf: b     .  

Это простопереход к одному и тому же адресу - бесконечный цикл (символ . означает «здесь» или «это местоположение»).

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

Наконец, векторный слот, который наиболееинтересен вектор IRQ:

ldr   pc,[pc,#-0xFF0]           // IRQ - read the VIC

Это похоже на обработчик для устройства NXP.

Он загружает регистр pc со значением, считанным из ячейки памяти, относительноpc зарегистрироваться.Так как в архитектуре ARM вектор IRQ равен всегда по адресу 0x00000018 (я собираюсь игнорировать реализации, которые могут отображать векторы в другом месте, или ARM, такие как Cortex-M3, которые используют другую векторную модель), и из-заВлияние конвейера инструкций на использование значения регистра PC для адресации, место в памяти, которое будет считываться этой инструкцией, будет 0xFFFFF030, что является адресом отображенного в памяти регистра VICVectAddr в 'Vectored Interrupt Controller`(VIC):

 'apparent'      Pipeline      offset in      effective
  PC value        effect       the opcode      address
-------------   ------------   -----------    ----------
  0x00000018  +  0x00000008  -  0x0000ff0  == 0xfffff030

Этот регистр устройства будет содержать адрес обработчика прерывания для только что возникшего прерывания (конечно, VIC должен быть правильно инициализирован, чтобы он знал этот адрес).

Таким образом, при выполнении инструкции ldr pc,[pc,#-0xFF0] в регистр pc загружается адрес подпрограммы обработчика прерываний для соответствующего устройства (в основном, переход к правому обработчику прерываний).

2 голосов
/ 24 марта 2011

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

Традиционно ARM так не делает. Большинство ядер ARM фактически выполняются по этому адресу, поэтому таблица содержит исполняемые инструкции. Поскольку каждые 4 байта в этой таблице есть точка входа, вы, в основном, хотите иметь некоторую разновидность инструкции перехода. Вы можете использовать более одной инструкции, но, как видите, вторая или третья инструкция становится точкой входа для других исключений. Если вы уверены, что у вас никогда не будет ни одного из этих других исключений, вы можете обойтись без него, но обычно это неразумно. Если вы ограничиваете себя одной инструкцией, вы можете выбрать относительную ветвь компьютера или загрузочный компьютер с некоторым соседним адресом. Итак, ldr pc, что-то загружает адрес первой инструкции некоторого кода в программный счетчик, чтобы он по существу переходил к этому коду. б) является сокращенным синтаксисом ассемблера (только для gnu?), означающим переход к себе или переход в бесконечном цикле. Если место назначения достаточно близко к таблице исключений, вы можете просто b __irq. Существуют различные решения и разные причины, по которым вы бы выбрали тот или иной путь, в который я не пойду.

Относительно новый Cortex-M3 и другие ARM-процессоры, использующие только thumb2 (thumb - сокращенная форма набора инструкций ARM, а thumb2 - расширение набора инструкций thumb). Вы можете запускать только thumb или thumb2 на Cortex-M3, но вы не можете выполнять какие-либо инструкции ARM, поэтому традиционная (ARM) модель таблицы инструкций либо должна измениться на таблицу из 16-битных 2-байтовых инструкций, либо изменить все вместе. Что они сделали, так это пошли на модель, очень похожую на большинство других процессоров, они пошли с таблицей адресов. Исключением является то, что по адресу 0 в таблице есть 32-битное значение, которое загружается в указатель стека, что является хорошей функцией для встраивания. После сброса ядро ​​будет считывать 32 бита с нулевого адреса, помещать это значение в указатель стека, считывать 32 бита по адресу 0x4 и помещать это значение в программный счетчик, по существу, переходя по этому адресу. Обратите внимание, что список исключений в cortex-m3 отличается от списка в традиционном ядре ARM. Например, в таблице cortex-m3 есть много векторов обработчиков прерываний.

0 голосов
/ 23 марта 2011

Попытка угадать:

    ldr   pc,_undf                  // undefined - _undf
    ldr   pc,_swi                   // SWI - _swi
    ldr   pc,_pabt                  // program abort - _pabt
    ldr   pc,_dabt                  // data abort - _dabt
    nop                             // reserved
    ldr   pc,[pc,#-0xFF0]           // IRQ - read the VIC
    ldr   pc,_fiq  

ldr кажется l oa d r egister pc с указателями на ISR, поэтомуэто своего рода переход к этим подпрограммам.

#if 0
#else

они пахнут как инструкции условной компиляции, как и препроцессор Си.Вкратце, этот

    ldr   pc,_swi                   // SWI - _swi

вызывает подпрограмму, хранящуюся в _swi, которая определяется как

_swi:   .word __swi                     // SWI

(потому что #if 0 никогда не будет истинным, поэтому имеет значение только часть #else), а __swi определяется несколькими строками ниже:

__swi:  b     .                         // SWI

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

...