FAQ | Points | Add... | Recent posts | Search | Register | Log in


Pisanie sterownika USB pod system linux.


Post new topic  Reply to topic      Main Page -> Forum Index -> Microcontrollers Generally -> Other Microcontrollers -> Pisanie sterownika USB pod system linux.
Author
Message
almendar
Poziom 3
Poziom 3


Joined: 22 Aug 2009
Posts: 5
Location: Warszawa

Post#1 Post from the author of the topic 22 Aug 2009 15:02   

[Linux Kernel - USB]


Witam, wszystkich forumowiczów. Jest to mój pierwszy post więc chciałem się przywitać!

Mam nadzieję, że ktoś będzie mi w stanie pomóc z następującym problemem:

jestem w trakcie pisania sterownika dla przetwornika A/D dla linuxa, kóry jest moim pierwszym a zarazem jest projektem zaliczeniowym na moich studiach. Podłączony jest on poprzez USB. Płytka ma 2 endpoiny z których jeden jest IN a drugi OUT, oba w trbie bulk, - sterowanie pracą i odbieranie danych.
Przy wykorzystaniu przykładu z jądra usb-skeleton.c udało mi się nawiązać łączność z płytką. Wysłałem jej polecenie na które przedstawiła mi się.

Teraz muszę spełnić wymagania. Sterownik ma umożliwić wielu programom dostęp do danych przy czym każdy program może zarządać dostępu do innego kanału i różnej częstotliwości. Ja muszę je jakoś pogodzić i wybrać najbardziej wypośrodkowaną możliwość.

Gdzie jest problem?
Nie rozumiem jak zachowuje się system przy połączeniu bulk. Gdy włączę próbkowanie i płytka zacznie wysyłać mi dane to kto je będzie odbierał? Jeżeli nikt to dojedzie do przepełnienia? Czy jest tak, że wywołanie read idzie od programu z przestrzeni użytkownika czy sterownik sam może siebie jakoś wywołać i zciągnąć od płytki dane i dodać do jakiegoś buforu?
Nie udało mi się nigdzie znaleźć sensownego rozwiązania tego problemu, ani tego jak to w praktyce wygląda.

Mam nadzieję, że znajdzie się ktoś na tyle dobry żeby naprowadzić mnie chociaż na trop...
Back to top
   
wojtekkk09
Poziom 12
Poziom 12


Joined: 07 Jul 2007
Posts: 85
Location: Jastrzębie Zdrój

Post#2 22 Aug 2009 16:10   

Re: [Linux Kernel - USB]


Wtiam!
Z tego co się orientuję, to transferem zarządza HOST, więc sama płytka nie może wysyłać danych w trybie BULK bez uprzedniego pozwolenia.

polecam:
http://www.beyondlogic.org/usbnutshell/usb4.htm#Bulk

Widzę również, że w usb-skeleton.c jest funkcja skel_read, w której podajesz bufor na odebrane dane i liczbę danych do odebrania.

Pozdrawiam
Wojt
Back to top
   
almendar
Poziom 3
Poziom 3


Joined: 22 Aug 2009
Posts: 5
Location: Warszawa

Post#3 Post from the author of the topic 22 Aug 2009 17:34   

Re: [Linux Kernel - USB]


Tak, ale...
Jeżeli odbiorę dane poprzez jeden proces to będę musiał się nimi jakoś podzielić z drugim.

Mam swój pomysł... Istnieje f-cja wykonywana po tym jak tylko oddelegowany urb zakończy swoje działanie. Po jednym odczycie w tej funkcji mógłbym zlecać następne odczyty. Wszystko inicjowało by się w ioctl a potem działało jak łańcuch. Dane szły by do buforów.

Czy może ktoś mi powiedzieć, że to dobry trop? :)
Back to top
   
Google

Google Adsense


Post# Post from the author of the topic 22 Aug 2009 17:34   





Back to top
   
flapo213
Poziom 18
Poziom 18


Joined: 21 Jan 2003
Posts: 549
Location: Rzeszów

Post#4 24 Aug 2009 21:06   

Re: [Linux Kernel - USB]


Witaj kolego.

Ja używam Linuxa Ubuntu i poczytałem conieco na temat USB i np mikrokontrolera STM32 jak co się odbywa. W USB jest tak jak podłączasz slave-a np. pendrive, USB->RS232 czy mp3-kę to jedna z linii przesyłowych D+ jest podciągana w slave-a do plusa 3.3V. Przy podłączaniu master wychwytuje to podciągnięcie i zaczyna wysyłać do urządzenie różne zapytania np. kto ty jesteś, urządzenie odsyła mu vendora i jakiego rodzaju połączenie ma być interrupt, bulk itd. (endpointy) później zaczyna się instalowanie driverów np. następnie urządzenie podsyła kolejne parametry np. wydajność prądową i jakieś inne dane (nie pamiętam dokładnie). Po tych operacjach urządzenie ma już skonfigurowane endpointy i może rozpocząć normalną pracę. Ja zrobiłem jedynie na STM32 taki jakby konwerter USB->RS232 więc nie muszę żadnych driverów pisać a działa to dokładnie tak jakbym zwykły port RS232 obsługiwał. Niestety jakbyś chciał dokładnie dowiedzieć się jak działa master (host) to chyba trzeba by usb.org poczytać na temat działania usb a to niestety ciężka lektura. Życzę sukcesów pozdrawiam

PS. Na linuchu da się w łatwy sposób odpalić tzw. monitor usb co i jak jest podsyłane, jak sobie myszkę podsłuchuję, jakby Cię interesowało jak to podsłuchać na ubuntu to daj znać.
Back to top
   
almendar
Poziom 3
Poziom 3


Joined: 22 Aug 2009
Posts: 5
Location: Warszawa

Post#5 Post from the author of the topic 24 Aug 2009 22:07   

Re: [Linux Kernel - USB]


flapo213 wielkie dzięki za odpowiedź. W zasadzie wiem już co i jak ale rozwinę post, może kiedyś komuś się do czegoś przyda.

Problem polegał głównie na tym, że normalnie gdy masz coś do odczytania od urządzenia np. przez port RS232 to generuje ono przerwanie i w przerwaniu możemy sobie odpowiednią maską sprawdzić co jest na rzeczy.

USB w trybie bulk nie generuje (chyba) żadnych przerwań, tylko samo czeka na to, żeby odebrać dane od niego. Urządzenie powinno mieć jakiś bufor bo przecież skoro nie ma przerwań to nikt tak szybko nie nadąży z odbieraniem.

Transfer do/z usb odbywa się asynchronicznie przy pomocy tzn. urb'ów. Wysyłasz urb do urządzenia a ono inicjuje transfer do nas lub od nas. Po wykonaniu transferu wywoływana jest funkcja complete, gdzie tego samego urb'a można zlecić do dalszego odbioru danych.

Możemy również skorzystać z blokującej, synchronicznej funkcji usb_blk_msg, która sprawdza się wtedy gdy urządzenie jest obsługiwane przez jeden program kliencki lub dane wysyłane przez urządzenie nie muszą być współdzielone przez kilka programów klienckich. Żadna z tych sytuacji nie zachodziła w moim przypadku.

Do transferu należy użyć urbów, które zapisują pobrane bajty od urządzenia do buforu sterownika a ten dopiero rozsyła je (właśnie w funkcji complete, wykonywanej po transferze) do buforów poszczególnych procesów. Procesy można przechować w polu private_data, w zdefiniowanej przez siebie strukturze, a identyfikować przez wskaźnik na struct file (z małej! Nie FILE z libc).
Gdy już roześlemy bajty do procesów (co wydaje mi się można zlecić taskletom?) wysyłamy następny urb nadal w funkcji complete do kolejnego transferu.

Start i stop urządzenia robimy w funkcji ioctl.



Mam nadzieję, że komuś ułatwi to chociaż trochę życie :)
Back to top
   
flapo213
Poziom 18
Poziom 18


Joined: 21 Jan 2003
Posts: 549
Location: Rzeszów

Post#6 24 Aug 2009 23:04   

Re: [Linux Kernel - USB]


Kolego almendar Twój opis jest super, ale tak tryb bulk rzeczywiście nie jest przerwaniowym trybem więc idzie kiedy ma czas a nie kiedy musi. Ale teraz nasuwa sie pytanie czy master który oczywiście musi mieć jakiś bufor nie odniera danych np po 512kb i nie żąda kolejnych - wiesz o co chodzi (żądam np 512kb i otrzymuję je czekam sobie i czekam np i wysyłam kolejen żądanie). Może zbyt banalnie to opisuję ale przyznam że nie wiem jak to dokładnie wygląda od strony mastera. Super post może się dobrze rozwinie i komuś jeszcze przyda. Napisz jak możesz czy dobrze to zrozumiałem.
Back to top
   
Google

Google Adsense


Post# 24 Aug 2009 23:04   





Back to top
   
almendar
Poziom 3
Poziom 3


Joined: 22 Aug 2009
Posts: 5
Location: Warszawa

Post#7 Post from the author of the topic 25 Aug 2009 09:53   

Re: [Linux Kernel - USB]


Źródła z których korzystam: ch13.pdf.
Rozdział dotyczy bezpośrednio obsługi USB. Jeżeli kogoś interesują inne zagadnienia to niech w url zmienia numerek po chxx na taki z zakresu 01-18. Wszystko po angielsku, ale tekst jest pisany dość lekko i czyta się całkiem zgrabnie.

Wracając do tematu, master ma bufor, który stworzy programista sterownika przy pmocy zwykłego kmalloc. Oto fragment kodu, który to ilustruje...
Code:
 
usb_fill_bulk_urb(urb, dev->udev,
                           usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
                           buf, writesize, adc22_write_bulk_callback, dev);
         urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
         usb_anchor_urb(urb, &dev->submitted);

         /* send the data out the bulk port */
         retval = usb_submit_urb(urb, GFP_KERNEL);

  (...)

         usb_free_urb(urb);


Funkcja usb_fill_urb przyjmuje wskazanie na bufor (tu buf) oraz jego rozmiar (writesize). Tutaj też widać wskaźnik na funkcję callback wywoływaną po transferze. To w niej zlecić można kolejny transfer.

Inaczej ma się sprawa w urządzeniu od którego odbieramy dane. To co teraz napiszę są to moje przypuszczenia. Sądzę, że bufor może w ogóle nie istnieć, urządzenie może np. wysyłać daną chwilową z momentu gdy nadeszła prośba o transfer. Tyle, że gdy urządzenie ma zadaną częstotliwość pobierania próbek to implikuje konieczność występowania buforu. Poza tym tryb bulk zapewnia pewną i bezbłędną transmisję. Po co taki typ transmisji skoro i tak nie zależało by nam na KAŻDEJ danej?
Back to top
   
Google

Google Adsense


Post# Post from the author of the topic 25 Aug 2009 09:53   





Back to top
   
fantom
Poziom 22
Poziom 22


Joined: 23 Mar 2003
Posts: 1616
Location: Łódź

Post#8 25 Aug 2009 10:43   

Re: [Linux Kernel - USB]


Jesli moge wtracic jako osoba ktora niegdys zajmowala sie USB to stosowanie trybu bulk do urzadzenia jakim jest A/D jest troszke nie na miejscu (chyba ze nie interesuje cie ciagla zmiana sygnalu tylko np wartosc chwilowa). Twoje przypuszczenia sa sluszne jesli chodzi o tryb bulk to znaczy urzadzenie odpowiada w momencie w ktorym jest zapytane calym wczesniej zadeklarowanym w deskryptorze endpointu buforem wiec moze sie zdarzyc tak ze z punktu widzenia aplikacji czesc danych przepadnie jesli aplikacja nie nadarza z wysylaniem requestow. Problem taki bedziesz mial jednak zawsze nie wazne czy uzyjesz trybu isochronous czy interrupt czy bulk, wszystko zalezy od wielkosci bufora. Dodatkowo tryb bulk generuje oczywiscie przerwanie w ktorym nalezy bufor uzupelnic przed wyslaniem. Co do obslugi procesow to zlecanie kopiowania taskletom jest pomyslem niezlym ale nalezy sie zastanowic czy koniecznym (w koncu ile moze trwac zwykle kopiowanie z pamieci do pamieci ?). Co innego odczyt z dysku.
Back to top
   
almendar
Poziom 3
Poziom 3


Joined: 22 Aug 2009
Posts: 5
Location: Warszawa

Post#9 Post from the author of the topic 25 Aug 2009 14:02   

Re: [Linux Kernel - USB]


Witam, wtrącenia od osób doświadczonych są nawet bardzo wskazane! :)

Co do sensowności trybu bulk w tego typu rządzeniach nie mogę dyskutować. Płytka, która dostarcza mi próbki została dostarczona przez mojego prowadzącego w ramach projektu zaliczeniowego na studiach. Dostałem co prawda jej firmware oraz zezwolenie na dowolną modyfikacje, ale cóż nie mam ani programatora ani chęci w kopaniu się przez grube setki kodu. Taka była out-of-the-box i tak ustawioną programuje.

Chociaż osobiście wydawało mi się od początku, że bardziej byłby sensowny tryb gdzie utrzymywany jest stały napływ próbek w zarezerwowanym z góry paśmie i nie koniecznie każda z nich jest tak ważna.

Faktycznie zlecanie taskletów może mijać się z celem. Kopiowanie pamięć-pamięć jest szybkie. Przyszło mi to do głowy jako element dydaktyczny, którego mógłbym użyć, żeby nauczyć się ich poprawnej obsługi.

Sprawa ma się tak, że to mój pierwszy sterownik i ruszyłem z tym 1,5 tygodnia temu. :) Wcześniej byłem kompletnie zielony z tego tematu i nowością było nawet jak kompilować i ładować taki sterownik. Na szczęście jest internet i bogata literatura do jądra Linuksa.

Pozwolę sobie wrzucić link do jeszcze jednej strony:
lxr.linux.no
Okazała się ona świetną "przeglądarką" kodu jądra i nasunęła mi wiele gotowych rozwiązań moich problemów.


Na koniec mam jeszcze pytanie do b. doświadczonych kolegów. Czy robienie prostych operacji zmiennopozycyjnych typu podzielenie dwóch liczb przez siebie raz na ileś jest b. kosztowne dla jądra?
Back to top
   
fantom
Poziom 22
Poziom 22


Joined: 23 Mar 2003
Posts: 1616
Location: Łódź

Post#10 25 Aug 2009 14:26   

Re: [Linux Kernel - USB]


almendar wrote:

Faktycznie zlecanie taskletów może mijać się z celem. Kopiowanie pamięć-pamięć jest szybkie. Przyszło mi to do głowy jako element dydaktyczny, którego mógłbym użyć, żeby nauczyć się ich poprawnej obsługi.

Jako zadanie dydaktyczne napewno super.

almendar wrote:

Sprawa ma się tak, że to mój pierwszy sterownik i ruszyłem z tym 1,5 tygodnia temu. :) Wcześniej byłem kompletnie zielony z tego tematu i nowością było nawet jak kompilować i ładować taki sterownik. Na szczęście jest internet i bogata literatura do jądra Linuksa.

W takim razie niezle ci idzie.

almendar wrote:

Na koniec mam jeszcze pytanie do b. doświadczonych kolegów. Czy robienie prostych operacji zmiennopozycyjnych typu podzielenie dwóch liczb przez siebie raz na ileś jest b. kosztowne dla jądra?

Jezeli chodzi o jadro to jest troche bardziej kosztowne (wiekszy narzut na kontekst procesora o wszystkie rejestry zmiennoprzecinkowe) ale generalnie nie przejmowal bym sie tym zbytnio.
Back to top
   
Post new topic  Reply to topic      Main Page -> Forum Index -> Microcontrollers Generally -> Other Microcontrollers -> Pisanie sterownika USB pod system linux.
Page 1 of 1
Similar topics
Pisanie Sterowników dla USB pod Windows LibUsb-Win32 (13)
Pisanie programów na ARM9 + LINUX (9)
Sterownik na USB pod Windows lub Linux. (5)
Programator ISP pod USB - system nie wykrywa Atmega8. (12)
pisanie w javie pod konsolą xp (5)
[asm] pisanie sterowników pod nt/2000/xp (3)
[ARM9][Linux]System embedded - problemy. (54)
ARM i linux jaka różnica? Jak taki system będzie działał? (8)
ARM + linux + kamerka USB (12)
USB<->RS232 na PL2303x. Linux. (7)

Page generation time: 0.086 seconds


FAQ || Administrator || Moderators || Widgets and banners || Contact
elektroda.pl topic RSS feed