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

 
 
 
Reply to this topicStart new topic
> Как в модуле Си увидеть функцию, объявленную в другом
NikP
сообщение Jun 17 2013, 04:25
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 168
Регистрация: 25-08-05
Пользователь №: 7 944



Изучаю STM32. Взял пример с сайта STM для STM322xG-EVAL, в котором шина USB используется как виртуальный COMport, и пытаюсь его немного переделать. Хочу, чтоб при нажатии кнопки на клавиатуре контроллер передавал компьютеру в ЦИКЛЕ массив из цифр 1-32, при повторном нажатии- чтоб останавливался. Возникла проблема: когда я пытаюсь организовать передачу из main вызывая функцию VCP_DataТx, то программа не компилируется - пишет либо "функция не определена" при простом вызове VCP_DataTx (), либо "недопустимо двойное определение" - на определение функции как "extern uint16_t VCP_DataTx ();". Функция VCP_DataTx () определена в исходной программе в модуле usbd_cdc_vcp.c . Как правильно поступить в данной ситуации?
Go to the top of the page
 
+Quote Post
Marto
сообщение Jun 17 2013, 04:30
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 103
Регистрация: 17-05-09
Из: Ижевск
Пользователь №: 49 190



подключить соотвествующий заголовочный файл (там где её прототип, должно называться usbd_cdc_vcp.h)?


--------------------
Шизоидный холерик
Go to the top of the page
 
+Quote Post
NikP
сообщение Jun 17 2013, 05:46
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 168
Регистрация: 25-08-05
Пользователь №: 7 944



Попробовал. Компиляция прошла с предупреждением: warning: #223-D: function "VCP_DataTx" declared implicitly. А линковщик выдал ошибку:
Error: L6218E: Undefined symbol VCP_DataTx (referred from app.o). Это можно обойти?
Go to the top of the page
 
+Quote Post
Flexz
сообщение Jun 17 2013, 06:21
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 252
Регистрация: 9-10-08
Из: Московская обл.
Пользователь №: 40 797



В файле usbd_cdc_vcp.c функция VCP_DataTx определена как static. Поэтому ее нельзя использовать в другом модуле, уберите static в объявлении и тогда можно будет подцепить ее в другом модуле.
Go to the top of the page
 
+Quote Post
NikP
сообщение Jun 17 2013, 06:28
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 168
Регистрация: 25-08-05
Пользователь №: 7 944



Меня смущает определение "static". Наверно, при написании программы его ввели с определённой целью. Если я его уберу, то не появятся новые "косяки"?
Go to the top of the page
 
+Quote Post
Marto
сообщение Jun 17 2013, 06:28
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 103
Регистрация: 17-05-09
Из: Ижевск
Пользователь №: 49 190



Весьма странно. Нет ли на VCP_DataTx() модификатора static?
Надо бы проект выложит сюда.

__
упс, уже опередили.
косяки не появятся, static нужен для того, чтобы отрубать доступ к функции вне единицы трансляции.


--------------------
Шизоидный холерик
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 17 2013, 06:36
Сообщение #7


Гуру
******

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



QUOTE (NikP @ Jun 17 2013, 09:28) *
Меня смущает определение "static". Наверно, при написании программы его ввели с определённой целью. Если я его уберу, то не появятся новые "косяки"?
Исходников не видел, но ваши рассуждения кажутся мне очень и очень логичными. Отсюда следует вывод - для передачи данных из вашего, пользовательского кода предусмотрена другая функция. И вам надо ее найти.


--------------------
На любой вопрос даю любой ответ
"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
Flexz
сообщение Jun 17 2013, 07:25
Сообщение #8


Местный
***

Группа: Свой
Сообщений: 252
Регистрация: 9-10-08
Из: Московская обл.
Пользователь №: 40 797



Цитата(Сергей Борщ @ Jun 17 2013, 10:36) *
Отсюда следует вывод - для передачи данных из вашего, пользовательского кода предусмотрена другая функция.

Не предусмотрена. Этот пример - банальный переходник USB-UART. Указанная функция вызывается из прерывания по RXNE и берет данные из UART, что бы передавать ей свои данные ее нужно слегка переписать.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 17 2013, 08:04
Сообщение #9


Гуру
******

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



QUOTE (Flexz @ Jun 17 2013, 10:25) *
Не предусмотрена.
...
чтобы передавать ей свои данные ее нужно слегка переписать.
Значит это пример того, как не надо писать программы.


--------------------
На любой вопрос даю любой ответ
"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
NikP
сообщение Jun 18 2013, 17:13
Сообщение #10


Частый гость
**

Группа: Участник
Сообщений: 168
Регистрация: 25-08-05
Пользователь №: 7 944



Иногда полезно обращаться к первоисточникам: почитал про то, как определяются функции, переопределил VCP_DataTx() как extern (вместо static) в модуле usbd_cdc_vcp.c , и всё прекрасно увиделось из модуля app.c ( из main). Может кому пригодится этот опыт.
Go to the top of the page
 
+Quote Post
Lagman
сообщение Jun 18 2013, 18:46
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245



Что это за первоисточник такой? Если в объявлении функции отсутствует спецификатор класса памяти, то по умолчанию принимается класс extern. Вам написали, что надо сделать заголовочный файл в котором перечислить прототипы функций, которые вы хотите использовать не только в текущем исходном файле, и уже подключать это заголовочный файл к другим исходным файлам (это все с условием что нет static)
Заголовочный файл
Go to the top of the page
 
+Quote Post
NikP
сообщение Jun 19 2013, 04:31
Сообщение #12


Частый гость
**

Группа: Участник
Сообщений: 168
Регистрация: 25-08-05
Пользователь №: 7 944



Я далеко не специалист в программировании, и не особо настаиваю на правильности того, что написал. Может, это совсем неправильно с точки зрения программирования на Си. Просто на практике так сделал - и заработало, без сбоев и тормозов.
Сведения же я взял так : набрал в яндексе "static в си" и первая ссылка оказалась helloworld.ru›texts/comp/lang/c/c/h16.htm .
Там и прочитал следующее :
"Спецификатор класса памяти в объявлении переменной может быть auto, register, static или extern. Если класс памяти не указан, то он определяется по умолчанию из контекста объявления. " и далее
"При объявлении переменной на внутреннем уровне может быть использован любой из четырех спецификаторов класса памяти, а если он не указан, то подразумевается класс памяти auto. "
Go to the top of the page
 
+Quote Post
XVR
сообщение Jun 19 2013, 08:38
Сообщение #13


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Цитата(NikP @ Jun 18 2013, 21:13) *
переопределил VCP_DataTx() как extern (вместо static) в модуле usbd_cdc_vcp.c , и всё прекрасно увиделось из модуля app.c ( из main).
Если автор программы определил в модуле функцию как static, это значит, что он не предполагал, что этой функцией будут пользоваться снаружи модуля. Когда вы сделали ее extern, до нее стало можно добраться и снаружи, но намерения первоначального автора модуля при этом не изменились rolleyes.gif
Так что позвать вы ее (функцию) теперь можете, но последствия этого вызова целиком на вашей совести.


Яркий пример - вы вытащили наружу функцию, которая работает с регистрами какого то аппаратного модуля и вызывается только из прерываний. Вызов этой функции снаружи (не из прерывания) может нарушить работу этого самого модуля, если в процессе ее вызова произойдет прерывание, и обработчик снова позовет эту функцию.
Go to the top of the page
 
+Quote Post
NikP
сообщение Jun 19 2013, 10:38
Сообщение #14


Частый гость
**

Группа: Участник
Сообщений: 168
Регистрация: 25-08-05
Пользователь №: 7 944



Цитата(XVR @ Jun 19 2013, 12:38) *
Яркий пример - вы вытащили наружу функцию, которая работает с регистрами какого то аппаратного модуля и вызывается только из прерываний.

Точно, на такие грабли я уже наступал. Спасибо за напоминание.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 09:55
Рейтинг@Mail.ru


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