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

 
 
 
Reply to this topicStart new topic
> Быстрое прерывание на AVR GCC
vladimir_orl
сообщение Jan 23 2014, 08:14
Сообщение #1


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

Группа: Участник
Сообщений: 191
Регистрация: 18-09-12
Из: Орёл
Пользователь №: 73 591



Здравствуйте. Использую связку STK500 + mega128 + AStudio6 в качестве даталоггера.
По прерыванию INT2 читаются значения двух пинов. Вот такой простой код:




Код
ISR (INT2_vect)
{
    m_master_byte |= (PINF & 0x01);
    m_slave_byte |= (PINC & 0x01);

    if (m_bit_counter <= 7)
    {
        ++m_bit_counter;
        if (m_bit_counter <= 7) {
            m_master_byte <<= 1;
            m_slave_byte <<= 1;
        } else {
            a_master_byte_array[m_byte_counter] = m_master_byte;
            a_slave_byte_array[m_byte_counter] = m_slave_byte;
        }
    } else {
        m_master_byte = 0;
        m_slave_byte = 0;
        m_bit_counter = 0;
        ++m_byte_counter;
    }
}


Но AVR GCC как известно наворачивает сохранение и восстановление контекста при работе с подпрограммами, вот касок листинга:

Код
00000204 <__vector_3>:
204:    1f 92           push    r1
206:    0f 92           push    r0
208:    0f b6           in    r0, 0x3f; 63
20a:    0f 92           push    r0
20c:    11 24           eor    r1, r1
20e:    0b b6           in    r0, 0x3b; 59
210:    0f 92           push    r0
212:    8f 93           push    r24
214:    9f 93           push    r25
216:    ef 93           push    r30
218:    ff 93           push    r31

... собственно сама работа ...

246:    ff 91           pop    r31
248:    ef 91           pop    r30
24a:    9f 91           pop    r25
24c:    8f 91           pop    r24
24e:    0f 90           pop    r0
250:    0b be           out    0x3b, r0; 59
252:    0f 90           pop    r0
254:    0f be           out    0x3f, r0; 63
256:    0f 90           pop    r0
258:    1f 90           pop    r1
25a:    18 95           reti




Т.е. время реакции на прерывание увеличивается.

Подскажите, есть ли какие опции у AVR GCC, позволяющие отключать эту обёртку. А то уже думаю этот ISR в отдельном asm файле сделать. Но обработчик хоть и небольшой, придётся повозиться, да и перепроверять заново надо будет. Отказаться от ISR тоже не выходить, т.к. там в основном цикле while тоже кода много. Кто-нибудь сталкивался с таким?

P.S. Кусок конечно у листинга, а не касок. Вроде текст перечитывал...
Go to the top of the page
 
+Quote Post
RabidRabbit
сообщение Jan 23 2014, 09:29
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 397
Регистрация: 3-12-09
Из: Россия, Москва
Пользователь №: 54 040



Можно, например, так:

ISR (INT2_vect,ISR_NAKED)
{
...
}

Но функция будет действительно голой, без сохранения регистра статуса и даже без reti (avr-gcc 4.7.2). Минимально нужно хотя бы asm("reti"); в конце поставить.


Go to the top of the page
 
+Quote Post
vladimir_orl
сообщение Jan 23 2014, 09:36
Сообщение #3


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

Группа: Участник
Сообщений: 191
Регистрация: 18-09-12
Из: Орёл
Пользователь №: 73 591



Спасибо большое. Это очень хорошо. Дальше буду смотреть по документации.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jan 23 2014, 09:39
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(vladimir_orl @ Jan 23 2014, 10:14) *
Использую связку в качестве даталоггера.
А что це такэ - даталоггер?

Цитата(vladimir_orl @ Jan 23 2014, 10:14) *
По прерыванию INT2 читаются значения двух пинов. Вот такой простой код:
Не такой уж и простой - там ещё и сохранение прочитанных битов в байты, а потом сохранение байтов в массивы.

Цитата(vladimir_orl @ Jan 23 2014, 10:14) *
Но AVR GCC как известно наворачивает сохранение и восстановление контекста при работе с подпрограммами, вот касок листинга:
Т.е. время реакции на прерывание увеличивается.

Цитата(vladimir_orl @ Jan 23 2014, 10:14) *
Подскажите, есть ли какие опции у AVR GCC, позволяющие отключать эту обёртку.
GCC не наворачивает, а сохраняет используемые в прерывании регистры. Как без этого?

Цитата(vladimir_orl @ Jan 23 2014, 10:14) *
А то уже думаю этот ISR в отдельном asm файле сделать.
Тоже можно, но не факт что намного быстрее получится.

Цитата(vladimir_orl @ Jan 23 2014, 10:14) *
Отказаться от ISR тоже не выходить, т.к. там в основном цикле while тоже кода много. Кто-нибудь сталкивался с таким?
Все рано или поздно с таким сталкиваются...Думаю, что надо менять прерывание в сторону его упрощения:
1) сохранять в ISR (INT2_vect) только биты и увеличивать счётчик принятых битов.
2) Когда будет принят байт нужно его сохранить во временной переменной и установить флаг приёма байта.
3а) Далее по этому флагу в основной программе записать байт в массив.
3б) Если цикл основной программы может быть дольше чем время передачи байта, вызвать программное прерывание, в котором байт записывается в массив.
3в) Можно что-нибудь ещё придумать. Например не логировать ничего - вам действительно нужны эти байты? Может эту задачу и решать-то не надо?
Go to the top of the page
 
+Quote Post
vladimir_orl
сообщение Jan 24 2014, 05:39
Сообщение #5


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

Группа: Участник
Сообщений: 191
Регистрация: 18-09-12
Из: Орёл
Пользователь №: 73 591



1) Даталоггер - в моём понимании читает значения линий (цифровых) в определённые значения времени. простенький цифровой осциллограф. А дальше уже на данные компьютере просматриваю что и как.


2) Я все переменные объявил как register. В листинге посмотрел - по честному в регистрах находятся.

3), 4) Попробую рискнуть без сохранения контекста поработать.

5) Тем более что написание программ на ассемблере чревато сложноуловимыми багами.

6) Да. Скорее всего буду сохранять значения линий во время ISR, а в основном теле уже смотреть.




Код
3в) Можно что-нибудь ещё придумать. Например не логировать ничего - вам действительно нужны эти байты? Может эту задачу и решать-то не надо?


Лучший выход - купить хороший цифровой осциллограф. Или PCI плату сбора данных...
Пробую сам сделать на ARM LPC, но пока не доделал.
Go to the top of the page
 
+Quote Post
megajohn
сообщение Jan 24 2014, 05:55
Сообщение #6


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

Группа: Свой
Сообщений: 1 080
Регистрация: 16-11-04
Из: СПб
Пользователь №: 1 143



нужно сократить число переменных в прерывании.
так что пишите оба сигнала в одих байт ( четный бит - одна линия, нечетный - другая линия ) И все в итоге пишите в один массив

еще как вариант зарезервировать пару регистров, чтобы компилятор их не юзал. А вы использовали бы их как глобальные переменные. Тогда не нужно лишний раз работать со стеком


--------------------
Марс - единственная планета, полностью населенная роботами (около 7 штук).
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 8th July 2025 - 14:08
Рейтинг@Mail.ru


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