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

Так как же все-таки работает банкирование регистров ARM-процессора?

Приветствую!

Приспичило тут оживить старца на ARM7TDMI в лице МК LPC2387. Лет этак 10 назад мучал такое ядро, но в составе другого МК. В общем, решил память освежить, что там, да как. Начал читать разные статейки, в том числе официальную документацию ARM. И так увлекся, что не заметил, что целевой МК pin-to-pin совместим с МК другой серии, но на более родном мне ядре Cortex-M3. И, казалось бы, можно забить и забыть ARM7TDMI, но один момент непонимания осадочек неприятный оставил (как спокойно спать теперь?:wink:).

В общем, в чем суть: есть 7 режимов работы процессора, в каждом режиме используется свой набор регистров, в большинстве случаев эти регистры общие (я про РОН). И вот возникает, например, FIQ. Дальше-то чего? Одни пишут, что регистры R8-R14 переписываются в соответствующие R8_fiq-R14_fiq, другие пишут, что это не так и что регистров одновременно доступно не 16, а аж 23... Брр.

Как я понимаю, эти регистры реально копируются, на что указывает способ возврата из того же FIQ: вычесть из R14_fiq смещение и загрузить в PC. Но тогда для работы в FIQ я должен получить доступ к R8-R14 основного банка, чтобы весь этот механизм вообще имел смысл. А документация пишет, что в режиме FIQ я должен пользоваться выделенными регистрами R8_fiq-R14_fiq. Но в них же копии данных для восстановления! Как я могу так их взять и затереть? Копирнуть в стек? Тогда напрочь теряется смысл переключения банка регистров...

Или как оно тогда правильно?

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


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

37 minutes ago, Arlleex said:

Как я понимаю, эти регистры реально копируются, на что указывает способ возврата из того же FIQ: вычесть из R14_fiq смещение и загрузить в PC.

Каким образом указывает?

Ничего никуда не копируется, естественно, просто два банка. Смещение адреса в LR объясняется работой конвейера.

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


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

1 час назад, Arlleex сказал:

Тогда напрочь теряется смысл переключения банка регистров...

Или как оно тогда правильно?

Как уже правильно заметили - для каждого режима просто свой банк регистров. Для большинства режимов - он небольшой (пара регистров насколько помню), а для FIQ - побольше. Смысл в том, чтобы загрузить в эти теневые FIQ-регистры переменные и держать их там, не загружая из памяти при каждой активизации FIQ (входе в FIQ-прерывание).

Во времена оные я как-то писал ISR использующий эту возможность. Мне удалось добиться стабильной работы этого ISR с частотой прерываний в несколько МГц. При том, что и фоновая программа исправна работала. На Cortex-ах даже бОльшей тактовой частоты такое уже - из области фантастики. :wink2:

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


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

10 часов назад, aaarrr сказал:

Каким образом указывает?

Вот тут, в п. 7.2 сказано, что, например, по завершении исключения SWI процессор должен выполнить переход MOVS PC, r14_svc, чтобы перейти к следующей за SWI инструкции. А для большинства исключений нужно предварительно вычесть смещение, чтобы выполнить ту команду, перед которой влетели в исключение. Как видно, адрес возврата (со смещением или без) хранится в регистре связи того режима, в который перешел процессор. Для меня логично предположить, что при возникновении условий перехода в другой режим, например FIQ, будет произведено копирование R8-R14 в R8_fiq-R14_fiq.

Зайду с другой стороны: если ничего никуда не копируется, то в новом режиме я могу пользоваться R8_newmode-R14_newmode как угодно. Но ведь в R14_newmode хранится адрес возврата! Это значит, что его использовать для своих нужд в обработчике будет нельзя. Ну дык и зачем тогда это самое банкирование... И, опять же, если ничего никуда не копируется, откуда в R14_newmode оказывается корректный адрес возврата, кроме как не копированием перед входом в исключение?

 

9 часов назад, jcxz сказал:

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

Тогда возникает закономерный вопрос: раз R14 в каждом режиме свой, то... Вот пример. Исполняется программа в режиме User. Работает с регистрами R0-R14, PC, CPSR, все как положено. И вдруг возникает исключение, например, FIQ. Входим в режим FIQ, начинаем обрабатывать исключение, и видим, что в R14_fiq хранится адрес возврата к программе пользователя. Но он же банкированный, казалось бы, я могу использовать его наравне с R8_fiq-R13_fiq для вызова небольших процедур, ан-нет! В нем хранится адрес возврата! Чтобы его юзать, его надо сначала сохранить где-нибудь. И это видится уже какой-то халтурой - регистр банкированный, а сохранять его все равно надо руками.

А если еще и вложенность исключений организовать, то вообще не понятно, какой банк регистров сохранять.

 

P.S. Похоже, до меня дошло. Сначала не понял, а потом кааак понял!:yes3: Все до безобразия просто и логично. Всем спасибо за разъяснения!

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


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

6 часов назад, Arlleex сказал:

Для меня логично предположить, что при возникновении условий перехода в другой режим, например FIQ, будет произведено копирование R8-R14 в R8_fiq-R14_fiq.

Это как раз нелогично: Какой тогда вообще смысл в теневых регистрах если так делать?

6 часов назад, Arlleex сказал:

Зайду с другой стороны: если ничего никуда не копируется, то в новом режиме я могу пользоваться R8_newmode-R14_newmode как угодно. Но ведь в R14_newmode хранится адрес возврата! Это значит, что его использовать для своих нужд в обработчике будет нельзя. Ну дык и зачем тогда это самое банкирование... И, опять же, если ничего никуда не копируется, откуда в R14_newmode оказывается корректный адрес возврата, кроме как не копированием перед входом в исключение?

В LR в любом режиме в любом исключении при входе в исключение копируется адрес возврата. А после этого можете его использовать как угодно (адрес возврата можно сохранить в стек например). Также как в Cortex-M.

6 часов назад, Arlleex сказал:

В нем хранится адрес возврата! Чтобы его юзать, его надо сначала сохранить где-нибудь. И это видится уже какой-то халтурой - регистр банкированный, а сохранять его все равно надо руками.

Ну и что? Ведь адрес возврата где-то должен быть, где-ж ему ещё быть??? Всё правильно. Сравните с Cortex-M: ARM7 из-за этих особенностей позволяет быстрее реагировать на простые (не вложенные) прерывания. В этом его плюс.

 

6 часов назад, Arlleex сказал:

А если еще и вложенность исключений организовать, то вообще не понятно, какой банк регистров сохранять.

Со вложенностью и с переключением задач РТОС на ARM7 всё сложно - там это довольно сложная процедура. В отличие от Cortex-M.

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


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

Согласен, сейчас мне все стало очевиднее.

Недавно разбирался с портом Cortex-A9 под FreeRTOS. Действительно, вложенность в таких архитектурах сделана довольно запутанно, но, в тоже время, довольно закономерно.

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


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

про А9 не скажу - там все наверняка хитро и куча "невидимых" для программиста регистров есть, но в ARM7TDMI какие сложности :)

при асинхронном событии надо сохранить указатель стека, РС и некие управляющие биты/флаги "слово управления" - так как в РИСК идеологии предполагается отсутствие стека (ну то есть оно возможно), то это все сохраняется в регистрах. а FIQ добавили по просьбам трудящихся (то ли опросили реалтаймщиков, то ли 51й кто-то из разработчиков АРМа видел :) и его практически нигде не использовали, то есть в РТОСах, которые я видел, переключалка контекста/вход в прерывание одним кодом описывалась - чтоб не усложнять

в синхронных переключениях (связано с правами доступа USER/SUPERUSER, и ошибки - они обычно не асинхронные для железа) тоже можно добавить дублирующих регистров: и быстрее, и защиту от несанкционированного доступа проще сделать

в класическом МИПСе (типа как первый РИСК) видимо недодумали и там под исключения регистры из общего файла тратятся - ну видимо патч пришлось применять, когда поняли, что к чему. это накладывает на программиста запрет на использование нескольких регистров общего назначения

а в SPARC-е вообще хотели от стека избавиться - там огромный регистровый файл, как бы замкнутый в кольцо, и при исключениях (и юзер может для в вызове своей функции) это "колесо" регистров проворачивается и чистые регистры "всегда" готовы

 

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


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

42 минуты назад, yes сказал:

про А9 не скажу - там все наверняка хитро и куча "невидимых" для программиста регистров есть, но в ARM7TDMI какие сложности :)

при асинхронном событии надо сохранить указатель стека, РС и некие управляющие биты/флаги "слово управления" - так как в РИСК идеологии предполагается отсутствие стека (ну то есть оно возможно), то это все сохраняется в регистрах.

Ну так у тех, кто не использовал понятно - никаких сложностей и не возникает.  :biggrin:  А кто использовал, тот знает.

"Никаких сложностей" это для прерывания IRQ (с разрешением вложенности) будет примерно так:

1) сохранить несколько регистров на текущем стеке (которые используются самим кодом системной функции входа в IRQ);

2) переключиться в другой режим (контекст) процессора, например SYS;

3) сохранить в этом контексте все остальные регистры CPU и скопировать сюда-же регистры с IRQ-стека, сохранённые на шаге 1;

4) прочитать из контроллера прерываний адрес прикладного ISR и вызвать его (из контекста SYS); не забываем что в ARM7 не было встроенного NVIC, а только внешний VIC (хотя его можно было не использовать);

5) восстановить часть регистров из стека, переключиться в режим IRQ;

6) выйти из ISR с одновременным восстановлением всего контекста со стека SYS и разрешением прерываний.

И это ещё не считая манипуляций с переменными ОСРВ если она используется! Если интересно - достаточно взглянуть на порт ARM7 для uCOS-II например. И сравнить с Cortex-M.

 

Цитата

а FIQ добавили по просьбам трудящихся (то ли опросили реалтаймщиков, то ли 51й кто-то из разработчиков АРМа видел :) и его практически нигде не использовали,

Не надо говорить за всех!

В ARM7/9 если повесить бОльшую часть прерываний на IRQ (с использованием VIC, переключений контекста, шедулером ОС и пр.), то на FIQ можно было оставить 1-2 быстрых прерывания. И работать с ними быстро без всего вышеописанного геморроя (но и без вложенности конечно).

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


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

еще про ARM - THUMB расскажите, как оно в ARM7 кудряво было оформлено :)

 

upd: то есть призываю не путать софтверную модель с хардверной, о которой, по-моему, речь.

upd2: подозреваю, что описанная процедура 1)-6) необходима для реализации защиты - то есть переключения из

ISR в режим USER (за SYS не уверен в необходимости) и вызова задачки пользователя в РТОСе

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


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

15 minutes ago, yes said:

upd2: подозреваю, что описанная процедура 1)-6) необходима для реализации защиты - то есть переключения из

ISR в режим USER (за SYS не уверен в необходимости) и вызова задачки пользователя в РТОСе

Процедура нужна была для реализации вложенных прерываний, к ОС прямого отношения не имеет. Из режима USER обратно не вернуться, поэтому SYS.

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


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

38 минут назад, yes сказал:

upd2: подозреваю, что описанная процедура 1)-6) необходима для реализации защиты - то есть переключения из

ISR в режим USER (за SYS не уверен в необходимости) и вызова задачки пользователя в РТОСе

Нет. Я же написал: "для реализации возможности вложенных прерываний". Переключение в SYS для этого необходимо исходя из принципов работы прерываний в классических ARM. Если разрешите прерывания оставшись при этом в режиме IRQ, то ближайшее вложенное IRQ-прерывание просто перепишет банковые регистры, разрушив их текущее содержимое. Т.е. - разрешать прерывания IRQ или FIQ находясь внутри того же контекста (IRQ / FIQ) - нельзя.

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


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

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

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

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

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

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

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

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

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

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