vladimir_orl 0 23 января, 2014 Опубликовано 23 января, 2014 · Жалоба Здравствуйте. Использую связку 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. Кусок конечно у листинга, а не касок. Вроде текст перечитывал... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RabidRabbit 0 23 января, 2014 Опубликовано 23 января, 2014 · Жалоба Можно, например, так: ISR (INT2_vect,ISR_NAKED) { ... } Но функция будет действительно голой, без сохранения регистра статуса и даже без reti (avr-gcc 4.7.2). Минимально нужно хотя бы asm("reti"); в конце поставить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vladimir_orl 0 23 января, 2014 Опубликовано 23 января, 2014 · Жалоба Спасибо большое. Это очень хорошо. Дальше буду смотреть по документации. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 23 января, 2014 Опубликовано 23 января, 2014 · Жалоба Использую связку в качестве даталоггера.А что це такэ - даталоггер? По прерыванию INT2 читаются значения двух пинов. Вот такой простой код:Не такой уж и простой - там ещё и сохранение прочитанных битов в байты, а потом сохранение байтов в массивы. Но AVR GCC как известно наворачивает сохранение и восстановление контекста при работе с подпрограммами, вот касок листинга: Т.е. время реакции на прерывание увеличивается. Подскажите, есть ли какие опции у AVR GCC, позволяющие отключать эту обёртку.GCC не наворачивает, а сохраняет используемые в прерывании регистры. Как без этого? А то уже думаю этот ISR в отдельном asm файле сделать.Тоже можно, но не факт что намного быстрее получится. Отказаться от ISR тоже не выходить, т.к. там в основном цикле while тоже кода много. Кто-нибудь сталкивался с таким?Все рано или поздно с таким сталкиваются...Думаю, что надо менять прерывание в сторону его упрощения: 1) сохранять в ISR (INT2_vect) только биты и увеличивать счётчик принятых битов. 2) Когда будет принят байт нужно его сохранить во временной переменной и установить флаг приёма байта. 3а) Далее по этому флагу в основной программе записать байт в массив. 3б) Если цикл основной программы может быть дольше чем время передачи байта, вызвать программное прерывание, в котором байт записывается в массив. 3в) Можно что-нибудь ещё придумать. Например не логировать ничего - вам действительно нужны эти байты? Может эту задачу и решать-то не надо? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vladimir_orl 0 24 января, 2014 Опубликовано 24 января, 2014 · Жалоба 1) Даталоггер - в моём понимании читает значения линий (цифровых) в определённые значения времени. простенький цифровой осциллограф. А дальше уже на данные компьютере просматриваю что и как. 2) Я все переменные объявил как register. В листинге посмотрел - по честному в регистрах находятся. 3), 4) Попробую рискнуть без сохранения контекста поработать. 5) Тем более что написание программ на ассемблере чревато сложноуловимыми багами. 6) Да. Скорее всего буду сохранять значения линий во время ISR, а в основном теле уже смотреть. 3в) Можно что-нибудь ещё придумать. Например не логировать ничего - вам действительно нужны эти байты? Может эту задачу и решать-то не надо? Лучший выход - купить хороший цифровой осциллограф. Или PCI плату сбора данных... Пробую сам сделать на ARM LPC, но пока не доделал. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
megajohn 3 24 января, 2014 Опубликовано 24 января, 2014 · Жалоба нужно сократить число переменных в прерывании. так что пишите оба сигнала в одих байт ( четный бит - одна линия, нечетный - другая линия ) И все в итоге пишите в один массив еще как вариант зарезервировать пару регистров, чтобы компилятор их не юзал. А вы использовали бы их как глобальные переменные. Тогда не нужно лишний раз работать со стеком Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться