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

 
 
> 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
Ответов (1 - 8)
aesok
сообщение Sep 3 2009, 15:42
Сообщение #2


Знающий
****

Группа: Участник
Сообщений: 596
Регистрация: 26-05-06
Из: Москва
Пользователь №: 17 484



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


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

Анатолий.
Go to the top of the page
 
+Quote Post
DpInRock
сообщение Sep 3 2009, 16:33
Сообщение #3


Гуру
******

Группа: Участник
Сообщений: 2 254
Регистрация: 4-05-07
Из: Moscow
Пользователь №: 27 515



Цитата
asm("reti""\n");

Цель самообучения какая?
Если уж используете зачем-то ассемблерные вставки, то тогда кто за вас листинг будет смотреть?


--------------------
On the road again (Canned Heat)
Go to the top of the page
 
+Quote Post
Marian
сообщение Sep 3 2009, 17:24
Сообщение #4


Частый гость
**

Группа: Участник
Сообщений: 148
Регистрация: 23-02-07
Пользователь №: 25 618



Цитата(AVR38 @ Sep 3 2009, 17:19) *
ISR(TIMER0_COMP_vect)
{
asm("reti""\n");
};

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


Компилятор для функции ISR(TIMER0_COMP_vect) сам вставит RETI .
Go to the top of the page
 
+Quote Post
ARV
сообщение Sep 4 2009, 07:10
Сообщение #5


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

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



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

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


--------------------
Я бы взял частями... но мне надо сразу.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Sep 4 2009, 11:22
Сообщение #6


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Есть выход - писать обработчики прерываний полостью на ASM в отдельном *.s файле (если ASM _действительно необходим_).
Напишите для начала на чистом С. Вдруг это вас устроит. Зачем лишняя морока...


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
777777
сообщение Sep 6 2009, 05:26
Сообщение #7


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

Группа: Участник
Сообщений: 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
_Pasha
сообщение Sep 6 2009, 07:09
Сообщение #8


;
******

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



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

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

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

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

Дык и не надо вызывать - лучше инлайнить. Наворачивать сложные прерывания - это моветон smile.gif
Go to the top of the page
 
+Quote Post
ARV
сообщение Sep 6 2009, 12:51
Сообщение #9


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

Группа: Свой
Сообщений: 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 Текстовая версия Сейчас: 23rd July 2025 - 22:12
Рейтинг@Mail.ru


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