реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Closed TopicStart new topic
> __raw прерывания
fmdost
сообщение Jun 11 2007, 22:07
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 479
Регистрация: 8-05-07
Из: г. Ставрополь. Северный Кавказ. Россия
Пользователь №: 27 606



Доброго времени суток, подскажите pls как в прерывании перенести сохранение регистров по своему усмотрению. Мне нужно как можно быстрее дёрнуть ногой, а потом выполнить С код.

камень mega88;

__interrupt //Штатно сохраняет все далее используемые регистры.

// и только после этого
PORTx=1;

//~далее С код

==========
А надо так

__interrupt

PORTx=1;

//Штатно сохранить все далее используемые регистры.
//~С код

В асме так делается очень часто, в описании на IAR и на CAVR нашёл только __raw, но он не сохраняет регистры вообще.
Go to the top of the page
 
+Quote Post
rezident
сообщение Jun 11 2007, 22:50
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Вам в пустыне уже все разжевали, теперь еще и тут та же пестня?
Ну вот вам пример. Правда для MSP430, т.к. ИАР для АВР не имею.
Исходный текст функции перывания.
Код
extern float calcBlaBla (float a_data, float b_data, float c_data);

#pragma vector = WDT_VECTOR
__interrupt __raw void WDTimer_ISR(void)
{ P1OUT^=BIT0;
  float tmp=calcBlaBla(1.0, 4.0, 2.0);
  printf("%f0.3", tmp);
}

А вот во что его скомпилировал ИАР.
Код
      49          #pragma vector = WDT_VECTOR

   \                                 In segment CODE, align 2
     50          __interrupt __raw void WDTimer_ISR(void)
   \                     WDTimer_ISR:
     51          { P1OUT^=BIT0;
   \   000000   D2E32100     XOR.B   #0x1, &0x21
     52            float tmp=calcBlaBla(1.0, 4.0, 2.0);
   \   000004   30120040     PUSH.W  #0x4000
   \   000008   0312         PUSH.W  #0x0
   \   00000A   0E43         MOV.W   #0x0, R14
   \   00000C   3F408040     MOV.W   #0x4080, R15
   \   000010   0C43         MOV.W   #0x0, R12
   \   000012   3D40803F     MOV.W   #0x3f80, R13
   \   000016   B012....     CALL    #calcBlaBla
     53            printf("%f0.3", tmp);
   \   00001A   0D12         PUSH.W  R13
   \   00001C   0C12         PUSH.W  R12
   \   00001E   3C40....     MOV.W   #`?<Constant "%f0.3">`, R12
   \   000022   B012....     CALL    #printf
     54          }
   \   000026   3152         ADD.W   #0x8, SP
   \   000028   0013         RETI

Как вы можете заметить в прерывании первой командой (XOR.B #0x1, &0x21) дергается нога контроллера P1.0 (инвертируется ее состояние). Потом в стек пихаются значения для функции calcBlaBla и вызывается сама функция. Затем вызывается printf. Стек выравнивается, т.к. все возвращаемые значения не используются. Дальше возврат из прерывания.
То что вам нужно, не так ли? wink.gif
Кстати, зачем вам нужно сохранять ВСЕ регистры? Мне это не понятно. Компилятор сохраняет в стеке только те из них, которые используются в вызываемой функции.
Go to the top of the page
 
+Quote Post
fmdost
сообщение Jun 11 2007, 23:10
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 479
Регистрация: 8-05-07
Из: г. Ставрополь. Северный Кавказ. Россия
Пользователь №: 27 606



Это СОВСЕМ не то что мне нужно, тк он НЕ СОХРАНИЛ используемые регистры. Все сохранять не надо, только те что компилятор юзает ДАЛЕЕ . Ваша программа дальше работать НЕ БУДЕТ! А в пустыне ничего кроме флуда небыло.

Сообщение отредактировал Т.Достоевский - Jun 11 2007, 23:36
Go to the top of the page
 
+Quote Post
rezident
сообщение Jun 11 2007, 23:32
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Опс! Ну да. Вы правы. Я забыл что это прерывание, а не простая функция sad.gif
Выходит что способ только один: писать начало обработчика прерывания на АСМе и включать остальную часть в виде вызова Си-ной функции. Это на тот случай, если не хочется ВЕСЬ обработчик на АСМе писать.
Go to the top of the page
 
+Quote Post
fmdost
сообщение Jun 11 2007, 23:39
Сообщение #5


Местный
***

Группа: Свой
Сообщений: 479
Регистрация: 8-05-07
Из: г. Ставрополь. Северный Кавказ. Россия
Пользователь №: 27 606



Но тогда придётся сохранять юзанные регистры ручками. Ни никогда больше не трогать С-шный обработчик. А что такой возможности в embedded средах нет, НЕВЕРЮ! Кстати про __raw есть только в пдф на мср, на авр нет! Проверял через поиск! Хотя работает.
Кстати у меня есть знакомый, крутой переводчик, как я ранише о нём не подумал. Сообщу что скажут на иаре!

Сообщение отредактировал Т.Достоевский - Jun 11 2007, 23:52
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 12 2007, 06:34
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Т.Достоевский @ Jun 12 2007, 02:39) *
А что такой возможности в embedded средах нет, НЕВЕРЮ!
А зря.
Цитата(Т.Достоевский @ Jun 12 2007, 02:39) *
Кстати про __raw есть только в пдф на мср, на авр нет!
Там оно называется или __task или __C_task.
Цитата(Т.Достоевский @ Jun 12 2007, 02:39) *
Проверял через поиск!
Почему бы вам просто не прочитать весь раздел описания, посвященный ключевым словам?
Цитата(Т.Достоевский @ Jun 12 2007, 02:39) *
Хотя работает.
Или наоборот, не работает, просто не вызывает ошибок при компиляции?
Ваша ошибка в самом алгоритме, вам на нее =AVR= на сахаре намекал. Вам надо подготовительную часть кода выполнить не в начале, а в конце прерывания:
Код
__interrupt
{
    std rxx,-Y //мк сохраняет все регистры используемые далее в С
    ~~~~~
    std rxx,-Y
    PORTx.y =1;//защелкнуть в защелке
    __enable_interrupt(); // уже можно разрешить вложенные

    //подготовить новый data
    PORTx.y =0;
    PORTxx=data;
}
А вообще прислушайтесь к тому, что говорит rezideent - Если у вас проблемы с индикацией от джиттера в несколько тактов, то надо менять алгоритм (или вообще ваш подход к построению алгоритмов), а не пытаться насиловать компилятор.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Jun 12 2007, 07:37
Сообщение #7


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Цитата(Т.Достоевский @ Jun 12 2007, 02:39) *
... про __raw есть только в пдф на мср, на авр нет! Проверял через поиск! Хотя работает.
...

Эта информация есть в /avr/doc/manuals.htm т. к. она новая, то в pdf ещё не вошла.

Цитата(Сергей Борщ @ Jun 12 2007, 09:34) *
...Там оно называется или __task или __C_task...

Это из другой оперы.
__task или __C_task работают с простыми функциями, а не с прерываниями, а для прерываний существует как раз __raw.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 12 2007, 10:30
Сообщение #8


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(IgorKossak @ Jun 12 2007, 10:37) *
Это из другой оперы.
__task или __C_task работают с простыми функциями, а не с прерываниями, а для прерываний существует как раз __raw.
Да, каюсь, "с прямым углом спутал". __raw появилось в EWAVR c версии 4.12


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
fmdost
сообщение Jun 12 2007, 11:29
Сообщение #9


Местный
***

Группа: Свой
Сообщений: 479
Регистрация: 8-05-07
Из: г. Ставрополь. Северный Кавказ. Россия
Пользователь №: 27 606



"Ваша ошибка в самом алгоритме, вам на нее =AVR= на сахаре намекал. Вам надо подготовительную часть кода выполнить не в начале, а в конце прерывания:"

Да Я же иак И ДЕЛАЮ!!!!!!!!!!! Просто эти 25 тактов сохранения в НАЧАЛЕ "__ interrupt" не дают погасить индикатор через tc_compa!!!
И получается мерцание на малой яркости.

"А что такой возможности в embedded средах нет, НЕВЕРЮ!
А зря."


А нафига они тогда нужны? =AVR= про грабли прав ? Эта вещь применяется ОЧЕНЬ часто, например:

push r16
in r16,SREG
push r16 //push SREG

sts r16,data
oit PORT,r16

;а дальше сохраняем всё что нужно далее
;получаем новый data то биш новую цифру для индикатора, благо не много, не в main же его!!!

pop ~~~ всё

reti

//за кого вы меня держите?

Сообщение отредактировал Т.Достоевский - Jun 12 2007, 11:36
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 12 2007, 12:46
Сообщение #10


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Т.Достоевский @ Jun 12 2007, 14:29) *
А нафига они тогда нужны? =AVR= про грабли прав ?
Не понял что такое "про грабли" - если вы имеете ввиду его фанатичную агитацию за асм, то нет. Но это отдельная тема и общаться об этом, а тем более с этим "божеством" я не имею желания. Поверьте, многими участниками этой конференции написано множество программ, и если у кого-то и возникала необходимость в подобных извращениях, то только не в таких простых задачах как динамическая индикация.
Цитата(Т.Достоевский @ Jun 12 2007, 14:29) *
Эта вещь применяется ОЧЕНЬ часто, например:
так и сделайте свое прерывание максимально коротким:
Код
__interrupt void UpdateRoutine()
{
    PORT = data;
}
Думаю что даже при отсутствии оптимизации получите искомый код с сохранением одного регистра.
Цитата(Т.Достоевский @ Jun 12 2007, 14:29) *
//за кого вы меня держите?
За человека, который задал вопрос, но в упор не слышит ответ что проблему надо решать иначе.
Много раз вам отвечали - нет, нельзя заставить компилятор сохранить лишь часть контекста до выполнения основной работы. Можно запретить сохранять контекст вообще, но тогда вам придется сохранять его самостоятельно когда захотите при помощи "обертки" на ассемблере и принять на себя всю ответственность за возможные "глюки".

Я не знаю что такое tc_compa и мне трудно понять, как постоянное смещение на N тактов начала обработки _каждого_ прерывания обновления индикатора относительно момента запуска контроллера может вызвать сбои индикации. Давайте вы нам расскажете более подробно обо всем алгоритме вашей индикации, а мы поможем вам изменить его так, чтобы без подобных затруднений все работало независимо от времени сохранения контекста.

P.S. и постарайтесь использовать общепринятую на этом форуме форму цитирования.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
fmdost
сообщение Jun 12 2007, 13:58
Сообщение #11


Местный
***

Группа: Свой
Сообщений: 479
Регистрация: 8-05-07
Из: г. Ставрополь. Северный Кавказ. Россия
Пользователь №: 27 606



Принцип такой tc0 это прерывание по переполнению
tc0_compa это прерывание по сравнению, с tco
тс0 0-255 как досчитал так прерывание, и с 0 и тд.
tc0_compa любое число 0-255 как только tc0=tc0_compa так прерывание.
tc0 используется для зажигания цифры
тс0_compa для гашения(автоматическая регулировка яркости). Вот тут то и загвоздка! При малых значениях tc_compa заметен "муар" на индикаторе.

Ещё раз повторю что, программа есть на асме. И прерывание там значительно длиннее по времени чем на С (На С я и так уже выкинул всё что мог). Но она пока отличает только круглое от квадратного(типа распознование формы). Одному такие задачи делать тяжело. Поэтому я хотел сделать всё на С чтобы получить помощь знакомого, специалиста по этим вопросам, который чистый С-ишник, и ему не надо знать систему каких то команд. То есть, сделать что-то типа АПИ.

Насчёт иара. Если там нет вещей которые применяются в 60% случаев, то возникает вопрес о целесообразности применения подобных сред. Поэтому НЕВЕРЮ.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jun 12 2007, 13:59
Сообщение #12


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Т.Достоевский @ Jun 12 2007, 03:39) *
Но тогда придётся сохранять юзанные регистры ручками. Ни никогда больше не трогать С-шный обработчик. А что такой возможности в embedded средах нет, НЕВЕРЮ!

Цитата(Сергей Борщ @ Jun 12 2007, 10:34) *
А зря.

Вы это о чем ? 07.gif

Есть очень простое решение...
Нужное прерывание описываем на ASM.
Функцию на С которая должна выполнятся дальше описываем как любое
гарантировано незадействованное прерывание.
В нужном нам прерывании дергаем ногой (сохраняя/восстанавливая если нужно SREG) и дальше
прыгаем jmp на адрес нашего "фиктивного" прерывания(функции). Все. smile.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 12 2007, 14:57
Сообщение #13


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Т.Достоевский @ Jun 12 2007, 16:58) *
Вот тут то и загвоздка! При малых значениях tc_compa заметен "муар" на индикаторе.
Занесите в tc_compa значение на "лишние" 5-10-20 (сколько там вам не хватает тактов) меньше. Прерывание будет возникать на столько же тактов раньше. "Муар" изчез? Нет. Вывод - виновата не _константная_ задержка, которая возникает из-за сохранения контекста, а джиттер, который возникает из-за того, что в момент возникновения этого прерывания обрабатывалось другое прерывание или какой-либо другой кусок кода, во время которого прерывания запрещены. Копайте там. Или используйте вывод compa, который формируется аппаратно и не зависит от запрета/разрешения прерываний. Не верите - сделайте как написал singlskv и убедитесь.
Цитата(Т.Достоевский @ Jun 12 2007, 16:58) *
Ещё раз повторю что, программа есть на асме. И прерывание там значительно длиннее по времени чем на С (На С я и так уже выкинул всё что мог).
А я вам повторю, что _константная_ задержка в этом месте не виновата.
Цитата(Т.Достоевский @ Jun 12 2007, 16:58) *
Насчёт иара. Если там нет вещей которые применяются в 60% случаев, то возникает вопрес о целесообразности применения подобных сред. Поэтому НЕВЕРЮ.
Вопрос о целесообразности каждый решает для себя сам. Вы можете решить его в пользу асма. Раз там нет таких вещей, значит ваша цифра 60% завышена как минимум на два порядка. Делайте выводы.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
fmdost
сообщение Jun 12 2007, 15:56
Сообщение #14


Местный
***

Группа: Свой
Сообщений: 479
Регистрация: 8-05-07
Из: г. Ставрополь. Северный Кавказ. Россия
Пользователь №: 27 606



Вы совеошенно правы прерывание мешает другое (адс) а это привёл как пример. В преврывании от адс вообше запрещать ничего не надо, лиш обозначить. Не в майне же флаги опрашивать. Напишу на иар. Если скажут что так нельзя присоединюсь к =АВР= тк. в этом случае ИАР это фикция. Не зря же в mcs51 80 годов разработки 4 приоритета прерыаний.

Цитата(singlskv @ Jun 12 2007, 17:59) *
Вы это о чем ? 07.gif

Есть очень простое решение...
Нужное прерывание описываем на ASM.
Функцию на С которая должна выполнятся дальше описываем как любое
гарантировано незадействованное прерывание.
В нужном нам прерывании дергаем ногой (сохраняя/восстанавливая если нужно SREG) и дальше
прыгаем jmp на адрес нашего "фиктивного" прерывания(функции). Все. smile.gif


Вот это пожалуйста поподробней!!! Так и пытался сделать но не пойму с синтаксисом (в С новичок). Не принимает он у меня jmp через функцию.

Сообщение отредактировал Т.Достоевский - Jun 12 2007, 15:58
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jun 12 2007, 16:05
Сообщение #15


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Сергей Борщ @ Jun 12 2007, 18:57) *
Не верите - сделайте как написал singlskv и убедитесь.

Если честно, я вобще не вникал в суть алгоритма/проблемы автора smile.gif
На сахаре автар попросил не вникать 07.gif

А вобще как-то это все странно, 25 лишних тактов и уже мерцание...

Афтар, приведите минимальный код в котором будет эта проблема
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Closed TopicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 28th May 2024 - 03:43
Рейтинг@Mail.ru


Страница сгенерированна за 0.01532 секунд с 7
ELECTRONIX ©2004-2016