Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: По ARM архитектуре (LPC2106)
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
SasaVitebsk
(Пожалуйста не предлагать варианты с ОС.)

Имеется несколько прерываний. Одно объявлено как FIQ и несколько по типу IRQ через VIC. Хочу сделать одно совтовое прерывание. Во время его работы должны быть разрешены все другие прерывания (вложенные).

Попытался его объявить следующим образом
Код
#pragma swi_number=VIC_SW                                // Èñïîëíåíèå êîììàíä
__irq  __arm    __nested    __swi    static void    ShowActive(void)

Пишет об ошибке. Убрал __irq - пишет, что __nested только с __irq может быть применено.

Пример из описалова по nested меня не устраивает, так как мне не надо во всех irq прерываниях разрешать fiq, а только в совтовом.

Может я неправильно __swi применяю и это не для данного случая. Если это так, то как необходимо проинициилизировать, вызвать и обработать. Если можно примерчик пож.

Заранее благодарю.
zltigo
Как-то все мутно изложено sad.gif. Но насколько можно понять "вложеные" тут ни сном ни духом. Просто разрешите прерывания в Вашем обработчике SWI и все.
SasaVitebsk
Цитата(zltigo @ Jun 16 2008, 23:42) *
Как-то все мутно изложено sad.gif


Хотел просто покороче.
Имеются прерывания irq от rs485 (Это просто для информации).

Имеется быстрое регулярное прерывание от таймера fiq.

Каждое N-ое прерывание fiq надо вызвать софтовое прерывание (N=56). При этом прерывание софтовое выполняется достаточно долго (3-30 прерываний fiq) и необходимо чтобы прерывания fiq и irq были бы разрешены.

Ещё раз почитав думаю что это можно сделать двумя способами. 1 через swi. 2 посредством VIC с вызывом прерываний с софтовым вектором. Во втором случае необходимо использовать ключевое слово __nested. Хотя пока в голове туман.

Вопрос если я хочу воспользоваться swi, то такие вопросы:
1) как вызвать прерывание
2) как его разрешить
3) если я вызову в прерывании fiq, то оно будет обработано по выходу?
4) Почему в данном случае не надо сохранять SPSR_irq

Если я воспользуюсь irq, то вроде бы всё понятно.
aaarrr
Туман надо ликвидировать smile.gif

Цитата(SasaVitebsk @ Jun 17 2008, 03:03) *
3) если я вызову в прерывании fiq, то оно будет обработано по выходу?

Нет, процессор тут же ломанется выполнять SWI.

Цитата(SasaVitebsk @ Jun 17 2008, 03:03) *
4) Почему в данном случае не надо сохранять SPSR_irq

Потому что процессор будет переключен в режим супервизора.
SasaVitebsk
значит эт мне не проокатывает. Небходимо irq nested. smile.gif
zltigo
Если хочется прямо так, как описали, то для irq вообще ничего делать не надо, для fiq - стандартные навороты ввиде сохранения SPSR и LR в стеке (гляньте канонический пример для организации вложенности для компиляторов, которые не имеют прибамбаса __nested) и в swi обработчике разрешить irq и fiq.
zltigo
Да, кстати, можете повесить длииинную обработку не на swi а на irq, "штатно" разрешить ему вложенность и софтово дергать irq из fiq. Я так как-то делал переключение контекста задачи в нештатных случаях "почти из fiq", дабы навороты по сохранетию контекста на fiq не вешать.
Обработчик в fiq взводит бит не используемого прерывания у которого установлен вектор и по выходу их fiq влетаем в обрабочик irq.
defunct
Цитата(SasaVitebsk @ Jun 17 2008, 02:03) *
Каждое N-ое прерывание fiq надо вызвать софтовое прерывание (N=56). При этом прерывание софтовое выполняется достаточно долго (3-30 прерываний fiq) и необходимо чтобы прерывания fiq и irq были бы разрешены.

Вы можете изложить объективную причину того, почему нельзя обработку этого некоего события (N=56) возложить на основной цикл программы?

Ведь только прямолинейная дубовая как бревно логика основного цикла программы с "delay_ms" могут этому помешать. Может лучше копать и что-то менять там? Сейчас у вас одно такое событие, но ведь их может быть 2, 5 ...100.. Что тогда? Под каждое свой IRQ?
GetSmart
Цитата(SasaVitebsk)
Каждое N-ое прерывание fiq надо вызвать софтовое прерывание (N=56). При этом прерывание софтовое выполняется достаточно долго (3-30 прерываний fiq) и необходимо чтобы прерывания fiq и irq были бы разрешены.
Я почти в каждом проекте делаю что-то очень похожее. Делается легко и непринуждённо. _swi не надо трогать, там немного по-другому делается. FIQ и IRQ выполняются в штатном режиме без особых извращений по запрету прерываний. Вобщем софтовое прерывание объявляется через _arm _irq _nested. Ему даётся самый или почти самый низкий приоритет - это как надо в проге. Разумеется в нём в начале разрешаются все проерывания (и FIQ) через __enable_interrupt, а перед концом запрещаются. После запрета сбрасывается бит данного прерывания в регистре VICSoftIntClear. А в FIQ прерывании после достижения N=56 устанавливается тот же бит прерывания в регистре VICSoftInt. Таким образом, когда FIQ закончится и не будет прерываний более приоритетных чем выбранный приоритет софтового прерывания, то выполнение перейдёт на это прерывание, а когда оно отработает, то выполнение вернётся в основную прогу например. Все прерывания с приоритетами выше софтового будут его прерывать и оперативно отрабатываться, а в софтовом при этом можно сидеть очень долго и не бояться, т.к. оно затормаживает только основную прогу. Вобщем очень удобная штука. При этом, основной проге не нужно знать об всех этих заморочках и анализировать фсякие флаги. В последней своей проге у меня даже два разных таких софтовых прерывания. Всё работает без глюков.

В качестве вектора в битовой карте регистров VICSoftInt и им подобным для такого обработчика есть вектор VIC_SW (имена находятся в файле iolpc2xxx.h), но можно использовать вектор и любой другой незадействованной в проекте периферии, например VIC_WDT, VIC_DEBUGRX, VIC_DEBUGTX и другие, и даже свободные биты до 31-ого включительно.
GetSmart
CODE
В голове инициализация векторов - такая:

VICIntEnClear = (uint32_t)-1; // Очистить все прерывания
VICSoftIntClear = (uint32_t)-1; // Очистить совтовые прерывания
#define VIC_CNTL_ENABLE_BIT 5
VICVectCntl0 = (1<<VIC_CNTL_ENABLE_BIT) | VIC_UART0; // Прерывание от USART0 - высший приоритет
VICVectAddr0 = (uint32_t)UART0_Handler;
VICIntEnable = (1<<VIC_TIMER0)|(1<<VIC_UART0); // Разрешить прерывание от таймера 0 и от USART0
VICIntSelect = (1<<VIC_TIMER0); // Прерывание от таймера 0 = FIQ
...
#define SHOW_INT VIC_SW // Âåêòîð ñîôòîâîãî ïðåðûâàíèÿ íà îáðàáîòêó êîììàíä

VICVectCntl15 = (1<<VIC_CNTL_ENABLE_BIT) | SHOW_INT; // Enable vector interrupt for context switcher
VICVectAddr15 = (uint32_t)ShowActive;
VICIntEnable = (1UL<<SHOW_INT);
VICVectAddr = 0; // Reset VIC logic
...


FIQ прерывание объявлено так

__fiq __arm void FIQ_Handler() // Отображение картинки Master, Slave
...
там вызов картинки
if(Flag.EnShow) VICSoftInt = (1<<SHOW_INT); // Выполнить прерывание
....
завершение так
VICVectAddr = 0;
}
....

Совтовое прерывание оформлено так
__arm __nested __irq static void ShowActive(void)// Исполнение комманд
...
Потом идёт кое какая критическая секция, где бы я не хотел иметь прерываний, тем не менее по JLINKу почемуто FIQ прерывания здесь разрешены
...
далее я разрешаю прерывания
...
__enable_interrupt();
...
из данного прерывания выхожу так
...
__disable_interrupt();
VICSoftIntClear = (1<<SHOW_INT); // Сбросить совтовое прерывание
VICVectAddr = 0;
// TST_CLR;
}
....


Что я вижу.
1) FIQ вызываются как положено
2) Ч/з нужное число прерываний FIQ устанавливается флаг совтового прерывания, и осуществляется переход на него.
3) при выходе из совтового прерывания возврат происходит не туда куда нужно


VICVectAddr = 0; => ставить в конце обработчика FIQа не нужно. FIQ работает в обход VICа. В конце обработчика нужно сбросить флаги прерывания периферии, которая вызвала FIQ. В данном случае флаги прерывания таймера 0. Если же поставить сброс VIC, то могут быть аномалии в работе проги. Т.к. если FIQ прервал IRQ, то после выхода из FIQ, VIC подумает что закончилось текущее IRQ и может вызвать повторно как текущее IRQ, так и IRQ с более низким приоритетом, прервав текущее (с более высоким).

static в заголовке прерывания никогда не ставлю. Честно говоря, даже не знаю зачем оно нужно.
(ЗЫ. Если кто знает - расскажите. Заодно встал сегодня на грабли в CCS3.3 который ругается когда переменная вне процедуры объявлена через static, а я её в хидере пытался через extern объявить, компилеру не понравилось вместе extern static ... Для меня этот статик загадочный какой-то. Только внутри процедуры знаю для чего он используется.)

Цитата
Потом идёт кое какая критическая секция, где бы я не хотел иметь прерываний, тем не менее по JLINKу почемуто FIQ прерывания здесь разрешены
Так и должно быть. Залетая в обработчик IRQ, проц запрещает только IRQ, а FIQ остаётся включённым, точнее каким и был раньше. Если нужна абсолютная критическая секция, то нужно "ручками" запрещать FIQ.

Цитата
3) при выходе из совтового прерывания возврат происходит не туда куда нужно
Очень может быть. Как уже написал раньше, сбросив VIC внутри FIQа процессор подумал, что SoftInt завершился и после этого могло вызваться любое другое прерывание, причём управление (сразу) могло не вернуться в SoftInt. Хотя в основную прогу управление вернутся не может пока не завершиться SoftInt.

На первый взгляд всё. Если после этого не заработает как надо, то почитаю ещё разок повнимательнее cool.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.