реклама на сайте
подробности

 
 
> Keil & AT91SAM7SXX & USB, USB HID работет и через час -3 часа отваливается.
Sanya_kv
сообщение Jun 17 2009, 07:25
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 185
Регистрация: 25-02-09
Из: Россия
Пользователь №: 45 369



Приветствую всех!
Пашу на Keil и AT91SAM7SXX взял готовый пример из кейла c:\Keil\ARM\Boards\Atmel\AT91SAM7S-EK\USB\HID\ скомпилировал. Устройство в виндах появляется обмен с ним идет, но через какое-то время(0,5 - 2, 3 часа) устройство выпадает из конфигурации винды, причем в диспетчере устройств его нет. Минут через 5 говорит: устройство подключенное к USB работает не правильно... . При всем этом программа на процессоре работает. Сброса процессора не было. Кто-нибудь сталкивался с этой проблемой?
Заранее благодарен.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Sanya_kv
сообщение Jun 17 2009, 10:29
Сообщение #2


Частый гость
**

Группа: Свой
Сообщений: 185
Регистрация: 25-02-09
Из: Россия
Пользователь №: 45 369



Разобрался с зависанием в функции прерывания USB_ISR.
Попадая в цикл while (isr = pUDP->UDP_ISR) { висит там до тех пор пока isr != 0
Код
void USB_ISR (void) /* __irq */{
  DWORD isr, csr, bkm, n;

  while (isr = pUDP->UDP_ISR) {

    /* End of Bus Reset Interrupt */
    if (isr & AT91C_UDP_ENDBUSRES) {
      USB_Reset();
      pUDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
    }
   ...
   }

итог5е приходит прерывание AT91C_UDP_WAKEUP, обработки которого нет в цикле и сброса его не ведется, проблема решается добавлением pUDP->UDP_ICR = AT91C_UDP_WAKEUP;
AT91C_UDP_WAKEUP - приходит в момент подключения или отключения USB разъёма, но не всегда.

Но основная проблема ещё не решена. Тормозит редкость возникновения ошибки.
Неужели никто не сталкивался с такой проблемой?
Go to the top of the page
 
+Quote Post
KAlex
сообщение Jun 17 2009, 10:47
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 387
Регистрация: 20-12-06
Из: Obninsk
Пользователь №: 23 719



Что делает "USB_Reset();"
А если поменять ресет местами с "pUDP->UDP_ICR = AT91C_UDP_ENDBUSRES;"
Go to the top of the page
 
+Quote Post
Sanya_kv
сообщение Jun 17 2009, 11:21
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 185
Регистрация: 25-02-09
Из: Россия
Пользователь №: 45 369



Цитата(KAlex @ Jun 17 2009, 14:47) *
Что делает "USB_Reset();"
А если поменять ресет местами с "pUDP->UDP_ICR = AT91C_UDP_ENDBUSRES;"


Вот все тело функции:
Код
void USB_ISR (void) /* __irq */{
  DWORD isr, csr, bkm, n;

  while (isr = pUDP->UDP_ISR) {

   if (isr & AT91C_UDP_WAKEUP)
      pUDP->UDP_ICR = AT91C_UDP_WAKEUP;//Это моё

    /* End of Bus Reset Interrupt */
    if (isr & AT91C_UDP_ENDBUSRES) {
      USB_Reset();
#if   USB_RESET_EVENT
      USB_Reset_Event();
#endif
      pUDP->UDP_ICR = AT91C_UDP_ENDBUSRES;
    }

    /* USB Suspend Interrupt */
    if (isr & AT91C_UDP_RXSUSP) {
      USB_Suspend();
#if   USB_SUSPEND_EVENT
      USB_Suspend_Event();
#endif
      pUDP->UDP_ICR = AT91C_UDP_RXSUSP;
    }

    /* USB Resume Interrupt */
    if (isr & AT91C_UDP_RXRSM) {
      USB_Resume();
#if   USB_RESUME_EVENT
      USB_Resume_Event();
#endif
      pUDP->UDP_ICR = AT91C_UDP_RXRSM;
    }

    /* External Resume Interrupt */
    if (isr & AT91C_UDP_EXTRSM) {
      USB_WakeUp();
#if   USB_WAKEUP_EVENT
      USB_WakeUp_Event();
#endif
      pUDP->UDP_ICR = AT91C_UDP_EXTRSM;
    }

    /* Start of Frame Interrupt */
    if (isr & AT91C_UDP_SOFINT) {
#if USB_SOF_EVENT
      USB_SOF_Event();
#endif
      pUDP->UDP_ICR = AT91C_UDP_SOFINT;
    }

    /* Endpoint Interrupts */
    for (n = 0; n < USB_EP_NUM; n++) {
      if (isr & (1 << n)) {

        csr = pUDP->UDP_CSR[n];

        /* Setup Packet Received Interrupt */
        if (csr & AT91C_UDP_RXSETUP) {
          if (USB_P_EP[n]) {
            USB_P_EP[n](USB_EVT_SETUP);
          }
          /* Setup Flag is already cleared in USB_DirCtrlEP */
          /* pUDP->UDP_CSR[n] &= ~AT91C_UDP_RXSETUP; */
        }

        /* Data Packet Received Interrupt */
        bkm = RX_DATA_BK[RxDataBank[n]];
        if (csr & bkm) {
          if (USB_P_EP[n]) {
            USB_P_EP[n](USB_EVT_OUT);
          }
          pUDP->UDP_CSR[n] &= ~bkm;
          if (DualBankEP & (1 << n)) {
            RxDataBank[n] ^= 1;
          }
        }

        /* Data Packet Sent Interrupt */
        if (csr & AT91C_UDP_TXCOMP) {
//          pUDP->UDP_CSR[n] &= ~AT91C_UDP_TXCOMP;
          if (TxDataBank[n]) {
            pUDP->UDP_CSR[n] |= AT91C_UDP_TXPKTRDY;
            TxDataBank[n] = 0;
          }
          if (USB_P_EP[n]) {
            USB_P_EP[n](USB_EVT_IN);
          }
          pUDP->UDP_CSR[n] &= ~AT91C_UDP_TXCOMP;
        }

        /* STALL Packet Sent Interrupt */
        if (csr & AT91C_UDP_STALLSENT) {
          if ((csr & AT91C_UDP_EPTYPE) == AT91C_UDP_EPTYPE_CTRL) {
            if (USB_P_EP[n]) {
              USB_P_EP[n](USB_EVT_IN_STALL);
/*            USB_P_EP[n](USB_EVT_OUT_STALL); */
            }
          }
          pUDP->UDP_CSR[n] &= ~AT91C_UDP_STALLSENT;
        }

      }
    }

  }

  *AT91C_AIC_EOICR = 0;                     /* End of Interrupt */
}


А вот Reset
Код
void USB_Reset (void) {
  DWORD n;

  /* Global USB Reset */
  pUDP->UDP_GLBSTATE &= ~(AT91C_UDP_FADDEN | AT91C_UDP_CONFG | AT91C_UDP_RMWUPE);
  pUDP->UDP_FADDR     =  AT91C_UDP_FEN;
  pUDP->UDP_ICR       =  0xFFFFFFFF;

  /* Reset & Disable USB Endpoints */
  for (n = 0; n < USB_EP_NUM; n++) {
    pUDP->UDP_CSR[n] = 0;
    RxDataBank[n] = 0;
    TxDataBank[n] = 0;
  }
  pUDP->UDP_RSTEP = 0xFFFFFFFF;
  pUDP->UDP_RSTEP = 0;

  /* Setup USB Interrupts */
  pUDP->UDP_IER = AT91C_UDP_RXSUSP | AT91C_UDP_RXRSM | AT91C_UDP_EXTRSM |
                  AT91C_UDP_SOFINT | (2^USB_EP_NUM - 1);

  /* Setup Control Endpoint 0 */
  pUDP->UDP_CSR[0] = AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL;
}


Менять их местами смысла не вижу pUDP->UDP_ICR очищает флаги прерываий. Но попробую.
Go to the top of the page
 
+Quote Post
singlskv
сообщение Jun 17 2009, 21:52
Сообщение #5


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Sanya_kv @ Jun 17 2009, 15:21) *
Код
  while (isr = pUDP->UDP_ISR) {
я вот не до конца уверен в правильности висения в прерывании по такому принципу,
те пока не обработаем все полученные и все вновь пришедшие прерывания...

Нужно посмотреть еще на Вашу функцию записи, там можно случайно зациклиться...
Go to the top of the page
 
+Quote Post
Sanya_kv
сообщение Jun 18 2009, 06:28
Сообщение #6


Частый гость
**

Группа: Свой
Сообщений: 185
Регистрация: 25-02-09
Из: Россия
Пользователь №: 45 369



Цитата(singlskv @ Jun 18 2009, 01:52) *
Нужно посмотреть еще на Вашу функцию записи, там можно случайно зациклиться...

Пример взят стандартный из c:\Keil\ARM\Boards\Atmel\AT91SAM7S-EK\USB\HID\ можите побалываться с ним. Устройство вылетает при интенсивном обмене, примерно 10 посылок в секунду. Опрос HID = 35млСек .
В Иар сделано по другому:
Код
    status = AT91C_BASE_UDP->UDP_ISR;
    status &= AT91C_BASE_UDP->UDP_IMR;
    ...
     if (status == AT91C_UDP_RXSUSP) {
    ...


Сообщение отредактировал Sanya_kv - Jun 18 2009, 06:29
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 21:39
Рейтинг@Mail.ru


Страница сгенерированна за 0.0144 секунд с 7
ELECTRONIX ©2004-2016