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

 
 
3 страниц V  < 1 2 3 >  
Reply to this topicStart new topic
> Как правильно создать многофайловый проект, Ошибка при линковке
Сергей Борщ
сообщение Dec 11 2007, 13:07
Сообщение #16


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(alexander55 @ Dec 11 2007, 12:29) *
Приятно сразу понять логику работы всей системы глядя на один модуль.
У меня в main.c обычно находятся собственно main() и __low_level_init(). Глядя на main() можно попытаться понять логику работы всей системы, правда есть одно исключение smile.gif :
Код
int main()
{
    OS::Run();
}
Цитата(alexander55 @ Dec 11 2007, 12:29) *
Детали находятся за рамками и если требуются, то понятно, где это можно посмотреть (глядя на модуль).
Так RS232_transmit_handler() - это и есть детали. А логика описывается getchar(), putchar() и hasinput(). Мне так кажется...
Цитата(SasaVitebsk @ Dec 11 2007, 12:58) *
Прерывание - метки времени. То есть там целый набор. smile.gif в том числе вызовы опроса клавиатуры.
В таком случае наименьшие накладные, наверное, можно получить если "набор" описать в заголовочных файлах как static inline функции.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
alexander55
сообщение Dec 11 2007, 13:39
Сообщение #17


Бывалый
*****

Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615



Цитата(Сергей Борщ @ Dec 11 2007, 16:07) *
У меня в main.c обычно находятся собственно main() и __low_level_init(). Глядя на main() можно попытаться понять логику работы всей системы, правда есть одно исключение smile.gif :
Код
int main()
{
    OS::Run();
}

Это логичный и устоявшийся модуль. biggrin.gif

Цитата(Сергей Борщ @ Dec 11 2007, 16:07) *
Так RS232_transmit_handler() - это и есть детали. А логика описывается getchar(), putchar() и hasinput(). Мне так кажется...

В данном случае так.

Цитата(Сергей Борщ @ Dec 11 2007, 16:07) *
В таком случае наименьшие накладные, наверное, можно получить если "набор" описать в заголовочных файлах как static inline функции.

Или включить максимальную оптимизацию по требуемому параметру.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Dec 11 2007, 15:20
Сообщение #18


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(alexander55 @ Dec 11 2007, 15:39) *
Или включить максимальную оптимизацию по требуемому параметру.
Не поможет. Если части обработчика в виде функций раскиданы по разным модулям, а из обработчика видны как extern func(), то при любой оптимизации встраивания не будет, а компилятор будет сохранять/восстанавливать ненужные регистры. Если же все функции встраиваются - у компилятора широкое поле для оптимизаций


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Panych
сообщение Apr 7 2008, 13:32
Сообщение #19


Местный
***

Группа: Свой
Сообщений: 335
Регистрация: 17-06-04
Из: Москва
Пользователь №: 35



Подниму тему, чтоб не плодить...
Объявляю внешнюю функцию:
Код
extern void LCD_INIT ( void );

В main делаю вызов
Код
  LCD_INIT();

Не работает. Вставляю в main тело функции - все работает.
IAR не ругается и не предупреждает.
Файлы прикрепил. Помогите понять, плиз smile.gif
Прикрепленные файлы
Прикрепленный файл  AVR_Project.zip ( 1.39 килобайт ) Кол-во скачиваний: 40
 


--------------------
Всегда не хватает времени, чтобы выполнить работу как надо, но на то, чтобы ее переделать, время находится. (Закон Мескимена.)
Go to the top of the page
 
+Quote Post
msalov
сообщение Apr 7 2008, 13:45
Сообщение #20


Знающий
****

Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045



Цитата(Panych @ Apr 7 2008, 16:32) *
Подниму тему, чтоб не плодить...
Объявляю внешнюю функцию:
Код
extern void LCD_INIT ( void );

В main делаю вызов
Код
  LCD_INIT();

Не работает. Вставляю в main тело функции - все работает.
IAR не ругается и не предупреждает.
В пятницу текст выводился, все вроде было именно так организовано - а в понедельник...
Файлы прикрепил. Помогите понять, плиз smile.gif

Судя по вашему проекту, функция LCD_INIT() у Вас не внешняя а очень даже локальная. Если уж решили разбивать проект на модули - доводите дело до конца, а не сводите все "модули" в один через #include.
С минимальной правкой того что есть, можно перенести прототип функции LCD_INIT() до тела самой функции.
Код
void LCD_INIT ( void );
void LCD_INIT ( void )
{
...
}

И ещё совет: все прототипы лучше описывать в заголовочных файлах.
Go to the top of the page
 
+Quote Post
Panych
сообщение Apr 7 2008, 14:15
Сообщение #21


Местный
***

Группа: Свой
Сообщений: 335
Регистрация: 17-06-04
Из: Москва
Пользователь №: 35



gotty
спасибо, сделал функцию внешней, IAR ругнулся на то, что в функции было объявлено
Код
extern void DELAYMKS ();
extern void DELAYMS ();

а не
Код
extern void DELAYMKS ( unsigned long mks );
extern void DELAYMS ( unsigned long ms );

исправил и все вроде заработало...


--------------------
Всегда не хватает времени, чтобы выполнить работу как надо, но на то, чтобы ее переделать, время находится. (Закон Мескимена.)
Go to the top of the page
 
+Quote Post
alux
сообщение Apr 8 2008, 12:04
Сообщение #22


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Цитата(gotty @ Apr 7 2008, 16:45) *
И ещё совет: все прототипы лучше описывать в заголовочных файлах.
... и чтобы исключить многократные включения заголовочных файлов в начале каждого хидера применять "заглушку" типа:
Код
#ifndef XXX_H
#define XXX_H

..................

#endif
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Apr 8 2008, 12:11
Сообщение #23


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(Panych @ Apr 7 2008, 17:15) *
gotty
спасибо, сделал функцию внешней, IAR ругнулся на то, что в функции было объявлено
Код
extern void DELAYMKS ();
extern void DELAYMS ();

очень правильно ругнулся, ибо () означает void, а вы туда переменные суёте...


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
ivainc1789
сообщение Apr 9 2008, 15:09
Сообщение #24


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

Группа: Свой
Сообщений: 1 175
Регистрация: 5-01-05
Пользователь №: 1 807



Тема о многостраничных файлах, задам и свой махонький вопрос. А как описать внешние метки? Например, в main.c у меня описана метка Sleep. В другом файле модуля есть необходимость в безусловном переходе на Sleep типа goto Sleep. Сходу в документации не нашел как " ласково попросить" компилятор считать метку Sleep внешней? Конструкции типа extern label Sleep естественно не прокатывают...
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Apr 9 2008, 15:51
Сообщение #25


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Цитата(ivainc1789 @ Apr 9 2008, 19:09) *
Тема о многостраничных файлах, задам и свой махонький вопрос. А как описать внешние метки? ...

#include <setjmp.h>
Описание можно посмотреть например здесь http://www.freetype.org/david/reliable-c.html#annex-A

Но можно вопрос - а зачем вам это надо???
Go to the top of the page
 
+Quote Post
rezident
сообщение Apr 9 2008, 21:55
Сообщение #26


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(ivainc1789 @ Apr 9 2008, 21:09) *
Тема о многостраничных файлах, задам и свой махонький вопрос. А как описать внешние метки? Например, в main.c у меня описана метка Sleep. В другом файле модуля есть необходимость в безусловном переходе на Sleep типа goto Sleep. Сходу в документации не нашел как " ласково попросить" компилятор считать метку Sleep внешней? Конструкции типа extern label Sleep естественно не прокатывают...
bb-offtopic.gif Жесть! 07.gif Использование goto в программах на Си вообще считается моветоном, а чтобы еще и скакать по goto из одного файла в другой мне бы вообще в голову не пришло cranky.gif
Насколько я понимаю метка всегда привязана к оператору или функции, поэтому ее область видимости ограничена этой самой функцией или модулем. В самом стандарте ANSI C про goto говорится что
Цитата
6.8.6.1 The goto statement
Constraints
1 The identifier in a goto statement shall name a label located somewhere in the enclosing
function. A goto statement shall not jump from outside the scope of an identifier having
a variably modified type to inside the scope of that identifier.

Т.е. стандартными средствами Си "прыгнуть" по goto, допустим, внутрь другой функции нельзя. Тем более нельзя для функции, описанной в другом модуле.
Go to the top of the page
 
+Quote Post
sKWO
сообщение Apr 13 2008, 10:55
Сообщение #27


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Добрый день!
Многофайловый проект, чёрт по.....
Подскажите, как обойти ошибку, извиняюсь что может быть повторяюсь.
Просто переопределения нигде не вижу, понимаю что чтото с включением файлов, пытался экстернить
но не помогло. Прикреплю проджект на всякий случай. Спросил на телесисах, но там молчок 05.gif
Error[e27]: Entry "EN" in module driver_lcd ( C:\Program Files\IAR Systems\test\testlsd\Debug\Obj\driver_lcd.r90 )
redefined in module main ( C:\Program Files\IAR Systems\test\testlsd\Debug\Obj\main.r90 )
ИАР версия 4.хх.
имею след код
файл bitdef.h
Код
#ifndef    BITDEF_H    
#define    BITDEF_H
#ifndef    BOOL_t  
#define    BOOL_t
typedef uint8_t bool_t;
#endif // BOOL_t
#ifndef    BitStr_t
#define    BitStr_t
typedef volatile uint8_t * port_t;
typedef struct{
  port_t Port;
  bool_t Bit;
}Port_Bit;
#endif // BitStr_t
#pragma inline=forced
void SETDDR(const Port_Bit * pb){
  *(pb->Port-1) |= 1 << pb->Bit;
}
#endif //BITDEF_H

файл driver_lcd.c
Код
#ifndef    driver_lcd_C  
#define    driver_lcd_C
#include "driver_lcd.h"
#include "delay.h"
// Команда на настройку выводов управления линиями управления ЖКИ на выход
void lcd_CMND_port_out(void)    {
                                        SETDDR(RW);\
                                        SETDDR(EN);\
                                        SETDDR(RS);\
                };
#endif //driver_lcd_C

файл driver_lcd.h
Код
#ifndef    driver_lcd_H
#define    driver_lcd_H
#include "bitdef.h"
// "E" Clock
Port_Bit dEN={&PORTB, 3};
const Port_Bit * EN = &dEN;
void lcd_CMND_port_out(void);
#endif //driver_lcd_H


Сообщение отредактировал sKWO - Apr 13 2008, 10:58
Прикрепленные файлы
Прикрепленный файл  testlsd.zip ( 25.62 килобайт ) Кол-во скачиваний: 25
 


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
alux
сообщение Apr 13 2008, 14:08
Сообщение #28


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Цитата(sKWO @ Apr 13 2008, 13:55) *
файл driver_lcd.h
Код
#ifndef    driver_lcd_H
#define    driver_lcd_H
#include "bitdef.h"
// "E" Clock
Port_Bit dEN={&PORTB, 3};   <<<<<<<<!!!!!!!!!!
const Port_Bit * EN = &dEN;   <<<<<<<<!!!!!!!!!!
#endif //driver_lcd_H

У вас в driver_lcd.h вынесено определение указателя EN. И это, естественно, является причиной переопределения. Нарушено правило одного определения. Перенесите определения в driver_lcd.с, а в driver_lcd.h объявите эти переменные с модификатором extern.

PS. Это же касается и других переменных.
И уберите обратные слеши в определении lcd_CMND_port_out. Они там ни к чему.

PS2. И
Код
#ifndef    driver_lcd_C  
#define    driver_lcd_C
...
... это лишнее.
Go to the top of the page
 
+Quote Post
sKWO
сообщение Apr 13 2008, 18:14
Сообщение #29


Местный
***

Группа: Участник
Сообщений: 355
Регистрация: 27-03-07
Из: Україна, Чуднів
Пользователь №: 26 530



Цитата(alux @ Apr 13 2008, 17:08) *
У вас в driver_lcd.h вынесено определение указателя EN. И это, естественно, является причиной переопределения. Нарушено правило одного определения. Перенесите определения в driver_lcd.с, а в driver_lcd.h объявите эти переменные с модификатором extern.

Спасибо добрый чел, а то как-то грустно было вместо файла driver_lcd.h в мейне подключать файл driver_lcd.c. Так компилится без ошибок. Поэтому и было
Код
#ifndef    driver_lcd_C  
#define    driver_lcd_C

smile.gif smile.gif smile.gif smile.gif
Сам знаю что не правильно, а с меня пиво beer.gif , щас программы нету под рукой но думаю что вопрос будет закрыт


--------------------
нельзя недооценивать предсказуемость глупости
Go to the top of the page
 
+Quote Post
Непомнящий Евген...
сообщение Apr 14 2008, 04:44
Сообщение #30


Знающий
****

Группа: Свой
Сообщений: 771
Регистрация: 16-07-07
Из: Волгодонск
Пользователь №: 29 153



Цитата(sKWO @ Apr 13 2008, 14:55) *
Код
typedef uint8_t bool_t;
...
typedef struct{
  port_t Port;
  bool_t Bit;
}Port_Bit;
...
Port_Bit dEN={&PORTB, 3};


Странно как то - eсли вы объявили тип bool_t, то зачем туда запихивать 3????

И вообще, ИМХО, очень уж у вас сложный способ устанавливать биты в порту smile.gif
Может быть, конечно, ваш компилятор все это соптимизирует...

И еще вопросик - зачем вам такие конструкции:
Цитата
Код
#ifndef    BOOL_t  
#define    BOOL_t
typedef uint8_t bool_t;
#endif // BOOL_t

У вас bool_t что, в разных h-файлах объявляется? Объявляйте только в одном, и затем включайте везде, куда надо. Код сильно упростится...
Go to the top of the page
 
+Quote Post

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

 


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


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