vusb в c++ окружении

Может быть кому-то будет интересно. Чтобы использовать firmware в папке hid-custom-rq (vusb-20100715) не только в C, но и в C++ проекте, нужно в общие заголовочники добавить вот такую вещь (на примере usbdrv.h):
#ifndef __usbdrv_h_included__
#define __usbdrv_h_included__

#ifdef __cplusplus
extern "C" {
#endif

...

#ifdef __cplusplus
}
#endif

#endif /* __usbdrv_h_included__ */

Makefile я использую от Eric B. Weddington, Jцrg Wunsch. В разделе исходников C++ пишем так:
CPPSRC = usbdrv/usbdrv.c usbdrv/oddebug.c 
CPPSRC += ISRList.cpp MCU.cpp MainUnit.cpp

# List Assembler source files here.
#     Make them always end in a capital .S.  Files ending in a lowercase .s
#     will not be considered source files but generated files (assembler
#     output from the compiler), and will be deleted upon "make clean"!
#     Even though the DOS/Win* filesystem matches both .s and .S the same,
#     it will preserve the spelling of the filenames, and gcc itself does
#     care about how the name is spelled on its command-line.
ASRC = usbdrv/usbdrvasm.S

# List any extra directories to look for include files here.
#     Each directory must be seperated by a space.
#     Use forward slashes for directory separators.
#     For a directory that has spaces, enclose it in quotes.
EXTRAINCDIRS = usbdrv

В папку obj добавляем папку usbdrv. Туда будут скидываться промежуточные объектные файлы и файлы листингов драйвера usbdrv. Без этой папки появляются ругательные сообщения.

extern «C» нужен для того, чтобы «подружить» объектные файлы C++ и C. При компиляции у нас соберутся в одно целое модули из C++, C и асм исходников. Пробовать лучше на стандартном светодиодном примере из комплекта vusb-20100715.

Существует русифицированная версия этих файлов. К сожалению, по невыясненной причине после компиляции почему-то в таблице векторов не появляется jmp на ISR для INT0. Поэтому рекомендую использовать оригинальные файлы.

П.С. О чём это:
1. USB для AVR. Часть 1. Вводная
2. USB для AVR. Часть 2. HID Class на V-USB
  • +1
  • 07 января 2012, 20:28
  • uni

Комментарии (9)

RSS свернуть / развернуть
А про что это вообще?
0
  • avatar
  • Aneg
  • 07 января 2012, 20:51
Это про использование программного usb (vusb) в проектах на С++. Я пишу на плюсах и мне в лом было просто создавать новый шаблон для проекта на Си. Вместо этого я слегка изменил исходники vusb, чтобы я мог спокойно ваять код в привычной для себя среде на «плюсах».
В общем, это для тех, кто в теме.
0
ИМХО, гораздо полезнее было бы, если бы расписали причины и суть этих примочек. А то решение якобы для VUSB, а на самом деле — для всех проектов написанных на C++/C или C++/ASM.
0
  • avatar
  • amx
  • 09 января 2012, 10:42
Суть этих «примочек» не так проста, тем более я не знаю как именно это работает для асма. Я пишу на C++, причём уже давно. Поскольку мне нравится стиль написания таковых программ для ПК, а в особенности, срЕды программирования, то пытаюсь, как могу, приспособить привычное для меня окружение при программирование контроллеров. Всё равно всё идёт к этому, достаточно сравнить контроллеры сейчас и 10 лет назад. Взять к примеру двухтомник М. Предко «Руководство по микроконтроллерам» (кто знает) и сравнить его со статьями тут. Это земля и ближний космос :) А лет 40 назад если почитать, то там вообще машинные коды можно встретить в литературе.

Так вот, суть этой «примочки» в том, что объектные файлы Си и С++ отличаются. Связано это с тем, что плюсы имеют такую штуку как перегрузку методов, в связи с чем появляются проблемы на этапе связывания объектных модулей — компоновщик не может сделать разрешение ссылок, т.е. без этих примочек всё скомпилируется, но возникнут ошибки связывания. Компоновщик честно укажет, что такой-то модуль ссылается на такие-то функции, но они не обнаружены — декорирование имён разное. Поэтому нужно как-то указать, что сишные функции могут использоваться в С++ модулях. Это и делается при помощи extern «C» — т.е. при компиляции в С++ декорирование имён функций должно быть в стиле Си, тогда компоновщик по такому имени найдёт функцию в Си-модуле.

Многие боятся переходить на Си, т.к. думают, что старый код нельзя будет использовать или что-то в этом роде. Вот достаточно не сложный пример того, что при помощи простой обёртки в виде extern «C» в заголовочниках сишных модулей вполне можно даже usb-драйвер использовать в С++ программе. Даже больше, там в коде присутствует ассемблерный модуль, что также не помешало в сборке проекта.

По-моему, neiver тут один из немногих кто мог бы что-то сказать по этому поводу гораздо лучше меня. Я пока тестирую vusb на metaboard плате, когда придёт Pinboard II, думаю, смогу написать что-нибудь более полезное в этом смысле.
0
Да вроде тут особо больше и нечего сказать.
Кстати, если не ошибаюсь, в extern «C» достаточно завертывать только символы, а не весь заголовочник. Макросы и прочий пропроцессор обрабатываются идентично для С и С++.
0
У меня было всего три ошибки связывания после компиляции. Сначала я решил к каждой функции отдельно приписать extern «C», но так «портятся» оригинальные модули, т.к. потом и не вспомнишь какие делал модификации в файлах, поэтому взял сразу всё в фигурные скобки. Если посмотреть описание действия extern «C» {...} в рунете, то можно найти как это влияет на код в каждом конкретном случае. Насколько я помню, ничего нет страшного в том, что мы включаем весь код заголовочника в это объявление.

П.С. Проблему с INT0 я не понял, т.к. не знаком близко с ассемблером для IAR. Файл usbdrvasm.S содержит код для одновременной компиляции в двух средах (IAR и GCC), как известно, они много чем отличаются :) Так вот, в этом файле есть ISR для INT0 и поначалу я боялся, что объявление вектора прерывания в ассемблерном модуле может не попасть в конечную сборку. Так оно и было в первый раз, пока я не взял оригинальный набор (vusb), после чего в map-файле увидел нужный вектор в нужном месте (я сравнивал карту памяти в Си и С++ программе после компиляции). Проект в железе не заводился, Windows ругалась на неопознанное устройство. Логично было предположить только на эту ошибку, т.к. в остальном код был практически идентичным.

Теперь я точно знаю, что можно объявить вектора одновременно в С++, Си и асме (разные, конечно) и всё встанет на свои места.
0
Вот, кстати, тут всё расписано: Compatibility of C and C++
0
Надо же, оказывается всё гораздо проще можно сделать и это уже давно сделано тут:
USB флешка на ATmega8 и V-USB. От идеи к готовому устройству...
Там в main.cpp уже есть пример как подключать vusp к cpp-проекту (IAR).

Нужно просто обернуть включения си-шных заголовочников:
#ifdef __cplusplus
extern "C" {
#endif
    #include "usbdrv/usbdrv.h"
    // Подключаем модуль отладки
    #include "usbdrv/oddebug.h"
#ifdef __cplusplus
}
#endif
0
  • avatar
  • uni
  • 11 января 2012, 11:00
Здесь уже мона смело вымахивать ifdef. Т.е.:

extern "C" {
    #include "usbdrv/usbdrv.h"
    // Подключаем модуль отладки
    #include "usbdrv/oddebug.h"
}

Поскольку в main.cpp __cplusplus явно определен.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.