Перейти к содержанию
    

Cortex-A9 вложенные прерыания

Появился вопрос в процессе одевания на голое железо обычной системы с 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 и остального).

 

 

зы: картинки просто как иллюстрация.

post-28634-1457294950_thumb.jpg

post-28634-1457294983_thumb.jpg

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Почитал... понял что тут (в armv7-a) всё совсем не так просто...

 

 

Если процессор стартует в supervisor mode и далее в нём работает, прерывания используют свой стек. А если я запущу в IRQ mode? при входе в прерывание не будет происходить перезагрузка SP и прерывания будут вложенными?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

загляните в примеры для 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}

............................

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Почитал... понял что тут (в armv7-a) всё совсем не так просто...

Наоборот - все просто, если о том, что в ядре - есть два прерывания IRQ и FIQ. FIQ, естественно, прерывает IRQ.

То есть такого типа вложенность есть. Любые другие форусы с вложеностью - ручками.

Собственно контролеры прерываний это не как у мелких кортексов - не пренадлежность ядра и могут быть разнообразными в зависимости от производителя. Что прикручивает STM не смотрел.

А если я запущу в IRQ mode? при входе в прерывание не будет происходить перезагрузка SP и прерывания будут вложенными?

ВСЕГДА устанавливаться начало собственного стека и соответственно никакой автоматической вложенности не может быть в принципе.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не прервёт ли исполнявшееся IRQ другое IRQ с большим приоритетом? Я про ситуацию "рукопашного" выхода из прерывания - не вернут ли меня назад, к началу обработчика? ARM-овский документ есть, но как-то в явном виде эту ситуацию я пока не нашел... чугунный слог, которым там всё описано, просто тяжело читать "насковзь".

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Разобрался... Самое необычное, что в старом проекте для 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

 

Остались ещё проблемы с маской приоритетов, но это уже не страшно...

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как выяснилось при тестировании на минимальной программе:

прерывания действительно "вложенны", обрабатываются так как надо (в нужном порядке соответственно назначенным приоритетам). Но!

После возникновения первого же прерывания основная программа перестает выполняться.

Вот RPR (running priority) и CPSR в разных точках:

 

Основная программа до возникновения первого из прерываний

FF 800001d3

 

Прерывание с меньшим приоритетом

10 60000193

 

Прерывание с большим приоритетом

08 80000193

 

Состояние RPR=FF больше не появляется ни разу.

 

UPD:

После возникновения первого же прерывания основная программа перестает выполняться

Всё нормально, просто тест был написан таким образом, что аппаратные прерывания возникали так часто (и с такими задержками внутри обработчиков), что в основной цикл никогда не возвращались...

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Странно...

Установка правильны образом сформированного значения в GICC_PMR должна запрещать прерывания с указанным и меньшим приоритетом. Однако, в моем случае почему-то иногда не срабатывает... __ISB() и __DSB() пробовал.

Присвоением значения в этот регистр ограждается критическая секция (работа со связанным списком из основного цикла и из прерывания не с самым высоким приоритетом. В системе существует ещё одно прерывание с более высоким приоритетом - и не имеет отношения к этому списку. Так замена избирательного запрещения прерываний в этом месте на __disable_irq() (модификация I в CPSR) и соответственно разрешение - даёт нормально работающую программу.

Изменено пользователем Genadi Zawidowski

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Наоборот - все просто, если о том, что в ядре - есть два прерывания IRQ и FIQ. FIQ, естественно, прерывает IRQ.

Не естестественно ;)

Насколько я помню ARM7: при входе в режим IRQ, процессор автоматически устанавливает запрет прерываний IRQ; при входе в режим FIQ автоматически устанавливает запрет FIQ & IRQ.

Но ничто не запрещает программисту хоть в начале ISR любой из этих запретов снять или установить дополнительно и тогда и IRQ сможет прервать FIQ-обработчик если очень хочется.

Как впрочем и вложенное прерывание (IRQ в IRQ или FIQ в FIQ) может возбудиться, но только надо быть аккуратным тут, так как будут перезаписаны теневые регистры регистрового файла для данного режима

(SP, LR, SPSR для IRQ-режима и ещё больше регистров для FIQ-режима).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Не естестественно ;)

"Естественно" писалось о аппаратном поведении встроенного в ядро механизма IRQ/FIQ, а не о том, как его можно расширять контроллерами прерываний и корректировать программно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...