Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Прерывания в компиляторе RealView
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
SanyaKID
Разбирались мы тут с прерываниями и накопали вот что. Компилятор armcc не делает разницы между IRQ и FIQ перываниями, и использует как в IRQ так и в FIQ режимах общие регистры R0-R7, сохраняя их в стеке при входе прерывания.
А вот в описании архитектуры ARM7TDMI сказано что в режиме FIQ регистры R8-R14 в нутри прерывания это banked registers, то есть они не пересекаются с регистрами R8-R14 вне прерывания и их не надо класть в стек.
Так вот, может кто знает, можно ли как-нибуть указать компилятору, чтобы он пользовался этими banked register, а не общими? Хотя и экономится всего 2 команды, но ради научного интереса хочется выжать из Fast Interrupta все на что он способен! smile.gif
GetSmart
Из ваших слов в стеке сохраняются только R0-R7. Так и должно быть.
zltigo
Цитата(SanyaKID @ Jun 27 2007, 10:17) *
Так вот, может кто знает, можно ли как-нибуть указать компилятору

Скорее всего, если это он сам не делает, то указать нельзя sad.gif.
У IAR тоже не совсем хорошо - пользует R8-R10, но если их не хватает, то начинает пользовать младшие, а не R11 и R12 sad.gif

Хотя, я, пожалуй, не прав на счет младших, когда копался в коде, забыл, что используется вызов подпрограмм и соответственно компилятор вынужден ими пользоваться и соответственно пользуется ими и для дугих целей.
SpiritDance
В realView при описании обработчика IRQ на С используется ключевое слово __irq. Для прерываний fiq никаких ключевых слов и средств работы с fiq на С нет.
SanyaKID
Цитата(SpiritDance @ Jun 27 2007, 12:41) *
В realView при описании обработчика IRQ на С используется ключевое слово __irq. Для прерываний fiq никаких ключевых слов и средств работы с fiq на С нет.


Да, но можно сделать так, чтобы оно вызывалось в режиме FIQ. В стартапе есть FIQ_Handler, содержащий адрес обработчика перываний FIQ. Если ему скормить адрес функции с ключевым словом __irq, и сделать одно из прерываний FIQ, то будет вызываться она.

А вообще, похоже всеже нельзя явно указать компилятору какие регистры использовать...
SpiritDance
Цитата(SanyaKID @ Jun 27 2007, 13:29) *
А вообще, похоже всеже нельзя явно указать компилятору какие регистры использовать...

Смысл ключевых слов именно в этом. А контроллеру прерываний вы можете скормить что угодно.
SanyaKID
Цитата(SpiritDance @ Jun 27 2007, 13:39) *
Смысл ключевых слов именно в этом. А контроллеру прерываний вы можете скормить что угодно.

Понятно, я не до конца вник во фразу smile.gif
Andy_ry
В STR91x лучше дело обстоит - для FIC выделен "свой собственный банк регистров для минимизации времени контекстного переключения". Вот только что это за регистры не сказано - фик знает. sad.gif
a3r3
Цитата(Andy_ry @ Jul 11 2007, 13:00) *
В STR91x лучше дело обстоит - для FIC выделен "свой собственный банк регистров для минимизации времени контекстного переключения". Вот только что это за регистры не сказано - фик знает. sad.gif

Только не лучше, а так же, как и у остальных процессоров с ARM ядром. Регистры R8-R12.
zltigo
Цитата(Andy_ry @ Jul 11 2007, 12:00) *
В STR91x лучше дело обстоит...

Если-бы Вы были внимательнее, то поняли, что обсуждается не отсутствие (который на самом деле присутствеет, как уже писалось, во всех ARM и документрован) отдельного банка регистров, а то, что RealView НЕ УМЕЕТ ИМ ПОЛЬЗОВАТЬСЯ.
SanyaKID
Цитата(zltigo @ Jul 11 2007, 19:09) *
Если-бы Вы были внимательнее, то поняли, что обсуждается не отсутствие (который на самом деле присутствеет, как уже писалось, во всех ARM и документрован) отдельного банка регистров, а то, что RealView НЕ УМЕЕТ ИМ ПОЛЬЗОВАТЬСЯ.


Да, пользоваться он ими действительно не умеет. В итоге, у меня получился вариант, когда в Си функция прерывания описана как IRQ, но настроена как FIQ и в стартапе FIQ Handler скормлен адрес этого самого обработчика, помеченного как FIQ. Вызываться обработчик должен немного быстрее, но ,вообще говоря, то, что компилятор не использует специальные регистры этого режима, сводит почти на нет все преимущество FIQ
SergeyDDD
Далай обработчик FIQ на ассемблере
SanyaKID
Цитата(SergeyDDD @ Jul 16 2007, 15:51) *
Далай обработчик FIQ на ассемблере

Я долго ждал, когда ж мне это скажут smile.gif
SergeyDDD
Цитата(SanyaKID @ Jul 17 2007, 10:40) *
Я долго ждал, когда ж мне это скажут smile.gif


Ну так...... Слушай меня.......

"Хотя и экономится всего 2 команды, но ради научного интереса хочется выжать из Fast Interrupta все на что он способен!"

А ваче то что может быть при такой постановке вопроса? И после всего написанного здесь.
kamedi_clab
Цитата(SanyaKID @ Jul 16 2007, 14:32) *
у меня получился вариант, когда в Си функция прерывания описана как IRQ, но настроена как FIQ и в стартапе FIQ Handler скормлен адрес этого самого обработчика, помеченного как FIQ.


Если нетрудно и возможно прицепите пример ваш.
defunct
Цитата(SergeyDDD @ Jul 17 2007, 17:33) *
Далай обработчик FIQ на ассемблере

+1
sergeeff
Что-то никак не пойму. Контроллер прерываний используется? Так на кой нужны какие-то отдельные функции со всякими умными __irq и прочим?

Контроллеру указываешь адрес любой функции void fff(void), а обработчик прерывания пишется один на всех в startup'e. Примеров тому - полно. Или хочется чего-то особо экзотического?
Сергей Борщ
Цитата(sergeeff @ Jul 21 2007, 00:21) *
а обработчик прерывания пишется один на всех в startup'e. Примеров тому - полно. Или хочется чего-то особо экзотического?
Индивидуальный обработчик на каждый источник позволяет компилятору сохранять на стеке только необходимые регистры. В общем же придется сохранять все.
AlexandrY
Лучше, лучше ... biggrin.gif

В STR91x есть специальное место для кеширования команды перехода по вектору.
На FIQ может экономиться куча тактов за счет того, что не надо читать команду из FLASH.


Цитата(a3r3 @ Jul 11 2007, 13:00) *
Только не лучше, а так же, как и у остальных процессоров с ARM ядром. Регистры R8-R12.
sergeeff
Цитата(Сергей Борщ @ Jul 21 2007, 11:54) *
Индивидуальный обработчик на каждый источник позволяет компилятору сохранять на стеке только необходимые регистры. В общем же придется сохранять все.


Не понимаю. Согласно стандарту вызова функций scratch регистры не сохраняются. Прерывание может прийти в любой момент времени. Значит обработчик должен сохранить именно scratch - остальные при необходимости и так сохранятся при вызове функции, если функции это надо. Ключевые слова типа __irq именно это и заставляют компилятор делать. Или нет?
AlexandrY
Вы правы, человек поднял проблему не подумавши.

Цитата(sergeeff @ Jul 21 2007, 14:35) *
Не понимаю. Согласно стандарту вызова функций scratch регистры не сохраняются. Прерывание может прийти в любой момент времени. Значит обработчик должен сохранить именно scratch - остальные при необходимости и так сохранятся при вызове функции, если функции это надо. Ключевые слова типа __irq именно это и заставляют компилятор делать. Или нет?
zltigo
Цитата(AlexandrY @ Jul 22 2007, 16:54) *
человек поднял проблему не подумавши.

Ну а если подумать над словами человека?
Это если компилятор знает про FIQ:
Код
FIQ_ISR_handler:
        MOV      R8,#+4
        LDR      R9,??FIQ_ISR_handler_0;; 0xffffffffe01fc140
        LDR      R10,??FIQ_ISR_handler_0+0x4;; fic_counter
??FIQ_ISR_handler_1:
        LDR      R11,[R10, #+0]
        ADD      R11,R11,#+1
        STR      R11,[R10, #+0]
        LDR      R11,[R9, #+0]
        ORR      R11,R11,#0x4
        STR      R11,[R9, #+0]
        STR      R8,[R9, #+0]
        LDR      R11,[R9, #+0]
        AND      R11,R11,#0x4
        LSRS     R11,R11,#+2
        BNE      ??FIQ_ISR_handler_1
        SUBS     PC,LR,#+4     ;; return


А это если ему что IRQ, что FIQ все едино
Код
FIQ_ISR_handler:
        PUSH     {R0-R3}
        MOV      R0,#+4
        LDR      R1,??FIQ_ISR_handler_0;; 0xffffffffe01fc140
        LDR      R2,??FIQ_ISR_handler_0+0x4;; fic_counter
??FIQ_ISR_handler_1:
        LDR      R3,[R2, #+0]
        ADD      R3,R3,#+1
        STR      R3,[R2, #+0]
        LDR      R3,[R1, #+0]
        ORR      R3,R3,#0x4
        STR      R3,[R1, #+0]
        STR      R0,[R1, #+0]
        LDR      R3,[R1, #+0]
        AND      R3,R3,#0x4
        LSRS     R3,R3,#+2
        BNE      ??FIQ_ISR_handler_1
        POP      {R0-R3}
        SUBS     PC,LR,#+4     ;; return
sergeeff
Пример классный (без иронии, я на досуге тоже подумывал о том, что было бы неплохо, если бы компилятор знал о FIQ). Но на практике навар будут только в случае, если для обработки fiq хватает четырех регистров на все про все. А часто такое бывает? Не думаю.
zltigo
Цитата(sergeeff @ Jul 22 2007, 22:18) *
Но на практике навар будут только в случае, если для обработки fiq хватает четырех регистров на все про все.

Нет.
1. Регистров 7;
2. Навар в виде экономии времени и стека на пушировании семи регистров FIQ банка будет абсолютно всегда, даже если потребуются все регистры, экономия почти двойная.

P.S.
Избегайте ненужного цитрования.
AlexandrY
Этот пример содержит подвох.
Достаточно юзеру снова резрешить FIQ прерывания на входе в такой обработчик и он получит глюков по полной. И при этом он будет иметь право требовать от ARM возмещения убытков.
Не забываем, что юзер будет писать на C и не подозревать как используются регистры.
А компилятор не будет пытаться расшифровать программу юзера на тему разрешил или нет он FIQ на входе в обработчик.

Вообщем есть стандарт "Procedure Call Standard for the ARM® Architecture"
Принебрегать им могут только компиляторы низкого уровня.
Скажите в каком компиляторе вы видели такой код, и я буду знать какой компилятор даже пробывать не стоит.



Цитата(zltigo @ Jul 22 2007, 22:59) *
Навар в виде экономии времени и стека на пушировании семи регистров FIQ банка будет абсолютно всегда, даже если потребуются все регистры, экономия почти двойная.
zltigo
Цитата(AlexandrY @ Jul 22 2007, 22:53) *
Этот пример содержит подвох.

Не больше, чем IRQ, который тоже не поддерживает вложенных прерываний без принятия дополнительных мер.
Цитата
Достаточно юзеру снова резрешить FIQ прерывания на входе в такой обработчик и он получит глюков по полной.

Как и при вложеных прерываниях в обработчик IRQ, и мириадах других случаев, если мифический юзер не будет ведать, что творит.
Цитата
Вообщем есть стандарт "Procedure Call Standard for the ARM® Architecture"

Который к обработчикам прерываний ни сном ни духом, однако.
Цитата
Скажите в каком компиляторе вы видели такой код

Любой, который имеет квалификатор __fiq. В данном конкретном случае IAR.
AlexandrY
Юзер на C не успеет вновь разрешить прерывания до сохранения регистров, так что здесь все чисто.
Т.е. я понимаю задача ставится все сделать в рамках C.
Кстати inline ассемблер в RealView тоже не даст юзеру исхитриться с разрешением прерываний.


Цитата(zltigo @ Jul 22 2007, 23:53) *
Как и при вложеных прерываниях в обработчик IRQ, и мириадах других случаев, если мифический юзер не будет ведать, что творит.
zltigo
Цитата(AlexandrY @ Jul 22 2007, 23:35) *
Юзер на C не успеет вновь разрешить прерывания до сохранения регистров, так что здесь все чисто.

Чисто? smile.gif А с SPSR_irq и LR_sys, что будет, если неразумный юзер их не сохранит 'просто' разрешив прерывания в обработчике? Короче, юзер должен быть разумным - без этого никак. Ну а разумный юзер для начала:
1. не будет в обработчик самого приоритетного прерывания вкладывать какие попало IRQ;
2. думать зачем иметь несколько FIQ;
3. очень крепко думать, зачем их делать вложенными;
4. и если вдруг придучает зачем, что будет очень странным для разумного юзера, поймет, что этот обработчик вовсе и не __fiq у него получися sad.gif и скажет компилятору, что это __irq.

За то, что мне, "разумному юзеру" не дают воспользоваться банком регистров FIQ я не скажу спасибо разработчикам такого компилятора. Ваши попытки оправдать отсутствие такой возможности у компилятора заботой о "неразумном юзере" очень неуклюжи sad.gif.
AlexandrY
Ok! Согласен. В принципе цели мы добились. Человек должен понять, что корректно написать быстрый обработчик без asm-а он не сможет.

Цитата(zltigo @ Jul 23 2007, 01:04) *
Чисто? smile.gif А с SPSR_irq и LR_sys, что будет, если неразумный юзер их не сохранит 'просто' разрешив прерывания в обработчике? Короче, юзер должен быть разумным - без этого никак. Ну а разумный юзер для начала:
1. не будет в обработчик самого приоритетного прерывания вкладывать какие попало IRQ;
2. думать зачем иметь несколько FIQ;
3. очень крепко думать, зачем их делать вложенными;
4. и если вдруг придучает зачем, что будет очень странным для разумного юзера, поймет, что этот обработчик вовсе и не __fiq у него получися sad.gif и скажет компилятору, что это __irq.

За то, что мне, "разумному юзеру" не дают воспользоваться банком регистров FIQ я не скажу спасибо разработчикам такого компилятора. Ваши попытки оправдать отсутствие такой возможности у компилятора заботой о "неразумном юзере" очень неуклюжи sad.gif.
zltigo
Цитата(AlexandrY @ Jul 23 2007, 00:49) *
Человек должен понять, что корректно написать быстрый обработчик без asm-а он не сможет.

Корректный - сможет. И более быстый для FIQ сможет. А c наворотами в виде вложенных прерываний без ASM не сможет.
Сергей Борщ
Цитата(sergeeff @ Jul 21 2007, 14:05) *
Не понимаю. Согласно стандарту вызова функций scratch регистры не сохраняются. Прерывание может прийти в любой момент времени. Значит обработчик должен сохранить именно scratch - остальные при необходимости и так сохранятся при вызове функции, если функции это надо. Ключевые слова типа __irq именно это и заставляют компилятор делать. Или нет?
Возможно я был не прав в своих заблуждениях. Давайте разбираться. То, что остальные регистры сохранятся при вызове функции вовсе не значит, что прерывание может их испортить. К scratch относятся R0-R3, R12. При возникновении исключения IRQ (а именно о нем шла речь в контексте многих обработчиков) переключаются только R13, R14 и значит общая "обертка" должна сложить на стек все 5 scratch регистров, ибо не имеет информации какой из них будет испорчен в конкретном обработчике. Если же мы даем компилятору возможность для каждого обработчика сгенерить свои пролог/эпилог, то для некоторых прерываний, в которых не все scratch регистры портятся, компилятор имеет право сохранять/восстанавливать только используемые (экономятся такты и место на стеке). Едем далее - в каждой самой "внешней" функции обработчика компилятор должен сохранить preserved регистры, которые используются. В случае индивидуального пролога/эпилога он может объединить в одну команду сохранение scratched и preserved регистров (сэкономив такты и код), а в случае общего пролога/эпилога ему придется делать две команды - сохранение scratched в прологе и сохранение preserved в теле обработчика. Аналогичные выкладки для эпилога.

Где ошибка в рассуждениях?
Цитата(AlexandrY @ Jul 22 2007, 16:54) *
Вы правы, человек поднял проблему не подумавши.
Если вы это про мой пост, то особенно хотелось бы услышать Ваши контр-аргументы.
sergeeff
Насчет умной функции обработчика прерывания. Думается тут как обычно - проблема теории и практики. Все аргументы, которые приведены - абсолютно правильные. Но. Предположим, что из функции обработчика прерывания вызывается еще какая-то "не умная" функция, которая обычным образом использует scratch регистры. И что делать тогда? Запретить вызовы функций? Выполнять какой-то изощренный анализ используемых регистров? Думается, что это одно из объяснений, почему многие производители компиляторов это дело похоронили.
zltigo
Цитата(sergeeff @ Jul 24 2007, 09:01) *
Но. Предположим, что из функции обраб отчика прерывания вызывается еще какая-то "не умная" функция, которая обычным образом использует scratch регистры.

Тогда будут использоватся наряду с собственными регистрами и R0..R3. Эффект от использования FIQ уменьшится, но не исчезнет. Кроме того, 'развесистые' обработчики FIQ так или иначе не влезают только в FIQ регистры и использование общих регистров этом случае начинается с scratch регистров.
Все вполне эффективно получается и без 'изощренного анализа'.
Цитата
И что делать тогда? Запретить вызовы функций?

Кроме того, если действительно это действительно быстрый обработчик, то действительно избегать вызовов функций и не только по причине использования ими регистров.
Цитата
Думается, что это одно из объяснений, почему многие производители компиляторов это дело похоронили.

'Обьяснений' ничего не объясняющих было уже много. Может достаточно?
SanyaKID
Ничего себе сколько тут уже понаписали... Вообщем-то вопрос насколько я помню, ставился так: умеет ли RealView работать с FIQ или нет. Оказалось что нет. И вполне понятно, что чтобы полностью использовать все прелести FIQ в данном компиляторе надо писать на ASM.

Тут кто-то просил исходники...

Это что касается обработчика
Код
void i2c_init()
{     
       PINSEL0       = 0x50;                         //Switch GPIO to I2C pins
        
    I2C0ADR = SLAVE_ADR;            
    I2C0CONSET = 0x44;                                                                                                
    VICIntSelect = 0x00000200;        
//VICVectCntl1 = 0x00000029;                  
//VICVectAddr1 = (unsigned)I2CISR;            

    I2C_ENABLE;                        
}

void I2CISR (void) __irq                        //I2C interrupt routine
{
    ...
}


А это в стартапе

Код
FIQ_Addr        DCD     FIQ_Handler
...
FIQ_Handler     B       I2CISR
...
                IMPORT  I2CISR


Так вот, у такого подхода, кроме того что такой обработчик будет вызываться немного быстрее чем просто IRQ, неожиданно появился новый плюс.
В проекте используется операционка RTX от Keil, в которой соответственно используются прерывания от таймера. Мне необходимо записывать во внутреннюю флеш. В IAP в момент записи нужно запрещать прерывания или убирать их в RAM. Однако нужно чтобы I2C все равно работал в момент записи.
В итоге, в теории, чтобы не ковыряться с прерыванием от таймера в RTX, можно запретить все IRQ на время записи/стирания флеша, а обработчик FIQ для I2c поместить в RAM. Кроме того для работы FIQ достаточно в RAM поместить только сам обработчик, так как его адрес лежит в регистре.

Щас попробую све это забацать. Посмотрим как будет работать.
Сергей Борщ
Цитата(sergeeff @ Jul 24 2007, 09:01) *
Предположим, что из функции обработчика прерывания вызывается еще какая-то "не умная" функция, которая обычным образом использует scratch регистры. И что делать тогда?
Дальше действует Procedure Call Standard for the ARM® Architecture. Т.е. необходимые scratch регистры сохраняет вызывающая функция, preserved регистры - вызывающая. Все равно остается поле для оптимизации. Собственно я защищаю только одну фразу:
Цитата(Сергей Борщ @ Jul 21 2007, 10:54) *
Индивидуальный обработчик на каждый источник позволяет компилятору сохранять на стеке только необходимые регистры. В общем же придется сохранять все.
Именно это является преимуществом индивидуального пролога/эпилога. Недостатком является увеличение кода.
GetSmart
Цитата(SanyaKID)
В итоге, в теории, чтобы не ковыряться с прерыванием от таймера в RTX, можно запретить все IRQ на время записи/стирания флеша, а обработчик FIQ для I2c поместить в RAM. Кроме того для работы FIQ достаточно в RAM поместить только сам обработчик, так как его адрес лежит в регистре.

Щас попробую све это забацать. Посмотрим как будет работать.
Ну а процессор настолько умный, что сам из регистра вектор копирует в R15 :-)

PS. При одном FIQе прописывать VICVectAddrX вообще-то не обязательно.
SanyaKID
Цитата(GetSmart @ Jul 24 2007, 19:02) *
Ну а процессор настолько умный, что сам из регистра вектор копирует в R15 :-)

PS. При одном FIQе прописывать VICVectAddrX вообще-то не обязательно.

Да, насчет векторов я неправ. Адрес обработчика FIQ тоже во FLASH лежит...
А в VICVectAddrX я ниче и не писал.
Сергей Борщ
Цитата(SanyaKID @ Jul 25 2007, 12:43) *
Да, насчет векторов я неправ. Адрес обработчика FIQ тоже во FLASH лежит...
Именно для таких случаев существует remap. Но его применение требует внимательной линковки.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.