Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Implementacja USB we wlasnym urzadzeniu ze sterownikiem WinUsb

oloam 09 May 2021 20:03 2715 13
  • Postanowilem podzielic sie z wami moimi doswiadczeniami wykorzystania interfejsu USB we wlasnych projektach.
    Jak wiadomo interfejs USB jest juz powszechnie dolaczanym interfejsem do mikrokontrolerow wiekszosci producentow na rynku.
    Sama obsluga USB zarowno po stronie mikrokontrolera jak i pc (a wlasciwie Windows) jest mniej przyjazna niz w wiekszosci uzywane do jej pory polaczenie rs232 (wlaczajac w to przejsciowki rs232<->usb).

    Po stronie mikrokontrolera producenci czesto dolaczaja przyklady obslugi USB jednak dotycza one konkretnych klas : HID, MSC, DFU, VPC.
    My jednak chcemy prosta komunikacje dwukierunkowa - wyslij, odbierz - tzw komunikacje bulk. Do tego celu pokaze jak przerobic klase VPC gdyz ona posiada to czego potrzebujemy - 2 endpointy (in,out) transmisji bulk. Natomiast wytniemy z deskryptorow endpoint komend i zmienimy klase z VCP na tzw Vendor class.

    Po stronie Windows sprawa jest bardziej skomplikowana, gdyz najpierw musimy 'znalezc' nasze urzadzenie w systemie wykorzystujac biblioteke systemowa SetupApi.dll a pozniej sterowac nim za pomoca funkcji biblioteki naszego drivera czyli WinUSB.dll. Zeby ulatwic programowanie dla tych, ktorzy czuja, ze nie dadza rady nawiazac polaczenia ze swoim urzadzeniem, napisalem prosta biblioteke dll, ktora sie podziele i opisze jej funkcje (w sumie cztery), ktore zapewnia komunikacje z naszym urzadzeniem.

    I. Mikrokontroler

    Jak napisalem wyzej, bede zmienial deskryptory klasy VCP. Platforma testowo-pokazowa bedzie CubeIde i mikrokontroler stm32f042. Jednak zmiana dekryptorow dotyczy kazdego sprzetu i producenta uc. Z powodzeniem testowalem to na mikrokontrolerach ST, NXP i TI.

    Zaczynamy:
    Tworzymy nowy projekt w CubeIde, konfigurujemy uc wg naszych potrzeb, wlaczamy USB w drzewie Connectivity a w drzewie Middleware USB_DEVICE ustawiamy na Communication Device Class (Virtual Port Com).
    Generujemy kod.
    Otwieramy plik usbd_cdc.c (Middlewares\ST\STM32_USB_Device_Library\Class\CDC\Src)
    W pliku przechodzimy linijki:
    Code: c
    Log in, to see the code

    Jest to deskryptor dla urzadzen HS. Wszystkie modyfikacje beda pokazane 'od gory' deskryptora.
    Zmieniamy ilosc interfejsow w linice:
    Code: c
    Log in, to see the code
    na 0x01
    komentujemy wszystko od linijki:
    Code: c
    Log in, to see the code

    do:
    Code: c
    Log in, to see the code

    W pozostalym niezakomentowanym kodzie zmieniamy wartosci:
    Code: c
    Log in, to see the code
    na 0x00
    Code: c
    Log in, to see the code
    na 0xFF

    Powyzsze powtazamy dla deskryptorow:
    USBD_CDC_CfgFSDesc i USBD_CDC_OtherSpeedCfgDesc

    Jako ze zmienila nam sie dlugosc deskryptora musimy zmienic wartosc zmiennej:
    USB_CDC_CONFIG_DESC_SIZ w pliku usbd_cdc.c (Middlewares\ST\STM32_USB_Device_Library\Class\CDC\Inc) z 67 na 32

    Wlasciwie to juz wszystko. Zalecam jednak zmiane VID i PID oraz opisy urzadzenia w pliku usbd_desc.c (USB_DEVICE\App)
    Ponizej filmik pokazujacy co do tej pory trzeba zrobic:

    Po wgraniu wsadu do uc i podlaczeniu do PC w managerze urzadzen powinnismy zobaczyc nasze urzadzenie.
    Implementacja USB we wlasnym urzadzeniu ze sterownikiem WinUsb

    II. Windows
    Do zainstalowania sterownikow proponuje wykorzystac program Zadig. Nie tylko zainstaluje nam sterowniki ale rowniez stworzy pakiet instalacyjny na inne PC.
    W tym kroku nie ma zbytnio co opisywac wiec znowu filmik:

    Po zainstalowaniu sterownikow w latalogu C:\Users\naszanazwauzytkownika\usb_driver pojawia sie paczka sterownikow dla naszego urzadzenia.
    Wlasciwie to juz wszystko - mozna zaczac pisac programy wymieniajace sie danymi z naszym urzadzeniem.
    Aby zobaczyc jak napisac przykladowa komunikacje PC<->nasze urzadzenie zapraszam do daleszj czesci artykulu.

    III.Komunikacja

    Do nawizania komunikacji uzyje napisanej przeze mnie biblioteki i srodowiska Delphi 10.3 (dzialanie biblioteki sprawdzilem rowniez piszac aplikacje na Visual Studio).
    Zaczne moze od opisu biblioteki.
    Biblioteka exportuje 4 funkcje:
    Code: delphi
    Log in, to see the code

    UsbDevInfo jest to rekord/struktura:
    Code: delphi
    Log in, to see the code


    Po przypisaniu zmiennej typu UsbDevInfo do funkcji UsbDevOpen wszystkie pola sa automatycznie ustawiane i jedynie najlepiej tylko modyfikowac pole timeout, ktore domyslnie ustawiane jest na 100.

    W delphi tworzymy nowy projekt. Na formatke wrzucamy button i memo. Deklarujemy nasz rekord, zmienna (globalna) tego rekordu i GUID naszego urzadzenia, ktore wezmiemy z katalogu sterownika z pliku .inf z linijki DeviceGUID:
    Code: delphi
    Log in, to see the code

    Importujemy wszystkie funkcje z biblioteki oloamusb.dll :
    Code: delphi
    Log in, to see the code

    W OnCreate formy:
    Code: delphi
    Log in, to see the code

    OnClick przycisku:
    Code: delphi
    Log in, to see the code

    W OnClose formy:
    Code: delphi
    Log in, to see the code

    Program gotowy. Oczywiscie nie ma tu sprawdzenia czy urzadzenie zostalo wykryte (czy uchwyt di.husb > 0)
    Zawartosc unitu - caly program:
    Code: delphi
    Log in, to see the code


    Po stronie mikrokontrolera (rozpatrujemy kontynuowanie programu z poczatku artykulu) bedziemy potrzebowac zmiennej i funkcji ktora znajduje sie w pliku usbd_cdc_if dlatego inkludujemy:
    Code: c
    Log in, to see the code

    oraz uzyskujemy dostep do zmiennych:
    Code: c
    Log in, to see the code

    sa to bufory ,ktore przechowuja man dane odebrane/do wyslania z/do USB
    W zmiennych deklarujemy jeszcze licznik, ktory bedziemy przesylac(aby widac bylo ze za kazdym razem dane sa inne):
    Code: c
    Log in, to see the code

    Na koniec w petli glownej:
    Code: c
    Log in, to see the code

    Efekt obu programow:


    Biblioteka:
    Attachments:

    Cool? Ranking DIY
    Can you write similar article? Send message to me and you will get SD card 64GB.
    About Author
    oloam
    Level 22  
    Offline 
    oloam wrote 682 posts with rating 190, helped 50 times. Live in city PozagranicamiPolski. Been with us since 2013 year.
  • #2
    .:KoSik:.
    Level 18  
    Fajnie to opisales.

    Ciekawy artykul ale zastanawiam sie po co ta cala "przeprawa". W czym takie rozwiazanie jest lepsze od VCP?
    Przeciez urzadzenie i tak nie przedstawia sie wlasna nazwa. Dopiero podmiana sterownika wymusza takie zachowanie.

    Moze zle to rozumiem, bo dalej wspomniales, ze mozna przygotowac sterownik, wiec rozumiem, ze mozna utworzyc sterownik, zainstalowac go na innym komputerze i wtedy nasze urzadzenie od poczatku bedzie sie przedstawialo prywatna nazwa?
  • #3
    oloam
    Level 22  
    .:KoSik:. wrote:
    Ciekawy artykul ale zastanawiam sie po co ta cala "przeprawa". W czym takie rozwiazanie jest lepsze od VCP?

    Przede wszystkim przepustowosc (predkosc transmisji), do dyspozycji masz pelna predkosc interfejsu, nie jestes zalezny od systemowych baudrrate. Brak marnowania czasu np na control endpoint. Przy przesylaniu wiekszej iolosci danych ma to znaczenie (zwlaszcza dla urzadzen HS). Wlasny protokol transmisji.Wysylajac bajt, wysylasz 8bitow a nie minimum 9 jak to ma w transmisji rs232.
    Jeszcze jedna wazna rzecz. Zawsze nawiazujemy komunikacje z naszym konkretnym urzadzeniem i nie musimy sie martwic pod ktorym portem com nasze urzadzenie sie zglasza.
    .:KoSik:. wrote:
    Moze zle to rozumiem, bo dalej wspomniales, ze mozna przygotowac sterownik, wiec rozumiem, ze mozna utworzyc sterownik, zainstalowac go na innym komputerze i wtedy nasze urzadzenie od poczatku bedzie sie przedstawialo prywatna nazwa?

    Dokladnie tak, paczke sterownikow generuje program Zadig. Sa sterowniki systemy x86 i x64. Instalujac urzadzenie na innym PC bedzie one widziane z ta nazwa ktora sobie stworzylismy.
  • #4
    Ondo
    Level 11  
    oloam wrote:
    .:KoSik:. wrote:
    Ciekawy artykul ale zastanawiam sie po co ta cala "przeprawa". W czym takie rozwiazanie jest lepsze od VCP?

    Przede wszystkim przepustowosc (predkosc transmisji), do dyspozycji masz pelna predkosc interfejsu, nie jestes zalezny od systemowych baudrrate. Brak marnowania czasu np na control endpoint. Przy przesylaniu wiekszej iolosci danych ma to znaczenie (zwlaszcza dla urzadzen HS). Wlasny protokol transmisji.Wysylajac bajt, wysylasz 8bitow a nie minimum 9 jak to ma w transmisji rs232.
    Jeszcze jedna wazna rzecz. Zawsze nawiazujemy komunikacje z naszym konkretnym urzadzeniem i nie musimy sie martwic pod ktorym portem com nasze urzadzenie sie zglasza.
    I tak i nie, w przypadku VCP nie ma czegoś takiego jak "bity", wszystko leci paczkami via USB, co więcej nie ma znaczenia czy ustawisz 9600 czy 100000kbit, paczki są identyczne, wykorzystają taką samą przepustowość, a różnica jest że OS poinformuje urządzenie USB jaką prędkością ma te dane wysłać dalej. Istnieje API systemowe Windows które pozwala na enumeracje urządzeń USB, pobranie nazwy (z nazwą COM w nawiasie) a później pobranie VID i PID urządzenia, dla lepszej identyfikacji. Zaletą WinUSB może być to że można mieć więcej urządzeń w systemie przypisanych do oddzielnych endpointów USB (np urządzenie kontrolne i urządzenie transmisji danych), chociaż z drugiej strony USB pozwala definiować urządzenia kompozytowe udającej więcej niż jeden port COM.

    oloam wrote:
    .:KoSik:. wrote:
    Moze zle to rozumiem, bo dalej wspomniales, ze mozna przygotowac sterownik, wiec rozumiem, ze mozna utworzyc sterownik, zainstalowac go na innym komputerze i wtedy nasze urzadzenie od poczatku bedzie sie przedstawialo prywatna nazwa?

    Dokladnie tak, paczke sterownikow generuje program Zadig. Sa sterowniki systemy x86 i x64. Instalujac urzadzenie na innym PC bedzie one widziane z ta nazwa ktora sobie stworzylismy.
    Niby fajnie ale i tak nie zadziała od pierwszego strzała, USB zadbało żeby trzeba było kupować licencję na VID, a Microsoft zadbał żeby trzeba było podpisywać sterowniki. Winusb czy Zadig są fajne wyłącznie do rozwiązań hobbystycznych lub startupowych.
  • #5
    oloam
    Level 22  
    Ondo wrote:
    I tak i nie, w przypadku VCP nie ma czegoś takiego jak "bity", wszystko leci paczkami via USB,

    Zgadzam sie, jezeli piszesz o komunikacji sterownik<->urzadzenie, jednak jezeli chodzi o aplikacja<->sterownik dane nadal sa wysylane wg potokolu rs232 i trzeba w niej ustawic dodatkowe bity (stopu parzystosci a ramka musi zaczynac sie od bitu startu). Skad aplikacja ma wiedzic czy laczy sie z VPC czy fizycznym COM?
    Ondo wrote:
    Niby fajnie ale i tak nie zadziała od pierwszego strzała, USB zadbało żeby trzeba było kupować licencję na VID, a Microsoft zadbał żeby trzeba było podpisywać sterowniki.

    Dotyczy to wszystkich urzadzen USB niezaleznie od klasy. Czesc producentow mikrokontrolerow pozwala uzywac swoich VID nawet do celow komercyjnych (oczywiscie z ograniczeniami np do pewnej ilosci sprzedanych sztuk) i po rejestracji otrzymujesz PID do swojego urzadzenia. Sprawa z licencjami jest bardzo skomplikowana. Wlasciciel VID nie moze odsprzedawac PID. Jednak jak uzyjesz 'nieprzypisany' VID do swojego urzadzenia to to nikt cie nie pozwie, chyba ze w miedzyczasie jakas firma wykupi ten VID to wtedy ma prawo domagac sie zaprzestania uzywania VID w twoim urzadzeniu. USB-IF wprowadzilo zakaz odsprzedazy PID, kiedy to wiele firm wykupowalo VID a nastepnie odsprzedawaly PID zarabiajac na tym wiecej niz wydaly na VID. Glosna sprawa byla spor miedzy USB-IF a MCS (producenta Bascom). MSC posiadal VID jeszcze przed wprowadzeniem zakazu odsprzedazy PID, kiedy USB-IF wprowadzilo zakaz to MCS nadal odsprzedawal PID. Nie pamietam czy sprawa skonczyla sie w sadzie ale MCS stal na stanowisku ze mial prawa do VID i PID i nie zaprzestal odsprzedazy PID. USB-IF 'odwolao' wiec VID przypisany do MCS. Jednak ze wzgledu na to ze VID nalezal juz do jednej firmy (MCS), to nie moze byc sprzedany innej firmie i jezeli bedziesz uzywal VID i PID od MCS (nadal sprzedaja PID) to raczej mozesz czuc sie bezpieczny. Ja np. mam wykupiony PID od MCS tak na wszelki wypadek. Poza tym jeszcze nie slyszalem o przypadku kiedy to firma zostala pozwana za uzywanie nieprzypisanego lub nieswojego VID.
    Jezeli chodzi o Microsoft, to dopoki mozna instalowac nipodpisane sterowniki, to tak jakby sprawy nie bylo...

    Quote:
    When you develop your own USB product you probably do not want to pay 2000$ for a Vendor ID.
    Why would you need a VID ? Each USB product requires an unique VID and PID number.
    Since the VID is a WORD(2 bytes) there are many possible numbers.

    Each of your unique products need a unique PID. This is also a WORD(2 bytes).

    Another option is to buy a PID from MCS. Together with the VID you will have a unique combination.
    MCS has sold PID's since 2005.
    When MCS purchased the VID, there was NO INFORMATION about the usage of the VID-PID.
    USB-IF was only focused to get a payment. There were no rules or conditions or a contract.

    That changed in June 2009 when USB-ORG wrote an email that it was not permitted to sell VID or PID.
    MCS pointed out that in The Netherlands you can not enforce or change rules AFTER a product/service is sold.
    So we continued as usual.
    In reaction USB-ORG offered our money back but that would mean existing customers would not have a valid PID anymore.
    So we got some more letters and finally USB-ORG wrote a letter that they revoked our VID.

    Of course our VID can not be re-used by USB-ORG. This means that our VID will still be unique.

    If you want to produce a USB device that need to be tested/verified by USB-ORG you need your own VID.
    If you only need a real unique VID & PID combination, you can still use ours.
    So what we offer is a unique VID & PID combination.
  • #6
    Ondo
    Level 11  
    oloam wrote:
    Ondo wrote:
    I tak i nie, w przypadku VCP nie ma czegoś takiego jak "bity", wszystko leci paczkami via USB,

    Zgadzam sie, jezeli piszesz o komunikacji sterownik<->urzadzenie, jednak jezeli chodzi o aplikacja<->sterownik dane nadal sa wysylane wg potokolu rs232 i trzeba w niej ustawic dodatkowe bity (stopu parzystosci a ramka musi zaczynac sie od bitu startu). Skad aplikacja ma wiedzic czy laczy sie z VPC czy fizycznym COM?
    No i tu tkwi magia VCP, obojętnie jakie parametry prędkości się ustawi, urządzenie tak samo dostanie dane. Cały czas mówię o urządzeniu (np procesorowi) ze stosem CDC, a nie konwerterowi typu FT232 podpiętemu pod UART procesora. Zaryzykowałbym nawet stwierdzenie, że można by nie ustawiać prędkości, ale boje się że ustawienia handshakingu będą z domyślnych wartości sterownika co może wymagać dodatkowego signalingu via USB.

    oloam wrote:
    Dotyczy to wszystkich urzadzen USB niezaleznie od klasy. [...]
    Jezeli chodzi o Microsoft, to dopoki mozna instalowac nipodpisane sterowniki, to tak jakby sprawy nie bylo...
    Dlatego mówię że WinUSB nie jest cudownym środkiem na rozwiązanie problemów z USB, jest tylko odrobinę pomocne.
  • #7
    oloam
    Level 22  
    Ondo wrote:
    No i tu tkwi magia VCP, obojętnie jakie parametry prędkości się ustawi, urządzenie tak samo dostanie dane.

    Napisalem wyzej, ze to sie zgadza, jednak piszesz tu o transferze serownik (VCP)<->urzadzenie a to tylko polowa drogi. Druga polowa jest aplikacja<->sterownik (VCP) i tu juz zadnej magii nie uswiadczysz. Do sterownika musisz wysylac dane zgodnie protokolem rs232. I to sterownik VCP musi przerobic ramke rs232 na pakiet USB przy nadawaniu i odwrotnie przy odbieraniu. Jeszcze wieksze watpliwosci mam przy odbieraniu danych. Przecierz dane musza byc odebrane (ze sterownika VCP) z danym baudrate (ktore mozna maksymalnie ustawic na zaledwie 128000 bps) inaczaj bedziesz otrzymywal bzdury. W sterowniku WinUsb dane wysylasz bezposrednio na endpointy jednokierunkowe z predkoscia 12 Mb/s (dla FS).
    Ondo wrote:
    Dlatego mówię że WinUSB nie jest cudownym środkiem na rozwiązanie problemów z USB, jest tylko odrobinę pomocne.

    Co ma do tego WinUsb? Zarowno WinUSB jak i usbser.sys (VPC) sa sterownikami.

    Moze pokusze sie o szybki test transferu dla obu sterownikow...
  • #8
    Ondo
    Level 11  
    oloam wrote:
    Ondo wrote:
    No i tu tkwi magia VCP, obojętnie jakie parametry prędkości się ustawi, urządzenie tak samo dostanie dane.

    Napisalem wyzej, ze to sie zgadza, jednak piszesz tu o transferze serownik (VCP)<->urzadzenie a to tylko polowa drogi. Druga polowa jest aplikacja<->sterownik (VCP) i tu juz zadnej magii nie uswiadczysz. Do sterownika musisz wysylac dane zgodnie protokolem rs232. I to sterownik VCP musi przerobic ramke rs232 na pakiet USB przy nadawaniu i odwrotnie przy odbieraniu. Jeszcze wieksze watpliwosci mam przy odbieraniu danych. Przecierz dane musza byc odebrane (ze sterownika VCP) z danym baudrate (ktore mozna maksymalnie ustawic na zaledwie 128000 bps) inaczaj bedziesz otrzymywal bzdury. W sterowniku WinUsb dane wysylasz bezposrednio na endpointy jednokierunkowe z predkoscia 12 Mb/s (dla FS).
    Nie rozumiem gdzie tutaj jest problem baudrate, skoro nie ma rzeczywistej konwersji z RS232. Aplikacja wywołuje WriteFile() z buforem, a dane "automagicznie" pojawiają się w buforze w RAM procesora.
    Kiedyś znalazłem taką implementację na 8bitowy PIC http://tomeko.net/index.php?stan=fastPICCDC autor twierdzi, że można osiągnąć 800kB/s.
  • #10
    Sareph
    Level 24  
    oloam wrote:
    Do sterownika musisz wysylac dane zgodnie protokolem rs232.
    Nope. Raz, że Windows obsługuje tylko dane do 8bit, a dwa, ze krótsze są reprezentowane jako 8 bit. W efekcie calusieńka drogę od aplikacji do STMa pokonują jako 8bit. A co sobie potem STM z nimi zrobi (może zignorować parę bitów przecież) to juz tylko kwestia tego jak napisano aplikację w tym STMie, czy innym uC.

    oloam wrote:
    Jeszcze wieksze watpliwosci mam przy odbieraniu danych. Przecierz dane musza byc odebrane (ze sterownika VCP) z danym baudrate (ktore mozna maksymalnie ustawic na zaledwie 128000 bps) inaczaj bedziesz otrzymywal bzdury.
    Nope. Aplikacja na PC ustawia sobie jakiś baudrate, ten baudrate wtedy trafia do uC jako "control message", a informacje o nim nie są więcej wymieniane. Ot jeśli potrzeba, uC ustawia potrzebną prędkość swojego portu szeregowego i z taką prędkością wysyła i odbiera dane do czasu nadejścia kolejnego pakietu "trzeba zmienić baudrate na inny". I jak Ci tu już napisali, póki ten COM nie wychodzi na zewnątrz serialem, baudrate nie ma najmniejszego znaczenia, to tylko zawartość pakietu na USB. Poza tym, mi tam i 1,5Mbps spokojnie działa w parze Win+STM32.
  • #11
    oloam
    Level 22  
    Macie racje, wszelkie ustawienia dla VCP nie maja znaczenia dla transmisji. Co wiecej, sama transmisja po VPC jest szybsza i to sporo. Jak znajde troche czasu to sprawdze postaram sie przesledzic gdzie tkwi przyczyna.
  • #12
    PiotrekD
    Level 13  
    Ondo wrote:

    oloam wrote:
    Dotyczy to wszystkich urzadzen USB niezaleznie od klasy. [...]
    Jezeli chodzi o Microsoft, to dopoki mozna instalowac nipodpisane sterowniki, to tak jakby sprawy nie bylo...
    Dlatego mówię że WinUSB nie jest cudownym środkiem na rozwiązanie problemów z USB, jest tylko odrobinę pomocne.


    Niestey WinUsb to tylko pod Win ... ale w ma jedną zaletę - można wykorzystać rurę w trybie izochronicznym a WinUsb ją obsłuży...
  • #13
    oloam
    Level 22  
    PiotrekD wrote:
    Niestey WinUsb to tylko pod Win

    Jest jeszcze libusb kotry mozesz uzyc w:
    Quote:
    Linux, macOS, Windows, OpenBSD/NetBSD, Haiku and Solaris
  • #14
    oloam
    Level 22  
    Przeprowadzilem kilka testow.Juz wiem skad wynika roznica w predkosci transferu.Mianowicie dla komunikacji VCP z poziomu sterownika nie ma zadnej komtroli transferu i musimy sobie ja napisac sami z poziomu aplikacji lub dac pewne opoznienie ktore zapewni nam odpiowiedni czas na poprawne nadanie/odebranie danych w transmisji. Z poziomu sterownika WinUSB nie musimy sie o to martwic. Otrzymujemy potwierdzenie nadanych/odebranych danych jak i np ilosc odebranych danych oraz bajtow nadpisanych (jezeli ze sterownika odbieramy mniej danych niz powinnismy).
    Do testow (po stronie PC) posluzyla prosta petla wysylajaca 1 bajt i odbierajaca 30 bajtow.
    Dla 10 transmisji:
    VCP - Implementacja USB we wlasnym urzadzeniu ze sterownikiem WinUsb
    jak widac na 10 transmisji mamy tylko 5 prawidlowo odebranych pakietow.
    to samo dla WinUSB - Implementacja USB we wlasnym urzadzeniu ze sterownikiem WinUsb