lons83 0 1 марта, 2014 Опубликовано 1 марта, 2014 (изменено) · Жалоба Здравствуйте, извините если такая тема уже повторялась. Но я никак не нашел ответа: Есть прога: #include func1 { .... } func2 { .... } func3 { .... } func4 { .... } IRQ // обработчик прерывания { .... } int main { while (1) { func1(); func2(); func3(); func4(); } } Предположим выполняется func3{} в этот момент срабатывает прерывание и передается обработчику IRQ после завершения IRQ, программа по адресу возврата возвращается к func3{}.... НО!!!!!! Как можно с помощью языка СИ сделать чтобы после возвращения из IRQ -> выполняться стала func1{} !!! ( поменять адрес возврата ) и уже после выполнения func1{} -> вернуться к func3{}; ?????????? Делал такое на ассмеблере, а тут как-то завис.... не понятно как в этом случае использовать ассемблерные вставки... а чтение программных прерываний ( SWI и SVC ) завели меня в тупик... Заранее спасибо. P.S. среда программирования Keil 4 . МК: stm cortex-m3 Изменено 1 марта, 2014 пользователем lons83 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DpInRock 0 1 марта, 2014 Опубликовано 1 марта, 2014 · Жалоба http://martin.hinner.info/ARM-Microcontrol...er-HOWTO-7.html Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 117 1 марта, 2014 Опубликовано 1 марта, 2014 · Жалоба чтобы после возвращения из IRQ -> выполняться стала func1{} !!! ( поменять адрес возврата ) и уже после выполнения func1{} -> вернуться к func3{}; ?????????? IRQ // обработчик прерывания { .... func1(); } И забыть про ассемблер. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 1 марта, 2014 Опубликовано 1 марта, 2014 · Жалоба Да, условия поменялись ... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lons83 0 1 марта, 2014 Опубликовано 1 марта, 2014 · Жалоба IRQ // обработчик прерывания { .... func1(); } И забыть про ассемблер. Можно и так... Только в этом случае Вы не выходите из прерывания. И если func1() не закончиться выполнятся до повторного входа в IRQ... то получиться рекурсия и через некоторое время контроллер зависает!!!! Поэтому я и хочу чтобы переход был после выхода из прерывания Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 10 1 марта, 2014 Опубликовано 1 марта, 2014 · Жалоба Можно и так... Только в этом случае Вы не выходите из прерывания. И если func1() не закончиться выполнятся до повторного входа в IRQ... то получиться рекурсия и через некоторое время контроллер зависает!!!! Поэтому я и хочу чтобы переход был после выхода из прерывания В Cortex-M3 есть программные прерывания. Можно установить флаг одного из них в IRQ, но приоритет такого прерывания должен быть ниже приоритета IRQ. В обработчике программного прерывания вызвать func1(). Тут и с пугающей рекурсией ничего не зависнет, просто будут потери вызовов func1(). Честно говоря, станно все это, ибо вызов func1() получается асинхронным со всеми вытекающими. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lons83 0 1 марта, 2014 Опубликовано 1 марта, 2014 · Жалоба В Cortex-M3 есть программные прерывания. Можно установить флаг одного из них в IRQ, но приоритет такого прерывания должен быть ниже приоритета IRQ. Не могли бы Вы здесь по подробнее.... тогда как мне задать вектор прерывания программного для func1(); ??? Ведь аппаратные вектора все заняты, а подставить func1(); под вектор с 0-31 не получается... да и не получиться наверно... Вообщем не понятно как указать что func1() - это программное прерывание... и как я понял оно будет вызываться из IRQ тогда зачем его делать программным?..... Тут и с пугающей рекурсией ничего не зависнет, просто будут потери вызовов func1(). на практике у меня зависало... особенно если func1() --- довольно приличная функция - например обработка видео массива... и тогда все храниться в стеке и через 2 минуты забивается.... а если func1() вынести в общий цикл то все нормально работает.... просто нужно чтобы func1() запускался прямо после IRQ , а во время выполнения func1() происходит 3-4 вызова IRQ.... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 10 1 марта, 2014 Опубликовано 1 марта, 2014 · Жалоба Не могли бы Вы здесь по подробнее.... тогда как мне задать вектор прерывания программного для func1(); ??? Ведь аппаратные вектора все заняты, а подставить func1(); под вектор с 0-31 не получается... да и не получиться наверно... Вообщем не понятно как указать что func1() - это программное прерывание... и как я понял оно будет вызываться из IRQ тогда зачем его делать программным?..... на практике у меня зависало... особенно если func1() --- довольно приличная функция - например обработка видео массива... и тогда все храниться в стеке и через 2 минуты забивается.... а если func1() вынести в общий цикл то все нормально работает.... просто нужно чтобы func1() запускался прямо после IRQ , а во время выполнения func1() происходит 3-4 вызова IRQ.... Аппаратный ничем не отличается от програмного. В Cortex-M3 поддерживается до 240 прерываний. Берете свободный вектор в таблице векторов прерываний (в стартапе). Туда пишете адрес func1() и разрешаете прерывание с выбранным номером предварительно настроив ему приоритет. Есть хорошая книга: "Джозеф Ю. Ядро CORTEX-M3 компании ARM. Полное руководство". Если func1() должно выполняться прямо после IRQ и IRQ вызываются в 3-4 раза чаще, чем обрабатывается func1(). То можно показать, что работать будет так: 1. Обрабатываются IRQ. 2. Только каждое 3-4 IRQ способно запустить func1(). 3. Никакие func2() и т.п. выполныться не будут. Тоже самое с успехом делает код: while(1) func1(); Разве нет? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lons83 0 1 марта, 2014 Опубликовано 1 марта, 2014 · Жалоба Аппаратный ничем не отличается от програмного. В Cortex-M3 поддерживается до 240 прерываний. Берете свободный вектор в таблице векторов прерываний (в стартапе). Туда пишете адрес func1() и разрешаете прерывание с выбранным номером предварительно настроив ему приоритет. Есть хорошая книга: "Джозеф Ю. Ядро CORTEX-M3 компании ARM. Полное руководство". А можете еще раз мне обьяснить: Как произойдет вызов этого программного прерывания? с аппаратным все понятно... а вот с программным? ведь если я помещу func1() - в обработчик - это ни чем не будет отличаться от вызова обычной функции... а если в обычном цикле программы, то тогда как? по какому то флагу? Спасибо за книжку. Завтра скачаю и посмотрю... Если func1() должно выполняться прямо после IRQ и IRQ вызываются в 3-4 раза чаще, чем обрабатывается func1(). То можно показать, что работать будет так: 1. Обрабатываются IRQ. 2. Только каждое 3-4 IRQ способно запустить func1(). 3. Никакие func2() и т.п. выполныться не будут. Тоже самое с успехом делает код: while(1) func1(); Разве нет? Кстати да... Вы правы... тут можно по разному это обыграть... надо подумать... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 10 1 марта, 2014 Опубликовано 1 марта, 2014 · Жалоба А можете еще раз мне обьяснить: Как произойдет вызов этого программного прерывания? с аппаратным все понятно... а вот с программным? ведь если я помещу func1() - в обработчик - это ни чем не будет отличаться от вызова обычной функции... а если в обычном цикле программы, то тогда как? по какому то флагу? Спасибо за книжку. Завтра скачаю и посмотрю... Если с аппаратным понятно, то хорошо. Софтовый тоже самое) Когда приходит запрос на обработку прерывания от периферийного модуля взводится флаг отложенного прерывания в модуле NVIC. Затем NVIC смотрит какие флаги взведены и выбирает из них один удовлетворяющий критериям (разрешение прерывания, приоритет и т.п.). Затем переходит к обработке прерывания совершая переход к функции, адрес которой указан в таблице векторов прерывания паралельно сбрасывая флаг отложенного прерывания. Процесс очень хорошо описан в книге. Таким образом Вы можете генерировать софтовые прерывания взводя флаги в NVIC. Кроме того, Вы можете софтово запускать обработчики аппаратных прерываний. Хуже: Вы можете снимать запрос на запуск аппаратного или софтового прерывания очищая флаг. Короче свобода полная. Никакого asm, все на Си. Правда для запуска софтовых прерываний в непривелегированном режиме требуется специальное на то разрешение. В книге вся инфа есть. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DpInRock 0 2 марта, 2014 Опубликовано 2 марта, 2014 (изменено) · Жалоба ПОхоже все запутались конкретно. До вызова прерывания выполнялась F1. После прерывания требуется выполнение F2. ПОСЛЕ ЗАВЕРШЕНИЯ F2 - видимо, требуется продолжить F1? Отсюда следует, что прерывание должно ЗАПОМНИТЬ контекст F1, при выходе из прерывания - заменить контекст F1 на ЗАРАНЕЕ ПОДГОТОВЛЕННЫЙ контекст F2. И после завершения F2 - F2 - должно восстановить контекст F1. === Это по сути - "обычный" переключатель задач. Это можно попытаться сделать для частного конкретного случая именно с F1 и F2. Но по затратам кода и прочего - ничем не будет отличаться от нормального переключателя. Ссылку на пример я приводил. Для кортекса - у которого есть два стека, есть два режима работы процессора - можно посметреть переключать от соот. порта FreeRtos, к примеру. Мой переключатель со всеми функциями занимает 40 строк кода на Си, и два десятка строк на ассемблере. И это очень хорошая цена за простую многозадачность. =============== Но правильное решение - от тов. Борща. Если алгоритм строго детерминирован, то текст функции следует прямо вставить в обработчик. И все страхи по поводу такого расположения должны быть исключены смыслом самого алгоритма. Изменено 2 марта, 2014 пользователем DpInRock Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
slavka012 0 2 марта, 2014 Опубликовано 2 марта, 2014 · Жалоба Можно и так... Только в этом случае Вы не выходите из прерывания. И если func1() не закончиться выполнятся до повторного входа в IRQ... то получиться рекурсия и через некоторое время контроллер зависает!!!! Поэтому я и хочу чтобы переход был после выхода из прерывания Что? Какая рекурся? Повторного входа в IRQ не может быть до выхода из него. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 3 марта, 2014 Опубликовано 3 марта, 2014 · Жалоба Все таки надо было оставить свой ответ в первый раз. Смотрите в сторону RTOS, например как реализовано переключение задач в FreeRTOS. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться