Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: startup asm
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Страницы: 1, 2, 3
sergey sva
Объясните как работает этот кот, с ассемблером плохо знаком, сейчас читаю,
но не совсем все понятно. А именно инструкция ldr записывает значение находящееся по адресу RESET_ADDR , в регистр pc,
переменная RESET_ADDR не где не объявляется так же как и pc ?
код взят отсюда : http://electronix.ru/forum/index.php?act=a...st&id=16569

Код
    ldr    pc, RESET_ADDR
    ldr    pc, UNDEF_ADDR
    ldr    pc, SWI_ADDR
    ldr    pc, PREFETCH_ABORT_ADDR
    ldr    pc, DATA_ABORT_ADDR
    .word    0
    ldr    pc, IRQ_ADDR
    ldr    pc, FIQ_ADDR
RESET_ADDR:        .word    RESET_handler
UNDEF_ADDR:        .word    UNDEF_handler
SWI_ADDR:        .word    SWI_handler
PREFETCH_ABORT_ADDR:    .word    PREFETCH_ABORT_handler
DATA_ABORT_ADDR:    .word    DATA_ABORT_handler
            .word    0
IRQ_ADDR:        .word    IRQ_handler
FIQ_ADDR:        .word    FIQ_handler
aaarrr
RESET_ADDR - это метка, зачем ее объявлять еще?
msalov
Предположу что это тааблица векторов прерываний smile.gif
и что куда загружается думаю понять не сложно из имён ссылок и регистра
sergey sva
В один регистр PC, по очереди запишутся адреса меток, или pc это счетчик и при каждой последующей записи
он инкриминируется ? Еще простой вопрос, что означает .word 0 ? Где можно прочитать по ассемблеру для арм,
здесь есть, но не подробно http://www.gaw.ru/html.cgi/txt/doc/micros/..._arm/survey.htm
Код
    ldr    pc, RESET_ADDR
    ldr    pc, UNDEF_ADDR
    ldr    pc, SWI_ADDR
    ldr    pc, PREFETCH_ABORT_ADDR
    ldr    pc, DATA_ABORT_ADDR
zltigo
Цитата(sergey sva @ Jan 14 2009, 18:56) *
В один регистр PC, по очереди запишутся адреса меток....

sad.gif да уж.... а что такое у нас PC? И что произойдет после первой-же в него записи? У Вас проблемы не с ASM а много более глубокие sad.gif
Цитата
Где можно прочитать по ассемблеру для арм,

Базовые понятия на http://arm.com Нюансы - в документации на конкретный ассемблер.
aaarrr
Цитата(sergey sva @ Jan 14 2009, 18:56) *
В один регистр PC, по очереди запишутся адреса меток, или pc это счетчик и при каждой последующей записи
он инкриминируется ?

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

Цитата(sergey sva @ Jan 14 2009, 18:56) *
Еще простой вопрос, что означает .word 0 ? Где можно прочитать по ассемблеру для арм

.word резервирует в памяти 32-х битное слово, надо полагать.

Особенности синтаксиса ассемблера в вашей среде лучше всего описаны в ее документации.
sergey sva
Цитата(zltigo @ Jan 14 2009, 19:26) *
sad.gif да уж.... а что такое у нас PC? И что произойдет после первой-же в него записи? У Вас проблемы не с ASM а много более глубокие sad.gif

Базовые понятия на http://arm.com Нюансы - в документации на конкретный ассемблер.


Да это верно, проблема гораздо глубже чем думал, не пойму как работает директива "Align 4" smile.gif
нашел такой текст прочел : не совсем понятно как выравнивается, к примеру если в pc 0x000000ff после align 4 какое значение там будет?
http://www.lib.kiev.ua/books/7/40n42.html
вот отрывок где эта директива используется:
Код
    .align    4
UNDEF_string:
    .asciz    "\r\nUNDEFINED INSTRUCTION Exception!!!"
    .align    4
SWI_string:
    .asciz    "\r\nSWI Exception!!!"
    .align    4
PREFETCH_ABORT_string:
    .asciz    "\r\nPREFETCH ABORT Exception!!!"
    .align    4
DATA_ABORT_string:
    .asciz    "\r\nDATA ABORT Exception!!!\r\n"
    .align    4
STOPPED_string:
    .asciz    "\r\nStopped!!!"
    .align    4

eclipse + yagarto
aaarrr
Цитата(sergey sva @ Jan 14 2009, 20:17) *
не совсем понятно как выравнивается, к примеру если в pc 0x000000ff после align 4 какое значение там будет?

0x000000ff, ибо align к PC ну никак не относится. Это просто указание ассемблеру, что следующий после align обект будет иметь соответствующее выравнивание.

Код
        ldr        r0, [r0]
        DCB        "ab"
        ALIGN    4
        ldr        r0, [r0]

Код
        0x0000006c:    e5900000    ....    LDR      r0,[r0,#0]
    $d
        0x00000070:    00006261    ab..    DCD    25185  <---- ассемблер добавил два байта для выравнивания
    $a
        0x00000074:    e5900000    ....    LDR      r0,[r0,#0]
sergey sva
Если правильно понял, код:
.align 4
UNDEF_string:
.asciz "abcdef"

строка abcdef занимает 6 байт но если использовать выравнивание
align 4 то она будет размещена в 8 байтах ?
zltigo
Цитата(sergey sva @ Jan 14 2009, 21:39) *
строка abcdef занимает 6 байт

Нет. Cемь.
Цитата
но если использовать выравнивание
align 4 то она будет размещена в 8 байтах ?

Нет. Семь или в зависимости от нюансов конткретного ассемблера, но совершенно вне зависимости от одиночного align перед этой строкой.
P.S.
Так и будете заниматься гаданиями?
sergey sva
Цитата
Так и будете заниматься гаданиями?

с удовольствием бы прочел мануал на asm, но пока найти не смог. sad.gif
Использую eclips + yagarto
sergeeff
Описание ассемблера: http://infocenter.arm.com/help/index.jsp?t...rm.doc.dui0068b
sergey sva
Наверно опять будет глупый вопрос, для чего нужно переключать режим ядра? откуда брать указатель на стек pstack ?

Код
ldr    r0, =   pstack                                           @ запись указателя на стек
msr    cpsr_c, #(UNDEF_MODE | I_BIT | F_BIT)    @ переключение режима ядра в UNDEF_MODE
mov    sp, r0                                                        @ запись в регистр sp указателя на стек
sub    r0, r0, #UNDEF_STACK_SIZE                    @ вычисление размера стека
msr    cpsr_c, #(ABT_MODE | I_BIT | F_BIT)      @ переключение режима ядра в Abort Mode выключение irq fiq
mov    sp, r0                                                   @ запись в регистр sp размер стека
zltigo
Цитата(sergey sva @ Jan 15 2009, 22:58) *
для чего нужно переключать режим ядра...

Забудьте пока про ассемблеры и ознакомьтесь для начала с собственно с микроконтроллером. Сколько у него режимов, стеков... Хотя на вопрос "откуда брать..." ответ надо искать еще более издалека.
sergey sva
С этим кажется разобрался, ядро настраивается отдельно, для каждого режима и стек тоже для каждого
режима свой.
Другой вопрос: правильно я распределил адреса, для стеков. Ремап не используется.
Начала адреса озу с 0x20000000 (at91sam7). Где нужно настраивать компоновщик ( в makefile ? )что бы
не записать в стек переменные которые будут использоваться в программе?
Код
    ldr    r0,     #0x20000900
    msr    cpsr_c, #(UNDEF_MODE | I_BIT | F_BIT)
    mov    sp, r0
    sub    r0, r0, #0x00000100
    msr    cpsr_c, #(ABT_MODE | I_BIT | F_BIT)
    mov    sp, r0
    sub    r0, r0, #0x00000100
    msr    cpsr_c, #(FIQ_MODE | I_BIT | F_BIT)
    mov    sp, r0
    sub    r0, r0, #0x00000100
    msr    cpsr_c, #(IRQ_MODE | I_BIT | F_BIT)
    mov    sp, r0
    sub    r0, r0, #0x00000100
    msr    cpsr_c, #(SVC_MODE | I_BIT | F_BIT)
    mov    sp, r0
    sub    r0, r0, #0x00000100
    msr    cpsr_c, #USR_MODE
    mov    sp, r0
    sub    sl, sp, #0x00000400
aaarrr
Цитата(sergey sva @ Jan 16 2009, 00:24) *
Начала адреса озу с 0x20000000 (at91sam7).

С количеством нулей ошиблись: ОЗУ у SAM7 начинается с 0x200000. Стек обычно располагают в конце ОЗУ, а не в начале.

P.S. Пожалуйста, используйте знаки препинания:
Цитата
другой вопрос правильно распределил адреса для стеков ремап не используется
- это можно примерно понять только с десятого прочтения.
sergey sva
Цитата
P.S. Пожалуйста, используйте знаки препинания:

Виноват, исправил.

Компоновщик настраиваться, в этом файле:
CODE
/* identify the Entry Point (_vec_reset is defined in file crt.s) */
ENTRY(_vec_reset)

/* specify the AT91SAM7S64 memory areas */
MEMORY
{
flash : ORIGIN = 0, LENGTH = 64K /* FLASH EPROM */
ram : ORIGIN = 0x00200000, LENGTH = 16K /* static RAM area */
}


/* define a global symbol _stack_end (see analysis in annotation above) */
_stack_end = 0x203FFC;

/* now define the output sections */
SECTIONS
{
. = 0; /* set location counter to address zero */

.text : /* collect all sections that should go into FLASH after startup */
{
*(.text) /* all .text sections (code) */
*(.rodata) /* all .rodata sections (constants, strings, etc.) */
*(.rodata*) /* all .rodata* sections (constants, strings, etc.) */
*(.glue_7) /* all .glue_7 sections (no idea what these are) */
*(.glue_7t) /* all .glue_7t sections (no idea what these are) */
_etext = .; /* define a global symbol _etext just after the last code byte */
} >flash /* put all the above into FLASH */

.data : /* collect all initialized .data sections that go into RAM */
{
_data = .; /* create a global symbol marking the start of the .data section */
*(.data) /* all .data sections */
_edata = .; /* define a global symbol marking the end of the .data section */
} >ram AT >flash /* put all the above into RAM (but load the LMA initializer copy into FLASH) */

.bss : /* collect all uninitialized .bss sections that go into RAM */
{
_bss_start = .; /* define a global symbol marking the start of the .bss section */
*(.bss) /* all .bss sections */
} >ram /* put all the above in RAM (it will be cleared in the startup code */

. = ALIGN(4); /* advance location counter to the next 32-bit boundary */
_bss_end = .; /* define a global symbol marking the end of the .bss section */
}
_end = .; /* define a global symbol marking the end of application RAM */

Где про это можно прочитать?
Пробовал запустить из командной строки, arm-elf-ld -?
Окно закрывается. Использую yagarto.

Модератор. Для цитирования объемных исходников используйте тэги codebox, вместо code.
Сергей Борщ
Цитата(sergey sva @ Jan 16 2009, 00:05) *
Где про это можно прочитать?
В документации на binutils.  Конкретно скрипты линкера (ld) - в документации на ld.
sergey sva
Буду читать. Мне еще не понятен один момент по работе прерываний:
После включения питания, контроллер переходит на первую строчку кода,
запись адреса вектора сброса в PC ldr pc, RESET_ADDR,
после происходит настройка ядра, стека, прочие настройки, таймеров, и дт
дальше вызов функции маин. В ней цикл for(;;){} , все зацикливается.
Возникло прерывании, например IRQ в PC должен записаться адрес кода где находится
программа обработки прерывания. Адрес метки программы прерываний нужно тоже записывать в какой то регистр?
aaarrr
Цитата(sergey sva @ Jan 16 2009, 15:37) *
Возникло прерывании, например IRQ в PC должен записаться адрес кода где находится
программа обработки прерывания. Адрес метки программы прерываний нужно тоже записывать в какой то регистр?

После получения сигнала IRQ ядро перейдет на вектор 0x18, затем Вам нужно прочитать адрес подпрограммы прерывания из контроллера прерываний (а он у каждого процессора свой, т.к. к ядру не относится) и обеспечить выполнение подпрограммы. Для SAM'а изучите раздел Advanced Interrupt Controller DS.
sergey sva
Как разместить метку, на асме по адресу 0x18 или 0x1C для того чтобы, после возникновения прерывания прочитать
регистр AIC_IVR и записать в PC?

Label: ((*)0x0000018 ) ??
zltigo
Цитата(sergey sva @ Jan 16 2009, 22:11) *
Как разместить метку, на асме ....

Ой smile.gif, что сейчас будет....
Код
                
         ORG 0x18
         ldr     pc,[pc,#-0xFF0]; Jump directly to the address given by the AIC

Тема напоминает строительство дома без фундамента sad.gif
P.S.
Может объединить c http://electronix.ru/forum/index.php?showtopic=57912&hl= до кучи?
sergey sva
Цитата
строительство дома без фундамента sad.gif

Ничего страшного Москва не сразу строилась. Было бы желание smile.gif smile.gif
Да это точно, что то будет smile.gif smile.gif
Понял что так можно перейти на выполнение кода находящегося по адресу,
но как разместить код по этому адресу 0х18? В документации написано что
после прерывания в счетчик программ будет записано 0х18 или 0х1С.
По этому адресу нужно разместить, код который будет читать вектор прерывания и записывать его в PC.
The CPSR is stored in SPSR_irq, the current value of the Program Counter is loaded in
the Interrupt link register (R14_irq) and the Program Counter (R15) is loaded with 0x18.
aaarrr
Цитата(sergey sva @ Jan 16 2009, 22:33) *
но как разместить код по этому адресу 0х18?

Помните код из своего первого поста? Вот он с небольшими модификациями:
Код
   ldr    pc, RESET_ADDR
    ldr    pc, UNDEF_ADDR
    ldr    pc, SWI_ADDR
    ldr    pc, PREFETCH_ABORT_ADDR
    ldr    pc, DATA_ABORT_ADDR
    .word    0
    ldr     pc,[pc,#-0xF20]; IRQ
    ldr     pc,[pc,#-0xF20]; FIQ
RESET_ADDR:        .word    RESET_handler
UNDEF_ADDR:        .word    UNDEF_handler
SWI_ADDR:        .word    SWI_handler
PREFETCH_ABORT_ADDR:    .word    PREFETCH_ABORT_handler
DATA_ABORT_ADDR:    .word    DATA_ABORT_handler
sergey sva
Если правильно понимаю? После перехода PC на адрес 0x1000018 происходит вычитания - 0хF20 программный счетчик переходит
на адрес AIC_IVR читается его значение и записывается в pc после выполняется программа обработки прерывания.
Запись в AIC_SVR0 - 31 нужно делать после сброса, после перехода по метке LAB1?

Код
0xFFFFF100    AIC_IVR
0xFFFFF104   AIC_FVR                                                                                


                 .global _start
                     _start:


0x1000000    ldr     pc,  lab1
0x1000004    ldr     pc,  lab2
0x1000008    ldr     pc,  lab3
0x100000C    ldr     pc, lab4
0x1000010    ldr     pc,  lab5
0x1000014   .word    0
0x1000018    ldr     pc,[pc,#-0xF20];               @IRQ_ADDR
0x100001C    ldr     pc,[pc,#-0xF20];               @  FIQ_ADDR    

lab1:
....
lab2:
....
aaarrr
Цитата(sergey sva @ Jan 17 2009, 01:18) *
Если правильно понимаю?

Почти: после перехода PC на адрес 0x18 (он же 0x100018 без ремапа - внимательнее с количеством нулей) произойдет загрузка регистра PC значением, расположенным по адресу PC-0xF20+8 = 0xFFFFF100 = AIC_IVR, и процессор отправится выполнять подпрограмму прерывания.

Цитата(sergey sva @ Jan 17 2009, 01:18) *
Запись в AIC_SVR0 - 31 нужно делать после сброса, после перехода по метке LAB1?

Ну не обязательно прямо так сразу и все. Не стоит забывать только про установку AIC_SPU.
zltigo
Цитата(aaarrr @ Jan 17 2009, 00:32) *
произойдет загрузка регистра PC значением, расположенным по адресу PC-0xF20+8



Где "магическое" число 8 две команды в конвеере.
sonycman
Цитата(aaarrr @ Jan 16 2009, 01:47) *
Стек обычно располагают в конце ОЗУ, а не в начале.

Скорее наоборот. Что IAR v5.1 (AVR), что Keil с RV (ARM) - стёк всегда среди начальных адресов ОЗУ, окружённый RW данными программы.
Почему так?
zltigo
Цитата(sonycman @ Jan 17 2009, 14:24) *
Скорее наоборот. Что IAR v5.1 (AVR), что Keil с RV (ARM)



Причем тут компиляторы вообще? Куда скажете, там и будет. Что там в неких демках идущих с каими-то компиляторами - дело "студентов" их писавших. Для реальных вещей надо думать конкретно куда и как. Для падающих стеков размещение в конце блока памяти является в общем случае максимально логичным.
sergey sva
Как обрабатывать исключительные ситуации, например Неопределенная инструкция?
Может есть рекомендации, или может ссылки на пример, желательно на asm.
aaarrr
Ссылка с рекомендациями. Для data abort и undefined instruction делаются аналогичные обработчики.
sergey sva
В функции prefetch_abort_handler_c должен быть еще какой то код,нужный для обработки прерывания?
aaarrr
Цитата(sergey sva @ Jan 17 2009, 21:48) *
В функции prefetch_abort_handler_c должен быть еще какой то код,нужный для обработки прерывания?

Нет, это самая обычная функция.
sergey sva
Понятно. Разбираюсь еще с ассемблером, появился вопрос, простой smile.gif ,
Подумал лучше спросить чем оставаться с сомнениями.
команда and логическое и, с флагом S выполняется если условие истинно.
Получается если:
mov R1 , #0xFF
ands R1 , R1, #0xFF
B lab1 условие истинное будет выполняться эта команда
B lab2 условие не истинное будет выполняться эта команда
aaarrr
Флаг S в команде указывает процессору, что нужно установить флаги в CPSR по результатам операции.
B lab1 будет выполняться всегда, BEQ lab2 - будет выполняться, если флаг Z установлен и т.д.
sergey sva
Если правильно понял:
mov R1 , #0xFF
ands R1 , R1, #0xFF
lab1 условие выполняется всегда
lab2 это условие и все что дальше, будет выполнятся если R1 && 0xFF истинно.
aaarrr
Цитата(sergey sva @ Jan 18 2009, 01:11) *
lab1 условие выполняется всегда
lab2 это условие и все что дальше, будет выполнятся если R1 && 0xFF истинно.

Ничего не понимаю. Что такое lab1 и lab2?
sergey sva
Виноват, не корректно поставил вопрос.

Если правильно понял:
mov R1 , #0xFF
ands R1 , R1, #0xFF
mov R2 , #0xFF @этот код выполняется всегда
mov R3 , #0xFF @этот код и все что дальше, будет выполнятся если R1 && 0xFF истинно.
.....
....
aaarrr
Цитата(sergey sva @ Jan 18 2009, 01:29) *
Если правильно понял:


mov R1, #0xFF
ands R1, R1, #0xFF
movne R2 , #0xFF ; этот код выполняется, если R1 & 0xFF != 0
mov R3 , #0xFF ;этот код выполняется всегда
sergey sva
Что проверяет _check_mapping: , для чего сохранять 0x12345678 в конец таблицы векторов, по адресу 0x200014 . ?

Код
_check_mapping:
    ldr    r0, =0x200014
    mov    r1, #0x14
    ldr    r2, =0x12345678
    str    r2, [r0]
    ldr    r0, [r1]
    cmp    r0, r2
    beq    _check_mapping_end
_mem_remap:
    @ RAM remap
    ldr    r0, =MC_BASE
    mov    r1, #1
    str    r1, [r0, #MC_RCR]
_check_mapping_end:
    mov    r0, #0x14
    mov    r1, #0
    str    r1, [r0]
aaarrr
check_mapping пишет 0x12345678 по адресу 0x200014 и проверяет, что по адресу 0x14 записано то же самое (т.е. ОЗУ отмаплено в нулевой адрес). Если это не так, выполняется remap.
sergey sva
Объясните, пожалуйста
Код
    AREA code1, DATA, READWRITE  @ DATA  эта директива как то влияет  на код , или это для удобства чтения кода ?

regs_temp            @метка
    SPACE    0x40  @указатель на структуру  0х40 ?

    END                 @ конец AREA1,  или  всей страницы кода?
aaarrr
Цитата(sergey sva @ Jan 18 2009, 19:08) *
Объясните, пожалуйста
Код
    AREA code1, DATA, READWRITE  @ DATA  эта директива как то влияет  на код , или это для удобства чтения кода ?

regs_temp            @метка
    SPACE    0x40  @указатель на структуру  0х40 ?

    END                 @ конец AREA1,  или  всей страницы кода?

AREA - указывает название и тип сегмента для линковки.
SPACE n - резервирует n байт памяти
END - конец файла

Все вышеперечисленное имеет смысл только для RVCT. У GCC дериктивы будут другими (.section, .zero и т.д).
sergey sva
Поправите если что не так понял. Изучаю доку, но не все же не понятно,
CPSR регистр статуса и регистр сохранного статуса SPSR , SPSR это резервный регист, в него нужно программно сохранять статус или он сам сохраняет
CPSR что то я не где это не нашел. Еще в программе обработки исключительной ситуации, вместе с включением прерываний ядро переключается в ABORT_MODE, а где его переводить в USER_MODE?
CODE

DATA_ABORT_handler:
sub r14, r14, #0x04
@ регистр связи r14 = r14 - 0x04
stmfd r13!, {r14}
@ Сохранить регистр R14 в Стеке
stmfd r13!, {r0-r3, r12}
@ Сохранить регистры r0 - r3 и r12 в Стеке
ldr r0, = regs_temp
@ Сохранить в r0 адрес структуры regs_temp
str r14, [r0], #0x04
@ Сохранить r14 в в структуре regs_temp
mov r14, r0
@ Записать в регистр связи адрес regs_temp
ldr r0, [r13]
@ Прочитать r0 из стека
stmia r14!, {r0-r12}
@ Сохранит в regs_temp регистры r0 - r12
mov r0, r14
@ Записать в r0 r14(адрес regs_temp)
mrs r14, SPSR
@ сохранить в r14, копию сохраненого статуса программы
stmfd r13!, {r14}
@ Сохранить в стеке регистр r14
orr r14, r14, #F_BIT
orr r14, r14, #I_BIT
@ запрет прерываний, логическое или r14 = r14 || #F_BIT || #I_BIT
msr CPSR_c, r14
@ запись в регистр статуса
stmia r0!, {r13-r14}
@ Сохранит в regs_temp регистры r13-r14
and r0, #F_BIT
and r0, #I_BIT
and r0, #ABT_MODE
@ логическое и, разрешение прерываний, переключение режима работы в аварийный.
@ r0 = r0 && #F_BIT && #I_BIT && #ABT_MODE
msr CPSR_c, r0
@ Записать в CPSR r0
ldr r0, = regs_temp
@ Записать в r0 указатель на regs_temp
@ bl func_obr_data_abort **** Вызов функции C
ldmfd r13!, {r0}
@ прочитать из стека r0
msr SPSR_c, r0
@ записать в регистр статуса r0. Возврат статуса.
ldmfd r13!, {r0-r3, r12, pc}^
@ Возврат програмного счетчика, и регистров r0-r3 r12 pc
@----------------------------------------------------------------------------------------

aaarrr
Код
    sub    r14,       r14, #0x04         @ LR_abt = LR_abt - 0x04
    stmfd  r13!,     {r14}               @ Сохранить LR_abt на стеке ABT
    stmfd  r13!,     {r0-r3, r12}        @ Сохранить r0 - r3 и r12 на стеке ABT
    ldr    r0, =      regs_temp          @ Загрузить в r0 адрес структуры regs_temp
    str    r14,      [r0], #0x04         @ Сохранить LR_abt в структуре regs_temp
    mov    r14,       r0                 @ Записать в LR_abt адрес regs_temp+4
    ldr    r0,       [r13]               @ Прочитать r0 из стека ABT
    stmia  r14!,     {r0-r12}            @ Сохранить в regs_temp+4 регистры r0 - r12
    mov    r0,        r14                @ Записать в r0 LR_abt (адрес regs_temp+56)
    mrs    r14,       SPSR               @ Загрузить в LR_abt копию сохраненого статуса программы
    stmfd  r13!,     {r14}               @ Сохранить в стеке ABT регистр LR_abt
    orr    r14,       r14, #F_BIT        @ запрет прерываний, побитовое ИЛИ r14 = r14 | #F_BIT | #I_BIT
    orr    r14,       r14, #I_BIT
    msr    CPSR_c,    r14                @ запись в регистр статуса, переключение в режим XXX
    stmia  r0!,      {r13-r14}           @ Сохранить в regs_temp+56 регистры SP_XXX и LR_XXX
    and    r0,       #F_BIT              @ ????????
    and    r0,       #I_BIT              @ ????????
    and    r0,       #ABT_MODE           @ ????????
    msr    CPSR_c,    r0                 @ Записать в CPSR r0, переключение в режим ABT
    ldr    r0, =     regs_temp           @ Записать в r0 указатель на regs_temp
@    bl     func_obr_data_abort           @ Вызов функции C
    ldmfd  r13!,     {r0}                @ прочитать r0 из стека ABT
    msr    SPSR_c,    r0                 @ записать в регистр сохраненного статуса r0. Возврат статуса.
    ldmfd  r13!,     {r0-r3, r12, pc}^   @ Возврат програмного счетчика, и регистров r0-r3 r12 pc, переключение в режим XXX


Вот здесь у вас что-то, мягко говоря, странное написано:
Код
    and    r0,       #F_BIT
    and    r0,       #I_BIT
    and    r0,       #ABT_MODE
    msr    CPSR_c,    r0


Цитата(sergey sva @ Jan 18 2009, 21:10) *
SPSR это резервный регист, в него нужно программно сохранять статус или он сам сохраняет CPSR

Сам сохраняет.

Цитата(sergey sva @ Jan 18 2009, 21:10) *
Еще в программе обработки исключительной ситуации, вместе с выключением прерываний ядро переключается в ABORT_MODE, а где его переводить в USER_MODE?

Обратите внимание на "^" в последней инструкции.
sergey sva
После чтения SPSR_c , устанавливаются биты #F_BIT | #I_BIT , после записывается в стек и в регистр CPSR_c
Режим не переключали, он сам переключается , в режим XXX (неопределенный а в эту обработку программа пришла из вектора 0х10 )?
Код
    mrs    r14,       SPSR               @ Загрузить в LR_abt копию сохраненого статуса программы
    stmfd  r13!,     {r14}               @ Сохранить в стеке ABT регистр LR_abt
    orr    r14,       r14, #F_BIT        @ запрет прерываний, побитовое ИЛИ r14 = r14 | #F_BIT | #I_BIT
    orr    r14,       r14, #I_BIT
    msr    CPSR_c,    r14                @ запись в регистр статуса, переключение в режим XXX
    stmia  r0!,      {r13-r14}           @ Сохранить в regs_temp+56 регистры SP_XXX и LR_XXX
    orr    r0,       #F_BIT              
    orr    r0,       #I_BIT              
    orr    r0,       #ABT_MODE          
    msr    CPSR_c,    r0                 @ Записать в CPSR r0, переключение в режим ABT
aaarrr
Цитата(sergey sva @ Jan 19 2009, 21:13) *
После чтения SPSR_c , устанавливаются биты #F_BIT | #I_BIT , после записывается в стек и в регистр CPSR_c
Режим не переключали, он сам переключается , в режим XXX (неопределенный а в эту обработку программа пришла из вектора 0х10 )?

SPSR сохраняется на стеке до того, как устанавливаются биты F и I. Режим XXX не неопределенный, а тот, в котором случилось исключение. Т.е. получается так: XXX->ABT->XXX->ABT->XXX.

Код
    orr    r0,       #F_BIT              
    orr    r0,       #I_BIT              
    orr    r0,       #ABT_MODE          
    msr    CPSR_c,    r0                 @ Записать в CPSR r0, переключение в режим ABT

Во-первых, Вы пропустили инициализацию R0, во-вторых, лучше бы найти "волшебное слово" для операции OR в ассемблере, чем плодить ненужные инструкции.
sergey sva
Вам, случайно не встречался пример обработки FIQ ? smile.gif
aaarrr
Цитата(sergey sva @ Jan 19 2009, 23:56) *
Вам, случайно не встречался пример обработки FIQ ? smile.gif

Что значит "случайно встречался"? smile.gif Когда надо было - писал.
В общем случае ничем не отличается от IRQ, кроме наличия теневого банка старших регистров.
sergey sva
Сделайте замечания что, тут я не правильно понял в irq обработчике, smile.gif
Еще вопрос по fiq , теневой регистр, вроде не мало прочел, не где это не встречалось , это R8 -R14
что в них сохраняется, тоже что и RL ?
CODE
@----------------------------------------------------------------------------------------
IRQ_handler:
sub lr, lr, #4 @ LR_IRQ - 4
stmfd sp!, {r0, r3, lr} @ сохранить в стеке IRQ, регистры R0 R1 и LR
ldr r0, = AIC_BASE @ чтение из AIC_BASE и запись в регистр R0
ldr r1, [r0, #AIC_IVR] @ чтение из r0 + #AIC_IVR и запись в регистр R1 вектора прерываний
mrs r0, SPSR @ Запись в регистр R0 Сохраненого Статуса SPSR
stmdb sp!, {r0} @ сохранить в стеке регистр R0 (статус до прервания)
mrs r0, CPSR @ Запись в регистре R0, и возврат в режим который был до прерывания
orr r0, r0, #SYS_MODE @ Логическое ИЛИ регистра R0 с #SYS_MODE с сохранением в R0
msr CPSR, r0 @ переключение ядра, в Системный режим
stmdb sp!, {r2, r3, r4, r5, r6, r7, r8, r9, r10, fp, ip, lr}@ сохранить в стеке SyS регистры r2, r3, r4, r5, r6, r7, r8, r9, r10, fp, ip, lr
mov lr, pc @ Копировать в LR регистр, регистр r14 + 0х04
bl r1 @ Переход на вектор программы обработки прерывания
ldmia sp!, {r2, r3, r4, r5, r6, r7, r8, r9, r10, fp, ip, lr}@ Прочитать из стека регистры r2, r3, r4, r5, r6, r7, r8, r9, r10, fp, ip, lr
mrs r0, CPSR @ сохранить в регистре R0 текущий статус
bic r0, r0, #SYS_MODE @ Логическая операция AND NOT регистра R0 и #SYS_MODE
orr r0, r0, #IRQ_MODE @ Логическое ИЛИ регистра R0 и #IRQ_MODE
msr CPSR, r0 @ Запись в регистр CPSR регистр R0 и переключение ядра в IRQ_mode,
ldr r0, = AIC_BASE @ чтение из AIC_BASE и запись в регистр R0 (базовый адрес AIC)
str r0, [r0, #AIC_EOICR] @ сохранить R0 по адресу R0 + #AIC_EOICR и сброс прерывания
ldmia sp!, {r0} @ чтение из стека и запись в R0 (статус до прерывания)
msr SPSR, r0 @ запись в SPSR регистр R0 (возврат статуса до прерывания)
ldmia sp!, {r0, r3, pc}^ @ запись в PC значения сохраненого, в момент возникновения прерывания и востановление регистров r0 r3, обновить CPSR
@----------------------------------------------------------------------------------------
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.