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

как поменять адрес возврата из IRQ

Здравствуйте, извините если такая тема уже повторялась. Но я никак не нашел ответа:

 

Есть прога:

#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

Изменено пользователем lons83

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


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

чтобы после возвращения из IRQ -> выполняться стала func1{} !!! ( поменять адрес возврата ) и уже после выполнения func1{} -> вернуться к func3{}; ??????????

IRQ   // обработчик прерывания
{
....
    func1();
}

И забыть про ассемблер.

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


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

IRQ   // обработчик прерывания
{
....
    func1();
}

И забыть про ассемблер.

 

Можно и так... Только в этом случае Вы не выходите из прерывания. И если func1() не закончиться выполнятся до повторного входа в IRQ... то получиться рекурсия и через некоторое время контроллер зависает!!!!

 

Поэтому я и хочу чтобы переход был после выхода из прерывания

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


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

Можно и так... Только в этом случае Вы не выходите из прерывания. И если func1() не закончиться выполнятся до повторного входа в IRQ... то получиться рекурсия и через некоторое время контроллер зависает!!!!

Поэтому я и хочу чтобы переход был после выхода из прерывания

В Cortex-M3 есть программные прерывания. Можно установить флаг одного из них в IRQ,

но приоритет такого прерывания должен быть ниже приоритета IRQ. В обработчике программного

прерывания вызвать func1(). Тут и с пугающей рекурсией ничего не зависнет, просто будут потери вызовов

func1(). Честно говоря, станно все это, ибо вызов func1() получается асинхронным со всеми вытекающими.

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


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

В Cortex-M3 есть программные прерывания. Можно установить флаг одного из них в IRQ,

но приоритет такого прерывания должен быть ниже приоритета IRQ.

Не могли бы Вы здесь по подробнее....

тогда как мне задать вектор прерывания программного для func1(); ???

Ведь аппаратные вектора все заняты, а подставить func1(); под вектор с 0-31 не получается... да и не получиться наверно...

 

Вообщем не понятно как указать что func1() - это программное прерывание... и как я понял оно будет вызываться из IRQ тогда зачем его делать программным?.....

 

Тут и с пугающей рекурсией ничего не зависнет, просто будут потери вызовов func1().

 

на практике у меня зависало... особенно если func1() --- довольно приличная функция - например обработка видео массива... и тогда все храниться в стеке и через 2 минуты забивается.... а если func1() вынести в общий цикл то все нормально работает.... просто нужно чтобы func1() запускался прямо после IRQ , а во время выполнения func1() происходит 3-4 вызова IRQ....

 

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


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

Не могли бы Вы здесь по подробнее....

тогда как мне задать вектор прерывания программного для 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();

 

Разве нет?

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


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

Аппаратный ничем не отличается от програмного. В 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();

 

Разве нет?

 

Кстати да... Вы правы... тут можно по разному это обыграть... надо подумать...

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


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

А можете еще раз мне обьяснить: Как произойдет вызов этого программного прерывания?

с аппаратным все понятно... а вот с программным? ведь если я помещу func1() - в обработчик - это ни чем не будет отличаться от вызова обычной функции... а если в обычном цикле программы, то тогда как? по какому то флагу?

Спасибо за книжку. Завтра скачаю и посмотрю...

Если с аппаратным понятно, то хорошо. Софтовый тоже самое)

Когда приходит запрос на обработку прерывания от периферийного модуля взводится флаг

отложенного прерывания в модуле NVIC.

Затем NVIC смотрит какие флаги взведены и выбирает из них один удовлетворяющий критериям

(разрешение прерывания, приоритет и т.п.). Затем переходит к обработке прерывания совершая переход

к функции, адрес которой указан в таблице векторов прерывания паралельно сбрасывая флаг отложенного

прерывания. Процесс очень хорошо описан в книге.

Таким образом Вы можете генерировать софтовые прерывания взводя флаги в NVIC.

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

Хуже: Вы можете снимать запрос на запуск аппаратного или софтового прерывания очищая флаг.

Короче свобода полная. Никакого asm, все на Си. Правда для запуска софтовых прерываний в непривелегированном

режиме требуется специальное на то разрешение. В книге вся инфа есть.

 

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


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

ПОхоже все запутались конкретно.

 

До вызова прерывания выполнялась F1. После прерывания требуется выполнение F2.

ПОСЛЕ ЗАВЕРШЕНИЯ F2 - видимо, требуется продолжить F1?

 

Отсюда следует, что прерывание должно ЗАПОМНИТЬ контекст F1, при выходе из прерывания - заменить контекст F1 на ЗАРАНЕЕ ПОДГОТОВЛЕННЫЙ контекст F2.

 

И после завершения F2 - F2 - должно восстановить контекст F1.

 

===

Это по сути - "обычный" переключатель задач.

Это можно попытаться сделать для частного конкретного случая именно с F1 и F2.

 

Но по затратам кода и прочего - ничем не будет отличаться от нормального переключателя.

Ссылку на пример я приводил.

 

Для кортекса - у которого есть два стека, есть два режима работы процессора - можно посметреть переключать от соот. порта FreeRtos, к примеру.

 

Мой переключатель со всеми функциями занимает 40 строк кода на Си, и два десятка строк на ассемблере.

И это очень хорошая цена за простую многозадачность.

===============

 

Но правильное решение - от тов. Борща.

Если алгоритм строго детерминирован, то текст функции следует прямо вставить в обработчик.

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

 

Изменено пользователем DpInRock

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


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

Можно и так... Только в этом случае Вы не выходите из прерывания. И если func1() не закончиться выполнятся до повторного входа в IRQ... то получиться рекурсия и через некоторое время контроллер зависает!!!!

 

Поэтому я и хочу чтобы переход был после выхода из прерывания

Что? Какая рекурся? Повторного входа в IRQ не может быть до выхода из него.

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


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

Все таки надо было оставить свой ответ в первый раз.

 

Смотрите в сторону RTOS, например как реализовано переключение задач в FreeRTOS.

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


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

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

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

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

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

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

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

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

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

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