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

камень mega88;

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

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

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

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

__interrupt

PORTx=1;

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

В асме так делается очень часто, в описании на IAR и на CAVR нашёл только __raw, но он не сохраняет регистры вообще.
rezident
Вам в пустыне уже все разжевали, теперь еще и тут та же пестня?
Ну вот вам пример. Правда для 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
Кстати, зачем вам нужно сохранять ВСЕ регистры? Мне это не понятно. Компилятор сохраняет в стеке только те из них, которые используются в вызываемой функции.
fmdost
Это СОВСЕМ не то что мне нужно, тк он НЕ СОХРАНИЛ используемые регистры. Все сохранять не надо, только те что компилятор юзает ДАЛЕЕ . Ваша программа дальше работать НЕ БУДЕТ! А в пустыне ничего кроме флуда небыло.
rezident
Опс! Ну да. Вы правы. Я забыл что это прерывание, а не простая функция sad.gif
Выходит что способ только один: писать начало обработчика прерывания на АСМе и включать остальную часть в виде вызова Си-ной функции. Это на тот случай, если не хочется ВЕСЬ обработчик на АСМе писать.
fmdost
Но тогда придётся сохранять юзанные регистры ручками. Ни никогда больше не трогать С-шный обработчик. А что такой возможности в embedded средах нет, НЕВЕРЮ! Кстати про __raw есть только в пдф на мср, на авр нет! Проверял через поиск! Хотя работает.
Кстати у меня есть знакомый, крутой переводчик, как я ранише о нём не подумал. Сообщу что скажут на иаре!
Сергей Борщ
Цитата(Т.Достоевский @ 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 - Если у вас проблемы с индикацией от джиттера в несколько тактов, то надо менять алгоритм (или вообще ваш подход к построению алгоритмов), а не пытаться насиловать компилятор.
IgorKossak
Цитата(Т.Достоевский @ Jun 12 2007, 02:39) *
... про __raw есть только в пдф на мср, на авр нет! Проверял через поиск! Хотя работает.
...

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

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

Это из другой оперы.
__task или __C_task работают с простыми функциями, а не с прерываниями, а для прерываний существует как раз __raw.
Сергей Борщ
Цитата(IgorKossak @ Jun 12 2007, 10:37) *
Это из другой оперы.
__task или __C_task работают с простыми функциями, а не с прерываниями, а для прерываний существует как раз __raw.
Да, каюсь, "с прямым углом спутал". __raw появилось в EWAVR c версии 4.12
fmdost
"Ваша ошибка в самом алгоритме, вам на нее =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, 14:29) *
А нафига они тогда нужны? =AVR= про грабли прав ?
Не понял что такое "про грабли" - если вы имеете ввиду его фанатичную агитацию за асм, то нет. Но это отдельная тема и общаться об этом, а тем более с этим "божеством" я не имею желания. Поверьте, многими участниками этой конференции написано множество программ, и если у кого-то и возникала необходимость в подобных извращениях, то только не в таких простых задачах как динамическая индикация.
Цитата(Т.Достоевский @ Jun 12 2007, 14:29) *
Эта вещь применяется ОЧЕНЬ часто, например:
так и сделайте свое прерывание максимально коротким:
Код
__interrupt void UpdateRoutine()
{
    PORT = data;
}
Думаю что даже при отсутствии оптимизации получите искомый код с сохранением одного регистра.
Цитата(Т.Достоевский @ Jun 12 2007, 14:29) *
//за кого вы меня держите?
За человека, который задал вопрос, но в упор не слышит ответ что проблему надо решать иначе.
Много раз вам отвечали - нет, нельзя заставить компилятор сохранить лишь часть контекста до выполнения основной работы. Можно запретить сохранять контекст вообще, но тогда вам придется сохранять его самостоятельно когда захотите при помощи "обертки" на ассемблере и принять на себя всю ответственность за возможные "глюки".

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

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

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

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

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

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

Есть очень простое решение...
Нужное прерывание описываем на ASM.
Функцию на С которая должна выполнятся дальше описываем как любое
гарантировано незадействованное прерывание.
В нужном нам прерывании дергаем ногой (сохраняя/восстанавливая если нужно SREG) и дальше
прыгаем jmp на адрес нашего "фиктивного" прерывания(функции). Все. smile.gif
Сергей Борщ
Цитата(Т.Достоевский @ 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% завышена как минимум на два порядка. Делайте выводы.
fmdost
Вы совеошенно правы прерывание мешает другое (адс) а это привёл как пример. В преврывании от адс вообше запрещать ничего не надо, лиш обозначить. Не в майне же флаги опрашивать. Напишу на иар. Если скажут что так нельзя присоединюсь к =АВР= тк. в этом случае ИАР это фикция. Не зря же в mcs51 80 годов разработки 4 приоритета прерыаний.

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

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


Вот это пожалуйста поподробней!!! Так и пытался сделать но не пойму с синтаксисом (в С новичок). Не принимает он у меня jmp через функцию.
singlskv
Цитата(Сергей Борщ @ Jun 12 2007, 18:57) *
Не верите - сделайте как написал singlskv и убедитесь.

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

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

Афтар, приведите минимальный код в котором будет эта проблема
fmdost
Цитата(singlskv @ Jun 12 2007, 20:05) *
Если честно, я вобще не вникал в суть алгоритма/проблемы автора smile.gif
На сахаре автар попросил не вникать 07.gif

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

Афтар, приведите минимальный код в котором будет эта проблема


http://caxapa.ru/90428.html + прерывание от адц с размешением в память 32 байт и выставлением флага.
singlskv
Цитата(Т.Достоевский @ Jun 12 2007, 19:56) *
Вот это пожалуйста поподробней!!! Так и пытался сделать но не пойму с синтаксисом (в С новичок). Не принимает он у меня jmp через функцию.

jmp на АСМе на абсолютный адрес где лежит jmp "фиктивного" обработчика(нужной С функции).
На С скорее всего такой трюк (jmp) описать не получится, тк нужно сохранять/восстанавливать
используемые для этого регистры
fmdost
Цитата(singlskv @ Jun 12 2007, 20:15) *
jmp на АСМе на абсолютный адрес где лежит jmp "фиктивного" обработчика(нужной С функции).
На С скорее всего такой трюк (jmp) описать не получится, тк нужно сохранять/восстанавливать
используемые для этого регистры

Получится, если фиктивное сделать без __raw. Не получается абсолютный адрес, нету такой, есть только относительный RJMP.
Если сделать так то и асма не нужно тк С код будет соизмерим. Но не вызывает он функции обозначенные как __interrupt!
singlskv
по Вашей ссылке прерывания ADC не увидел, дальше не копал
Цитата(Т.Достоевский @ Jun 12 2007, 20:19) *
Получится, если фиктивное сделать без __raw.
Дык __raw подразумевает сохранение ручками
Цитата
Если сделать так то и асма не нужно тк С код будет соизмерим. Но не вызывает он функции обозначенные как __interrupt!

конечно не вызывает, interrupt это не функция
там прокатит только абсолютный jmp
можете его в ASM обработчике через DB xx, xx написать
fmdost
В том то и дело, в меге нету абсолютного jmp!. Пытаюсь сделать как на асме, RJMP метка. Ассемблер сам вычисляет смещение. Вот и думаю как эту метку на С записать чтоб то-же сам вычислял.
slog
Ты и тут уже :-)

__indirect_jump_to((unsigned long)&Имя_функции);

Стек может испортиться, надо смотреть что компилятор наделает, и если что исправлять.
fmdost
Цитата(slog @ Jun 12 2007, 21:11) *
Ты и тут уже :-)
__indirect_jump_to((unsigned long)&Имя_функции);

Стек может испортиться, надо смотреть что компилятор наделает, и если что исправлять.


Вот это уже интерестней.

А Я везде, просто не знал что иар это игрушка
singlskv
Цитата(Т.Достоевский @ Jun 12 2007, 21:15) *
Вот это уже интерестней.

А Я везде, просто не знал что иар это игрушка

не...,
inderect jump для прерываний не прокатит
скорее смотри на:
_OPC(opCode)
ну или что то же самое на __insert_opcode(opCode)
rezident
Цитата(singlskv @ Jun 12 2007, 23:21) *
не...,
inderect jump для прерываний не прокатит
скорее смотри на:
_OPC(opCode)
ну или что то же самое на __insert_opcode(opCode)

В ИАР же вроде стандартная Сишная директива asm работает
Т.Достоевский, попробуйте так
Код
#pragma vector=TIMER_VECTOR
__interrupt __raw void Timer_ISR(void)
{  PORTx=1;
    asm("PUSH R31");
    asm("PUSH R30");
    asm("PUSH R29");
    ....
    funcBlaBlaBla();
    ...
    asm("POP R29");
    asm("POP R30");
    asm("POP R31");
}
fmdost
Цитата(slog @ Jun 12 2007, 21:11) *
__indirect_jump_to((unsigned long)&Имя_функции);

Уиточни пожалуйста мнемонику. Особенно если вместо имя функции прямой адрес. А то я уже час буквы гоняю.

Цитата(rezident @ Jun 12 2007, 23:57) *
В ИАР же вроде стандартная Сишная директива asm работает
Т.Достоевский, попробуйте так
Код
#pragma vector=TIMER_VECTOR
__interrupt __raw void Timer_ISR(void)
{  PORTx=1;
    asm("PUSH R31");
    asm("PUSH R30");
    asm("PUSH R29");
    ....
    funcBlaBlaBla();
    ...
    asm("POP R29");
    asm("POP R30");
    asm("POP R31");
}

все сохранять не нужно, а не все, тогда обработчик нельзя больше трогать, но скорее всего ПРИДЁТСЯ. В этом то и соль что придётся трогать не мне. Так бы я его на асме уже-б давно....
rezident
Цитата(Т.Достоевский @ Jun 13 2007, 02:14) *
все сохранять не нужно, а не все, тогда обработчик нельзя больше трогать, но скорее всего ПРИДЁТСЯ. В этом то и соль что придётся трогать не мне. Так бы я его на асме уже-б давно....

Все регистры сохранить "про запас" и обработчик больше не трогать. А "трогать" вашему коллеге "чистому Сишнику" нужно только лишь функцию funcBlaBlaBla.
fmdost
__indirect_jump_to((unsigned long)&Имя_функции);
__indirect_jump_to((unsigned long) 0x000001);
Не хочет у меня есть эти вещи. Но не ругается если просто __indirect_jump_to(unsigned long); Чего я опять не так делаю?
slog
Незнаю

#pragma vector = TIMER0_OVF0_vect
__interrupt __raw
void T0ovf(void)
{
PORTA=tmp;
__indirect_jump_to(0x0001);
}

компилируется в (листинг)

21 __interrupt __raw
22 void T0ovf(void)
\ T0ovf:
23 {
\ 00000000 REQUIRE ?Register_R15_is_global_regvar
24 PORTA=tmp;
\ 00000000 BAFB OUT 0x1B, R15
25 __indirect_jump_to(0x0001);
\ 00000002 E0E1 LDI R30, 1
\ 00000004 E0F0 LDI R31, 0
\ 00000006 9409 IJMP
26 }
Сергей Борщ
Цитата(Т.Достоевский @ Jun 12 2007, 23:49) *
Не хочет у меня есть эти вещи. Но не ругается если просто __indirect_jump_to(unsigned long); Чего я опять не так делаю?
Подозреваю, что не включили заголовочный файл, в котором находится объявление функции __indirect_jump_to(). Изучайте, чем вызов функции отличается от ее объявления и чем объявление функции отличается от ее определения.
Rst7
Делаю так обычно, ужос конечно, но что поделать:

в .c
Код
#pragma vector=0x0E //Неиспользуемый вектор
__interrupt void doADC(void)
{
  char c=OCR1B;
  //  unsigned int d;
//  __enable_interrupt();
  switch(ADCstate)
  {
  default:
....
и далее


в .asm (тоже подключен к проекту)
Код

        RSEG CODE:CODE:NOROOT(1)
intADC:
        SEI
        EXTERN doADC
        RJMP doADC

        COMMON INTVEC:CODE:ROOT(1)
        ORG 22
        RJMP    intADC
        END


соответственно в асм можно вставить быстрый код

И даже еще проще и лучше, без доп. асмов
Код
#include "iom8.h"
#include "inavr.h"


//Также в настройках проекта запретить линкеру диагностику w22
#pragma diag_suppress=Ta006
__interrupt void IntLong(void)
{
  __no_operation();
  __no_operation();
  __no_operation();
  __no_operation();
  __no_operation();
  __no_operation();
}
#pragma diag_default=Ta006

#pragma vector=TIMER1_OVF_vect
__raw __interrupt void I1(void)
{
  __enable_interrupt();
  ((void (*)(void))IntLong)();
}

int main( void )
{
  return 0;
}


Код
      1          #include "iom8.h"
      2          #include "inavr.h"
      3          
      4          
      5          //Также линкеру запретить w22
      6          #pragma diag_suppress=Ta006

   \                                 In segment CODE, align 2, keep-with-next
      7          __interrupt void IntLong(void)
   \                     IntLong:
      8          {
      9            __no_operation();
   \   00000000   0000               NOP
     10            __no_operation();
   \   00000002   0000               NOP
     11            __no_operation();
   \   00000004   0000               NOP
     12            __no_operation();
   \   00000006   0000               NOP
     13            __no_operation();
   \   00000008   0000               NOP
     14            __no_operation();
   \   0000000A   0000               NOP
     15          }
   \   0000000C   9518               RETI
     16          #pragma diag_default=Ta006
     17          
     18          #pragma vector=TIMER1_OVF_vect

   \                                 In segment CODE, align 2, keep-with-next
     19          __raw __interrupt void I1(void)
   \                     I1:
     20          {
     21            __enable_interrupt();
   \   00000000   9478               SEI
     22            ((void (*)(void))IntLong)();
   \   00000002   ....               RCALL   IntLong
     23          }
   \   00000004   9518               RETI
     24          

   \                                 In segment CODE, align 2, keep-with-next
     25          int main( void )
   \                     main:
     26          {
     27            return 0;
   \   00000000   E000               LDI     R16, 0
   \   00000002   E010               LDI     R17, 0
   \   00000004   9508               RET
     28          }

   \                                 In segment INTVEC, offset 0x10, root
   \                     `??I1??INTVEC 16`:
   \   00000010   ....               RJMP    I1


Но все это костыли, применение которых должно быть оправдано на 150% и им не место в обычных проектах.

И вот расширенный вариант, из которого все виднее

Код
#include "iom8.h"
#include "inavr.h"
#include "string.h"


//Также линкеру запретить w22
#pragma diag_suppress=Ta006
__interrupt void IntLong(void)
{
  strcmp("abc","def");
}
#pragma diag_default=Ta006

#pragma vector=TIMER1_OVF_vect
__raw __interrupt void I1(void)
{
  __enable_interrupt();
  PORTB|=0x1;
  ((void (*)(void))IntLong)();
}

int main( void )
{
  return 0;
}


Код
      1          #include "iom8.h"

   \                                 In segment ABSOLUTE, at 0x38
   \   union <unnamed> volatile __io _A_PORTB
   \                     _A_PORTB:
   \   00000000                      DS 1
      2          #include "inavr.h"
      3          #include "string.h"
      4          
      5          
      6          //Также линкеру запретить w22
      7          #pragma diag_suppress=Ta006

   \                                 In segment CODE, align 2, keep-with-next
      8          __interrupt void IntLong(void)
   \                     IntLong:
      9          {
   \   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
     10            strcmp("abc","def");
   \   00000020   ....               LDI     R18, LOW((`?<Constant "abc">` + 4))
   \   00000022   ....               LDI     R19, HIGH((`?<Constant "abc">` + 4))
   \   00000024   ....               LDI     R16, LOW(`?<Constant "abc">`)
   \   00000026   ....               LDI     R17, (`?<Constant "abc">`) >> 8
   \   00000028   ....               RCALL   strcmp
     11          }
   \   0000002A   BF8F               OUT     0x3F, R24
   \   0000002C   9109               LD      R16, Y+
   \   0000002E   9119               LD      R17, Y+
   \   00000030   9129               LD      R18, Y+
   \   00000032   9139               LD      R19, Y+
   \   00000034   9149               LD      R20, Y+
   \   00000036   9159               LD      R21, Y+
   \   00000038   9169               LD      R22, Y+
   \   0000003A   9179               LD      R23, Y+
   \   0000003C   9009               LD      R0, Y+
   \   0000003E   9019               LD      R1, Y+
   \   00000040   9029               LD      R2, Y+
   \   00000042   9039               LD      R3, Y+
   \   00000044   91E9               LD      R30, Y+
   \   00000046   91F9               LD      R31, Y+
   \   00000048   9189               LD      R24, Y+
   \   0000004A   9518               RETI
     12          #pragma diag_default=Ta006
     13          
     14          #pragma vector=TIMER1_OVF_vect

   \                                 In segment CODE, align 2, keep-with-next
     15          __raw __interrupt void I1(void)
   \                     I1:
     16          {
     17            __enable_interrupt();
   \   00000000   9478               SEI
     18            PORTB|=0x1;
   \   00000002   9AC0               SBI     0x18, 0x00
     19            ((void (*)(void))IntLong)();
   \   00000004   ....               RCALL   IntLong
     20          }
   \   00000006   9518               RETI
fmdost
Цитата(Сергей Борщ @ Jun 13 2007, 11:07) *
Подозреваю, что не включили заголовочный файл, в котором находится объявление функции __indirect_jump_to(). Изучайте, чем вызов функции отличается от ее объявления и чем объявление функции отличается от ее определения.

Оказалось проще, надо комп перегрузить.

Цитата(Rst7 @ Jun 13 2007, 12:12) *
Делаю так обычно, ужос конечно, но что поделать:

Супер!!! То что надо!!!!!!!! Огромное СПАСИБО!!!
IgorKossak
Цитата(Т.Достоевский @ Jun 13 2007, 12:50) *
Супер!!! То что надо!!!!!!!! Огромное СПАСИБО!!!

Так у Вас получилось что хотели в итоге или просто понравилось?
fmdost
Цитата(IgorKossak @ Jun 13 2007, 18:19) *
Так у Вас получилось что хотели в итоге или просто понравилось?

И понравилось и получилось. Особенно то что я не один работаю с реалтайм. Использовал раньше ijmp z, прямо на "фиктивный" вектор, теперь можно средствами "чистого С". Хотя странно почему такого в иаре нет . Подождём что иар ответит.
IgorKossak
Цитата(Т.Достоевский @ Jun 13 2007, 20:02) *
...Хотя странно почему такого в иаре нет . Подождём что иар ответит.

Не понятно, разве Rst7 не по ИАРу ответил или не на "чистом" С?
И как Вы собираетесь от ИАРа ответ получить? По моему они отвечают только зарегистрированным пользователям и на запросы, адресованные именно к ним по почте (здесь они врядли идеи черпают cool.gif ).
fmdost
Цитата(IgorKossak @ Jun 13 2007, 22:21) *
Не понятно, разве Rst7 не по ИАРу ответил или не на "чистом" С?
И как Вы собираетесь от ИАРа ответ получить? По моему они отвечают только зарегистрированным пользователям и на запросы, адресованные именно к ним по почте (здесь они врядли идеи черпают cool.gif ).

Я на С новичок, но мне кажется что ((void (*) (void deceit_int)(); это "чистый С" хотя и не катит в CAVR

А С иаром wink.gif "голь на выдумки хитра" Чай то-же на географическом говорят beer.gif . Ответят.
SasaVitebsk
Извините, что я вмешиваюсь в столь лихо закрученную тему. Но если у Вас дрожание происходит из-за другого прерывания (по ADC), то я Вам предложу несколько, на мой взгляд более простых решений. И именно в рамках IAR. Попробуйте их сделать.

1) Самое простое и возможно эффективное. Во всяком случае Вам не придётся ломать программу.
Первой командой прерывания ADC введите __enable_interrupt();

2) По скольку динамическая индикация - вещь явно периодическая, а АЦП Вы явно вызываете по таймеру или привязываете его ко времени другим способом, то выкиньте вообще прерывание по ADC. Работайте следующим образом.
В начале прерывания динамической индикации - считываете предыдущее значение АЦП. В конце меняете канал и запускаете следующее измерение.
Если время опроса АЦП у вас меньше времени регенерации - то вызывайте регенерацию по N-ному прерыванию от АЦП.


Можно и ещё предложений много сделать. Главное, чтобы моя мысль до Вас дошла. За всю жизнь мне не разу не приходилось делать прерывание от АЦП. Сложно даже представить себе ситуацию когда это нужно. Как и прерывание от SPI передачи. Малоэффективно. Потери на обработку прерывания велики по сравнению с ожиданием результата. Рекомендую применять синхронное чтение, когда результат - гарантировано будет получен.


Извиняюсь, если я не правильно оценил задачу и ответил не на Ваши вопросы. smile.gif
fmdost
Цитата(SasaVitebsk @ Jun 14 2007, 00:20) *
Извините, что я вмешиваюсь в столь лихо закрученную тему. Но если у Вас дрожание происходит из-за другого прерывания (по ADC), то я Вам предложу несколько, на мой взгляд более простых решений. И именно в рамках IAR. Попробуйте их сделать.

Всё что Вы говорите совершенно верно. Для меня "дрожание" индикатора это частный случай изучения тонких моментов языка С и конкретных сред разработки. К сожалению тех. документация на среды разработки оставляет желать много лудшего. Зачастую изучить систему команд нового микроконтроллера бывает значительно проще, чем написать пустую функцию main() во вновь изучаемой среде. По этому опыт людей столкнувшихся с подобными проблемами трудно переоценить. А отсутствие упоминания о действуещем модификаторе __raw наводит на мысль о наличии других недокументированных модификаторов, дающих возможность получить, желаемый в данном случае результат.
Со своей точки зрения могу сказать, отсутствие таких возможностей в IAR сильно снижает его привлекательность для малых микроконтроллеров, таких как обсуждаемый нами mega88.
Со своей стороны приложу все усилия для того, что бы получить разяснения по недосказанным, и поверхностно описанным моментам в описании IAR С компилятора. maniac.gif
Rst7
Про недокументированные модификаторы для AVR поищите на форуме слова __x, __z, __x_z, __z_x - тоже понравится wink.gif

добавлено позже: Ах пардон, оказывается, они уже упоминаются в доке на 4.30... Пойду погляжу в exe-файл, может еще чего интересного появилось wink.gif
SasaVitebsk
В этом смысле платформы для микропроцессоров даже лучше чем аналогичные для PC. Некоторых вещей совершенно не упоминается, к примеру, в DELFI, хотя это совершенно не мешает их использовать. Если конечно знаешь что они есть! smile.gif Но в этом как раз и вопрос!

Поэтому как бы не хвалили родную документацию, хорошая книга на русском языке от знающего автора и умеющего донести свои знания, - безусловно лучше. Только вот где эти авторы в области МК? К сожалению их практически нет и выбирать не из чего.

Приведу пример для DELFI. Использую процедуру
BitBlt(Image1.Canvas.Handle,0,0,Image1.Width,Image1.Height,BackGnd2.Canvas.Handl
e,0,0,SRCCOPY);
Появилась ещё в DELFI5. Подсмотрел у Стива Тейксейры и Ксавье Паченко http://www.libex.ru/detail/book66580.html. Великолепная книга, ставшая для меня настольной с совершенно отличным изложением.
В хелпе DELFI 7 упоминания о ф-ции не нашёл. Но прекрасно работает. И такие примеры - на каждом углу в области программирования на PC.

Думаю лет ч/з 20 появится хорошие книги по IAR, правда будут ли они кому нужны???


При том при всём - не отчаивайтесь. Я например недавно пытался переписать одну маленькую процедуру, которая вызывается огромное число раз, в IAR C на ассемблер. При этом следует признать, что на ассемблере я писал длительное время. Так вот при том что конкретные единичные операции удаётся написать эффективней, компилятор красивей работает с переменными. И выигрыш в результате получился плёвый, по сравнению с более грамотной Си программой. Так что я оставил Си текст, просто оптимизировал его. Вот и получается что знание ассемблера помогает красивее написать Си процедуру. Потому, что ты заранее предполагаешь как компилятор будет поступать. А следовательно - чем лучше ты знаешь компилятор - тем эффективней будут программы. Надо отходить от асемблера.
Dog Pawlowa
Цитата(SasaVitebsk @ Jun 14 2007, 20:44) *
... Вот и получается что знание ассемблера помогает красивее написать Си процедуру. Потому, что ты заранее предполагаешь как компилятор будет поступать. А следовательно - чем лучше ты знаешь компилятор - тем эффективней будут программы....

Тут не помешало бы вспомнить ув. Bill'a. Он, хотя и покинул эмбеддерское интернетовское сообщество сейчас, сумел раньше посеять хорошие семена, которые дали достойные всходы smile.gif
fmdost
Цитата(SasaVitebsk @ Jun 14 2007, 21:44) *
Вот и получается что знание ассемблера помогает красивее написать Си процедуру. Потому, что ты заранее предполагаешь как компилятор будет поступать. А следовательно - чем лучше ты знаешь компилятор - тем эффективней будут программы. Надо отходить от асемблера.

От себя добавлю "надо отходить от асемблера" особенно в свете появления двух, и 8-и(восьми) ядерных микроконтроллеров.
IgorKossak
Вот и славненько!
На этой мажорной ноте предлагаю Т.Достоевскому, как автору, закрыть тему. Если, конечно, добавить по теме больше нечего или спросить.
fmdost
Цитата(IgorKossak @ Jun 15 2007, 01:04) *
Вот и славненько!
На этой мажорной ноте предлагаю Т.Достоевскому, как автору, закрыть тему. Если, конечно, добавить по теме больше нечего или спросить.

Есть! А как её закрыть?
Закрывайте!
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.