|
|
  |
Проблема с отправкой пaкетов по UDP (AT91SAM7S), наблюдаются пропуски пакетов при приеме |
|
|
|
Mar 25 2010, 09:56
|
Местный
  
Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241

|
Ниже приведен кусок основного цикла программы, отвечающий за формирование и отправку данных через UDP. При приеме данных на хост периодически теряются пакеты (60 байт), а то и по несколько пакетов за раз. Количество потерь возрастает, если подключать девайс к более слабой машине. Код while(1) { if(recA_1) //если 32-битное слово готово к отправке на хост { if(!(regUDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY)) //если свободен буфер UDP { unsigned int crc = 0; unsigned int by = recA_1; for(unsigned int ib=0;ib<32;ib++) //Подсчет бита четности { crc = crc^(by&0x1); by >>=1; } if(crc) { unsigned int rec = recA_1; regUDP->UDP_FDR[AT91C_EP_IN] = 11; //командное слово regUDP->UDP_FDR[AT91C_EP_IN] = rec&0xff; //Разбивка 32-битного передаваемого слова на байты unsigned int m_stat = rec>>8; regUDP->UDP_FDR[AT91C_EP_IN] = m_stat&0xff; m_stat = rec>>16; regUDP->UDP_FDR[AT91C_EP_IN] = m_stat&0xff; m_stat = rec>>24; regUDP->UDP_FDR[AT91C_EP_IN] = m_stat&0xff; kA--; // счетчик записанных слов в FIFO UDP }// if(rcrc1) } recA_1 = 0; if(kA==0) //Если FIFO заполнен (12 слов по 5 байт, 60 байт) { regUDP->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY; regUDP->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP); kA=12; } }
}//while(1) Почему потеря при приеме хостом идет пакетами? Как пользоваться 2-мя банками при передачи на хост?
|
|
|
|
|
Mar 25 2010, 10:11
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Цитата(Bulat @ Mar 25 2010, 12:56)  Почему потеря при приеме хостом идет пакетами? Так делать нельзя: Код regUDP->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY; regUDP->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP); Почитайте правила доступа к CSR в DS. Цитата(Bulat @ Mar 25 2010, 12:56)  Как пользоваться 2-мя банками при передачи на хост? 1. Загружаем в FIFO самый первый пакет, ставим TXPKTRDY, переходим к п.2 2. Загружаем в FIFO следующий пакет, переходим к п.3 3. Ждем установки TXCOMP, ставим TXPKTRDY, снимаем TXCOMP, переходим к п.2
|
|
|
|
|
Mar 25 2010, 10:58
|
Местный
  
Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241

|
Цитата(aaarrr @ Mar 25 2010, 15:11)  Так делать нельзя: Код regUDP->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY; regUDP->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP); Почитайте правила доступа к CSR в DS. 1. Загружаем в FIFO самый первый пакет, ставим TXPKTRDY, переходим к п.2 2. Загружаем в FIFO следующий пакет, переходим к п.3 3. Ждем установки TXCOMP, ставим TXPKTRDY, снимаем TXCOMP, переходим к п.2 а вот так правильно будет сделать? Код while(1) { if(recA_1) { if(!(regUDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY)) { regUDP->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP); ...
kA--;
} if(kA==0) { regUDP->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY; kA=12; } } }//while(1)
|
|
|
|
|
Mar 25 2010, 12:44
|
Местный
  
Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241

|
Цитата(aaarrr @ Mar 25 2010, 17:26)  Нет. надо ожидать TXCOMP, только потом повторную запись производить?
|
|
|
|
|
Mar 25 2010, 15:05
|
Местный
  
Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241

|
Цитата(aaarrr @ Mar 25 2010, 18:36)  Да. И TXCOMP можно снимать только после установки TXPKTRDY. Я не могу зависать программу на ожидании TXCOMP, поэтому я сделал следующим образом Код while(1) // MAIN infinite LOOP { if(f_wr_b0 == 1) //первая запись в банк { if(!(regUDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY)) { ... //заполнение буфера ... kA--; } if(kA==0) { regUDP->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY; kA=12; f_wr_b0 = 0; } }//if(f_wr_b0 == 1)
else //последующие записи в банк { if(regUDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) { regUDP->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP); ... //заполнение буфера ... kA--; } if(kA==0) { regUDP->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY; kA=12; } } }//while(1)
но так вообще перестала работать...
|
|
|
|
|
Mar 25 2010, 18:03
|
Местный
  
Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241

|
Цитата(aaarrr @ Mar 25 2010, 20:44)  Придется смочь. Я попытался через 2 банка передавать данные на хост CODE while(1) // MAIN infinite LOOP { if(bank == 0) { if(!(regUDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY)) { //заполняем первый банк ... } if(kA==0) { bank = 1; regUDP->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY; kA=12; } } else //if(bank = 1) { if(chTXC == 0) //второй банк не заполнен { //заполняем второй банк ... if(kA==0) chTXC = 1; }
else //второй банк заполнен { if(regUDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) { chTXC = 0; regUDP->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY; regUDP->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP); kA = 12; } }//else chTXC == 1 }//else if(bank = 1) }
То есть тут я не задерживаю выполнение основного цикла программы на ожидании TXCOMP, а просто периодически опрашиваю его в основном цикле. Но так нестабильно работает. Бывает нормально, стабильно передает данные по USB, а бывает почти сразу захлебывается и перестает передавать. И всеравно пропусков много.
|
|
|
|
|
Mar 30 2010, 05:45
|
Местный
  
Группа: Участник
Сообщений: 206
Регистрация: 12-10-06
Из: ufa
Пользователь №: 21 241

|
Вы писали Цитата(aaarrr @ Mar 25 2010, 15:11) 3. Ждем установки TXCOMP, ставим TXPKTRDY, снимаем TXCOMP, переходим к п.2 CODE if(bank == 0) { if(!(regUDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY)) { //запись в FIFO 5 байт kA--; } if(kA==0) { bank = 1; regUDP->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY; kA=12; } }//if(bank == 0) else //if(bank = 1) { //if(chTXC == 0) //bank 1 åùå íå çàïîëíåí //запись в FIFO 5 байт kA--; if(kA==0) { //chTXC = 1; while(!(regUDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)); regUDP->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY; regUDP->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP); kA = 12; } }//else if(bank = 1)
В соответствии с тем, что вы писали и что в документации, после записи во второй банк ожидаю TXCOMP, устанавливаю TXPKTRDY и сбрасываю TXCOMP Код while(!(regUDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)); regUDP->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY; regUDP->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP);
|
|
|
|
|
Mar 30 2010, 08:39
|
Гуру
     
Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448

|
Еще раз читаем документацию: Цитата WARNING: Due to synchronization between MCK and UDPCK, the software application must wait for the end of the write operation before executing another write by polling the bits which must be set/cleared.
//! Clear flags of UDP UDP_CSR register and waits for synchronization #define Udp_ep_clr_flag(pInterface, endpoint, flags) { \ pInterface->UDP_CSR[endpoint] &= ~(flags); \ while ( (pInterface->UDP_CSR[endpoint] & (flags)) == (flags) ); \ }
//! Set flags of UDP UDP_CSR register and waits for synchronization #define Udp_ep_set_flag(pInterface, endpoint, flags) { \ pInterface->UDP_CSR[endpoint] |= (flags); \ while ( (pInterface->UDP_CSR[endpoint] & (flags)) != (flags) ); \ }
Note: In a preemptive environment, set or clear the flag and wait for a time of 1 UDPCK clock cycle and 1peripheral clock cycle. However, RX_DATA_BLK0, TXPKTRDY, RX_DATA_BK1 require wait times of 3 UDPCK clock cycles and 3 peripheral clock cycles before accessin DPR. От себя добавлю, что на время выполнения Udp_ep_clr_flag и Udp_ep_set_flag нужно запрещать прерывания.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|