Kompozytowe urządzenia USB na mikrokontrolerach z serii LPC134x
Deskryptor urządzenia w przykładowym programie
Polami deskryptora urządzenia definiującymi urządzenie są: klasa urządzenia, podklasa i protokół (patrz: fragment kodu poniżej zaznaczony na czerwono). Pola te tworzą Multi-Interface Function Class Code, a ich wartości wynoszą odpowiednio 0xEF, 0x02 i 0x01. Stała USB_DEVICE_CLASS_MISCELLANEOUS ma wartość 0xEF.
/* Standardowy deskryptor urządzenia USB */
const uint8_t USB_DeviceDescriptor[] = {
USB_DEVICE_DESC_SIZE, /* bLength */
USB_DEVICE_DESCRIPTOR_TYPE, /* bDescriptorType */
WBVAL(0x0200), /* 2.0 */ /* bcdUSB */
USB_DEVICE_CLASS_MISCELLANEOUS, /* bDeviceClass */
0x02, /* bDeviceSubClass */
0x01, /* bDeviceProtocol */
USB_MAX_PACKET0, /* bMaxPacketSize0 */
WBVAL(USB_VENDOR_ID), /* idVendor */
WBVAL(USB_PROD_ID), /* idProduct */
WBVAL(USB_DEVICE), /* 1.00 */ /* bcdDevice */
0x01, /* iManufacturer */
0x02, /* iProduct */
0x03, /* iSerialNumber */
0x01 /* bNumConfigurations: jedna możliwa konfiguracja*/
};
Deskryptor przypisania interfejsu w przykładowym programie
Interface Association Descriptor (IAD) przypisuje kilka interfejsów do jednej funkcji lokalnej. W omawianym przypadku mamy dwa interfejsy CDC (komunikacja i dane) i pojedynczą funkcję logiczną, odpowiadającą klasie urządzeń CDC.
Gdyby urządzenie to nie było urządzeniem kompozytowym, kod klasy urządzenia zdefiniowany w deskryptorze urządzenia byłby ustawiony na USB_DEVICE_CLASS_MISCELLANEOUS, co daje automatyczne przypisanie i nie byłoby potrzeby używania deskryptora IAD. System operacyjny próbowałby wtedy załadować osobne sterowniki dla każdego z interfejsów CDC.
/* deskryptor IAD służący do przypisania interfejsów CDC */
USB_INTERFACE_ASSOCIATION_DESC_SIZE, /* bLength */
USB_ASSOCIATION_DESCRIPTOR_TYPE, /* bDescriptorType */
USB_CDC_CIF_NUM, /* bFirstInterface */
2, /* bInterfaceCount */
USB_DEVICE)CLASS_COMMUNICATIONS, /* bFunctionClass */
CDC_ABSTRACT_CONTROL_MODEL, /* bFunctionSubClass */
0, /* bFunctionProtocol */
0, /* iFunction (indeks deskryptora znakowego opisującego tę funkcję */
Przedstawiony IAD przypisuje dwa interfejsy nadając polu bFirstInterface wartość USB_CDC_CIF_NUM będącą numerem pierwszego interfejsu, a polu bInterfaceCount (odpowiedzialnemu za liczbę interfejsów) wartość dwa.
UWAGA: Przypisanie wielu interfejsów jest możliwe tylko dla interfejsów numerowanych kolejno, a przedstawiony powyżej deskryptor IAD musi zostać umieszczony bezpośrednio przed interfejsami, do których się odnosi. |
Załączony przykładowy program
Kod załączonego przykładu znajduje się w folderze usbcomp_msd_cdc. Zawiera funkcję main() z nieskończoną pętlą oraz zestaw bibliotecznych funkcji wspomagających i implementujących podstawowy stos urządzenia USB oraz obsługę klas CDC/ACM oraz MSD.
Funkcja main() przeprowadza jednorazowo inicjalizację stosu USB i klas, a następnie przechodzi do pętli, w której przetwarzane są znaki z kanału komunikacyjnego. Obsługa pamięci masowej oraz nadawanie i odbiór znaków są oparte na przerwaniach.
Funkcje odczytu i pisania do pamięci masowej pracują na buforze RAM o rozmiarze tylko 4kB, wbudowana pamięć flash nie jest używana.
Aby uruchomić przykładowy kod należy podłączyć do płytki LPCXpresso przewód USB i zaprogramować mikrokontroler na płytce. Po zaprogramowaniu i uruchomieniu programu, komputer rozpozna najpierw urządzenie USB typu pamięć masowa i zamontuje nowy napęd dyskowy zawierający plik tekstowy. Następnie rozpozna urządzenie USB typu „VCOM” i zapyta o sterownik. Należy wskazać systemowi plik .inf znajdujący się w folderze usbcomp_msd_cdc, a Windows zainstaluje domyślny sterownik szeregowy USB.
W tym momencie na nowo zamontowanym dysku powinno się dać zapisywać i odczytywać pliki, a jednocześnie przez wirtualny port COM wysyłać i odbierać znaki. Szybkość transmisji powinna być taka, jak zostało to skonfigurowane dla portu CDC.
Jedynym problemem, jaki może wystąpić przy próbie użycia przykładowego programu jest instalacja sterowników w systemie Windows. Jako że wszystkie przykładowe projekty wykorzystują te same identyfikatory Vendor ID oraz Product ID, jeśli najpierw próbujemy uruchomić przykład urządzenia HID (Human Interface Device), a następnie urządzenia CDC, Windows może spróbować zastosować sterownik HID dla urządzenia CDC. Aby sobie z tym poradzić, należy odinstalować urządzenie HID w Menadżerze Urządzeń Windows, odłączyć płytkę od komputera i podłączyć ją ponownie. Windows powinien wtedy zidentyfikować urządzenie poprawnie i zainstalować prawidłowy sterownik.
Opisywany projekt wykorzystuje kod z biblioteki CMSISv1p30_LPC13xx (dla plików CMSIS 1.30) i projekt zawierający tę bibliotekę musi istnieć w tej samej przestrzeni pracy (workspace), aby niniejszy projekt mógł się skompilować poprawnie. Dodatkowe informacje można znaleźć w komentarzach pliku config.h.
Szczegóły obsługi przykładowego programu w systemie Windows
Znajdujący się w folderze usbcomp_msd_cdc plik lpc14x-vcom.inf istnieje, aby pomagać przy ładowaniu właściwych sterowników USB w systemie Windows dla opisywanego urządzenia, co umożliwia mu pracę jako wirtualny port COM.
W pliku znajduje się linia zatytułowana [DeviceList], która wygląda następująco:
%DESCRIPTION%=LPC134xUSB, USB\VID_1FC9&PID_0003&MI_01
Linia ta przypisuje urządzeniu CDC plik systemowy sterownika usbser.sys i sprawia, że system ładuje ten sterownik w czasie procesu wyliczania (enumeration).
VID_1FC9 oraz PID_0003 to identyfikatory producenta i produktu dla tego urządzenia. Fragment MI_01 (MI oznacza Multiple Interface – wiele interfejsów) odnosi się do drugiego interfejsu w urządzeniu i mówi systemowi, aby przypisał ten interfejs ze sterownikiem, który jest ładowany. Urządzenie CDC jest drugim interfejsem, jego deskryptor interfejsu był drugi w kolejności po deskryptorze konfiguracji, jak to było opisane wcześniej.
Bibliografia
- Nota aplikacyjna NXP AN11018: USB composite device on the LPC134; 2010
- http://www.beyondlogic.org/usbnutshell/usb5.shtml#DeviceDescriptors
- USB Interface Association Descriptor Device Class Code and Use Model; 2003
- Specyfikacja USB 2.0
- Interface Association Descriptors Engineering Change Notice