fk0, легенда (03.05.2016 21:54, просмотров: 965) ответил SciFi на Стартап для кортекс на асме - это трэш, угар и содомия. Всех расстрелять, адназначна.
Я для ARM7 писал на асме, и обработчик прерываний тоже. А он там, в отличии от жалких кортексов, достаточно замороченный.
/* $Id$ */
/* vim: set syntax=armasm: */
/* ROM mode, vectors in ROM */
#include "AT91SAM7X256_inc.h"
#include "exits.h"
.arm
.text
/* Секция содержит вектора прерываний и быстрые обработчики прерываний,
* секция может быть размещена (скопирована) в ОЗУ */
.section .vectors, "ax"
ldr pc, =_start /* 0x00 Reset */
ldr pc, =UNDEF /* 0x04 Undefined Instruction */
ldr pc, =SWI /* 0x08 Software Interrupt */
ldr pc, =ABORT /* 0x0C Prefetch Abort */
ldr pc, =DABORT /* 0x10 Data Abort */
nop /* 0x14 reserved */
ldr pc, =IRQ /* 0x18 IRQ */
FIQ: /* 0x1c FIQ */
/* переключение в режим супервизора для использования общего
* с программой стека и запрет прерываний */
mov r11, r0 /* r0 прерванной программы, r7..r15 -- fiq */
ldr r0, [r12, #AIC_FVR] /* подтверждение/снятие запроса, чтение вектора AIC */
msr CPSR_c, #I_BIT|F_BIT|ARM_MODE_SVC
/* см: http://www.chiark. …docs/CodeStds/APCS.txt
* сохраняются регистры разрушаемые при вызове функций */
stmfd sp!, {r1-r3, r12, lr}
mov lr, pc /* вызов функции обработки FIQ */
bx r0
ldmia sp!, {r1-r3, r12, lr}
msr CPSR_c, #I_BIT|F_BIT|ARM_MODE_FIQ
mov r0, r11
subs pc, lr, #4
/* Обработка ложных прерываний */
SPU:
mov pc, lr
.global _exit
/* unhandled interrupts -- call _exit(code), code must be defined in exits.h */
SWI: mov r0, #EX_UNEXP_SWI
b _exit
ABORT: mov r0, #EX_CODE_ABORT
b _exit
DABORT: mov r0, #EX_DATA_ABORT
b _exit
UNDEF: mov r0, #EX_UNDEF
b _exit
.section .text
.func IRQ
IRQ:
/* на IRQ-стеке сохраняется адрес возврата, SPSR_irq и регистры -- 3 слова */
sub lr, lr, #4 /* адрес возврата для загрузки в pc */
stmfd sp!, {lr}
mrs lr, SPSR
stmfd sp!, {lr}
stmfd sp!, {r0}
/* чтение вектора/подтверждение для данного прерывания */
ldr lr, =AT91C_BASE_AIC
ldr r0, [lr, #AIC_IVR]
str lr, [lr, #AIC_IVR] /* для поддержки отладки */
/* переключение и обработка прерывания на стеке пользователя */
msr CPSR_c, #ARM_MODE_SVC /* разрешаются вложенные прерывания */
stmfd sp!, {r1-r3, r12, lr} /* сохр. регистров, см. FIQ комментарий */
mov lr, pc
bx r0
ldmia sp!, {r1-r3, r12, lr}
/* переключение обратно в IRQ с запретом прерываний */
msr CPSR_c, #I_BIT|ARM_MODE_IRQ
ldr lr, =AT91C_BASE_AIC
str lr, [lr, #AIC_EOICR] /* сигнализация конца обработки для AIC */
/* загрузка 3 регистров из IRQ стека, см. выше */
ldmia sp!, {r0}
ldmia sp!, {lr}
msr SPSR_cxsf, lr
ldmia sp!, {pc}^ /* и загрузка SPSR в CPSR -- возврат из прерывания */
.size IRQ, .-IRQ
.endfunc
.section .text
.global _start
.func _start
.equ ARM_MODE_USR, 0x10
.equ ARM_MODE_FIQ, 0x11
.equ ARM_MODE_IRQ, 0x12
.equ ARM_MODE_SVC, 0x13
.equ ARM_MODE_ABT, 0x17
.equ ARM_MODE_UND, 0x1b
.equ ARM_MODE_SYS, 0x1f
.equ I_BIT, 0x80
.equ F_BIT, 0x40
_start:
/* Установка стеков для IRQ и режима супервизора (FIQ не использует стек),
* предполагается, что программа исполняются в режиме супервизора. */
/* Для FIQ в r8 сохраняется адрес AIC */
msr CPSR_c, #ARM_MODE_FIQ|I_BIT|F_BIT
ldr r8, =AT91C_BASE_AIC
/* установка векторов по-умолчанию */
ldr r0, =UNDEF
add r1, r8, #AIC_SVR
mov r2, #31*4
set_irqvec0:
str r0, [r1, r2]
subs r2, r2, #4
bcc set_irqvec0
/* установка вектора SPU */
ldr r0, =SPU
str r0, [r8, #AIC_SPU]
/* сброс запросов прерывания всех уровней */
mov r0, #16 /* was 8 -- для надёжности. :-/ */
ldr r1, =AT91C_BASE_AIC
clr_irqrq0:
str r1, [r1, #AIC_EOICR]
subs r0, r0, #1
bcc clr_irqrq0
/* режим IRQ имеет стек 3(слова)*4(sizeof)*8(уровней) минимум */
set_stacks:
msr CPSR_c, #ARM_MODE_IRQ|I_BIT|F_BIT
ldr SP, =_ram_top-4
sub r0, SP, #128 /* размер стека IRQ */
msr CPSR_c, #ARM_MODE_SVC|I_BIT|F_BIT
mov SP, r0
.global hardware_init
/* функция hardware_init() осуществляет настройку watchdog, контроллера памяти,
* тактового генератора, портов ввода-вывода -- всего, что должно
* инициализироваться немедленно после сброса, до относительно медленной
* инициализации libc и т.п. ВОЗМОЖНО, В Т.Ч. И ВЕКТОРОВ ПРЕРЫВАНИЙ! */
ldr r0, =hardware_init
mov lr, pc
bx r0
/* enable interrupts */
msr CPSR_c, #ARM_MODE_SVC /* XXX */
/* копирование содержимого секции .data из ПЗУ в ОЗУ: _etext --> _data.._edata */
.global __data_load__
.global __data_start__
.global __data_end__
copy_data:
ldr r0, =__data_load__
ldr r1, =__data_start__
ldr r2, =__data_end__
copy_data1:
cmp r1, r2
ldrlo r3, [r0], #4
strlo r3, [r1], #4
blo copy_data1
/* заполнение секции .bss нулём */
.global __bss_start__
.global __bss_end__
zero_bss:
ldr r0, =__bss_start__
ldr r1, =__bss_end__
mov r2, #0
zero_bss1:
cmp r0, r1
strlo r2, [r0], #4
blo zero_bss1
/* вызов конструкторов C++ */
.global __ctors_start__
.global __ctors_end__
call_ctors:
ldr r0, =__ctors_start__
ldr r1, =__ctors_end__
b call_ctors2
call_ctors1:
ldr r2, [r0], #4
stmfd sp!, {r0-r1} /* сохр. r0-r1 на стеке */
mov lr, pc
bx r2
ldmia sp!, {r0-r1}
call_ctors2:
cmp r0, r1
blo call_ctors1
/* вызов функции main() */
.global main
mov r0, #0 /* int argc, char *argv[] */
mov r1, r0
mov r2, r0 /* ? */
mov fp, r0
mov r7, r0 /* ? */
ldr r4, =main
mov lr, #-4 /* возврат из main() по адресу 0 */
bx r4
.size _start, .-_start
.endfunc
.section .text
.global di
.global ei
.func di
di: msr CPSR_c, #ARM_MODE_SVC|I_BIT
mov pc, lr
.endfunc
.func ei
ei: msr CPSR_c, #ARM_MODE_SVC
mov pc, lr
.endfunc
.end
[ZX]