Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Вылет в Abort после LDR
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Alexashka
Поскажите пожалуйста, в проекте для ARM под IAR происходит такая беда, после возникновения прерывания (неважно какого из двух) прога попадает в приведенный ассемблерный код, после чего должна перейти собственно на обработчик, но происходит какаято ерунда.

Код
irqHandler:
        /* Save interrupt context on the stack to allow nesting */
        SUB     lr, lr, #4
        STMFD   sp!, {lr}
        MRS     lr, SPSR
        STMFD   sp!, {r0, lr}

        /* Write in the IVR to support Protect Mode */
        LDR     lr, =AT91C_BASE_AIC
        LDR     r0, [r14, #AIC_IVR]
        STR     lr, [r14, #AIC_IVR]


После выполнения 6-й инструкции (пошагово в окне дизассемблера) я попадаю в ячейку с адресом 0x10 (вроде как Abort). Может я чего не понимаю, но LDR по идее должна просто грузить значение в r0. Или тут сложнее? Что конкретно делает данная инструкция LDR r0, [r14, #AIC_IVR]. В дизассемблере эта строчка выглядит так:

Код
        LDR     r0, [r14, #AIC_IVR]
     0x200048: 0xe59e0100     LDR       R0, [LR, #0x100]


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

Update
Все нашел в чем проблема (и как я не заметил сразу, наверно это всё понедельник sm.gif), предыдущая строчка
LDR lr, =AT91C_BASE_AIC
0x200044: 0x00000000 ANDEQ R0, R0, R0
не загружает в LR ничего, видимо с определением чтото, буду разбираться.
Странно что ассемблер не ругается
Aleph
Цитата(Alexashka @ Dec 19 2011, 07:49) *
LDR lr, =AT91C_BASE_AIC
0x200044: 0x00000000 ANDEQ R0, R0, R0
не загружает в LR ничего, видимо с определением чтото, буду разбираться.
Странно что ассемблер не ругается
Есть подозрение, что ассемблер такого сгенерить не мог. Проверьте сразу после ресета, до выполнения чего бы то ни было, что по этому адресу находится. Если LDR, а не 0x0, то кто-то пишет по этому адресу.
Alexashka
Цитата(Aleph @ Dec 19 2011, 13:45) *
<br />Есть подозрение, что ассемблер такого сгенерить не мог. Проверьте сразу после ресета, до выполнения чего бы то ни было, что по этому адресу находится. Если LDR, а не 0x0, то кто-то пишет по этому адресу.<br /><br />
<br /><br /><br />
Точно! sm.gif Так и оказалось, банально переполнение массива -поменял число элементов массива, а размерность не поправил.
Alexashka
Снова здорова. Решил замутить обработчик FIQ прерываний. В исходном проекте под IAR5.1 его не было, нашел проект под какойто 4й IAR, вставил из него стартап файл в свой проект, однако он не захотел компилятся. Тогда я перенес в свой стартап только функцию fiqHandler, и вообщемто я в нее попадаю, но та же проблема что и в первом посте, из этой функции вылетаю черте куда. Ошибка возникает при загрузке
ldr r0 , [r14, #AIC_FVR]
в r0 явно грузится какаято шняга
и дальше должен перейти на обработчик
;- Branch to the routine pointed by the AIC_FVR
mov r14, pc
bx r
и вот тут происходит аборт.
#AIC_FVR нигде не нашел, откуда он вообще берется?

Вот код функции из стартапа
Цитата
fiqHandler:

;- Switch in SVC/User Mode to allow User Stack access for C code
; because the FIQ is not yet acknowledged

;- Save and r0 in FIQ_Register
mov r9,r0
ldr r0 , [r14, #AIC_FVR]
msr CPSR_c,#I_BIT | F_BIT | ARM_MODE_SVC
;- Save scratch/used registers and LR in User Stack
stmfd sp!, { r1-r3, r12, lr}

;- Branch to the routine pointed by the AIC_FVR
mov r14, pc
bx r0

;- Restore scratch/used registers and LR from User Stack
ldmia sp!, { r1-r3, r12, lr}

;- Leave Interrupts disabled and switch back in FIQ mode
msr CPSR_c, #I_BIT | F_BIT | ARM_MODE_FIQ

;- Restore the R0 ARM_MODE_SVC register
mov r0,r9

;- Restore the Program Counter using the LR_fiq directly in the PC
subs pc,lr,#4


Собственно теперь все строки кода нормальные, никаких нулей нету, но вот передаваемое значение #AIC_FVR какоето левое.
Вообще есть у когонибудь рабочий стартап с обработчиком FIQ под IAR5 или 6 версии?
Добавлено: Вообщем в качестве #AIC_FVR подставляется значение 0x00000104, похоже на правду? А что в LR должно при этом находится?
GetSmart
Цитата(Alexashka @ Dec 30 2011, 11:17) *
ldr r0 , [r14, #AIC_FVR]
в r0 явно грузится какаято шняга
и дальше должен перейти на обработчик
;- Branch to the routine pointed by the AIC_FVR
mov r14, pc
bx r0
и вот тут происходит аборт.
#AIC_FVR нигде не нашел, откуда он вообще берется?

Тут явно ошибка в непонятно кем написанном обработчике. При залёте в FIQ, R14 (aka LR) содержит адрес возврата (-4). С чего бы это относительно него происходит загрузка адреса обработчика из контроллера прерываний. По логике, этот R14 нужно сперва сохранить в стеке, потом обнулить, а потом использовать как базу при обращении к контроллеру прерываний. Но равно можно юзать любой другой регистр в качестве базы. У меня вообще первой командой иногда стоит сохранение регистров в стеке, вместе с LR.

Про AIC_FVR не могу сказать, т.к. с Atmel ARM дело не имел. Но вероятно это тот же регистр, который содержит вектор для IRQ. В NXP ARM именно так - регистр общий. Но когда обработчик FIQ в системе один, то этот регистр вектора вообще читать не обязательно. Можно сразу прыгать на этот единственный вектор.
Alexashka
Цитата(GetSmart @ Dec 30 2011, 12:30) *
Тут явно ошибка в непонятно кем написанном обработчике. При залёте в FIQ, R14 (aka LR) содержит адрес возврата (-4). С чего бы это относительно него происходит загрузка адреса обработчика из контроллера прерываний. По логике, этот R14 нужно сперва сохранить в стеке, потом обнулить, а потом использовать как базу при обращении к контроллеру прерываний. Но равно можно юзать любой другой регистр в качестве базы. У меня вообще первой командой иногда стоит сохранение регистров в стеке, вместе с LR.

Про AIC_FVR не могу сказать, т.к. с Atmel ARM дело не имел. Но вероятно это тот же регистр, который содержит вектор для IRQ. В NXP ARM именно так - регистр общий. Но когда обработчик FIQ в системе один, то этот регистр вектора вообще читать не обязательно. Можно сразу прыгать на этот единственный вектор.

Извиняюсь, это мой глюк, пока экспериментировал с этими регистрами, забыл вернуть как было. laughing.gif
А был там R8 вместо R14. Про него в шапке функции написано: R8 is initialize in Cstartup.
Вообщем я его проинициировал =AT91C_BASE_AIC и все заработало. Но возник другой вопрос. Код отвечающий за вход-выход из обычного IRQ только чуть чуть длиннее, чем для FIQ, желание использовать FIQ возникло в виду слишком долгого входа в простое прерывание. Но судя по всему с FIQ я не получу существенной выгоды в скорости? В чем тут можно сэкономить? Не сохранять/восстанавливать РОН и соотв.не использовать их в подпрограмме FIQ? Я по простоте душевной полагал, что происходит переключение банков, и в FIQ можно не боятся испортить значения регистров РОН в которых лежат данные основной программы. Выходит это не так?
GetSmart
R8-R12 индивидуальные для FIQ. Их можно не сохранять. Но обработчик на Си будет юзать R0-R7, которые придётся сохранять. Всю скорость FIQ можно поиметь только написав обработчик на асме в идеале даже не юзая R0-R7.
Alexashka
Цитата(GetSmart @ Dec 30 2011, 14:17) *
R8-R12 индивидуальные для FIQ. Их можно не сохранять. Но обработчик на Си будет юзать R0-R7, которые придётся сохранять. Всю скорость FIQ можно поиметь только написав обработчик на асме в идеале даже не юзая R0-R7.

Ясно, спасибо. А можно както указать компилятору не использовать R0-R7 в обработчике FIQ? LR и R12 я так понимаю можно не сохранять так как они банкируются, интересно для чего это делается в данном коде? А вот R4-R7 не сохраняются, видимо компилятору достаточно первых 4 регистра.
GetSmart
Цитата(Alexashka @ Dec 30 2011, 21:05) *
А можно както указать компилятору не использовать R0-R7 в обработчике FIQ? LR и R12 я так понимаю можно не сохранять так как они банкируются,...

Какому компилятору? - хотя не важно. Скажу только за IAR. Там есть служебное слово __fiq, которое указывает, что сохранять в обработчике R8-R12 не нужно. Но функции, вызываемые из этой функции-обработчика будут юзать младшие регистры.

ЗЫ. LR сохранять надо полюбому. Почему - читайте документацию на АРМ.
Alexashka
Цитата(GetSmart @ Dec 30 2011, 20:19) *
Какому компилятору? - хотя не важно. Скажу только за IAR. Там есть служебное слово __fiq, которое указывает, что сохранять в обработчике R8-R12 не нужно. Но функции, вызываемые из этой функции-обработчика будут юзать младшие регистры.

ЗЫ. LR сохранять надо полюбому. Почему - читайте документацию на АРМ.

Добавил в обработчик FIQ директиву __fiq и теперь внутри обработчика используются только регистры R8-R12. Это очень радует! Сохранение регистров R0...R7 перед входом в обработчик выкинул, LR тоже не сохраняю, т.к у меня нет вложенных быстрых прерываний, вообщем время входа в обработчик уменьшилось раза в 3 наверно. Однако почемуто теперь возврат из обработчика делается не копированием в PC значения из LR, а с декрементом на 4, поэтому перед входом в обработчик приходится в LR записывать значение PC+4. Зачем так сделано не понял. Если не указывать директиву __fiq то выход из обработчика делается без декремента. 05.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.