GenaSPB 11 6 марта, 2016 Опубликовано 6 марта, 2016 (изменено) · Жалоба Появился вопрос в процессе одевания на голое железо обычной системы с super loop. Железо - Renesas RZ/A1L. Что есть: Вот такой код обработчика в ассемблере: IRQHandler: /* Save interrupt context on the stack to allow nesting */ sub lr, lr, #4 stmfd sp!, {lr} mrs lr, SPSR stmfd sp!, {r0, lr} // save VFP/Neon data registers VPUSH {d0-d15} // same as s0-s31 // save VFP/Neon FPSCR register FMRX r0, fpscr stmfd sp!, {r0-r3, r4, r12, lr} ldr r2, =IRQHandlerSafe mov lr, pc bx r2 /* And jump... */ ldmia sp!, {r0-r3, r4, r12, lr} // restore VFP/Neon FPSCR register FMXR fpscr, r0 // restore VFP/Neon data registers VPOP {d0-d15} // same as s0-s31 ldmia sp!, {r0, lr} msr SPSR_cxsf, lr ldmia sp!, {pc}^ И его продолжение в C: void IRQHandlerSafe(void) { /* const uint32_t icchpir = */ (void) INTC.ICCHPIR; const uint32_t icciar = INTC.ICCIAR; (* intc_func_table [icciar & 0x03FF]) (); /* Call interrupt handler */ INTC.ICCEOIR = icciar & 0x1FFF; } Сейчас всё работает в случае, если среди прерываний нет разделения на группы с меньшим и большим приоритетами. Стоит добавить, получается "каша" - похоже, что выполнение более приоритетного прерывания не рапрещает выполнение менее приоритетного. Установка при инициализации процессора значения в регистре priority mask на менее приоритетное прерывание - оно естественно запрещается... Вопрос - как это должно тут выглядеть? (на STM32 с архитектурой Cortex-M4 и Cortex-M7 это всё работает, с использованием тамошних механизмов BASEPRI и остального). зы: картинки просто как иллюстрация. Изменено 6 марта, 2016 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 6 марта, 2016 Опубликовано 6 марта, 2016 · Жалоба Почитал... понял что тут (в armv7-a) всё совсем не так просто... Если процессор стартует в supervisor mode и далее в нём работает, прерывания используют свой стек. А если я запущу в IRQ mode? при входе в прерывание не будет происходить перезагрузка SP и прерывания будут вложенными? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AndrejM 0 7 марта, 2016 Опубликовано 7 марта, 2016 · Жалоба загляните в примеры для freertos , там есть для cortex-a9 реализация FreeRTOS_IRQ_Handler в файле portASM.s . стартуете в supervisor , в обработчике снова в него переключаетесь FreeRTOS_IRQ_Handler ; Return to the interrupted instruction. SUB lr, lr, #4 ; Push the return address and SPSR PUSH {lr} MRS lr, SPSR PUSH {lr} ; Change to supervisor mode to allow reentry. CPS #SVC_MODE ; Push used registers. PUSH {r0-r4, r12} ............................ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 1 7 марта, 2016 Опубликовано 7 марта, 2016 · Жалоба Почитал... понял что тут (в armv7-a) всё совсем не так просто... Наоборот - все просто, если о том, что в ядре - есть два прерывания IRQ и FIQ. FIQ, естественно, прерывает IRQ. То есть такого типа вложенность есть. Любые другие форусы с вложеностью - ручками. Собственно контролеры прерываний это не как у мелких кортексов - не пренадлежность ядра и могут быть разнообразными в зависимости от производителя. Что прикручивает STM не смотрел. А если я запущу в IRQ mode? при входе в прерывание не будет происходить перезагрузка SP и прерывания будут вложенными? ВСЕГДА устанавливаться начало собственного стека и соответственно никакой автоматической вложенности не может быть в принципе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 7 марта, 2016 Опубликовано 7 марта, 2016 (изменено) · Жалоба Не прервёт ли исполнявшееся IRQ другое IRQ с большим приоритетом? Я про ситуацию "рукопашного" выхода из прерывания - не вернут ли меня назад, к началу обработчика? ARM-овский документ есть, но как-то в явном виде эту ситуацию я пока не нашел... чугунный слог, которым там всё описано, просто тяжело читать "насковзь". Изменено 7 марта, 2016 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 8 марта, 2016 Опубликовано 8 марта, 2016 (изменено) · Жалоба Разобрался... Самое необычное, что в старом проекте для AT91SAM7S64 было именно так сделано... Разобрался снова в коде более чем пять лет назад писанном... Я не мог догадаться, что в результате начинает использоваться два стека. А я всё искал способ "выгрести" всё из стека IRQ и перенести в главный (SVC). Обработчик теперь выглядит так: IRQHandler: /* Save interrupt context on the stack to allow nesting */ sub lr, lr, #4 stmfd sp!, {lr} mrs lr, SPSR stmfd sp!, {r0, lr} msr CPSR_c, #ARM_MODE_SVC | I_BIT // added ***** stmfd sp!, {r1-r3, r4, r12, lr} // save VFP/Neon data registers VPUSH {d0-d15} // same as s0-s31 // save VFP/Neon FPSCR register FMRX r2, fpscr PUSH {r2} ldr r2, =IRQHandlerSafe mov lr, pc bx r2 /* And jump... */ // restore VFP/Neon FPSCR register POP {r2} FMXR fpscr, r2 // restore VFP/Neon data registers VPOP {d0-d15} // same as s0-s31 ldmia sp!, {r1-r3, r4, r12, lr} msr CPSR_c, #ARM_MODE_IRQ | I_BIT // added ***** ldmia sp!, {r0, lr} msr SPSR_cxsf, lr Остались ещё проблемы с маской приоритетов, но это уже не страшно... Изменено 8 марта, 2016 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 9 марта, 2016 Опубликовано 9 марта, 2016 (изменено) · Жалоба Как выяснилось при тестировании на минимальной программе: прерывания действительно "вложенны", обрабатываются так как надо (в нужном порядке соответственно назначенным приоритетам). Но! После возникновения первого же прерывания основная программа перестает выполняться. Вот RPR (running priority) и CPSR в разных точках: Основная программа до возникновения первого из прерываний FF 800001d3 Прерывание с меньшим приоритетом 10 60000193 Прерывание с большим приоритетом 08 80000193 Состояние RPR=FF больше не появляется ни разу. UPD: После возникновения первого же прерывания основная программа перестает выполняться Всё нормально, просто тест был написан таким образом, что аппаратные прерывания возникали так часто (и с такими задержками внутри обработчиков), что в основной цикл никогда не возвращались... Изменено 9 марта, 2016 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 9 марта, 2016 Опубликовано 9 марта, 2016 (изменено) · Жалоба Странно... Установка правильны образом сформированного значения в GICC_PMR должна запрещать прерывания с указанным и меньшим приоритетом. Однако, в моем случае почему-то иногда не срабатывает... __ISB() и __DSB() пробовал. Присвоением значения в этот регистр ограждается критическая секция (работа со связанным списком из основного цикла и из прерывания не с самым высоким приоритетом. В системе существует ещё одно прерывание с более высоким приоритетом - и не имеет отношения к этому списку. Так замена избирательного запрещения прерываний в этом месте на __disable_irq() (модификация I в CPSR) и соответственно разрешение - даёт нормально работающую программу. Изменено 9 марта, 2016 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 226 10 марта, 2016 Опубликовано 10 марта, 2016 · Жалоба Наоборот - все просто, если о том, что в ядре - есть два прерывания IRQ и FIQ. FIQ, естественно, прерывает IRQ. Не естестественно ;) Насколько я помню ARM7: при входе в режим IRQ, процессор автоматически устанавливает запрет прерываний IRQ; при входе в режим FIQ автоматически устанавливает запрет FIQ & IRQ. Но ничто не запрещает программисту хоть в начале ISR любой из этих запретов снять или установить дополнительно и тогда и IRQ сможет прервать FIQ-обработчик если очень хочется. Как впрочем и вложенное прерывание (IRQ в IRQ или FIQ в FIQ) может возбудиться, но только надо быть аккуратным тут, так как будут перезаписаны теневые регистры регистрового файла для данного режима (SP, LR, SPSR для IRQ-режима и ещё больше регистров для FIQ-режима). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 1 10 марта, 2016 Опубликовано 10 марта, 2016 · Жалоба Не естестественно ;) "Естественно" писалось о аппаратном поведении встроенного в ядро механизма IRQ/FIQ, а не о том, как его можно расширять контроллерами прерываний и корректировать программно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться