Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Не могу решить проблему вызова функций IAR
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
haker_fox
Здравствуйте! Моя программа состоит из нескольких модулей. Есть главный модуль main.c, в нем для инициализации различных частей программы вызываются функции из других модулей. Причем эти функции используются однократно, при запуске программы. Уровень оптимизации стоит максимальный и по размеру кода. Просмотрев дизассемблированный текст, я увидел, что эти функции вызываются с помощью rcall. Нельзя ли что-нибудь настроить, чтоб тело этих функции помещалось на место команды rcall, т.е. чтобы они не вызывались (ведь больше они не где не используются), таким образом экономим память (оптимизация то по размеру).

В общем мой вопрос так звучит: как сделать, чтоб однократно используемые функции не вызывались, а их тело помещалось вместо вызова подпрограммы.
prottoss
Цитата(haker_fox @ Oct 27 2005, 07:29)
В общем мой вопрос так звучит: как сделать, чтоб однократно используемые функции не вызывались, а их тело помещалось вместо вызова подпрограммы.
*


Вообще для этого в IAR (не знаю как в других средах) есть директива #pragma inline=forced.
Но язаметил такую особенность - если функция , например void if(), объявленная как inline, и функция которая вызывает void if(), находятся в одном модуле, то void if(), компилируется как inline без call и ret. Если же функции в разных модулях, то функция void if(), вызывается через call.
haker_fox
Цитата
Вообще для этого в IAR (не знаю как в других средах) есть директива #pragma inline=forced.
Но язаметил такую особенность - если функция , например void if(), объявленная как inline, и функция которая вызывает void if(), находятся в одном модуле, то void if(), компилируется как inline без call и ret. Если же функции в разных модулях, то функция void if(), вызывается через call.


А нельзя ли это автоматизировать, что сам компилятор это выполнял. А то трудно уследить какие функции будут использоваться однократно.
prottoss
Цитата(haker_fox @ Oct 27 2005, 07:58)
А нельзя ли это автоматизировать, что сам компилятор это выполнял. А то трудно уследить какие функции будут использоваться однократно.


Я использую директиву #pragma inline=forced в основном в прерываниях, для разделения задачи на более мелкие подзадачи - так удобнее потом в этом разбираться и мне, и тем, для кого я пишу. Да и при написания процедуры обработки прерывания, если внутри процедуры нет вызовов call, код компилируется меньше за счет сокращения числа сохраненных РОН. А вообще наверное есть смысл подставлять данную директиву везде, если есть вероятность вызова функции всего один раз. На счет автоматизации этого процесса ничего сказать не могу.
haker_fox
2prottoss: спасибо! Я поставля эти директивы в обработчиках прерываний, где функции точно вызываются единожды.
starter48
Цитата(haker_fox @ Oct 27 2005, 06:29)
В общем мой вопрос так звучит: как сделать, чтоб однократно используемые функции не вызывались, а их тело помещалось вместо вызова подпрограммы.
*

1) Нужно чтобы вызываемые ф-ии были в одном модуле с вызывающей ф-ей.
2) Нужно написать модификатор static перед вызываемой ф-ей.
3) К этим пунктами иногда тербуется включить оптимизацию по скорости (проверь экспериментально). Тогда компилятор сам достаточно умно решает инлайнить ф-ю или нет.
haker_fox
Но если разместить функции в одном модуле, то пропадет наглядность программы, видимо надо чихнуть на этот "беспредел" компилятора.
starter48
Цитата(haker_fox @ Oct 28 2005, 21:29)
Но если разместить функции в одном модуле, то пропадет наглядность программы, видимо надо чихнуть на этот "беспредел" компилятора.
*

Можешь модуль разбить на несколько с помощью #include smile.gif
Вообще это свойство компилятора. Ф-ии для работающие вместе должны объединяться в модулях. Если есть ф-я, которую нужно инлайнить в нескольких модулях , то объяви её static и запихни в подключенный в эти моули .h файл.
Т.о. модули компилируются отдельно, при этом компилятор ничего не знает о ф-ях в других модулях, кроме прототипов. И только потом линкером сгенерированный из модулей код объединяется.
prottoss
Цитата(starter48 @ Oct 28 2005, 22:41)
Можешь модуль разбить на несколько с помощью #include smile.gif
Вообще это свойство компилятора. Ф-ии для работающие вместе должны объединяться в модулях. Если есть ф-я, которую нужно инлайнить в нескольких модулях , то объяви её static и запихни в подключенный в эти моули .h файл.
Т.о. модули компилируются отдельно, при этом компилятор ничего не знает о ф-ях в других модулях, кроме прототипов. И только потом линкером сгенерированный из модулей код объединяется.


Компилятор то знает все обо всех функциях, на то он и компилятор. Другое дело, что он не подставляет тело функции из одного модуля, в тело функции из другого. Но если написать тело в .h файл, возможно это и прокатит.
Но тут такая белиберда получится, что ой-ой.

Допустим в модуле объявлена глобальная переменная, а нужная нам инлайн-функция должна работать с этой пременной. Как этой функции, которая описанна в хедере, рассказать что в одноименном модуле для него приготовленна переменная. Писать еще одну функцию в модуле, которая будет возвращать значение переменной инлайн-функции?
starter48
Цитата(prottoss @ Oct 28 2005, 22:15)
Компилятор то знает все обо всех функциях, на то он и компилятор. Другое дело, что он не подставляет тело функции из одного модуля, в тело функции из другого.
*

Нет, компилятор знает только прототип ф-ии из .h для внешнего модуля, но не тело ф-ии. Исходя из прототипа производится проверка числа и типов аргументов, а в объектный файл ставится rcall без адреса. Реальный адрес проставляется линкером на этапе линковки.

Цитата(prottoss @ Oct 28 2005, 22:15)
Но если написать тело в .h файл, возможно это и прокатит.
Но тут такая белиберда получится, что ой-ой.
Допустим в модуле объявлена глобальная переменная, а нужная нам инлайн-функция должна работать с этой пременной. Как этой функции, которая описанна в хедере, рассказать что в одноименном модуле для него приготовленна переменная. Писать еще одну функцию в модуле, которая будет возвращать значение переменной инлайн-функции?
*


Нужно объявить переменную как extern в .h файле с функцией.
Т.е. в основном модуле пишем:
Код
#include"submodule.h"

int myvar;

void main (void)
{
 myfunc();
}

а в submodule.h пишем:
Код
#ifndef __submodule_h
#define __submodule_h

extern int myvar;

static void myfunc (void)
{
..... здесь используем myvar
}

#endif
prottoss
Цитата(starter48 @ Oct 28 2005, 23:52)
Нужно объявить переменную как extern в .h файле с функцией.


Тогда объясните зачем вообще нужны отдельные модули, раз уж на то пошло.
Давайте будем писать все в одном модуле, чтоб все все знали обо всех :-)
starter48
Цитата(prottoss @ Oct 28 2005, 23:12)
Тогда объясните зачем вообще нужны отдельные модули, раз уж на то пошло.

1) Проще разбираться в исходниках, когда программа разбита на идеологически законченные блоки.
2) К программе можно прилинковать модуль написанный на другом языке.
3) Каждый модуль можно скомпилировать со своими настройками компилятора.
4) Программа быстрее перекомпилируется, т.к. компилятор компилирует только изменившиеся модули.
Цитата(prottoss @ Oct 28 2005, 23:12)
Давайте будем писать все в одном модуле, чтоб все все знали обо всех :-)
*

Да, если проект не очень большой, то так обычно и делается.
prottoss
Цитата(starter48 @ Oct 29 2005, 00:39)
1) Проще разбираться в исходниках, когда программа разбита на идеологически законченные блоки.
2) К программе можно прилинковать модуль написанный на другом языке.
3) Каждый модуль можно скомпилировать со своими настройками компилятора.
4) Программа быстрее перекомпилируется, т.к. компилятор компилирует только изменившиеся модули.


К этому Вы забыли еще добавить
5) разграничение пространства имен.
starter48
Цитата(prottoss @ Oct 28 2005, 23:53)
Цитата(starter48 @ Oct 29 2005, 00:39)
1) Проще разбираться в исходниках, когда программа разбита на идеологически законченные блоки.
2) К программе можно прилинковать модуль написанный на другом языке.
3) Каждый модуль можно скомпилировать со своими настройками компилятора.
4) Программа быстрее перекомпилируется, т.к. компилятор компилирует только изменившиеся модули.


К этому Вы забыли еще добавить
5) разграничение пространства имен.
*


Да, причём, это можно поставить на первое место.
Зачем спрашивал, если сам всё знаешь? smile.gif
prottoss
Цитата(starter48 @ Oct 29 2005, 01:11)
Зачем спрашивал, если сам всё знаешь? smile.gif


Цитата(starter48 @ Oct 28 2005 @ 23:52)
Нужно объявить переменную как extern в .h файле с функцией.


Где ж тут разграничение пространства имен? Если глобальные переменные одного модуля известны всем модулям?
starter48
Цитата(prottoss @ Oct 29 2005, 01:59)
Цитата(starter48 @ Oct 29 2005, 01:11)
Зачем спрашивал, если сам всё знаешь? smile.gif


Цитата(starter48 @ Oct 28 2005 @ 23:52)
Нужно объявить переменную как extern в .h файле с функцией.


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


А как ты собрался инлайнить ф-ю одного модуля в другой, если эта ф-я использует статические переменные в другом модуле?
Переменные, которые ты собрался использовать во встраиваемых ф-ях нужно сделать видимыми для всех, т.к. статическую переменную оптимизатор может просто выкинуть.
При инлайне код ф-ии встраивается в код соответствующего модуля, значит, и доступ к используемым в этой ф-ии переменным из этого модуля должен быть.
Разграничение пр-ва имён будет действовать на те переменные и ф-ии, которые объявлены со словом static. Вообще, все переменные и ф-ии, которые не используются в других модулях следует объявлять как static, т.к. это развязывает руки компилятору для оптимизации.
prottoss
Цитата(starter48 @ Oct 29 2005, 03:29)
А как ты собрался инлайнить ф-ю одного модуля в другой, если эта ф-я использует статические переменные в другом модуле?
Переменные, которые ты собрался использовать во встраиваемых ф-ях нужно сделать видимыми для всех, т.к. статическую переменную оптимизатор может просто выкинуть.


Я не собирался и не собираюсь ничего инлайнить. Эти вопросы к автору темы. Я использую инлайн функции только для прерываний или для функций и только в одном модуле с целью оптимизировать код в модуле.

Как правило один модуль в проекте отвечает за какой то один блок устройства. Это сродни классу в СРР, если вы пишите на протом Си. Поэтому, глобальные переменные одного модуля, я не показываю никогда другому модулю. Если же мне надо получить доступ к переменным одного модуля у другого, я делаю функции GetЧтоТо { return g_ЧтоТо; } или SetЧтоТо(value) { g_ЧтоТо = value;} и объявляю их в хедере модуля. Это все, конечно, не буквально, но что то в этом духе.

Пускай данные конструкции замедляют код, на за то они придают уверенности мне, что мой проект не грохнется где то на середине исполнения модуля.
Мы слишком часто в погоне за скоростью исполнения забываем про конструкции и алгоритмы. В итоге получив скорость, получаем головную боль, хромающую программу и потерянное время.
_artem_
Po moemu C99 podderzivaet inline keyword . No IAR ego (C99) ne podderzivaet . )

Drugoe resenie pisat inline funkcii na makro . No pomoemu nado ispolzovat figurnie skobki dlya declaration vremennix peremennix . Xotya mogu i osibatsya .
halfdoom
Цитата(haker_fox @ Oct 27 2005, 02:29)
Моя программа состоит из нескольких модулей. Есть главный модуль main.c, в нем для инициализации различных частей программы вызываются функции из других модулей. Причем эти функции используются однократно, при запуске программы. Уровень оптимизации стоит максимальный и по размеру кода.

Функции из разых модулей не могут быть встроены. Что-бы обойти эти поблемы последние версии иар имеют ключик позволяющий компилировать несколько модулей одновременно с формированием одного объектного файла.
Balaganov
Цитата(halfdoom @ Oct 31 2005, 13:40) *
Цитата(haker_fox @ Oct 27 2005, 02:29)
Моя программа состоит из нескольких модулей. Есть главный модуль main.c, в нем для инициализации различных частей программы вызываются функции из других модулей. Причем эти функции используются однократно, при запуске программы. Уровень оптимизации стоит максимальный и по размеру кода.

Функции из разых модулей не могут быть встроены. Что-бы обойти эти поблемы последние версии иар имеют ключик позволяющий компилировать несколько модулей одновременно с формированием одного объектного файла.

Если можно поподробнее что за ключ? Искал в хелпе на 4.11а, но видимо плохо.
zltigo
Цитата(Balaganov @ Nov 26 2005, 13:38) *
Если можно поподробнее что за ключ? Искал в хелпе на 4.11а, но видимо плохо.


--mfc
Enable multiple file compilation

В IAR ARM ANSI C/C++ Compiler V4.30A-P050906/W32
имеет место быть, правда помечен, как эспериментальный.
А в хелпах его, как и многого другого, нет.
Balaganov
Цитата(zltigo @ Nov 27 2005, 01:26) *
Цитата(Balaganov @ Nov 26 2005, 13:38) *

Если можно поподробнее что за ключ? Искал в хелпе на 4.11а, но видимо плохо.


--mfc
Enable multiple file compilation

В IAR ARM ANSI C/C++ Compiler V4.30A-P050906/W32
имеет место быть, правда помечен, как эспериментальный.
А в хелпах его, как и многого другого, нет.

А для AVR нету подобного? А то студия при пошаговой отладке не переходит на include файл если функция в нем является inline sad.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.