Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Interrupt i IAR
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Nikola Kirov
Необходимо переключат функции которъе въизъиваются на перервание.
Сделал
extern __near void (* pTX_InterruptFunction)(void);

а сам interrupt
Код
#pragma vector = USART_TXC_vect
__interrupt void TXCinterrupt(void)
{
 pTX_InterruptFunction();
}


все работает но вот такое генерируется
Код
  \   00000000   93BA               ST      -Y, R27
  \   00000002   93AA               ST      -Y, R26
  \   00000004   938A               ST      -Y, R24
  \   00000006   93FA               ST      -Y, R31
  \   00000008   93EA               ST      -Y, R30
  \   0000000A   923A               ST      -Y, R3
  \   0000000C   922A               ST      -Y, R2
  \   0000000E   921A               ST      -Y, R1
  \   00000010   920A               ST      -Y, R0
  \   00000012   937A               ST      -Y, R23
  \   00000014   936A               ST      -Y, R22
  \   00000016   935A               ST      -Y, R21
  \   00000018   934A               ST      -Y, R20
  \   0000001A   933A               ST      -Y, R19
  \   0000001C   932A               ST      -Y, R18
  \   0000001E   931A               ST      -Y, R17
  \   00000020   930A               ST      -Y, R16
  \   00000022   B78F               IN      R24, 0x3F
    54            pTX_InterruptFunction();
  \   00000024   ....               LDI     R26, LOW(pTX_InterruptFunction)
  \   00000026   ....               LDI     R27, (pTX_InterruptFunction) >> 8
  \   00000028   91ED               LD      R30, X+
  \   0000002A   91FC               LD      R31, X
  \   0000002C   9509               ICALL
    55          }
  \   0000002E   BF8F               OUT     0x3F, R24
  \   00000030   9109               LD      R16, Y+
  \   00000032   9119               LD      R17, Y+
  \   00000034   9129               LD      R18, Y+
  \   00000036   9139               LD      R19, Y+
  \   00000038   9149               LD      R20, Y+
  \   0000003A   9159               LD      R21, Y+
  \   0000003C   9169               LD      R22, Y+
  \   0000003E   9179               LD      R23, Y+
  \   00000040   9009               LD      R0, Y+
  \   00000042   9019               LD      R1, Y+
  \   00000044   9029               LD      R2, Y+
  \   00000046   9039               LD      R3, Y+
  \   00000048   91E9               LD      R30, Y+
  \   0000004A   91F9               LD      R31, Y+
  \   0000004C   9189               LD      R24, Y+
  \   0000004E   91A9               LD      R26, Y+
  \   00000050   91B9               LD      R27, Y+
  \   00000052   9518               RETI

И как видно перервание становится медленое.
А мои функции совсем простенкие,такое сохранение регистров не нужно.
Явно что то не так делаю. Как правилно ето делат?
ig_z
Цитата(Nikola Kirov @ Oct 20 2005, 01:04)
И как видно перервание становится медленое.
А мои функции совсем простенкие,такое сохранение регистров не нужно.
Явно что то не так делаю. Как правилно ето делат?
*


Если вызываемая функция и вызывающая находятся в разных модулях, то компилятор не может знать о простоте или сложности вашей функции и совершенно корректно сохранит все регистры. Выход - помещать эти функции в один модуль. ( хотя вроде есть среды с =умными= линкерами для подобных ситуаций, но у иара он точно этого не делает - жертва универсальности)

А если эти функции в одном модуле и оптимизация включена - тогда дело дрянь. Только на асме
Alex11
Все не совсем так - при выключенном оптимизаторе, как только в interrupt-функции появляется вызов другой функции, то сохраняются все регистры. При включенном - если функция в этом же модуле, то сохраняются только требуемые (это для IAR 4.11). Но следует быть аккуратным с оптимизатором, он очень любит выбрасывать куски программы не смотря на объявления переменных volatile.
Pat
Цитата(Nikola Kirov @ Oct 20 2005, 01:04)
Необходимо переключат функции которъе въизъиваются на перервание.
Сделал 
extern __near void (* pTX_InterruptFunction)(void);

а сам interrupt
[code]
#pragma vector = USART_TXC_vect
__interrupt void TXCinterrupt(void)
{
  pTX_InterruptFunction();
}

А мои функции совсем простенкие,такое сохранение регистров не нужно.
Явно что то не так делаю. Как правилно ето делат?
*


Что бы компилятор не творил такие безобразия можно сделать следующее
1) Не вызывать функцию из обработчика прерываний а описать все в теле
#pragma vector = USART_TXC_vect
__interrupt void TXCinterrupt(void)
{
}
2) Обязательно использовать в качестве ваших переменных, которые используются в прерывании, залоченные регистры ну те которые объявляются в IAR как
__regvar __no_init volatile unsigned char val @ 13;
Так же их надо залочить в опциях

Потеряете совместимость с другими компиляторами, но если у вас все переменные будут залочены компилятор будет сохранять в стеке только SREG.
IgorKossak
Цитата(Pat @ Oct 20 2005, 09:22)
2) Обязательно использовать в качестве ваших переменных, которые используются в прерывании, залоченные регистры ну те которые объявляются в IAR как
__regvar __no_init volatile unsigned char val      @ 13;
Так же их надо залочить в опциях
*


Не следует этим слишком увлекаться, т. к. некоторые библиотечные функции используют регистры R4 - R7.
Залочивание этих регистров может привести к некорректной работе при вызове оных функций. Поэтому IAR не рекомендует залочивать более 9 регистров (хотя и позволяет это сделать).
Runner
Цитата(Pat @ Oct 20 2005, 08:22)
Что бы компилятор не творил такие безобразия можно сделать следующее
1) Не вызывать функцию из обработчика прерываний а описать все в теле
#pragma vector = USART_TXC_vect
__interrupt void TXCinterrupt(void)
{
}
2) Обязательно использовать в качестве ваших переменных, которые используются в прерывании, залоченные регистры ну те которые объявляются в IAR как
__regvar __no_init volatile unsigned char val      @ 13;
Так же их надо залочить в опциях

Потеряете совместимость с другими компиляторами, но если у вас все переменные будут залочены компилятор будет сохранять в стеке только SREG.
*

1)Очень даже правильно. Как раз тот случай, когда директивы и макросы вместо функций будут к месту.
2) Из опыта - есть ограничения на количество регистров, залоченных под глобальные переменные - не более 9 (или 8?). Если залочить больше будут проблеммы с линковкой.
Полезная документашка лежит под http://atmel.com/dyn/resources/prod_documents/doc1234.pdf - совмещение asm и C. Там есть пример функции обработчика прерывания на asm-e в С программе.
Runner
Цитата(IgorKossak @ Oct 20 2005, 09:59)
Цитата(Pat @ Oct 20 2005, 09:22)
2) Обязательно использовать в качестве ваших переменных, которые используются в прерывании, залоченные регистры ну те которые объявляются в IAR как
__regvar __no_init volatile unsigned char val      @ 13;
Так же их надо залочить в опциях
*


Не следует этим слишком увлекаться, т. к. некоторые библиотечные функции используют регистры R4 - R7.
Залочивание этих регистров может привести к некорректной работе при вызове оных функций. Поэтому IAR не рекомендует залочивать более 9 регистров (хотя и позволяет это сделать).
*


И так всегда! Пока чешу репу уже ответят...
Nikola Kirov
Проблем с переключение задач которъие въиполняется на перервание слишком сериознъи. Я просто удивлен что такая фирма как IAR так подходит к етому вопросу.

У меня ест одна идея
Код
#pragma vector = 0x1000
__interrupt void Usart_Trnasmit()
{
-------------
-------------
}

так обявляем функции которъие нада переключат

проблем как организироват само переключение
если захочу поставит
__task void TrInterrupt(void) @ USART_TXC_vect
и там в асме переходит к нужнои функции
компилер ругается что на етот адрес могу толко __interrupt ставит.
Pat
Цитата(Runner @ Oct 20 2005, 11:14)
2) Из опыта - есть ограничения на количество регистров, залоченных под глобальные переменные - не более 9 (или 8?). Если залочить больше будут проблеммы с линковкой.
*

Всего залочить можно 12 регистров R4 - R15.
Проблеммы могут возникнуть только в случае, если использовать функции из родных ИАРовских библиотек. Особенно это касается математических функций с float в качестве аргумента. Там вообще ничего не даст залочить.
Если же все самописаное то проблем нет.
BVU
Цитата(Nikola Kirov @ Oct 20 2005, 12:18)
Проблем с переключение задач которъие въиполняется на перервание слишком сериознъи. Я просто удивлен что такая фирма как IAR так подходит к етому вопросу.

У меня ест одна идея
Код
#pragma vector = 0x1000
__interrupt void Usart_Trnasmit()
{
-------------
-------------
}

так обявляем функции которъие нада переключат

проблем как организироват само переключение
если захочу поставит
__task void TrInterrupt(void) @ USART_TXC_vect
и там в асме переходит к нужнои функции
компилер ругается что на етот адрес могу толко __interrupt ставит.
*

Nikola,
в классических системах это делается немного по другому. В теле Вашего прерывания должен находиться переход (call) на адрес расположенный в оперативной памяти (строго фиксировано), где размещается еще один вызов функции (переключение на функцию) адресс которой подставляется (настраивается в данный момент времени) в зависимости от логики работы программы. Так Вы получаете расширение ресурсов своего преравания. Что касается скорости выполнения, то здесь теряется время на дополнительный вызов. На asm это реализуется просто, как это сделать корректно на 'C' - надо подумать.
Nikola Kirov
Кажется нашел решение

Код
__near void (* pTX_InterruptFunction)(void);


#pragma vector =  USART_RXC_vect
__interrupt void RXCinterrupt(void)
{
 asm(" call pRX_InterruptFunction");
}


так все ОК но не знаю еще не будут ли глюки в работе
VladislavS
Цитата(BVU @ Oct 20 2005, 11:49)
в классических системах это делается немного по другому.  В теле Вашего прерывания должен находиться переход (call) на адрес расположенный в оперативной памяти (строго фиксировано), где размещается еще один вызов функции (переключение на функцию) адресс которой подставляется (настраивается в данный момент времени) в зависимости от логики работы программы. Так Вы получаете расширение ресурсов своего преравания.  Что касается скорости выполнения, то здесь теряется время на дополнительный вызов. На asm это реализуется просто, как это сделать корректно на 'C' - надо подумать.


С AVR это не пройдет, так как адресное пространство кода и данных раздельное и сегменты кода во flash лежать обычно.
BVU
Цитата(VladislavS @ Oct 20 2005, 17:11)
Цитата(BVU @ Oct 20 2005, 11:49)
в классических системах это делается немного по другому.  В теле Вашего прерывания должен находиться переход (call) на адрес расположенный в оперативной памяти (строго фиксировано), где размещается еще один вызов функции (переключение на функцию) адресс которой подставляется (настраивается в данный момент времени) в зависимости от логики работы программы. Так Вы получаете расширение ресурсов своего преравания.  Что касается скорости выполнения, то здесь теряется время на дополнительный вызов. На asm это реализуется просто, как это сделать корректно на 'C' - надо подумать.


С AVR это не пройдет, так как адресное пространство кода и данных раздельное и сегменты кода во flash лежать обычно.
*


Да, конечно же... AVR имеет архитектуру гарвардского типа. sad.gif
Если бы не высокая производительность выполнения команд, AVR бы проигравал со своей системой прерывания во всех отношениях...
Надо подумать как это обойти?!
Nikola Kirov
Етот метод которъи я описл деиствително работает и регистръи не сохраняются в само перервание вообще.
Но не знаю какая разница ест между функция перервания и объчная функция в аспекте сохранения регистров. И почему у IAR толко функции перервании сохраняют все регистръи если обратится к другои фунцкции.
Если кто то может обяснит разницу можно и наити каие подводнъие камни ест в метода которъй нашел я.
dxp
Цитата(BVU @ Oct 20 2005, 19:27)
Цитата(VladislavS @ Oct 20 2005, 17:11)
Цитата(BVU @ Oct 20 2005, 11:49)
в классических системах это делается немного по другому.  В теле Вашего прерывания должен находиться переход (call) на адрес расположенный в оперативной памяти (строго фиксировано), где размещается еще один вызов функции (переключение на функцию) адресс которой подставляется (настраивается в данный момент времени) в зависимости от логики работы программы. Так Вы получаете расширение ресурсов своего преравания.  Что касается скорости выполнения, то здесь теряется время на дополнительный вызов. На asm это реализуется просто, как это сделать корректно на 'C' - надо подумать.


С AVR это не пройдет, так как адресное пространство кода и данных раздельное и сегменты кода во flash лежать обычно.
*


Да, конечно же... AVR имеет архитектуру гарвардского типа. sad.gif
Если бы не высокая производительность выполнения команд, AVR бы проигравал со своей системой прерывания во всех отношениях...
Надо подумать как это обойти?!
*


Прошу прощения, что вмешиваюсь. Тут все не так и все гораздо проще. IAR делит регистры на local и scratch. Первые - это регистры, которые в вызываемой функции компилятор может использовать только предварительно сохранив их с последующим восстановлением перед выходом. Т.е. это, так называемые, call preserved регистры. Вторые - это регистры, которые компилятор при вызове функции может юзать по своему усмотрению. Из этого следует: если имеет место вызов любой функции (тело которой компилятору в точке компиляции не видно) из прерывания, то компилятор не может делать никаких предположений об использовании регистров в этой функции и обязан сохранить все scratch регистры - local регистры ему тут сохранять не надо, т.к. они, если необходимо, будут сохранены в вызываемой функции. Что мы и наблюдаем в приведенном задавшим вопрос фрагменте - сохранены только scratch регистры.

Это поведение компилятора корректное, гарантирующее от возникновения коллизий из-за асинхронного доспупа к регистрам. К архитектуре проца это отношения не имеет. Возьмите фон неймановский MSP430, там поведение в обработчике прерывания будет ровно таким же.

Если не хочется иметь этот оверхед, то единственным корректным путем будет разместить тело функции прямо внутри обработчка прерывания - как уже посоветовали. Чтобы не загромождать ISR можно функцию оставить, но объявить как встраиваемую (inline) и поместить ее определение в заголовочный файл, включаемый в исходник, где определен ISR.

Все остальные "финты ушами" вроде вызова функции через асмовую вставку - это быть самому себе злобным буратиной. В этом случае, когда возникнет прерывание и управление будет передано в функцию, которая не является ISR (т.к. компилятор не знает, что функция эта вызвана асинхронно по отношению к потоку управления), в этой функции будут без ограничений использоваться scratch регистры, значения которых, не будут сохранены (с последующим восстановлением). В результате огребете гору замечательных и труднопресказуемых глюков. Оно надо? Никогда ни в коем случае так делать нельзя. Если уж вызываете функцию без сохранения контекста компилятором, то делайте это сами руками. Такая необходимость может возникнуть при написании переключателя конткестов в вытесняющий RTOS.
Nikola Kirov
Спосибо DXP. Тепер все стало более понятно.
Но если ползоватся inline функции,компилер игнорирует inline.
вот что получается.
Код
  \   00000000   938A               ST      -Y, R24
  \   00000002   93FA               ST      -Y, R31
  \   00000004   93EA               ST      -Y, R30
  \   00000006   923A               ST      -Y, R3
  \   00000008   922A               ST      -Y, R2
  \   0000000A   921A               ST      -Y, R1
  \   0000000C   920A               ST      -Y, R0
  \   0000000E   937A               ST      -Y, R23
  \   00000010   936A               ST      -Y, R22
  \   00000012   935A               ST      -Y, R21
  \   00000014   934A               ST      -Y, R20
  \   00000016   933A               ST      -Y, R19
  \   00000018   932A               ST      -Y, R18
  \   0000001A   931A               ST      -Y, R17
  \   0000001C   930A               ST      -Y, R16
  \   0000001E   B78F               IN      R24, 0x3F
    66            Trnasmit();                          //    !!!!!!!!!!!!!!!!!!!  Ето inline функция
  \   00000020   ........           CALL    ??Trnasmit
    67          }
  \   00000024   BF8F               OUT     0x3F, R24
  \   00000026   9109               LD      R16, Y+
  \   00000028   9119               LD      R17, Y+
  \   0000002A   9129               LD      R18, Y+
  \   0000002C   9139               LD      R19, Y+
  \   0000002E   9149               LD      R20, Y+
  \   00000030   9159               LD      R21, Y+
  \   00000032   9169               LD      R22, Y+
  \   00000034   9179               LD      R23, Y+
  \   00000036   9009               LD      R0, Y+
  \   00000038   9019               LD      R1, Y+
  \   0000003A   9029               LD      R2, Y+
  \   0000003C   9039               LD      R3, Y+
  \   0000003E   91E9               LD      R30, Y+
  \   00000040   91F9               LD      R31, Y+
  \   00000042   9189               LD      R24, Y+
  \   00000044   9518               RETI

Ест ли идея почему так получается?
dxp
Цитата(Nikola Kirov @ Oct 21 2005, 16:46)
Спосибо DXP. Тепер все стало более понятно.
Но если ползоватся inline функции,компилер игнорирует inline.
вот что получается.
Код
  \   00000000   938A               ST      -Y, R24
  \   00000002   93FA               ST      -Y, R31
   .............
  \   0000001C   930A               ST      -Y, R16
  \   0000001E   B78F               IN      R24, 0x3F
    66            Trnasmit();                          //    !!!!!!!!!!!!!!!!!!!  Ето inline функция
  \   00000020   ........           CALL    ??Trnasmit
    67          }
  \   00000024   BF8F               OUT     0x3F, R24
  \   00000026   9109               LD      R16, Y+
   .............
  \   00000042   9189               LD      R24, Y+
  \   00000044   9518               RETI

Ест ли идея почему так получается?
*

Надо убедиться, что определение функции "Trnasmit()" видно в точке ее вызова. Если компилятор не видит в точке вызова тела функции, он, очевидно, не может ее встроить. Включите определение этой функции в заголовочный файл и подключите его к исходному, где Ваш ISR.

Еще компилятор может умничать и подавлять встраивание - например, считать, что функция большая и ее встраивать нецелесообразно. Этот "интеллект" компилятора можно подавить с помощью #pragma inline=forced, размещенной перед прототипом или определением функции.
Nikola Kirov
да ето с #pragma inline=forced помогло.
но я должен переключат 8 разнъе функции на переключение уходит много время.
Получается тоже как сделал сначала с помощи указателя.

Должно имется какои то метод сделат на C бъстрее. В асме возможно,почему не может на C сделат.

Принцип ясен нада все функции написат как функции перервания.
В функция перервания которъе нада переключат при помочи указателя въизават необходимои функции.В самои функции прерервания ест толко переход к функции которъи указъивает указател и поетому не нада и регистръи сохранят.
Необходимъие регистри будут правилно сохраненъи и возтоновленнъие в самои функции,потому что они написанъие как функции перервания.

В логике работъи нечего сложное нет,вопрос как ето сделат в ИАР-е
Виктория
Цитата(Nikola Kirov @ Oct 21 2005, 19:28)
да ето с #pragma inline=forced помогло.
но я должен переключат 8 разнъе функции на переключение уходит много время.
Получается тоже как сделал сначала с помощи указателя.

Должно имется какои то метод сделат на C бъстрее. В асме возможно,почему не может на C сделат.

Принцип ясен нада все функции написат как функции перервания.
В функция перервания которъе нада переключат при помочи указателя въизават необходимои функции.В самои функции прерервания ест толко переход к функции которъи указъивает указател и поетому не нада и регистръи сохранят.
Необходимъие регистри будут правилно сохраненъи и возтоновленнъие в самои функции,потому что они написанъие как функции перервания.

В логике работъи нечего сложное нет,вопрос как ето сделат в ИАР-е
*


Nikola, если условия Вашей задачи переложить на Cи, то вот это нужно?
Код
interrupt IRQHandler()
{ void (*func[8])();

.....
// по какому-то условию вызов требуемой функции
    (*func[i])();
....
}


Спрашиваю пока, чтобы уяснить Вашу задачу.
Nikola Kirov
На проверки условия уходит много циклов. А нада бъистрее. Нада сделат как описал с указател к функции. Проблем как ето реализироват в ИАР
Виктория
Цитата(Nikola Kirov @ Oct 21 2005, 20:32)
На проверки условия уходит много циклов. А нада бъистрее. Нада сделат как описал с указател к функции. Проблем как ето реализироват в ИАР
*


Так я и спрашивала про формулировку задачи, а то текстом очень туманно.
Может поправите мой текст на Си, чтобы понять Вашу задачу. А уж потом подумаем про быстродействие и что нужно указать дополнительно компилятору.

К сожалению, я прощаюсь до завтра. sad.gif
Виктория
To Nikola. Вот эти условия Вашей задачи не совсем понятны:

Цитата
...но я должен переключат 8 разнъе функции....


Цитата
В функция перервания которъе нада переключат при помочи указателя въизават необходимои функции.В самои функции прерервания ест толко переход к функции которъи указъивает указател...



В конце концов Вы можете переключение функции осуществлять с помощью библиотечной функции установки вектора прерываний. Если же таковой нету в IAR, то свою написать не сложно (в самом крайнем случае на ассемблере).

В общем-то, эта функция должна делать это
Код
void setvect(int IRQ_num, __interrupt void (*IRQ_Handler)())
{unsigned long *p;   //это указатель на адрес вектора прерываний
 *p=(unsigned long)IRQ_Handler;
}


К сожалению, я не знаю архитектуру и систему команд для Вашего контроллера. Это только идея, а с Вашей стороны должно быть творческое использование этой идеи применительно к архитектуре: на основе знаний как располагаются вектора прерываний и что они представляют собой - просто адреса подпрограмм обработки прерываний или JMP на подпрограмму (в последнем случае setvect незначительно усложнится).

Посмотрите еще раз на предыдущие советы выше (нечто подобное уже посоветовали).
VladislavS
To Vic1

Уже псали, что на AVR этот номер не пройдет из-за архитектуры гарвардского типа с сегментами кода размещенными во flash.
Nikola Kirov
Спосибо Vic1 но тут вопрос относится к специфике IAR-а и AVR.

Опят, должно получится ето,но проблем как ето реализироват
Цитата
Принцип ясен, нада все функции написат как функции перервания.
В функция перервания которая нада переключат при помочи указателя въизават необходимои функции.В самои функции прерервания ест толко переход к функции которъи указъивает указател и поетому не нада и регистръи сохранят.
Необходимъие регистри будут правилно сохраненъи и возтоновленнъие в самои функции,потому что они написанъие как функции перервания

Возможно и неправилно обяснил по руски.Вот пример в коде
Код
#pragma vector =  USART_TXC_vect
__interrupt void TXCinterrupt()               /// Так должно въиглядет само перервание
{
     pActiv_TXinterrupt_Function();   /// ето указател к функции
}


А сами функции должно въиглядет так
Код
#pragma vector =  XXXXXXXX_vect
__interrupt Funct1()
{
-----------
}
#pragma vector =  XXXXXXXX_vect
__interrupt Funct2()
{
-----------
}


сам указател декларирован так
Код
void (__interrupt * pActiv_TXinterrupt_Function)(void);




Нашел решение которъие работает.
pActiv_TXinterrupt_Function въизъиваю из асме.
для Funct1,Funct2 ползуюс из векторов перервании которъие не ползуется в програме.
Но ето мне не нравится и не хватют свободнъие вектор прерервания
VladislavS
Извини, но твоя проблема не стоит выеденного яица. Напиши весь код в теле обработчика прерывания и все. Неужели твои функции настолько ГИГАНТСКИЕ, что нельзя объединить? Не забывай - это прерывание и код должен быть очень коротким и быстрым. А если код обработчика прерывания настолько большой, что его проблемно сделать без функций, то насколько в процентном соотношении он увеличится от добавления сохранения в стек?
Nikola Kirov
VladislavS как думаеш сколко циклов уходят на переключение в тело обработчика етих 8-9 разнъе задач.
Время переключение соизмеримо с время въиполнения десиствия которъие нада въполнит.
Думаю что проблем ясно обяснил. И пример каторъи работает бъстро и как нада указал.
Вопрос как коректно сказат IAR-а что из него хочем.
prottoss
Вызовы функций внутри обработчика всегда приводят к сохранению множества регистров - об этом уже говорилось. На 70-80% помогает, если функции делать с директивой #inline forced.

Может вопрос не совсем в тему (или в принцип). А зачем переключать задачи. Не проще ли сделать через условие "if {.... } else {....}", а для вектора определить глобальную переменную, по которой он будет определять номер задачи. Осободятся регистры от хранения указателя адреса функции. Вместо 16-разрядных опций сравнения указателя будут 8-и разрядные и т.д.
Nikola Kirov
Цитата
Вместо 16-разрядных опций сравнения указателя будут 8-и разрядные и т.д.

protoss Възов функции через указател не приводит к никакие 16-разрядных опций сравнения.

Вообще вопрос очен сложнъи и решение может дат толко человек кто очен глубоко понимает IAR.

Опят скажу решение которое нашел работает,не сохраняет излишнее регистри,не теряет время на пререключения задач.
Если у вас мало задач ,можно восползоватся из него. Всегда ест свободнъие векторъи перервания.
Проблем что нада функции писат как перервания и ползаватся из свободнъие векторъи а у меня задач много и не хватают.
А и должно ест метод каторъи сделает все так и без използования свободнъих векторов и асмовъие вставки.
prottoss
Цитата(Nikola Kirov @ Oct 22 2005, 22:13)
Цитата
Вместо 16-разрядных опций сравнения указателя будут 8-и разрядные и т.д.

А и должно ест метод каторъи сделает все так и без използования свободнъих векторов и асмовъие вставки.
*



Могу предложить тебе один метод. Как всегда это только мысль, которую, скорее всего ты сможешь развить. Не буду писать на полнстью ASM, а напишу как алгоритм. И так:

1. Входим в прерывание (выполняем какие то действия)
2. Вычисляем адрес нужной нам функции
3. Загружаем в стек адрес перехода (например командой PUSH)
4. Выходим из прерывания.

Правда, здесь необходимо, иметь ввиду некоторые ньюансы.

Во первых писать вектор придется на ASM, т.к не вижу, как и где в Си вставить оператор asm("PUSH (HI)ptr"); asm ("PUSH (LO(ptr)"), да так, чтоб после него шла команда RETI.

Во вторых во время работы исполняемой после прерывания функции будут возникать другие разрешенные прерывание, в том числе и то, которое эту функцию вызвало, так что время выполнения функции ограничено минимальным периодом возникающего прерывания.

В третьих, нужно отслеживать,какие регистры сохранять в функции, потому как эту функцию компилятор за прерывание (и за вызываемую в прерывании)
считать не будет, соответственно не будет сохранять все задействованные в функции регистры, а только те, которые он посчитает нужными сохранить.

Вот такой расклад. Может быть все написанное выше, полный бред. Не судите сильно строго, это пришло мне в голову после сна :-) но до выполнения зарядки.
Nikola Kirov
Цитата
Может быть все написанное выше, полный бред. Не судите сильно строго, это пришло мне в голову после сна :-) но до выполнения зарядки.
*

Да так.
Если не сложно не мешаи в ету тему.
prottoss
Цитата(Nikola Kirov @ Oct 23 2005, 01:58)
Да так.
Если не сложно не мешаи в ету тему.


Как скажешь. Я больше не буду участвовать ни в одной твоей теме.
Виктория
To Nikola - все понятно, тогда думаю дальше blush.gif . Не может быть, что Ваша задача не решаема.

To VladislavS
Цитата(VladislavS @ Oct 20 2005, 18:11)
Цитата(BVU @ Oct 20 2005, 11:49)
в классических системах это делается немного по другому.  В теле Вашего прерывания должен находиться переход (call) на адрес расположенный в оперативной памяти (строго фиксировано), где размещается еще один вызов функции (переключение на функцию) адресс которой подставляется (настраивается в данный момент времени) в зависимости от логики работы программы. Так Вы получаете расширение ресурсов своего преравания.  Что касается скорости выполнения, то здесь теряется время на дополнительный вызов. На asm это реализуется просто, как это сделать корректно на 'C' - надо подумать.


С AVR это не пройдет, так как адресное пространство кода и данных раздельное и сегменты кода во flash лежать обычно.
*



Уточните, пожалуйста, вообще нет в системе команд - команд записи в сегменты кода или из-за того, что программа обычно во flash?
Виктория
Цитата(Nikola Kirov @ Oct 22 2005, 15:18)
Вот пример в коде
Код
#pragma vector =  USART_TXC_vect
__interrupt void TXCinterrupt()               /// Так должно въиглядет само перервание
{
     pActiv_TXinterrupt_Function();   /// ето указател к функции
}


А сами функции должно въиглядет так
Код
#pragma vector =  XXXXXXXX_vect
__interrupt Funct1()
{
-----------
}
#pragma vector =  XXXXXXXX_vect
__interrupt Funct2()
{
-----------
}


сам указател декларирован так
Код
void (__interrupt * pActiv_TXinterrupt_Function)(void);




Нашел решение которъие работает.
pActiv_TXinterrupt_Function въизъиваю из асме.
для Funct1,Funct2 ползуюс из векторов перервании которъие не ползуется в програме.
Но ето мне не нравится и не хватют свободнъие вектор прерервания
*


А зачем переключаемые 8 функций подвешивать на вектора прерываний? Как без asm-вызова обойтись - подумать еще надо cranky.gif . А вектора прерываний зачем использовать - разве нельзя указатель на обычную функцию? Или Вы таким образом хотите сохранить те регистры, которые внутри этих функций - непонятно cranky.gif
Nikola Kirov
Цитата
А зачем переключаемые 8 функций подвешивать на вектора прерываний? Как без asm-вызова обойтись - подумать еще надо cranky.gif . А вектора прерываний зачем использовать - разве нельзя указатель на обычную функцию? Или Вы таким образом хотите сохранить те регистры, которые внутри этих функций - непонятно cranky.gif


Прочтите внимателно что написал DXP когда обяснял разница между нормалние функции и функции перервания.
VladislavS
Цитата(Vic1 @ Oct 23 2005, 15:49)
Уточните, пожалуйста, вообще нет в системе команд - команд записи в сегменты кода или из-за того, что программа обычно во flash?
*


Команда записи в сегмент кода есть - процессор сам себя может перепрограммировать. Но, так как адресные пространства данных и кода раздельные, у контроллера в штатных режимах работы данные в RAM, а код во FLASH. AVR это вам не ARM, зато намного проще.
Виктория
Цитата(dxp @ Oct 21 2005, 10:05)
Прошу прощения, что вмешиваюсь. Тут все не так и все гораздо проще. IAR делит регистры на local и scratch. Первые - это регистры, которые в вызываемой функции компилятор может использовать только предварительно

....

Все остальные "финты ушами" вроде вызова функции через асмовую вставку - это быть самому себе злобным буратиной. В этом случае, когда возникнет прерывание и управление будет передано в функцию, которая не является ISR (т.к. компилятор не знает, что функция эта вызвана асинхронно по отношению к потоку управления), в этой функции будут без ограничений использоваться scratch регистры, значения которых, не будут сохранены (с последующим восстановлением). В результате огребете гору замечательных и труднопресказуемых глюков. Оно надо? Никогда ни в коем случае так делать нельзя. Если уж вызываете функцию без сохранения контекста компилятором, то делайте это сами руками. Такая необходимость может возникнуть при написании переключателя конткестов в вытесняющий RTOS.
*



Nikola, я имела в виду, то что подчеркнуто в QUOTE
Т.е. если уж Вы все-равно вынуждены использовать asm-вставку, то и делайте в ней сохранение регистров.
Плюсы - избавитесь от 8 вынужденно занимаемых векторов прерываний и число сохраняемых регистров при вызове по указателю можно уменьшить (т.е. сохраняются только те регистры, которые действительно используются в 8 переключаемых функций).
Минусы - необходимо знать, какие именно это регистры.

Это, если решение Вашей задачи на Си окажется невозможным.
Nikola Kirov
Решил проблем.
В фаила \src\template\cfgm16.xcl увеличил -D_..X_INTVEC_SIZE

Ето конечно в целости очен некрасивое решение но никто не предложил более приемливъи вариант.
Nikola Kirov
Никто ли не знает как ето написат как то нормалнее?
Old1
Цитата(Nikola Kirov @ Oct 20 2005, 02:04) *
Необходимо переключат функции которъе въизъиваются на перервание.
Сделал
extern __near void (* pTX_InterruptFunction)(void);

а сам interrupt
Код
#pragma vector = USART_TXC_vect
__interrupt void TXCinterrupt(void)
{
 pTX_InterruptFunction();
}


все работает но вот такое генерируется
Код
  \   00000000   93BA               ST      -Y, R27
  \   00000002   93AA               ST      -Y, R26
  \   00000004   938A               ST      -Y, R24
  \   00000006   93FA               ST      -Y, R31
  \   00000008   93EA               ST      -Y, R30
  \   0000000A   923A               ST      -Y, R3
  \   0000000C   922A               ST      -Y, R2
  \   0000000E   921A               ST      -Y, R1
  \   00000010   920A               ST      -Y, R0
  \   00000012   937A               ST      -Y, R23
  \   00000014   936A               ST      -Y, R22
  \   00000016   935A               ST      -Y, R21
  \   00000018   934A               ST      -Y, R20
  \   0000001A   933A               ST      -Y, R19
  \   0000001C   932A               ST      -Y, R18
  \   0000001E   931A               ST      -Y, R17
  \   00000020   930A               ST      -Y, R16
  \   00000022   B78F               IN      R24, 0x3F
    54            pTX_InterruptFunction();
  \   00000024   ....               LDI     R26, LOW(pTX_InterruptFunction)
  \   00000026   ....               LDI     R27, (pTX_InterruptFunction) >> 8
  \   00000028   91ED               LD      R30, X+
  \   0000002A   91FC               LD      R31, X
  \   0000002C   9509               ICALL
    55          }
  \   0000002E   BF8F               OUT     0x3F, R24
  \   00000030   9109               LD      R16, Y+
  \   00000032   9119               LD      R17, Y+
  \   00000034   9129               LD      R18, Y+
  \   00000036   9139               LD      R19, Y+
  \   00000038   9149               LD      R20, Y+
  \   0000003A   9159               LD      R21, Y+
  \   0000003C   9169               LD      R22, Y+
  \   0000003E   9179               LD      R23, Y+
  \   00000040   9009               LD      R0, Y+
  \   00000042   9019               LD      R1, Y+
  \   00000044   9029               LD      R2, Y+
  \   00000046   9039               LD      R3, Y+
  \   00000048   91E9               LD      R30, Y+
  \   0000004A   91F9               LD      R31, Y+
  \   0000004C   9189               LD      R24, Y+
  \   0000004E   91A9               LD      R26, Y+
  \   00000050   91B9               LD      R27, Y+
  \   00000052   9518               RETI

И как видно перервание становится медленое.
А мои функции совсем простенкие,такое сохранение регистров не нужно.
Явно что то не так делаю. Как правилно ето делат?

2 Nikola Kirov Если эта тема вам еще интересна, то сохранение регистров можно отключить используя квалификатор __raw при определении функции обработчика прерывания, или если он не поддерживается вашей версией компилятора можно еще попробовать __noreturn, правда сохранение регистров (если это требуется) тогда ложится на вас...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.