|
|
  |
Как правильно создать многофайловый проект, Ошибка при линковке |
|
|
|
Dec 11 2007, 13:07
|

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

|
Цитата(alexander55 @ Dec 11 2007, 12:29)  Приятно сразу понять логику работы всей системы глядя на один модуль. У меня в main.c обычно находятся собственно main() и __low_level_init(). Глядя на main() можно попытаться понять логику работы всей системы, правда есть одно исключение  : Код int main() { OS::Run(); } Цитата(alexander55 @ Dec 11 2007, 12:29)  Детали находятся за рамками и если требуются, то понятно, где это можно посмотреть (глядя на модуль). Так RS232_transmit_handler() - это и есть детали. А логика описывается getchar(), putchar() и hasinput(). Мне так кажется... Цитата(SasaVitebsk @ Dec 11 2007, 12:58)  Прерывание - метки времени. То есть там целый набор.  в том числе вызовы опроса клавиатуры. В таком случае наименьшие накладные, наверное, можно получить если "набор" описать в заголовочных файлах как static inline функции.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Dec 11 2007, 13:39
|
Бывалый
    
Группа: Свой
Сообщений: 1 584
Регистрация: 7-08-07
Пользователь №: 29 615

|
Цитата(Сергей Борщ @ Dec 11 2007, 16:07)  У меня в main.c обычно находятся собственно main() и __low_level_init(). Глядя на main() можно попытаться понять логику работы всей системы, правда есть одно исключение  : Код int main() { OS::Run(); } Это логичный и устоявшийся модуль. Цитата(Сергей Борщ @ Dec 11 2007, 16:07)  Так RS232_transmit_handler() - это и есть детали. А логика описывается getchar(), putchar() и hasinput(). Мне так кажется... В данном случае так. Цитата(Сергей Борщ @ Dec 11 2007, 16:07)  В таком случае наименьшие накладные, наверное, можно получить если "набор" описать в заголовочных файлах как static inline функции. Или включить максимальную оптимизацию по требуемому параметру.
|
|
|
|
|
Apr 7 2008, 13:32
|
Местный
  
Группа: Свой
Сообщений: 335
Регистрация: 17-06-04
Из: Москва
Пользователь №: 35

|
Подниму тему, чтоб не плодить... Объявляю внешнюю функцию: Код extern void LCD_INIT ( void ); В main делаю вызов Код LCD_INIT(); Не работает. Вставляю в main тело функции - все работает. IAR не ругается и не предупреждает. Файлы прикрепил. Помогите понять, плиз
--------------------
Всегда не хватает времени, чтобы выполнить работу как надо, но на то, чтобы ее переделать, время находится. (Закон Мескимена.)
|
|
|
|
|
Apr 7 2008, 13:45
|
Знающий
   
Группа: Свой
Сообщений: 526
Регистрация: 24-08-07
Из: Беларусь, Минск
Пользователь №: 30 045

|
Цитата(Panych @ Apr 7 2008, 16:32)  Подниму тему, чтоб не плодить... Объявляю внешнюю функцию: Код extern void LCD_INIT ( void ); В main делаю вызов Код LCD_INIT(); Не работает. Вставляю в main тело функции - все работает. IAR не ругается и не предупреждает. В пятницу текст выводился, все вроде было именно так организовано - а в понедельник... Файлы прикрепил. Помогите понять, плиз  Судя по вашему проекту, функция LCD_INIT() у Вас не внешняя а очень даже локальная. Если уж решили разбивать проект на модули - доводите дело до конца, а не сводите все "модули" в один через #include. С минимальной правкой того что есть, можно перенести прототип функции LCD_INIT() до тела самой функции. Код void LCD_INIT ( void ); void LCD_INIT ( void ) { ... } И ещё совет: все прототипы лучше описывать в заголовочных файлах.
|
|
|
|
|
Apr 7 2008, 14:15
|
Местный
  
Группа: Свой
Сообщений: 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 ); исправил и все вроде заработало...
--------------------
Всегда не хватает времени, чтобы выполнить работу как надо, но на то, чтобы ее переделать, время находится. (Закон Мескимена.)
|
|
|
|
|
Apr 8 2008, 12:04
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

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

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

|
Цитата(Panych @ Apr 7 2008, 17:15)  gottyспасибо, сделал функцию внешней, IAR ругнулся на то, что в функции было объявлено Код extern void DELAYMKS (); extern void DELAYMS (); очень правильно ругнулся, ибо () означает void, а вы туда переменные суёте...
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Apr 9 2008, 15:51
|
Знающий
   
Группа: Свой
Сообщений: 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Но можно вопрос - а зачем вам это надо???
|
|
|
|
|
Apr 9 2008, 21:55
|
Гуру
     
Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882

|
Цитата(ivainc1789 @ Apr 9 2008, 21:09)  Тема о многостраничных файлах, задам и свой махонький вопрос. А как описать внешние метки? Например, в main.c у меня описана метка Sleep. В другом файле модуля есть необходимость в безусловном переходе на Sleep типа goto Sleep. Сходу в документации не нашел как " ласково попросить" компилятор считать метку Sleep внешней? Конструкции типа extern label Sleep естественно не прокатывают...  Жесть!  Использование goto в программах на Си вообще считается моветоном, а чтобы еще и скакать по goto из одного файла в другой мне бы вообще в голову не пришло  Насколько я понимаю метка всегда привязана к оператору или функции, поэтому ее область видимости ограничена этой самой функцией или модулем. В самом стандарте 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, допустим, внутрь другой функции нельзя. Тем более нельзя для функции, описанной в другом модуле.
|
|
|
|
|
Apr 13 2008, 10:55
|

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

|
Добрый день! Многофайловый проект, чёрт по..... Подскажите, как обойти ошибку, извиняюсь что может быть повторяюсь. Просто переопределения нигде не вижу, понимаю что чтото с включением файлов, пытался экстернить но не помогло. Прикреплю проджект на всякий случай. Спросил на телесисах, но там молчок 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
--------------------
нельзя недооценивать предсказуемость глупости
|
|
|
|
|
Apr 13 2008, 14:08
|
Знающий
   
Группа: Свой
Сообщений: 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 ... ... это лишнее.
|
|
|
|
|
Apr 13 2008, 18:14
|

Местный
  
Группа: Участник
Сообщений: 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 Сам знаю что не правильно, а с меня пиво  , щас программы нету под рукой но думаю что вопрос будет закрыт
--------------------
нельзя недооценивать предсказуемость глупости
|
|
|
|
|
Apr 14 2008, 04:44
|
Знающий
   
Группа: Свой
Сообщений: 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???? И вообще, ИМХО, очень уж у вас сложный способ устанавливать биты в порту  Может быть, конечно, ваш компилятор все это соптимизирует... И еще вопросик - зачем вам такие конструкции: Цитата Код #ifndef BOOL_t #define BOOL_t typedef uint8_t bool_t; #endif // BOOL_t У вас bool_t что, в разных h-файлах объявляется? Объявляйте только в одном, и затем включайте везде, куда надо. Код сильно упростится...
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|