AVR32 - problem z USB (bit detach)

Nov 14, 2009 8 Replies

Witam,



Znów utknąłem przy AT32UC3B0256.



Mam na linii VBUS napięcie 5V, zeruję rejestr UDCON (a więc i bit DETACH) a mimo to żadna z linii (D+ lub D-) nie zostaje podciągnięta do plusa.



Czy ktoś dysponuje tym prockiem i mógłby sprawdzić czy to działa?



SM


Tak szczegółowe pytania o AVR32 zadawaj lepiej na forum

formatting link
szybciej dostaniesz odpowiedź.

Name pisze:

No to spróbuję.

Najpierw miałem problem z bitem VBUS w rejestrze USBSTA. Zgodnie z PDF powinien on odzwierciedlać stan napięcia na linii VBUS (w trybie device):

"In device mode, the VBUS bit follows the Session_valid comparator output:

- it is set when the voltage on the VBUS pad is higher than or equal to

1.4 V;

- it is cleared when the voltage on the VBUS pad is lower than 1.4 V."

No i lipa. U mnie nie działa. Nie widzi żadnych zmian na VBUS. Dopiero ustawienie bitu OTGPADE w USBCON spowodowało iż bit VBUS zmieniał się za zmianami napięcia na linii VBUS.

Pewnie podobny numer jest z DETACH - znowu jakaś kombinacja o której nawet się w PDFie nie zająknęli.

SM

Ale my tez sie chetnie czego dowiemy :-)

J.

No to niech Kolega Sebastian pisze tu pytania i odpowiedzi z AVRFreaks ;)...

Pozdrawiam Konop

Wziąłem się za przeglądanie przykładów atmela dostarczanych z AVR32 Przykład usb_cdc. Możliwa praca albo z FREERTOS albo z poolingiem. W obu przypadkach część funkcji jest realizowana na przerwaniach. Biorę pod uwagę tylko tę cześć programu, które odpowiada wyłącznie za tryb pracy DEVICE.

Najpierw mamy wywołanie: pm_configure_usb_clock() Spoko. Uruchamia PLL1 dla USB na 48MHz.

Potem: usb_task_init(); Też w miarę OK.

  1. Instaluje handler przerwania.
  2. Wymusza tryb pracy DEVICE.
  3. Wywołuje usb_device_task_init(); Ten też OK.
  4. Uruchamia pad OTG
  5. Uruchamia USBE
  6. Odmraża zegar dla USB
  7. I tu uwaga! Uruchamia przerwanie USB od VBUS (kontroli napięcia zasilania na lini VBUS).

Inicjalizację mamy za sobą. Teraz w kółko wywoływana jest procedura usb_task() która w przypadku DEVICE wywołuje usb_device_task().

Co widzimy na początku usb_device_task():

if (!usb_connected && Is_usb_vbus_high()) { usb_start_device();

Czyli: usb_connected to flaga programu. Oczywiście wyzerowana. Is_usb_vbus_high() natomiast robi pooling USBSTA bitu VBUS. Czyli usb_start_device() zostanie wywołane w momencie podania napięcia na VBUS.

I byłoby OK, ale zajrzyjmy do procedury obsługi przerwań od USB, czyli usb_general_interrupt(void):

if (Is_usb_vbus_transition() && Is_usb_vbus_interrupt_enabled()) { Usb_ack_vbus_transition(); if (Is_usb_vbus_high()) { usb_start_device();

Tutaj w przerwaniu mamy dokładnie to samo w pętli głównej, tyle że na przerwaniach. W momencie przyjścia napięcia na VBUS zostaje wywołana ta sama procedura co w programie głównym. Co będzie jeśli przerwanie przyjdzie wtedy, kiedy główna procedura będzie odczytywała stan bitu VBUS w USBSTA? Zostanie dwukrotnie wywołane usb_start_device(). Mało prawdopodobna sytuacja, ale możlwia. I co wtedy? Będziemy mieć np. podwójne zaalokowanie pamięci dla endpoint 0. Bardzo wredny błąd, bo ciężki do wychwycenia.

Dlatego chciałem napisać własną obsługę USB CDC niż korzystać z wątpliwych gotowców atmela, tyle że procek nie bardzo chce pracować wg tego co piszą w PDFie.

Robię tak:

// usbb base

mov.w r12, USBB_BASE

// disable usb, freeze clock, force device mode

mov.w r0, (1 << USBCON_FRZCLK) | (1 << USBCON_OTGPADE) | (1 << USBCON_UIMOD) | (1 << USBCON_VBUSHWC) st.w r12[USBB_USBCON], r0

// enable usb, unfreeze clock, force device mode

mov.w r0, (1 << USBCON_USBE) | (1 << USBCON_OTGPADE) | (1 << USBCON_UIMOD) | (1 << USBCON_VBUSHWC) st.w r12[USBB_USBCON], r0

// enable endpoint

mov r0, (1 << UERST_EPEN0) st.w r12[USBB_UERST], r0

// configure endpoint

mov.w r0, (3 << UECFG_EPSIZE) | (1 << UECFG_ALLOC) st.w r12[USBB_UECFG0], r0

// attach

mov r0, 0 st.w r12[USBB_UDCON], r0

I lipa. Attach nie działa. Żadna z linii D+/D- nie zostaje podciągnięta.

SM

Znalazłem!!!

Pisałem program jednocześnie w C (AVR32) i moim czystym ASMie. W C działa, w ASMie nie.

Zacząłem szukać różnicy.

Błąd jest w PDFie Atmela doc32059.pdf.

Na stronie 57 mamy:

0x0060 GCCTRL 0x0064 - 0x00BC Reserved

A powinno być:

0x0060 GCCTRL0 - GCLK0 pin 0x0064 GCCTRL1 - GCLK1 pin 0x0068 GCCTRL2 - GCLK2 pin 0x006C GCCTRL3 - USBB

Ustawiałem więc zegar dla "GCLK0 pin" a nie dla "USBB".

Po zmianie GCCTRL na GCCTRL3 mój ASM też działa.

SM

No to niezłe kwiatki Atmel robi w PDFach... taka "drobna różnica" :P...

Właśnie trochę pisuję z atmelem. Mają to poprawić.

Podobnie nasiedziałem się nad bitem VBUS. W PDF nie napisali że działa on tylko jak się uaktywni bit OTGPADE.

No i brak opisu jak się właściwie dobrać do pamięci FIFO USB bezpośrednio CPU (bez DMA). W tej chwili adresuję ją jak zwykły SRAM od adresu 0xD0000000 plus offset dla endpoint. Początkowo sądziłem że jak to jest FIFO to będzie jeden rejestr do odczytu w którym kolejno dostaję bajty jak ze stosu. Z jednej strony USB dopisuje bajty, z drugiej ja odbieram - tak jak działa FIFO. A tu wychodzi na to że adresuje się FIFO jak zwykły SRAM.

W tej chwili piszę w ASMie własną bibliotekę USB CDC. Wzoruję się na przykładzie atmela, ale jakieś 2/3 nadmiarowe kodu wywalam. No i robię wszystko w jednej pętli. Może uda się bez przerwań to zrobić.

SM

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required