Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: GCC и Simulator AVR Studio 4.17
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
AVR38
Здравствуйте!
Запарился на такой простой с виду штуке, написанной в самообучающих целях:

контроллер ATmega32, AVR Studio 4.17, WinAVR-20090313
в обработчике прерывания от TCNT0 была сделана ассемблерная вставка. В эмуляторе при выходе из прырывания не восстаналивается из стека адрес возврата и происходит сброс программы. Даже при урезнии ассемблерной вставки до вида:

ISR(TIMER0_COMP_vect)
{
asm("reti""\n");
};

баг не пропадает.
Подскажите, где нагрешил?
aesok
Цитата(AVR38 @ Sep 3 2009, 18:19) *
Подскажите, где нагрешил?


asm("reti""\n"); - Это страшный грех!

Анатолий.
DpInRock
Цитата
asm("reti""\n");

Цель самообучения какая?
Если уж используете зачем-то ассемблерные вставки, то тогда кто за вас листинг будет смотреть?
Marian
Цитата(AVR38 @ Sep 3 2009, 17:19) *
ISR(TIMER0_COMP_vect)
{
asm("reti""\n");
};

баг не пропадает.
Подскажите, где нагрешил?


Компилятор для функции ISR(TIMER0_COMP_vect) сам вставит RETI .
ARV
ассемблерные вставки в AVR-GCC - это совсем не так просто.... компилятор запросто может самостоятельно обрамлять вашу вставку дополнительными командами (типа push-pop), поэтому ваш reti из середины вставки очень запросто может рушить весь стек!

и если уж очень хочется использовать ассемблерно-вставленный вариант обработчика прерываний, то используйте атрибут ISR_NAKED, что ли... но, конечно, прежде изучите документацию на WinAVR!!!
demiurg_spb
Есть выход - писать обработчики прерываний полостью на ASM в отдельном *.s файле (если ASM _действительно необходим_).
Напишите для начала на чистом С. Вдруг это вас устроит. Зачем лишняя морока...
777777
Цитата(AVR38 @ Sep 3 2009, 18:19) *
ISR(TIMER0_COMP_vect)
{
asm("reti""\n");
};


Когда задаете вопрос, нужно в первую очередь писать что вы хотите добиться, из приведенного фрагмента это не понятно - для чего подпрограмма обработки прерываний состоящая из одного возврата? Если там есть еще какие-то команды, обозначайте их как-то, многоточиями например. А для чего в нее надо вставлять reti? Ведь это подпрограмма обработки прерываний, компилятор знает об этом и вставит эту команду сам, это ведь очевидно. Если нужно выйти из середины программы, пиши return - это ведь программа на Си.

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

Цитата(ARV @ Sep 4 2009, 11:10) *
компилятор запросто может самостоятельно обрамлять вашу вставку дополнительными командами (типа push-pop)

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

Цитата(demiurg_spb @ Sep 4 2009, 15:22) *
Есть выход - писать обработчики прерываний полостью на ASM в отдельном *.s файле (если ASM _действительно необходим_).

Я знаю только одну причину - если из прерывания нужно вызвать какую-то функцию, тогда в обработчик вставляется сохранение и восстановдление всех регистров, так как компилятор не знает какие из них используются в функции.
Цитата(demiurg_spb @ Sep 4 2009, 15:22) *
Напишите для начала на чистом С. Вдруг это вас устроит. Зачем лишняя морока...

+1000
_Pasha
Цитата(777777 @ Sep 6 2009, 08:26) *
А вообще, ассемблерные вставки - это дичайшая глупость, я вообще не предстваляю зачем компиляторы разрешают их.

Тоже так думал - но все-же несколько моментов оказались удобными. Пример - правильное умножение 16бит * 16бит с результатом 32бита
Цитата
добавление такой вставки вызовет необходимость отключения оптимизатора!

Как раз оптимизатор там нужен для того, чтобы назначить "правильные" регистры для работы вставки. Остальное - оптимизировано вручную. smile.gif

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

Дык и не надо вызывать - лучше инлайнить. Наворачивать сложные прерывания - это моветон smile.gif
ARV
Цитата(777777 @ Sep 6 2009, 09:26) *
Ошибаетесь. Ничего он вставлять не будет, он тупо вставит эти команды, более того, добавление такой вставки вызовет необходимость отключения оптимизатора!
не ошибаюсь. вы, наверное, считаете, что ассемблерные вставки в GCC тупо 1 к 1 компилируются в код? ну, если речь идет о командах типа NOP - это действительно так. но в GCC имеется механизм для создания вставок с параметрами, и вот тут-то компилятор может разгуляться вовсю. так что вставка вставке рознь... вот пример:
Код
#include <avr/io.h>
#include <avr/interrupt.h>

volatile uint8_t value;

ISR(TIMER0_OVF_vect){
    asm (
    "in %0, %1" :
    "=r" (value) :
    "I" (_SFR_IO_ADDR(PORTD))
    );
}

int main(void)
{
}
а вот листинг результата (только часть, касающаяся ISR:
Код
ISR(TIMER0_OVF_vect){
  44:    1f 92           push    r1
  46:    0f 92           push    r0
  48:    0f b6           in    r0, 0x3f; 63
  4a:    0f 92           push    r0
  4c:    11 24           eor    r1, r1
  4e:    8f 93           push    r24
    asm (
  50:    82 b3           in    r24, 0x12; 18
  52:    80 93 60 00     sts    0x0060, r24
    "in %0, %1" :
    "=r" (value) :
    "I" (_SFR_IO_ADDR(PORTD))
);

}
  56:    8f 91           pop    r24
  58:    0f 90           pop    r0
  5a:    0f be           out    0x3f, r0; 63
  5c:    0f 90           pop    r0
  5e:    1f 90           pop    r1
  60:    18 95           reti
обратите на то, чего нет в ассемблерной вставке, но есть в коде (касается R24) - я об этом и говорил

а теперь представьте себе, что ассемблерная вставка выглядела бы так:
Код
    asm (
    "in %0, %1\n\t"
    "reti" :
    "=r" (value) :
    "I" (_SFR_IO_ADDR(PORTD))
    );
вроде никакого криминала - считали из порта в переменную и выход из прерывания (так хотелось), но ведь получится-то реально полный крах стека:
Код
ISR(TIMER0_OVF_vect){
  44:    1f 92           push    r1
  46:    0f 92           push    r0
  48:    0f b6           in    r0, 0x3f; 63
  4a:    0f 92           push    r0
  4c:    11 24           eor    r1, r1
  4e:    8f 93           push    r24
    asm (
  50:    82 b3           in    r24, 0x12; 18
  52:    18 95           reti
  54:    80 93 60 00     sts    0x0060, r24
    "in %0, %1\n\t"
    "reti" :
    "=r" (value) :
    "I" (_SFR_IO_ADDR(PORTD))
    );
}
  58:    8f 91           pop    r24
  5a:    0f 90           pop    r0
  5c:    0f be           out    0x3f, r0; 63
  5e:    0f 90           pop    r0
  60:    1f 90           pop    r1
  62:    18 95           reti

поэтому я и предупредил автора топика, что перед тем, как делать вставки в GCC надо изучить, как их делать правильно...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.