AVR32 - problem z USB (bit detach)

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

Reply to
SM
Loading thread data ...

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

formatting link
szybciej dostaniesz odpowiedź.

Reply to
Name

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

Reply to
SM

Ale my tez sie chetnie czego dowiemy :-)

J.

Reply to
J.F.

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

Pozdrawiam Konop

Reply to
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

Reply to
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

Reply to
SM

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

Reply to
Konop

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

Reply to
SM

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.