SergeyVas 0 19 января, 2009 Опубликовано 19 января, 2009 · Жалоба После чтения 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 64 19 января, 2009 Опубликовано 19 января, 2009 · Жалоба После чтения 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 в ассемблере, чем плодить ненужные инструкции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergeyVas 0 19 января, 2009 Опубликовано 19 января, 2009 · Жалоба Вам, случайно не встречался пример обработки FIQ ? :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 64 19 января, 2009 Опубликовано 19 января, 2009 · Жалоба Вам, случайно не встречался пример обработки FIQ ? :) Что значит "случайно встречался"? :) Когда надо было - писал. В общем случае ничем не отличается от IRQ, кроме наличия теневого банка старших регистров. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergeyVas 0 19 января, 2009 Опубликовано 19 января, 2009 · Жалоба Сделайте замечания что, тут я не правильно понял в irq обработчике, :) Еще вопрос по fiq , теневой регистр, вроде не мало прочел, не где это не встречалось , это R8 -R14 что в них сохраняется, тоже что и RL ? @---------------------------------------------------------------------------------------- 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 @---------------------------------------------------------------------------------------- Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 64 19 января, 2009 Опубликовано 19 января, 2009 · Жалоба Сделайте замечания что, тут я не правильно понял в irq обработчике, :) Вроде все правильно поняли, только вот обработчик - дрянь :( Еще вопрос по fiq , теневой регистр, вроде не мало прочел, не где это не встречалось , это R8 -R14 что в них сохраняется, тоже что и RL ? Теневые регистры FIQ - R8-R12 (R13 и R14 и так у всех свои). В них ничего не сохраняется, они просто существуют только в режиме FIQ, из других режимов к ним доступа нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergeyVas 0 19 января, 2009 Опубликовано 19 января, 2009 · Жалоба >вот обработчик - дрянь где бы посмотреть как он должен работать правильно, или что лучше изменить ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 64 19 января, 2009 Опубликовано 19 января, 2009 · Жалоба где бы посмотреть как он должен работать правильно, или что лучше изменить ? В приведенном вами коде выполняется несколько абсолютно бессмысленных действий: 1. Ручное чтение AIC_IVR 2. Переход в режим SYS с запрещенными прерываниями 3. Сохранение всех подряд регистров при вызове подпрограммы Теперь как все это исправить: 1. Если уж у AIC есть механизм автовекторинга, то грех его не использовать: 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 Т.е. сразу, первой же командой, переходим на адрес из AIC_IVR. 2. Если Вы не планируете использовать вложенные прерывания, то можно на этом остановитться, и оформлять обработчики стандартно: RVCT: __irq void handler(void); GCC: void handler(void) __attribute__ ((interrupt ("IRQ"))); и т.д. 2a. Если же нужны вложенные прерывание, то каждое из них снабжаем своей оберткой: irq_wrapper ; Модифицируем и сохраняем LR sub r14, r14, #0x04 stmfd sp!, {r14} ; Сохраняем SPSR и r0 на стеке IRQ mrs r14, SPSR stmfd sp!, {r0, r14} ; Включаем прерывания и переключаемся в режим SYS mrs r14, CPSR bic r14, r14, #I_BIT orr r14, r14, #ARM_MODE_SVC msr CPSR_c, r14 ; Сохраняем только нужные регистры на стеке USER/SYS stmfd sp!, {r1-r3, r12, r14} ; Вызываем C-обработчик bl irq_handler ; Восстанавливаем регистры ldmfd sp!, {r1-r3, r12, r14} ; Запрещаем прерывания, переключаемся в режим IRQ mrs r0, CPSR bic r0, r0, #ARM_MODE_SYS orr r0, r0, #I_BIT :OR: ARM_MODE_IRQ msr CPSR_c, r0 ; Извещаем AIC об окончании обработки прерывания ldr r0, =AT91C_BASE_AIC str r0, [r0, #AIC_EOICR] ; Восстанавливаем SPSR_irq и r0 из стека IRQ ldmfd sp!, {r0, r14} msr SPSR_cxsf, r14 ; Загружаем в PC модифицированный LR и переключаем режим ldmfd sp!, {pc}^ В этом случае C-обработчик будет обычной процедурой: void handler(void); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergeyVas 0 20 января, 2009 Опубликовано 20 января, 2009 · Жалоба В инструкции msr SPSR_cxsf, r14 есть флаги или модификаторы, не знаю как правильно называются. Флаг C разрешает модифицировать только биты 0 - 7,флаг X разрешает модифицировать только биты 8 - 15,s 16 - 23,f24-31. когда они все установлены, разрешено модифицировать все биты статуса ядра, а зачем их устанавливать все? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 64 20 января, 2009 Опубликовано 20 января, 2009 · Жалоба когда они все установлены, разрешено модифицировать все биты статуса ядра, а зачем их устанавливать все? Ну, восстановить-то SPSR мы должны полностью. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergeyVas 0 20 января, 2009 Опубликовано 20 января, 2009 (изменено) · Жалоба А в чем будет разница, если не устанавливать cxsf ? :) msr SPSR , r14 Изменено 20 января, 2009 пользователем sergey sva Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 64 20 января, 2009 Опубликовано 20 января, 2009 · Жалоба А в чем будет разница, если не устанавливать cxsf ? :) msr SPSR , r14 Во-первых, написать msr SPSR , r14 Вам нормальный ассемблер не позволит, заставив указать хотя бы одно поле. А если позволит, то сам сделает cxsf. Применительно к коду обработчика прерывания, не восстановление хотя бы одного из полей SPSR грозит трудновыловимыми глюками при работе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 20 января, 2009 Опубликовано 20 января, 2009 · Жалоба В приведенном вами коде выполняется несколько абсолютно бессмысленных действий: 1. Ручное чтение AIC_IVR 2. Переход в режим SYS с запрещенными прерываниями По п.1. Ручное чтение AIC_IVR не такое уж зло. При этом достаточно написать один обработчик прерываний для всех функций прерываний, а не обрамлять каждую из них соответствуюшим кодом. По п.2 Переход в режим SYS с запрещенными прерываниями. Так и вы тоже самое делаете в приведенном примере для вложенных прерываний. Кстати, как то набрел на такой обработчик, который короче и быстрее, но требует 128 байт в irq стеке: ;16 instructions (16*8) = 128 bytes in irq_stack ;40 bus cycles IRQ_Handler_Entry: sub lr, lr, #4 stmfd sp!, {r4-r6, lr} mrs r4, SPSR ldr r5, =AT91C_BASE_AIC ldr r6, [r5, #AIC_IVR] str r6, [r5, #AIC_IVR] nop msr CPSR_c, #ARM_MODE_SYS stmfd sp!, {r0-r3, r12, lr} mov lr, pc bx r6 ldmia sp!, {r0-r3, r12, lr} msr CPSR_c, #I_BIT | ARM_MODE_IRQ str r0, [r5, #AIC_EOICR] msr SPSR_cxsf, r4 ldmia sp!, {r4-r6, pc}^ ;; using more IRQ stack... the linker config file may ;; have to be fixed ; ENDP Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SergeyVas 0 20 января, 2009 Опубликовано 20 января, 2009 · Жалоба Если не ошибаюсь, то в этом обработчике, переход на вектор прерывания будет с выключенными прерываниями, если вдруг обработка немного затянется а прерывания будут выключены то данные потеряются. А для чего это перезапись? ldr r6, [r5, #AIC_IVR] str r6, [r5, #AIC_IVR] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 20 января, 2009 Опубликовано 20 января, 2009 · Жалоба Если не ошибаюсь, то в этом обработчике, переход на вектор прерывания будет с выключенными прерываниями, если вдруг обработка немного затянется а прерывания будут выключены то данные потеряются. А для чего это перезапись? ldr r6, [r5, #AIC_IVR] str r6, [r5, #AIC_IVR] Ошибаетесь. Переход на функцию обработки прерывания происходит при разрешенных прерываниях (мы же переключились в SYS режим). При чтении по AT91C_BASE_AIC->AIC_IVR в r6 загружается адрес функции обработки прерывания. А запись туда же - сброс AIC'a, чтобы он мог обрабатывать последующие прерывания. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться