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

 
 
> Оптимизация прерываний, Прошу совета
Dmitro25
сообщение Mar 31 2010, 05:47
Сообщение #1


Участник
*

Группа: Свой
Сообщений: 60
Регистрация: 4-04-07
Пользователь №: 26 770



Здравствуйте.
Пишу проект на IAR for AVR.
Возникло желание посмотреть, какой код формирует компилятор для прерываний. Оказалось, что в начале процедуры прерывания сохраняется в data-stack, а конце - восстанавливается 15 регистров общего назначения, хотя вызываемые из прерывания функции не требуют такого количества регистров. Я сначала подумал, что всё дело в том, что вызываемая из прерывания функция находится в другом модуле проекта, перенёс её в тот же модуль, где находится процедура прерывания, но отличий не увидел. Такое же ненужное сохранение множества регистров.
Разумное сохранение регистров я увидел только тогда, когда компилятор включил текст вызываемой функции в процедуру прерывания (inline). Если по какой-то причине inline функции не получается, снова бессмысленное сохранение регистров.
Чтобы не быть голословным, привожу код:
Код
#include <ioavr.h>

#pragma optimize=no_inline
void DoNothing()
{
}

#pragma vector = TIMER1_COMPA_vect
__interrupt void ext_int0_isr_routine(void)
{
  DoNothing();
}

int main( void )
{
  return 0;
}

Оптимизация стоит максимальная по скорости.
Подскажите, как этого можно избежать? Очень хотелось бы из прерывания вызывать функции, в т.ч. из других модулей, и иметь при этом оптимальный код.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Dmitro25
сообщение Mar 31 2010, 08:28
Сообщение #2


Участник
*

Группа: Свой
Сообщений: 60
Регистрация: 4-04-07
Пользователь №: 26 770



2dxp:
Цитата
Как раз понятное и объяснимое поведение. По-другому просто и быть не может

Ваш пост не дописан... Но, по-моему, если следовать разуму, зачем компилятору сохранять регистры перед вызовом функции, внутри которой, как ему ТОЧНО известно, ни один из этих регистров не используется.
Приведите пример, в котором только такое поведение разумно.

2MrYuran:
Цитата
Попробуйте принудительно заинлайнить функцию

Я понимаю, что, скорее всего, придётся делать именно так.
Просто изначально я хотел вызывать из прерывания функции, расположенные в других модулях проекта. Задача была вот в чём: создать для каждого периферийного устройства свой модуль в проекте (для инкапсуляции), а по прерываниям в основном модуле проекта вызывать соответствующие функции модулей периферийных устройств. При этом структура проекта получается более "прозрачной": в основном модуле сосредоточены все прерывания, а каждый из подключаемых модулей - это некий "чёрный ящик" с входом для прерываний и набором других входов и выходов в виде функций.
Однако, сделать процедуру прерывания в другом модуле "inline" у меня не получилось. Без специальных ключей линкер её выбрасывает, а если ставить "#pragma object_attribute=__root", всё равно это транслируется в "call" из прерывания.
Ещё, кстати, один вопрос к оптимальности трансляции, почему в "call", а не в rcall, если пока размер кода проекта не превышает 2кБ?
Go to the top of the page
 
+Quote Post
dxp
сообщение Mar 31 2010, 09:26
Сообщение #3


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(Dmitro25 @ Mar 31 2010, 15:28) *
2dxp:

Ваш пост не дописан...
Глюк форума. Все дописано.

Цитата(Dmitro25 @ Mar 31 2010, 15:28) *
Но, по-моему, если следовать разуму, зачем компилятору сохранять регистры перед вызовом функции, внутри которой, как ему ТОЧНО известно, ни один из этих регистров не используется.

Это откуда ему "ТОЧНО известно" это? Вот представьте, что вы компилятор, вам дали обработчик прерывания, в нем есть вызов функции, но кроме вызова ничего нет - самой функции вы не видите, ее исходного кода у вас нет, есть только прототип, чтобы вы могли ее правильно вызвать. Все.

Цитата(Dmitro25 @ Mar 31 2010, 15:28) *
Приведите пример, в котором только такое поведение разумно.

Вызов из ISR любой функции, представление которой в точке вызова неизвестно. См выше.

Цитата(Dmitro25 @ Mar 31 2010, 15:28) *
Я понимаю, что, скорее всего, придётся делать именно так.

И никак иначе, если не хотите тупого оверхеда.

Цитата(Dmitro25 @ Mar 31 2010, 15:28) *
Просто изначально я хотел вызывать из прерывания функции, расположенные в других модулях проекта. Задача была вот в чём: создать для каждого периферийного устройства свой модуль в проекте (для инкапсуляции), а по прерываниям в основном модуле проекта вызывать соответствующие функции модулей периферийных устройств. При этом структура проекта получается более "прозрачной": в основном модуле сосредоточены все прерывания, а каждый из подключаемых модулей - это некий "чёрный ящик" с входом для прерываний и набором других входов и выходов в виде функций.

Имхо, не самый лучший подход. Намного лучше обработчики прерываний рассовать по модулям, чтобы каждый был поближе к "своему" коду (с которым ISR связан). Еще лучше модули организовать в виде классов, а ISR сделать статическими функциями-членами классов.

Цитата(Dmitro25 @ Mar 31 2010, 15:28) *
Однако, сделать процедуру прерывания в другом модуле "inline" у меня не получилось.

Естественно. Для того, чтобы функция могла быть встроенной, компилятор должен иметь ее полный код в точке вызова - иначе как он будет встраивать? Точнее, что он будет встраивать, если он не видит потрохов функции? Иными словами, встраиваемая функция должна быть определена до точки ее вызова (хоть в заголовочном файле).

Цитата(Dmitro25 @ Mar 31 2010, 15:28) *
Ещё, кстати, один вопрос к оптимальности трансляции, почему в "call", а не в rcall, если пока размер кода проекта не превышает 2кБ?

А откуда компилятор знает о размере кода проекта? Размер кода проекта знает только линкер и то уже после сборки всего проекта. А инструкции вызова ставит компилятор. Если хотите rcall, задавайте опции процессора (-v), которые скажут компилятору, что памяти программ меньше 8к, и тогда компилятор будет ставить rcall.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post

Сообщений в этой теме
- Dmitro25   Оптимизация прерываний   Mar 31 2010, 05:47
- - mempfis_   КодВозникло желание посмотреть, какой код формируе...   Mar 31 2010, 06:34
- - Dmitro25   2mempfis: ЦитатаПопробуйте вместо вызова функции в...   Mar 31 2010, 06:47
|- - MrYuran   Цитата(Dmitro25 @ Mar 31 2010, 09:47) Под...   Mar 31 2010, 07:24
|- - dxp   Цитата(Dmitro25 @ Mar 31 2010, 13:47) Вот...   Mar 31 2010, 08:06
|- - Сергей Борщ   Цитата(Dmitro25 @ Mar 31 2010, 10:28) пер...   Mar 31 2010, 09:33
|- - defunct   Цитата(Dmitro25 @ Mar 31 2010, 11:28) Зад...   Apr 4 2010, 23:06
- - Dmitro25   2dxp: Спасибо за советы. Всё-таки не удержусь от т...   Mar 31 2010, 10:31
|- - Сергей Борщ   Цитата(Dmitro25 @ Mar 31 2010, 12:31) Есл...   Mar 31 2010, 10:51
|- - dxp   Цитата(Dmitro25 @ Mar 31 2010, 17:31) В п...   Mar 31 2010, 11:28
- - Dmitro25   2Сергей Борщ: ЦитатаТогда внесите обработчик в сиш...   Mar 31 2010, 11:48
|- - MrYuran   Цитата(Dmitro25 @ Mar 31 2010, 14:48) При...   Mar 31 2010, 12:59
- - MALLOY2   Вам же говорили глобальный флаг, а в основном цикл...   Mar 31 2010, 12:44
- - Dmitro25   2:MALLOY2 Глобальный флаг у меня в другом месте в ...   Mar 31 2010, 13:17
- - XVR   Что бы компилятор понял в процедуре прерывания, чт...   Apr 1 2010, 10:44


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

 


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


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