|
Выход из прерывания в требуемую точку |
|
|
|
 |
Ответов
|
May 17 2011, 16:04
|
Местный
  
Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769

|
Цитата(kovigor @ May 17 2011, 19:18)  В правильно спроектированном ПО необходимости в таких действиях обычно не возникает. Продумайте структуру вашего проекта еще раз ... Зря вы так. Есть масса задач где прыжок по определенному адресу при обработке прерывания наиболее оптимальный вариант.
|
|
|
|
|
May 17 2011, 18:15
|
Местный
  
Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769

|
Цитата(aaarrr @ May 17 2011, 20:19)  Ну, хоть бы пример привели, а то так не интересно. Могу и пример, но только с тем же 51-м. Вот тот же UART. У нас есть сложный протокол по RS-485 где сидит много устройств. Протокол примерно такой. 1-й байт - номер устройства. Если номер наш, то обрабатываем дальше, иначе игнорируем всю посылку. 2-й байт номер протокола тут идут варианты. В зависимости от протокола мы либо принимаем, либо передаем, и количество байт разное. Но реакция должна быть мгновенной, т.е. обрабатывать мы должны на лету, это задано в ТЗ. Если всю эту хрень делать без прерываний по ожиданию приема/передачи, программа получается простой. Принимаем-сравниваем-переходим на нужную метку. Примерно так MOV A,SBUF M1: CJNE A,#1, M2 ;обработка протокола 1 JMP BEGIN M2: CJNE A,#2, M3 ;обработка протокола 2 JMP BEGIN
.... и.т.д. Но так нельзя - программа только и делает что висит-ждет очередной байт. А вот по прерываниям простота заканчивается. По любому приему происходит переход на один и тот же адрес обработчика и дальше надо заводить кучу дополнительных флагов чтоб помнить текущую фазу протокола, и оборачивается это кучей запутанных ветвлений. Вот здесь положение спасает переход по определенному адресу. После обработки очередного байта, мы заносим в переменную адрес следующего обработчика и при следующем прерывании прыгаем сразу в эту точку. При таком методе программа получается намного проще, а реакция на обработку быстрее. Поэтому лично я давно делаю обработку UARTа именно так. Другой более простой случай. Надо дождаться на пине например 1, и тут же среагировать на это. Если в лоб ждать то будет так: WAIT: JNB P1.0,WAIT ; обработка события
Но тогда цикл может висеть бесконечно долго, нужен выход по таймауту. Обычный метод - ввести в цикл счетчик, его инкрементировать, сравнивать и добавить дополнительный переход. Но цикл многократно удлинится, а с ним и время реакции. Выход - оставить цикл без счетчика, а ввести таймерное прерывание с возвратом на TIMEOUT: WAIT: JNB P1.0,WAIT ; обработка события TIMEOUT: ; идем дальше
Здесь немного другой случай, адресный переход идет не на обработку прерывания, а после возврата, но суть та же. А еще таким методом можно организовать многозадачность повесив на таймер такой обработчик, чтоб он запоминал адрес предыдущего вызова, а возвращал на адрес следующей, и так перебирал все задачи по кругу. Цитата(AHTOXA @ May 17 2011, 21:11)  В контроллерах семейства 8051 это делалось для того, чтобы изобразить "вложенные прерывания". В кортексах вложенные прерывания есть изначально, и так извращаться не требуется. То есть, ваш вариант "в определенный момент выйти из прерывания (UART) в требуемую точку, а уж оттуда потом продолжить выполнения с места, где возникло прерывание" практически полностью эквивалентен варианту "в конце прерывания вызвать нужную функцию". Вовсе нет. Во-первых в 51-х можно сделать вложенное прерывание. Во-вторых как я описал выше, вложенность тут ни при чем
|
|
|
|
|
May 17 2011, 18:51
|

Нечётный пользователь.
     
Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417

|
Цитата(paskal @ May 17 2011, 21:15)  А вот по прерываниям простота заканчивается. По любому приему происходит переход на один и тот же адрес обработчика и дальше надо заводить кучу дополнительных флагов чтоб помнить текущую фазу протокола, и оборачивается это кучей запутанных ветвлений. Вот здесь положение спасает переход по определенному адресу. После обработки очередного байта, мы заносим в переменную адрес следующего обработчика и при следующем прерывании прыгаем сразу в эту точку. Код // Компиляторо-зависимые атрибуты/прагмы опускаем void (*real_handler)() = initial_handler; // void interrupt_handler() { real_handler(); // внутри всех обработчиков при необходимости перезаносится переменная real_handler } Что-то мне кажется, что от возникновения прерывания до начала работы реального обработчика это будет быстрее, чем занесение в стек дополнительного адреса возврата для «возврата» в некий процесс. Быстрее этого будет только перемещение таблицы векторов в ОЗУ и замена вектора в той таблице.
--------------------
Ну, я пошёл… Если что – звоните…
|
|
|
|
|
May 17 2011, 19:14
|
Местный
  
Группа: Свой
Сообщений: 352
Регистрация: 29-10-06
Из: Тула
Пользователь №: 21 769

|
Цитата(ReAl @ May 17 2011, 22:51)  Что-то мне кажется, что от возникновения прерывания до начала работы реального обработчика это будет быстрее, чем занесение в стек дополнительного адреса возврата для «возврата» в некий процесс. Напомню что пример был по обработке сложного протокола с большим количеством вариантов. Переход по адресу хоть и требует дополнительных действий, но происходит СРАЗУ в нужное место. А альтернатива этому методу - долго лазить по дереву state_machine с помощью флагов и ветвлений. Цитата(KnightIgor @ May 17 2011, 22:55)  Что Вы тут описали, это одна из возможных реализаций state machine - давно известная и наглядная штука для ветвлящихся алгоритмов. Конечно известная. Речь не о стэйтмашине вообще, а о том что реализовать ее можно либо адресами переходов, либо набором флагов и переменных состояния с последующими ветвлениями по этим флагам. И первый способ и нагляднее и быстрее.
|
|
|
|
|
May 17 2011, 20:04
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(paskal @ May 18 2011, 01:14)  Конечно известная. Речь не о стэйтмашине вообще, а о том что реализовать ее можно либо адресами переходов, либо набором флагов и переменных состояния с последующими ветвлениями по этим флагам. И первый способ и нагляднее и быстрее. Дело в том, что вызов функции - это тоже "переход по адресу":) И вместо "адреса перехода" вы можете хранить в переменной "адрес функции", соответствующей текущему состоянию. О чём вам и написал ReAl. Разница же между "вызовом функции"(он же "переход по адресу") и "подменой адреса возврата из прерывания", о которой спрашивал топикстартер, заключается в том, что во втором случае перед переходом по адресу происходит окончание прерывания. Вопрос в том, нужно ли это топикстартеру, и что ему это даст. В 8051 это давало разрешение прерываний (о чём написал я). А в кортексах - не даёт ничего. (Вернее, кое что конечно меняется, но не так радикально).
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
Сообщений в этой теме
Krom Выход из прерывания в требуемую точку May 17 2011, 13:48 scifi Цитата(Krom @ May 17 2011, 17:48) Контрол... May 17 2011, 14:04    KnightIgor Цитата(paskal @ May 17 2011, 20:15) А вот... May 17 2011, 18:55    ReAl Цитата(paskal @ May 17 2011, 21:15) Друго... May 17 2011, 19:05   VslavX Цитата(aaarrr @ May 17 2011, 19:19) Ну, х... May 17 2011, 19:10   Krom Цитата(aaarrr @ May 17 2011, 20:19) Ну, х... May 18 2011, 05:15    scifi Цитата(Krom @ May 18 2011, 09:15) Пример:... May 18 2011, 05:22     Krom Цитата(scifi @ May 18 2011, 09:22) Некрас... May 18 2011, 05:47      scifi Цитата(Krom @ May 18 2011, 09:47) а главн... May 18 2011, 06:17       Krom Цитата(scifi @ May 18 2011, 10:17) И кост... May 18 2011, 06:50 VladislavS Кусок кода, который используется и в прерывании, и... May 17 2011, 15:41 klen редизайн системы однозначно, и чем раньше тем мень... May 17 2011, 15:49 brag Сохранить адрес возврата (в регистре или в памяти,... May 17 2011, 16:21 AHTOXA Цитата(Krom @ May 17 2011, 19:48) Контрол... May 17 2011, 17:11 Krom Цитата(AHTOXA @ May 17 2011, 21:11) практ... May 18 2011, 05:26  scifi Цитата(Krom @ May 18 2011, 09:26) Команды... May 18 2011, 05:30 Александр_С А кто вам мешает использовать указатель на функцию... May 17 2011, 19:00 scifi В дополнение к вышесказанному: "Преждевременн... May 17 2011, 19:10 ReAl Цитата(Krom @ May 17 2011, 16:48) ; сохра... May 17 2011, 21:09 _Pasha Цитата(Krom @ May 18 2011, 08:15) Пример:... May 18 2011, 05:34 Александр_С Переключаться на другую задачю всегда надо через P... May 18 2011, 07:01 Krom Цитата(Александр_С @ May 18 2011, 11:01) ... May 18 2011, 07:14 Александр_С //Формирование прерывания "PendSV_Handler... May 18 2011, 07:15 VladislavS Можно перед выходом из прерывания настроить таймер... May 18 2011, 07:34 brag ЦитатаТо есть, ваш вариант "в определенный мо... May 18 2011, 12:24 _Pasha Цитата(brag @ May 18 2011, 15:24) все быс... May 18 2011, 14:56 d__ Можно попробовать механизм setjmp & longjmp. П... May 19 2011, 06:35 zovsilab Правильно ли сделал запись по формированию и вызов... May 20 2011, 11:59 brag ну типа правильно, не помню только что там с приор... May 20 2011, 12:20
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|