Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Определение inline функции
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Cредства разработки для МК > IAR
sonycman
Есть несколько файлов исходника:
LCD.h с объявлением функции:
Код
inline    void    lcdClearScreen();

LCD.c с определением:
Код
inline    void    lcdClearScreen()
{
    lcdWriteCommand(0x01);
};

и вызов этой функции из третьего файла I2C.c:
Код
#include    "lcd.h"
...
lcdClearScreen();

Что-то первый раз столкнулся с тем, что, при компиляции файла I2C.c, компилер выдаёт ошибку про отсутствие определения этой функции 07.gif
Вышел из положения включением определения функции в хедер LCD.h:
Код
inline    void    lcdClearScreen()
{
    lcdWriteCommand(0x01);
};

Получается, inline функции необходимо определять сразу при объявлении?
Сергей Борщ
Цитата(sonycman @ Dec 13 2008, 12:38) *
Получается, inline функции необходимо определять сразу при объявлении?
Нет, не так. Просто компилятор должен иметь тело функции на момент встраивания. Иначе откуда он узнает, что именно встраивать? А откуда он возьмет тело - из заголовочного файла или из начала исходника, в котором встретил точку встраивания или из середины этого исходника - не важно. Обычно тело inline-функции размещают в заголовочном файле, чтобы его можно было встроить в любом исходнике, куда подключен заголовок. Ничто не мешает совместить объявление и определение такой функции, что часто и делается для небольших по размеру функций.
sonycman
А, понятно smile.gif
То есть компилер за один проход должен создать объектный файл? А для не-встраиваемых внешних функций, определённых в других файлах, генерируются простые обращения в виде вызовов, а уже линкер потом записывает конкретные адреса?

Спасибо! a14.gif
Сергей Борщ
Цитата(sonycman @ Dec 13 2008, 22:29) *
То есть компилер за один проход должен создать объектный файл? А для не-встраиваемых внешних функций, определённых в других файлах, генерируются простые обращения в виде вызовов, а уже линкер потом записывает конкретные адреса?
Да, именно так. Причем для встраиваимых функций и обращений не будет. Все тело будет вставлено туда, где для обычной функции был бы вызов.
Rash
возникла таже проблема, но так и не понял как её решить.
Можно пример кода, где и что объявлять?
_Артём_
Цитата(Rash @ Jun 2 2012, 19:56) *
Можно пример кода, где и что объявлять?


Объявлять можно в h-файле
Код
#define LED_PORT PORTB
#pragma inline=forced
inline void LedOn() {
    LED_PORT|=(1<<LED_PIN);
}

или так:
Код
#define PRAGMA(x) _Pragma( #x )
#define INLINE PRAGMA( inline=forced ) static

INLINE void LedOn() {
    LED_PORT|=(1<<LED_PIN);
}

Rash
спасибо, т.е. тело функции должно быть в h файле?
Может можно сделать что бы inline объявления были в h, а реализация в С файлах
_Артём_
Цитата(Rash @ Jun 2 2012, 20:35) *
т.е. тело функции должно быть в h файле?

Может быть и в с-файле:
Код
#pragma inline=forced
inline static void OffLed()
{
    PORTD.DIRSET=1;
    PORTD.OUTCLR=1;
}


int main() {
    OffLed();


Цитата(Rash @ Jun 2 2012, 20:35) *
Может можно сделать что бы inline объявления были в h, а реализация в С файлах

У меня такое сделать не получалось (а зачем оно надо?): линкер ругается чем то наподобии "Undefined OffLed". Видимо это неспроста.
Rash
Цитата(_Артём_ @ Jun 2 2012, 22:23) *
У меня такое сделать не получалось (а зачем оно надо?): линкер ругается чем то наподобии "Undefined OffLed". Видимо это неспроста.


Да не получается. Перепробовал наверное вариантов 20, так и не нашёл как.
Удобно в С файлах код, а в h описание ф-ций.
Dog Pawlowa
Цитата(Rash @ Jun 2 2012, 23:46) *
Да не получается.

очевидная общая логика, не обязательно связанная с программированием - чтобы что-то куда-то вставить, нужно знать что именно вставлять.
VladislavS
Что-то вы проблему на ровном месте придумали. Чтобы встроить функцию в месте вызова она должна быть определена в той же единице компиляции, где происходит вызов. Грубо говоря, в том же c-файле, либо в подключенном h-файле, что для компилятора по сути одно и то же.
Rash
не знаю проблема или нет, но я хотел бы видеть вой код так:

описание инлайн функции в файл1.h, код выполнения в файл1.с, а вызов функции, т.е. её встраивание было в файл2.с.
Сергей Борщ
QUOTE (Rash @ Jun 3 2012, 16:43) *
не знаю проблема или нет
Проблема. Потому что во время компиляции файл2.c компилятор понятия не имеет ни о существовании файл1.c, ни о его содержимом и, соответветственно, о том, что же именно ему нужно вставить в место вызова этой функции. Чтобы он имел возможность встроить, тело функции должно быть ему доступно, а значит располагаться либо в файл2.c, либо в любом файле, включенном в него директивой #include. Других вариантов нет.

Хотите красоты - делайте функцию невстраиваемой. По этому пути пошли создатели CMSIS. В ней, чтобы записать одно значение в один регистр вызывается функция со всеми вытекающими тормозами и раздутием кода.
_Артём_
Цитата(Сергей Борщ @ Jun 3 2012, 16:53) *
Хотите красоты - делайте функцию невстраиваемой. По этому пути пошли создатели CMSIS.

Это красота?
В CMSIS полно inline-функций.
В чём неправильность их пути?

Цитата(Сергей Борщ @ Jun 3 2012, 16:53) *
В ней, чтобы записать одно значение в один регистр вызывается функция со всеми вытекающими тормозами и раздутием кода.

А как лучше делать?

aaarrr
Цитата(_Артём_ @ Jun 4 2012, 01:39) *
А как лучше делать?

Лучше просто писать в регистр.
_Артём_
Цитата(aaarrr @ Jun 4 2012, 00:59) *
Лучше просто писать в регистр.

Как просто...
А почему они не пишут "просто в регистр"?
aaarrr
Цитата(_Артём_ @ Jun 4 2012, 02:17) *
А почему они не пишут "просто в регистр"?

От большого ума, надо полагать. Увы, вижу массу примеров, как на пустом месте создается "библиотека", бессмысленная и беспощадная. CMSIS - как раз один из таких случаев.
AHTOXA
Мне кажется, тут разные люди говорят о разных CMSIS-ах. Та часть, которая от собственно ARM - она состоит вообще исключительно из *.h файлов с инлайн-функциями и определениями структур. (Это файлы core_cm0.h, core_cm3.h, core_cm4.h, core_cm4_simd.h, core_cmFunc.h, core_cmInstr.h.) Остальное - это уже от производителя конкретного контроллера. И здесь уже конечно бывают наворотыsm.gif
Кстати, ST здесь на удивление скромны - всего-лишь startup_xxx.s и system_xxx.c. Остальное - опять же хидеры. Зато уж в своей StdPeriph библиотеке они уже оторвались по полнойsm.gif

_Артём_
Цитата(AHTOXA @ Jun 4 2012, 07:21) *
Зато уж в своей StdPeriph библиотеке они уже оторвались по полнойsm.gif

И не только они: NXP, EFM - тоже самое делают.
aaarrr
Цитата(AHTOXA @ Jun 4 2012, 08:21) *
Кстати, ST здесь на удивление скромны - всего-лишь startup_xxx.s и system_xxx.c. Остальное - опять же хидеры. Зато уж в своей StdPeriph библиотеке они уже оторвались по полнойsm.gif

Мне хватило просмотра кода вычисления делителя UART - остальную часть библиотек ST забраковал не глядя.
AHTOXA
Цитата(aaarrr @ Jun 4 2012, 18:33) *
Мне хватило просмотра кода вычисления делителя UART - остальную часть библиотек ST забраковал не глядя.

Да, это шедеврsm.gif Но это не CMSIS, вот я о чём.
scifi
Цитата(aaarrr @ Jun 4 2012, 16:33) *
Мне хватило просмотра кода вычисления делителя UART - остальную часть библиотек ST забраковал не глядя.

+1. STишная библиотека вызывает стойкое отвращение.
Причём особого смысла в её существовании не вижу: руководство по МК всё равно нужно читать, а для облегчения программирования регистров можно придумать очень небольшой набор макросов. Регистры МК довольно понятные. А в сложных случаях (таймеры) попытка сделать обёртку для упрощения может всё только запутать. Лучше в руководстве всё подробно расписать.
Dog Pawlowa
Цитата(scifi @ Jun 4 2012, 15:43) *
STишная библиотека вызывает стойкое отвращение.
Причём особого смысла в её существовании не вижу

Я вот тоже отвращение испытываю, но подергался-подергался и работаю с библиотекой.
Не критично. Но зло берет. Смайлик неудовлетворения.
aaarrr
Цитата(AHTOXA @ Jun 4 2012, 16:41) *
Да, это шедеврsm.gif Но это не CMSIS, вот я о чём.

Дык, в CMSIS тоже всплывают косяки периодически.

Цитата(Dog Pawlowa @ Jun 4 2012, 16:47) *
...подергался-подергался и работаю с библиотекой.

У меня были такие мысли, пока окучивал USB на STM32F40x. Сделано как будто специально, чтобы максимально неудобно софт писать было sad.gif
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.