|
Непонятки с UDP у SAM7S64 |
|
|
|
May 24 2007, 07:35
|
Участник

Группа: Участник
Сообщений: 45
Регистрация: 4-11-05
Из: Tomsk
Пользователь №: 10 464

|
Зашел в тупик, бьюсь не первый день. Может, что подскажете?
Делаю HID-устройство на SAM7S64. Обслуживаю прерывание от EP0 стандартно: получаю запрос, разгребаю его и отправляю в ответ дескриптор или репорт. Для справки: размер EP0 равен 8 байтам, а дескрипторы и репорты могут быть больше.
Суть проблемы: Если перед загрузкой в FIFO очередной порции данных флаг TXCOMP опрашиваю поллингом в цикле (так сделано в примере HID mouse от Atmel) - все работает как надо, вопросов нет. Но крутиться в прерывании как-то некрасиво. Если же я начинаю делать "подкачку" данных в прерывании по TXCOMP, то, почему-то, не отправляется уже вторая порция данных.
Например, обрабатывается запрос хоста GET_DESCRIPTOR_DEVICE: 1) по прерыванию от EP0 выгребаю запрос из FIFO 2) формирую дескриптор устройства 3) первые 8 байт дескриптора загружаю в FIFO и поднимаю TXPKTRDY 4) жду прерывания от TXCOMP - и оно приходит 5) сбрасываю TXCOMP 6) очередную порцию дескриптора загружаю в FIFO и поднимаю TXPKTRDY и ничего не передается, хост ждет некоторое время и обрывает транзакцию IN.
Про необходимость правильной реакции на обрыв транзакции знаю. Где могут быть грабли? Любые соображения приму с багодарностью.
PS. Обратите внимание, что в случае поллинга флага TXCOMP все работает как часы, поэтому обсуждать правильность реализации протокола, видимо, не имеет смысла.
|
|
|
|
3 страниц
1 2 3 >
|
 |
Ответов
(1 - 14)
|
May 24 2007, 08:24
|

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

|
Цитата(sgrig @ May 24 2007, 11:35)  5) сбрасываю TXCOMP Попробуй так if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) { pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP); while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP); }
|
|
|
|
|
May 24 2007, 08:35
|
Участник

Группа: Участник
Сообщений: 45
Регистрация: 4-11-05
Из: Tomsk
Пользователь №: 10 464

|
Цитата(KAlex @ May 24 2007, 15:24)  Попробуй так if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) { pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP); while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP); } Так и делаю, примеры я разобрал по "косточкам" и все попробовал. Похоже, я чего-то не понимаю. Кстати, такая же "подкачка" для TWI работает без проблем.
|
|
|
|
|
May 24 2007, 09:32
|

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

|
Вот кусок рабочего кода. Никаких прерываний. AT91F_UDP_IsConfigured вызывается постоянно из основного цикла. __arm static void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, u_int length){ u_int cpt = 0; AT91_REG csr; do { cpt = MIN(length, 8); length -= cpt; while (pUdp->UDP_CSR[0] & AT91C_UDP_TXPKTRDY) if ( pUdp->UDP_ISR & AT91C_UDP_RXSUSP ) return; while (cpt--) pUdp->UDP_FDR[0] = *pData++; if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) { pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP); while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP); } pUdp->UDP_CSR[0] |= AT91C_UDP_TXPKTRDY; do { csr = pUdp->UDP_CSR[0]; // Data IN stage has been stopped by a status OUT if (csr & AT91C_UDP_RX_DATA_BK0) { pUdp->UDP_CSR[0] &= ~(AT91C_UDP_RX_DATA_BK0); return; } } while ( !(csr & AT91C_UDP_TXCOMP) ); } while (length); if (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP) { pUdp->UDP_CSR[0] &= ~(AT91C_UDP_TXCOMP); while (pUdp->UDP_CSR[0] & AT91C_UDP_TXCOMP); } }
__arm void AT91F_USB_SendStall(AT91PS_UDP pUdp) { pUdp->UDP_CSR[0] |= AT91C_UDP_FORCESTALL; while ( !(pUdp->UDP_CSR[0] & AT91C_UDP_ISOERROR) ); pUdp->UDP_CSR[0] &= ~(AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR); AT91F_UDP_ResetEp ( pUdp, 1); while (pUdp->UDP_CSR[0] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR)); }
__arm static void AT91F_HID_Enumerate(AT91PS_HID pHid) { AT91PS_UDP pUDP = pHid->pUdp; uc08 bmRequestType, bRequest; ushort wValue, wIndex, wLength, wStatus;
if ( !(pUDP->UDP_CSR[0] & AT91C_UDP_RXSETUP) ) return;
bmRequestType = pUDP->UDP_FDR[0]; bRequest = pUDP->UDP_FDR[0]; wValue = (pUDP->UDP_FDR[0] & 0xFF); wValue |= (pUDP->UDP_FDR[0] << 8); wIndex = (pUDP->UDP_FDR[0] & 0xFF); wIndex |= (pUDP->UDP_FDR[0] << 8); wLength = (pUDP->UDP_FDR[0] & 0xFF); wLength |= (pUDP->UDP_FDR[0] << 8);
if (bmRequestType & 0x80) { pUDP->UDP_CSR[0] |= AT91C_UDP_DIR; while ( !(pUDP->UDP_CSR[0] & AT91C_UDP_DIR) ); } pUDP->UDP_CSR[0] &= ~AT91C_UDP_RXSETUP; while ( (pUDP->UDP_CSR[0] & AT91C_UDP_RXSETUP) );
// Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1 switch ((bRequest << 8) | bmRequestType) { case STD_GET_DESCRIPTOR: run = 0; if (wValue == 0x100) // Return Device Descriptor AT91F_USB_SendData(pUDP, devDescriptor, MIN(sizeof(devDescriptor), wLength)); else if (wValue == 0x200) // Return Configuration Descriptor AT91F_USB_SendData(pUDP, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength)); else if (wValue == 0x300) // Return Configuration Descriptor AT91F_USB_SendData(pUDP, String0, MIN(sizeof(String0), wLength)); else if (wValue == 0x302) // Return Configuration Descriptor AT91F_USB_SendData(pUDP, String1, MIN(sizeof(String1), wLength)); else if (wValue == 0x303) // Return Configuration Descriptor AT91F_USB_SendData(pUDP, String1, MIN(sizeof(String1), wLength)); else AT91F_USB_SendStall(pUDP); break; ... поскипано __arm static uc08 AT91F_UDP_IsConfigured(AT91PS_HID pHid) { AT91PS_UDP pUDP = pHid->pUdp; AT91_REG isr = pUDP->UDP_ISR; if (isr & AT91C_UDP_ENDBUSRES) { pUDP->UDP_ICR = AT91C_UDP_ENDBUSRES; // reset all endpoints pUDP->UDP_RSTEP = (unsigned int) -1; pUDP->UDP_RSTEP = 0; // Enable the function pUDP->UDP_FADDR = AT91C_UDP_FEN; // Configure endpoint 0 pUDP->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL); } else if (isr & AT91C_UDP_EPINT0) { pUDP->UDP_ICR = AT91C_UDP_EPINT0; AT91F_HID_Enumerate(pHid); } ...поскипано
|
|
|
|
|
May 24 2007, 12:45
|
Участник

Группа: Участник
Сообщений: 45
Регистрация: 4-11-05
Из: Tomsk
Пользователь №: 10 464

|
Цитата(KAlex @ May 24 2007, 16:32)  Вот кусок рабочего кода. Никаких прерываний. AT91F_UDP_IsConfigured вызывается постоянно из основного цикла. ................................... Вопрос как раз и состоял в том, как это все заставить работать ПО ПРЕРЫВАНИЯМ. Без прерываний проблем нет, но это же вариант совсем пионерский.
|
|
|
|
|
May 24 2007, 14:40
|
Участник

Группа: Участник
Сообщений: 45
Регистрация: 4-11-05
Из: Tomsk
Пользователь №: 10 464

|
Цитата(KAlex @ May 24 2007, 20:17)  О! А проверка TXPKTRDY где? А вот с этого места, пожалуйста, подробнее. Зачем его проверять? Ведь TXCOMP устанавливается после падения TXPKTRDY.
|
|
|
|
|
May 25 2007, 07:41
|

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

|
Цитата(sgrig @ May 24 2007, 18:40)  Ведь TXCOMP устанавливается после падения TXPKTRDY. По лигике вещей, так оно и должно быть. Но в даташите об этом ни слова: >>Данный флаг используется для генерации транзакции "Ввод данных" (в направлении устройство->>хост). Программа устройства проверяет возможность записи данных в FIFO путем оценки состояния >>TXPKTRDY, который должен быть равен нулю. Передача в FIFO выполняется путем записи в регистр >>UDP_ FDRx. Сразу после передачи данных в FIFO программа должна уведомить об этом USB->>устройство путем установки бита TXPKTRDY. После этого можно начинать транзакцию USB. TXCOMP >>устанавливается сразу после приема данных хостом. И по cкольку у нас поток "управление", в котором при детекции ошибки повторение автоматическое, то ХЗ, что первым падает и устанавливается.
|
|
|
|
|
May 25 2007, 09:52
|
Участник

Группа: Участник
Сообщений: 45
Регистрация: 4-11-05
Из: Tomsk
Пользователь №: 10 464

|
Попробовал и это. Не помогло. Пойду напьюсь, может просветление наступит
|
|
|
|
|
May 25 2007, 10:15
|

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

|
Цитата(sgrig @ May 25 2007, 13:52)  Попробовал и это. Не помогло. Пойду напьюсь, может просветление наступит Тоже иногда надо. А то  Цитата(sgrig @ May 24 2007, 11:35)  Например, обрабатывается запрос хоста GET_DESCRIPTOR_DEVICE: 1) по прерыванию от EP0 выгребаю запрос из FIFO 2) формирую дескриптор устройства 3) первые 8 байт дескриптора загружаю в FIFO и поднимаю TXPKTRDY 4) жду прерывания от TXCOMP - и оно приходит 5) сбрасываю TXCOMP 6) очередную порцию дескриптора загружаю в FIFO и поднимаю TXPKTRDY и ничего не передается, хост ждет некоторое время и обрывает транзакцию IN. Про RXSETUP не забыл?
|
|
|
|
|
May 25 2007, 10:28
|
Участник

Группа: Участник
Сообщений: 45
Регистрация: 4-11-05
Из: Tomsk
Пользователь №: 10 464

|
Цитата(KAlex @ May 25 2007, 17:15)  Тоже иногда надо. А то  Про RXSETUP не забыл? Конечно нет. Я же говорю, если TXCOMP ждать в цикле, то все работает. Если в прерывании, то кирдык.
|
|
|
|
|
May 28 2007, 05:26
|
Участник

Группа: Свой
Сообщений: 45
Регистрация: 19-04-07
Пользователь №: 27 172

|
Цитата(sgrig @ May 25 2007, 16:28)  Например, обрабатывается запрос хоста GET_DESCRIPTOR_DEVICE: 1) по прерыванию от EP0 выгребаю запрос из FIFO 2) формирую дескриптор устройства 3) первые 8 байт дескриптора загружаю в FIFO и поднимаю TXPKTRDY 4) жду прерывания от TXCOMP - и оно приходит 5) сбрасываю TXCOMP 6) очередную порцию дескриптора загружаю в FIFO и поднимаю TXPKTRDY и ничего не передается, хост ждет некоторое время и обрывает транзакцию IN. Насколько я помню, сначала нужно поднять TXPKTRDY, а уже потом сбросить TXCOMP
|
|
|
|
|
May 28 2007, 09:10
|
Участник

Группа: Участник
Сообщений: 45
Регистрация: 4-11-05
Из: Tomsk
Пользователь №: 10 464

|
Цитата(Calculator @ May 28 2007, 12:26)  Насколько я помню, сначала нужно поднять TXPKTRDY, а уже потом сбросить TXCOMP Делал и так, те же balls, side view. Похоже, косяк в кристалле: биты TXCOMP и STALLSENT не вызывают прерывание EP0INT, при этом RXSETUP и RX_DATA_BK работают, как описано в DS.
|
|
|
|
|
May 28 2007, 17:38
|
Участник

Группа: Новичок
Сообщений: 28
Регистрация: 7-11-06
Пользователь №: 22 038

|
Цитата(sgrig @ May 24 2007, 10:35)  3) первые 8 байт дескриптора загружаю в FIFO и поднимаю TXPKTRDY 6) очередную порцию дескриптора загружаю в FIFO и поднимаю TXPKTRDY А какой размер второго пакета? Случайно не 8, и к тому же это последний пакет?
|
|
|
|
|
May 29 2007, 03:36
|
Участник

Группа: Участник
Сообщений: 45
Регистрация: 4-11-05
Из: Tomsk
Пользователь №: 10 464

|
Цитата(YKonstantin @ May 29 2007, 00:38)  А какой размер второго пакета? Случайно не 8, и к тому же это последний пакет? Нет, эту фишку я тоже знаю. Там действительно косяк с прерыванием.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|