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

 
 
> GCC и Simulator AVR Studio 4.17, развертывание контекста при выходе из прерывания
AVR38
сообщение Sep 3 2009, 14:19
Сообщение #1





Группа: Участник
Сообщений: 11
Регистрация: 3-09-09
Пользователь №: 52 181



Здравствуйте!
Запарился на такой простой с виду штуке, написанной в самообучающих целях:

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

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

баг не пропадает.
Подскажите, где нагрешил?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
777777
сообщение Sep 6 2009, 05:26
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357



Цитата(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

Сообщение отредактировал 777777 - Sep 6 2009, 05:22
Go to the top of the page
 
+Quote Post
ARV
сообщение Sep 6 2009, 12:51
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 143
Регистрация: 30-09-08
Из: Новочеркасск
Пользователь №: 40 581



Цитата(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 надо изучить, как их делать правильно...


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th August 2025 - 20:35
Рейтинг@Mail.ru


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