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