Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[STM32][C/CrossWorks]Obsługa USB

01 Maj 2012 00:36 2142 2
  • Poziom 8  
    Korzystam z:
    Układ STM32 P103 (procesor STM32 F103 RBT6)
    Programator ARM-USB-OCD-H
    Środowisko CrossWorks v2.1.1

    Problem:
    Pisząc własną obsługę USB wzorowałem się na przykładzie dla Keila (USB HID) i paczce z przykładowymi programami do USB ze strony Olimexa dla układu STM32 P103. Pierwszy (dla Keila) nie działał (operował na innych PINach itp.) ale był bardziej zrozumiale napisany (tzn bez masy dodatkowych bibliotek) a drugi działał na tyle, że system rozpoznawał podłączenie urządzenia USB (nie testowałem dalej).

    Po długich i męczących bojach z niskim poziomem, do których nie byłem przyzwyczajony ani na nie przygotowany (między innymi szalone błędy spowodowane zbyt małym stackiem/heapem czy złą kolejnością niektórych akcji lub wykonywaniem ich zbyt długo (używanie czegokolwiek z malloc-em w obsłudze przerwania nie kończyło się zwykle dobrze)) w końcu udało mi się osiągnąć względną stabilność i otrzymuję od hosta USB pakiet SETUP.

    Pierwszym problemem jest fakt, że pakiet ten według opisu na http://www.beyondlogic.org/usbnutshell/usb6.shtml#SetupPacket powinien wyglądać trochę inaczej (zgadzają się dwa pierwsze bajty definiujące jakie to żądanie dokładna ich wartość to 0x80, 0x06 (GET_DESCRIPTOR dla device), 0x00, 0x00, 0x00, 0x01, 0x00, 0x00).
    Drugi problem jest taki, że po wpisaniu pierwszych 8 bajtów deskryptora do buffora i wpisania ich liczby do przesłania do rejestru COUNT_TX oraz ustawieniu stanu EP0 na TX VALID mimo, że dostaję potwierdzenie przesłania i w końcu po przesłaniu jednego pakietu 8 bajtowego (według http://www.lvr.com/usbcenum.htm punkt 8 i dalej) lub całego deskryptora i ustawieniu stanu EP0 na RX VALID nigdy nie dostaję innego pakietu SETUP niż żądanie GET DESCRIPTOR a powinienem dostać przypisany adres a następnie przesłać deskryptor konfiguracji.



    W związku z tym pytanie czy znacie jakieś źródło (przeczytałem cały rozdział o USB z STM32 reference manual ale są tam opisane poszczególne fazy często ogólnikowo a nie np. ich kolejność itp), które opisuje z punktu widzenia programisty co po kolei należy robić?

    Kod programu dałem w załączniku są tam też moje pierwsze testy układu STM32 P103 w postaci obsługi diody, przycisku oraz timerów w miarę ładnie (w moim mniemaniu przynajmniej jako osoby dopiero zaczynającej pisać programy na mikro kontrolery) poukładane.
    Nie korzystam z żadnych bibliotek oprócz systemowej definiującej rejestry i konfigurującej zegary jako, że te które do tej pory widziałem tyle samo albo i więcej komplikują niż pomagają.

    Kolejność w jakiej teraz konfiguruję i obsługuję USB:
    - konfiguracja zegarów układu w tym PLL (używanego przez USB)
    - ustawienie preskalacji zegara PLL dla USB
    - "start" USB (wyłącznie power down i włączenie force reset)
    - włączenie zegara odpowiednich peryferiów, konfiguracja GPIO, remapowania i pinów
    - "odłączenie" USB (reset pinu odpowiedzialnego za to czy host USB widzi podłączone urządzenie USB)
    - inicjalizacja własnej struktury kolejkującej pakiety odebrane i do przesłania przez USB
    - ustawienie przerwań, adresu tablicy buforów, konfiguracja buforów, endpointów, przypisanie adresu (0x00) i odblokowanie połączeń (w tablicy DADDR)
    - wyłącznie force reset, wyzerowanie rejestru przerwań dla USB i włączenie przerwań USB przez NVIC

    - obsługa przerwań (reset, wakeup, suspend, correct transfer)
    - odebranie przez EP0 pakietu SETUP (żądanie deskryptora)
    - zapisanie 8 bajtów deskryptora w odpowiednim rejestrze i przesłanie ich po ustawieniu statusu EP0 na TX VALID
    - odebranie przerwania correct transfer i jeżeli są dalsze dane do przesłania (w mojej kolejce) to ustawienie znowu statusu EP0 na TX VALID
    - !!! tutaj powinienem odebrać pakiet SETUP ustawiający adres urządzenia i potem na tym adresie odbierać dalsze pakiety i przesłać wszystkie deskryptory ale to nigdy nie ma miejsca
  • Poziom 8  
    Rozwiązałem część problemu (źle rozumiałem adresowanie w Packet Memory ale dzięki zerowaniu tego obszaru pamięci podczas resetu USB i podglądu w debugerze + podglądnięciu jednego z przykładów zrozumiałem jak to działa) i otrzymuję teraz prawidłowe żądanie GET_DESCRIPTOR.
    W trakcie pisania tego postu też w końcu doszedłem do tego co robię źle... błąd oczywiście debilny. "EPxREG(EP_NUM) &= ~(EP_CTR_RX);" robiłem czyszcząc flagę przerwania zapominając, że rejestr ten zmienia część bitów przez bit toggle czyli 1 & 1 w ich przypadku daje 0 a nie 1 i w ten cudowny sposób wykładałem program :/

    Mam nadzieję, że z resztą już sobie poradzę ale póki co mam jeszcze jedno małe teoretyczne pytanko jeśli ktoś się zna:
    - rozmiar packet memory dla mojego układu wynosi 512 bajtów... jednak co drugie słowo (2 bajty) są zawsze zerowe (co wynika z dziwnej budowy tej pamięci) i nie da się do nich pisać itp. czy to znaczy, że po ich odliczeniu oraz rejestrów buforów (też są w tej pamięci) mam do dyspozycji nawet mniej niż 200 bajtów realnie na bufory wszystkich endpointów? Czy może wspomniane 512 bajtów dotyczy realnej pojemności czyli licząc bajty pomija się te bezużyteczne?

    PS. Skasowałem plik z 1 postu jako, że jest już dawno nieaktualny (nawet w funkcje testowe guzika i timera już po moich testach i wprowadzeniu kilku "ulepszeń" bez sprawdzenia wkradł się bug już poprawiony) ale jeśli komuś by zależało mogę wrzucić nowszą wersję a kiedyś nawet ostateczną (chociaż oficjalne prawa do pliku wkrótce po tym będą należeć do pewnej uczelni :P).

    edit:
    Ok drugie pytanie... co po otrzymaniu adresu? Według opisu procesu enumeracji USB powinienem otrzymać żądania kolejnych deskryptorów (konfiguracji, interfejsu, endpointa itp.) na nowy adres jednak znowu nic się nie dzieje.
  • Poziom 8  
    Proces enumeracji pomyślnie zakończony jednak teraz od kilku już dni borykam się z problemem od strony PC związanego z brakiem sterownika.
    Nawet podszywając się urządzenia typu MassStorage itp co według przykładów nie wymaga dodatkowych sterowników w dalszym ciągu urządzenie nie jest rozpoznawane albo gdy próbuję ze sterownikiem własnym dostaję błąd "Nie można uruchomić tego urządzenia (kod 10)." (przerobiony sterownik do virtualcom port (dostarczony z przykładem jest dla WinXP i w ogóle nie działa pod Win7)). Próbowałem nawet programem Diver Wizard stworzyć nowy ale ten sam błąd.

    Macie jakieś rady? Coś oprócz VID/PID i klasy się ustawia do "podszywania" się pod inne urządzenia i czy to w ogóle ma sens? Nie zależy mi na żadnych bajerach programowych, chciałbym tylko móc w końcu przesłać jakiekolwiek dane przez to USB.

    edit:
    Już przebrnąłem przez to jakiś czas temu więc temat do zamknięcia ;)