редактировать: см. мой ответ ниже
Я довольно новичок в платформе Arduino и сейчас создаю проект USB HID с библиотекой attiny85 (Trinket) AdaFruit. Смотрите также мой предыдущий ответ на вопрос об опциях этой библиотеки:
Изменить / Переопределить Брелок (attiny85) Идентификационное имя USB, имя устройства
Я поставлен в тупик из-за редкого ограничения, связанного с C (см. Также последний комментарий в ответе в ссылке выше на предыдущий вопрос), разделенного позднего связывания двоичных файлов путем раздельной компиляции. Если вы хотите изменить параметры USB-устройства, вы должны изменить саму библиотеку, что странно для меня, потому что это библиотека.
Например, если вы включаете заголовочный файл с измененными параметрами перед загрузкой библиотеки, ничего не изменится, потому что он неизвестен библиотеке, потому что он также должен быть включен в эту библиотеку.
Пример: это не работает:
#include "myUSBOptions.h"#include "TrinketHidCombo.h"
Другой подход:
Поэтому мне нужно изменить саму библиотеку для каждого проекта, в этом случае usbconfig.h
файл. Это звучит немного глупо для меня, потому что это библиотека и может использоваться другими проектами. Может быть, это ошибка дизайна в библиотеке Adafruit, такие вещи, как vendorname, devicename и т. д. должны быть необязательными ВНЕ этой библиотеки, а также ваши настройки могут быть перезаписаны при обновлении библиотеки. И … вам нужно снова отредактировать файл для каждого отдельного проекта.
Таким образом, у меня возникла идея включить дополнительный заголовочный файл в usbconfig.h
файл, #include "user_usbconfig.h"
это требует только одного изменения. Но это не единственный usbconfig.h
файл, доступно как минимум три версии! Создайте один файл user_usbconfig.h в каталоге проекта. Написал пакетный файл для его автоматизации и включите в каталог проекта, чтобы вы могли изменить параметры, просто щелкнув по нему при переключении проекта.
Добавлена строка в файлах usbconfig.h:
.......
#include "cmdline_defs.h"
#ifndef __usbconfig_h_included__
#define __usbconfig_h_included__
#include "user_usbconfig.h" // <-- added this
.......
Например, user_usbconfig.h включен в проект
/* DEVICE SETTINGS */
/* Version number of the device: Minor number first, then major number. */
#define USB_CFG_DEVICE_VERSION 0x00, 0x01/* VENDOR_NAME
* These two values define the vendor name returned by the USB device. The name
* must be given as a list of characters under single quotes. The characters
* are interpreted as Unicode (UTF-16) entities.
* If you don't want a vendor name string, undefine these macros.
* ALWAYS define a vendor name containing your Internet domain name if you use
* obdev's free shared VID/PID pair. See the file USB-IDs-for-free.txt for
* details.
*/
#define USB_CFG_VENDOR_NAME 'm', 'y', 'C', 'o', 'm', 'p', 'a', 'n', 'y', 'n'
#define USB_CFG_VENDOR_NAME_LEN 10/* DEVICE_NAME
* Same as above for the device name. If you don't want a device name, undefine
* the macros. See the file USB-IDs-for-free.txt before you assign a name if
* you use a shared VID/PID.
*/
#define USB_CFG_DEVICE_NAME 'm', 'y', 'D', 'e', 'v', 'i', 'c', 'e'
#define USB_CFG_DEVICE_NAME_LEN 8/* SERIAL_NUMBER
* Same as above for the serial number. If you don't want a serial number,
* undefine the macros.
* It may be useful to provide the serial number through other means than at
* compile time. See the section about descriptor properties below for how
* to fine tune control over USB descriptors such as the string descriptor
* for the serial number.
*/
/*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */
/*#define USB_CFG_SERIAL_NUMBER_LEN 0 */
Пример исходного кода myProject.ino, ничего не делает, кроме активации USB:
#include "TrinketHidCombo.h"
void setup()
{
TrinketHidCombo.begin();
}
void loop() // Main program - main()
{
// do nothing, check if USB needs anything done
TrinketHidCombo.poll();
}
Пакетный файл, который я создаю, добавлен в каталог проекта:
@echo off
rem ********************************************************
rem * setTrinketUSBLibraryOptions.bat *
rem * ---------------------------------------------------- *
rem * Author : Erwin Haantjes *
rem * Project : Arduino Trinket USB *
rem * Dev date : 11-06-2016 *
rem * Last changed : 11-06-2016 *
rem * What it do : 'Copy' (link) USB options project to *
rem * Trinket lib to make settings optional.*
rem * *
rem ********************************************************rem *** Config parts that can be modified if required
SET ARDUINO_LIB_DIR=F:\Program Files\Arduino\DigiSpark\Digispark-Arduino-1.0.4\libraries
SET USER_HEADER_FILE=user_usbconfig.h
SET ATU_HEADER_FILE=usbconfig.h
SET ATU_DIRNAME1=TrinketHidCombo
SET ATU_DIRNAME2=TrinketKeyboard
SET ATU_DIRNAME3=TrinketMouse
SET ATU_HEADER_FILE1=%ARDUINO_LIB_DIR%\%ATU_DIRNAME1%\%ATU_HEADER_FILE%
SET ATU_HEADER_FILE2=%ARDUINO_LIB_DIR%\%ATU_DIRNAME2%\%ATU_HEADER_FILE%
SET ATU_HEADER_FILE3=%ARDUINO_LIB_DIR%\%ATU_DIRNAME3%\%ATU_HEADER_FILE%
SET ATU_USER_HEADER_FILE1=%ARDUINO_LIB_DIR%\%ATU_DIRNAME1%\%USER_HEADER_FILE%
SET ATU_USER_HEADER_FILE2=%ARDUINO_LIB_DIR%\%ATU_DIRNAME2%\%USER_HEADER_FILE%
SET ATU_USER_HEADER_FILE3=%ARDUINO_LIB_DIR%\%ATU_DIRNAME3%\%USER_HEADER_FILE%
rem *** START
echo.
echo.
echo Set Thrinket USB Library options to match your project
echo ------------------------------------------------------
echo.
if "@%1"=="@/?" goto USAGE
if "@%1"=="@-?" goto USAGE
goto INTRO
:USAGE
SET USAGEMODE=true
echo Created by Erwin Haantjes 2016
echo.
echo USAGE:
echo %0 [/?,/C,-?,-C]
echo.
echo SWITCHES:
echo - ? Shows this help
echo - C Use copy command instead of symlink to hardcopy the "%USER_HEADER_FILE%" to it's targets
echo.
:INTRO
rem *** WARNING and NOTICE
echo WARNING:
echo - This batch changes/symlink options to be able to config the Trinket USB Library by project easily. Run this file once each time you work on a project to be sure you are using the right settings.
echo - If a physical %USER_HEADER_FILE% file exists in the library directory, it will be deleted!
echo.
echo NOTICE:
echo - Each "%ATU_HEADER_FILE%" file in (parts/the) Trinket USB library must include the line: #include "%USER_HEADER_FILE%" at top of the file after #define __usbconfig_h_included__ .
echo - Once applying this 'patch', you can change USB settings in the "%USER_HEADER_FILE%" file in this directory on the fly without the need to run this batch again. Just compile it after a change and your changes will be 'visible'.
echo.
echo.
echo Library directory is set to:
echo %ARDUINO_LIB_DIR%
echo.
echo.
if "%USAGEMODE%"=="true" goto END
echo Do you want to continue? Press any key.
pause >NUL
echo.
rem *** Check destinations
if exist "%USER_HEADER_FILE%" goto NEXT1
goto ERROR_NO_USER_FILE
:NEXT1
if exist "%ATU_HEADER_FILE1%" goto NEXT2
goto ERROR_LIB_NOT_EXISTS
:NEXT2
if exist "%ATU_HEADER_FILE2%" goto NEXT3
goto ERROR_LIB_NOT_EXISTS
:NEXT3
if exist "%ATU_HEADER_FILE3%" goto NEXT4
goto ERROR_LIB_NOT_EXISTS
:NEXT4
goto APPLY
rem *** ERRORS
:ERROR_NO_USER_FILE
echo ERROR: Create a "%USER_HEADER_FILE%" in this directory first.
goto ABORTED
:ERROR_LIB_NOT_EXISTS
echo %ATU_HEADER_FILE1%
echo ERROR: Check the directory location match your Arduino IDE setup, see "ARDUINO_LIB_DIR" at top of this batch file. Check also if you have the Trinket USB Library currently installed.
goto ABORTED
:APPLY
echo All seems to be fine, applying patch (symlinks).....
echo Checking and removing target files....
if exist "%ATU_USER_HEADER_FILE1%" goto REMOVE1
goto APPLY_NEXT2
:REMOVE1
echo Remove symlink of "%ATU_USER_HEADER_FILE1%" ....
del "%ATU_USER_HEADER_FILE1%"
:APPLY_NEXT2
if exist "%ATU_USER_HEADER_FILE2%" goto REMOVE2
goto APPLY_NEXT3
:REMOVE2
echo Remove symlink of "%ATU_USER_HEADER_FILE2%" ....
del "%ATU_USER_HEADER_FILE2%"
:APPLY_NEXT3
if exist "%ATU_USER_HEADER_FILE3%" goto REMOVE3
goto APPLY_NEXT
:REMOVE3
echo Remove file/symlink of "%ATU_USER_HEADER_FILE3%" ....
del "%ATU_USER_HEADER_FILE3%"
:APPLY_NEXT
echo.
if "@%1"== "@/c" goto APPLY_COPY
if "@%1"== "@/C" goto APPLY_COPY
if "@%1"== "@-c" goto APPLY_COPY
if "@%1"== "@-C" goto APPLY_COPY
echo Applying symlinks....
mklink /H "%ATU_USER_HEADER_FILE1%" "%USER_HEADER_FILE%"mklink /H "%ATU_USER_HEADER_FILE2%" "%USER_HEADER_FILE%"mklink /H "%ATU_USER_HEADER_FILE3%" "%USER_HEADER_FILE%"goto SUCCESS
:APPLY_COPY
echo Copy file(s)....
copy "%USER_HEADER_FILE%" "%ATU_USER_HEADER_FILE1%"copy "%USER_HEADER_FILE%" "%ATU_USER_HEADER_FILE2%"copy "%USER_HEADER_FILE%" "%ATU_USER_HEADER_FILE3%"SET COPYMODE=true
goto SUCCESS
:ABORTED
echo Batch aborted due error.
goto END
:SUCCESS
echo.
echo SUCCESS!
echo NOTICE:
echo - Patch succesfully applied when no error is visible on screen.
if "%COPYMODE%"=="true" echo - Because you specify the copymode switch, you have to take care of updates yourself. Run this batch file again when you have changed USB settings.
:END
SET USAGEMODE=
SET COPYMODE=
echo.
echo Press any key to exit...
pause >NUL
:DIE
echo.
Вывод и вопрос:
Хотя этот метод работает нормально, я все еще не удовлетворен и задаюсь вопросом, есть ли более простой способ без изменения какой-либо строки кода библиотеки. Более «на ходу» решение, так что вам не нужно думать об этом, чтобы избежать ошибок и других головных болей.
После долгого времени я узнаю, как компилятор Arduino компилирует код. Это не проблема C / C ++, на самом деле это ошибка в компиляторе Arduino, порядок объединения и компиляции. Также компилятор добавляет определенный код перед компиляцией.
Временное решение:
Включите ваши библиотеки / независимости с использованием h-файла проекта exra. Defines before include не будет работать, потому что метод compile включает h-файлы до того, как будут применены определения (в вашем ino-файле). При использовании определений, например, для изменения библиотеки требуется отдельный h-файл. Например, «myproject.inc.h», который включает в себя все библиотеки, которые вы хотите использовать.
Теперь все определения, которые вы укажете до включения библиотеки, будут применены.
Пример:
myproject.ino
#include "myproject.inc.h"
void setup()
{
TrinketHidCombo.begin();
}
void loop() // Main program - main()
{
// do nothing, check if USB needs anything done
TrinketHidCombo.poll();
}
myproject.inc.h
#define USB_CFG_VENDOR_NAME 'm', 'y', 'C', 'o', 'm', 'p', 'a', 'n', 'y', 'n'
#define USB_CFG_VENDOR_NAME_LEN 10
#include "TrinketHidCombo.h"
Других решений пока нет …