Arlleex 131 13 июля, 2019 Опубликовано 13 июля, 2019 · Жалоба Приветствую! Приспичило тут оживить старца на ARM7TDMI в лице МК LPC2387. Лет этак 10 назад мучал такое ядро, но в составе другого МК. В общем, решил память освежить, что там, да как. Начал читать разные статейки, в том числе официальную документацию ARM. И так увлекся, что не заметил, что целевой МК pin-to-pin совместим с МК другой серии, но на более родном мне ядре Cortex-M3. И, казалось бы, можно забить и забыть ARM7TDMI, но один момент непонимания осадочек неприятный оставил (как спокойно спать теперь?). В общем, в чем суть: есть 7 режимов работы процессора, в каждом режиме используется свой набор регистров, в большинстве случаев эти регистры общие (я про РОН). И вот возникает, например, FIQ. Дальше-то чего? Одни пишут, что регистры R8-R14 переписываются в соответствующие R8_fiq-R14_fiq, другие пишут, что это не так и что регистров одновременно доступно не 16, а аж 23... Брр. Как я понимаю, эти регистры реально копируются, на что указывает способ возврата из того же FIQ: вычесть из R14_fiq смещение и загрузить в PC. Но тогда для работы в FIQ я должен получить доступ к R8-R14 основного банка, чтобы весь этот механизм вообще имел смысл. А документация пишет, что в режиме FIQ я должен пользоваться выделенными регистрами R8_fiq-R14_fiq. Но в них же копии данных для восстановления! Как я могу так их взять и затереть? Копирнуть в стек? Тогда напрочь теряется смысл переключения банка регистров... Или как оно тогда правильно? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 13 июля, 2019 Опубликовано 13 июля, 2019 · Жалоба 37 minutes ago, Arlleex said: Как я понимаю, эти регистры реально копируются, на что указывает способ возврата из того же FIQ: вычесть из R14_fiq смещение и загрузить в PC. Каким образом указывает? Ничего никуда не копируется, естественно, просто два банка. Смещение адреса в LR объясняется работой конвейера. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 13 июля, 2019 Опубликовано 13 июля, 2019 · Жалоба 1 час назад, Arlleex сказал: Тогда напрочь теряется смысл переключения банка регистров... Или как оно тогда правильно? Как уже правильно заметили - для каждого режима просто свой банк регистров. Для большинства режимов - он небольшой (пара регистров насколько помню), а для FIQ - побольше. Смысл в том, чтобы загрузить в эти теневые FIQ-регистры переменные и держать их там, не загружая из памяти при каждой активизации FIQ (входе в FIQ-прерывание). Во времена оные я как-то писал ISR использующий эту возможность. Мне удалось добиться стабильной работы этого ISR с частотой прерываний в несколько МГц. При том, что и фоновая программа исправна работала. На Cortex-ах даже бОльшей тактовой частоты такое уже - из области фантастики. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 14 июля, 2019 Опубликовано 14 июля, 2019 · Жалоба 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. Похоже, до меня дошло. Сначала не понял, а потом кааак понял! Все до безобразия просто и логично. Всем спасибо за разъяснения! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 14 июля, 2019 Опубликовано 14 июля, 2019 · Жалоба 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. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 131 14 июля, 2019 Опубликовано 14 июля, 2019 · Жалоба Согласен, сейчас мне все стало очевиднее. Недавно разбирался с портом Cortex-A9 под FreeRTOS. Действительно, вложенность в таких архитектурах сделана довольно запутанно, но, в тоже время, довольно закономерно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yes 5 15 июля, 2019 Опубликовано 15 июля, 2019 · Жалоба про А9 не скажу - там все наверняка хитро и куча "невидимых" для программиста регистров есть, но в ARM7TDMI какие сложности :) при асинхронном событии надо сохранить указатель стека, РС и некие управляющие биты/флаги "слово управления" - так как в РИСК идеологии предполагается отсутствие стека (ну то есть оно возможно), то это все сохраняется в регистрах. а FIQ добавили по просьбам трудящихся (то ли опросили реалтаймщиков, то ли 51й кто-то из разработчиков АРМа видел :) и его практически нигде не использовали, то есть в РТОСах, которые я видел, переключалка контекста/вход в прерывание одним кодом описывалась - чтоб не усложнять в синхронных переключениях (связано с правами доступа USER/SUPERUSER, и ошибки - они обычно не асинхронные для железа) тоже можно добавить дублирующих регистров: и быстрее, и защиту от несанкционированного доступа проще сделать в класическом МИПСе (типа как первый РИСК) видимо недодумали и там под исключения регистры из общего файла тратятся - ну видимо патч пришлось применять, когда поняли, что к чему. это накладывает на программиста запрет на использование нескольких регистров общего назначения а в SPARC-е вообще хотели от стека избавиться - там огромный регистровый файл, как бы замкнутый в кольцо, и при исключениях (и юзер может для в вызове своей функции) это "колесо" регистров проворачивается и чистые регистры "всегда" готовы Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 15 июля, 2019 Опубликовано 15 июля, 2019 · Жалоба 42 минуты назад, yes сказал: про А9 не скажу - там все наверняка хитро и куча "невидимых" для программиста регистров есть, но в ARM7TDMI какие сложности :) при асинхронном событии надо сохранить указатель стека, РС и некие управляющие биты/флаги "слово управления" - так как в РИСК идеологии предполагается отсутствие стека (ну то есть оно возможно), то это все сохраняется в регистрах. Ну так у тех, кто не использовал понятно - никаких сложностей и не возникает. А кто использовал, тот знает. "Никаких сложностей" это для прерывания 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 быстрых прерывания. И работать с ними быстро без всего вышеописанного геморроя (но и без вложенности конечно). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yes 5 15 июля, 2019 Опубликовано 15 июля, 2019 · Жалоба еще про ARM - THUMB расскажите, как оно в ARM7 кудряво было оформлено :) upd: то есть призываю не путать софтверную модель с хардверной, о которой, по-моему, речь. upd2: подозреваю, что описанная процедура 1)-6) необходима для реализации защиты - то есть переключения из ISR в режим USER (за SYS не уверен в необходимости) и вызова задачки пользователя в РТОСе Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 63 15 июля, 2019 Опубликовано 15 июля, 2019 · Жалоба 15 minutes ago, yes said: upd2: подозреваю, что описанная процедура 1)-6) необходима для реализации защиты - то есть переключения из ISR в режим USER (за SYS не уверен в необходимости) и вызова задачки пользователя в РТОСе Процедура нужна была для реализации вложенных прерываний, к ОС прямого отношения не имеет. Из режима USER обратно не вернуться, поэтому SYS. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 184 15 июля, 2019 Опубликовано 15 июля, 2019 · Жалоба 38 минут назад, yes сказал: upd2: подозреваю, что описанная процедура 1)-6) необходима для реализации защиты - то есть переключения из ISR в режим USER (за SYS не уверен в необходимости) и вызова задачки пользователя в РТОСе Нет. Я же написал: "для реализации возможности вложенных прерываний". Переключение в SYS для этого необходимо исходя из принципов работы прерываний в классических ARM. Если разрешите прерывания оставшись при этом в режиме IRQ, то ближайшее вложенное IRQ-прерывание просто перепишет банковые регистры, разрушив их текущее содержимое. Т.е. - разрешать прерывания IRQ или FIQ находясь внутри того же контекста (IRQ / FIQ) - нельзя. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться