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

 
 
 
Reply to this topicStart new topic
> USB в at91rm9200, Проблемы с enumeration
sergeeff
сообщение Feb 17 2006, 17:48
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Коллеги!

Столкнулся с неожиданной для себя проблемой. Реализовал USB на at91rm9200 в соответствии с примерами с www.atmel.com. Иногда наблюдается совершенно удивительная вещь (точнее только когда хочу использовать USB-IF тест). Генерится прерывание. Устанавливается бит RXSETUP. Читаю FIFO c control endpoint’a. А там не новая команда, а “хвост” того, что я записал в это FIFO при посылке на host дескриптора или чего-то еще. Соответственно весь процесс enumeration рушится, и тест вообще устройство не обнаруживает. Причем, если из теста выхожу, переключается USB стек в компьютере обратно, и мое устройство благополучно распознается и подключается. Это что аппаратная ляпа в UDP Atmel’a?

Никто не сталкивался с аналогичными проблемами? Я пробовал различные USB 2.0 hub’ы. Единственно, что в компьтере USB 2.0 контроллер остается тем же.

С наилучшими пожеланиями.
Go to the top of the page
 
+Quote Post
sapID
сообщение Feb 21 2006, 12:27
Сообщение #2


Участник
*

Группа: Свой
Сообщений: 24
Регистрация: 21-10-04
Из: Пермь, РФ
Пользователь №: 934



Тоже столкнулся с этим
Думал кеш дурит - отключение кеша не помогает
Причем, в регистре UDP_CSR[0] длина FIFO==0
Немного помогает такой код в обработке SETUP:


if ( !(pUDP->UDP_CSR[0] & AT91C_UDP_RXSETUP) )
return;

do
i32=pUDP->UDP_CSR[0];
while (((i32>>16)&0xFF)<8);

// далее как в примере...
bmRequestType = pUDP->UDP_FDR[0];
...

причины и решения пока не нашел

Сообщение отредактировал sapID - Feb 21 2006, 12:29
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Feb 22 2006, 18:20
Сообщение #3


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Спасибо за идею, sapID.

В понедельник буду на работе – проверю. О результатах сообщу.
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Feb 28 2006, 06:16
Сообщение #4


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Увы, эта идея не работает. Так что собака зарыта где-то в другом месте.
Go to the top of the page
 
+Quote Post
sapID
сообщение Mar 1 2006, 07:05
Сообщение #5


Участник
*

Группа: Свой
Сообщений: 24
Регистрация: 21-10-04
Из: Пермь, РФ
Пользователь №: 934



Я нашел свой косяк (вернее Атмела).
В файле lib_AT91RM9200.h неправильно были прописаны функции AT91F_UDP_EnableEp () и AT91F_UDP_DisableEp () (выделено жирным).
Выяснилось после сравнения с аналогичным файлом для SAM7.
Еще дописал туда несколько функций для совместимости с SAM7.
Теперь то, что относится к UDP в файле lib_AT91RM9200.h выглядит так:

/* *****************************************************************************
SOFTWARE API FOR UDP
***************************************************************************** */
//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_EnableIt
//* \brief Enable UDP IT
//*----------------------------------------------------------------------------
__inline void AT91F_UDP_EnableIt (
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned int flag) // \arg IT to be enabled
{
//* Write to the IER register
pUDP->UDP_IER = flag;
}

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_DisableIt
//* \brief Disable UDP IT
//*----------------------------------------------------------------------------
__inline void AT91F_UDP_DisableIt (
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned int flag) // \arg IT to be disabled
{
//* Write to the IDR register
pUDP->UDP_IDR = flag;
}

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_SetAddress
//* \brief Set UDP functional address
//*----------------------------------------------------------------------------
__inline void AT91F_UDP_SetAddress (
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned char address) // \arg new UDP address
{
pUDP->UDP_FADDR = (AT91C_UDP_FEN | address);
}


//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_EnableEp
//* \brief Enable Endpoint
//*----------------------------------------------------------------------------
__inline void AT91F_UDP_EnableEp (
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned char endpoint) // \arg endpoint number
{
pUDP->UDP_CSR[endpoint] |= AT91C_UDP_EPEDS;
}

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_DisableEp
//* \brief Enable Endpoint
//*----------------------------------------------------------------------------
__inline void AT91F_UDP_DisableEp (
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned char endpoint) // \arg endpoint number
{
pUDP->UDP_CSR[endpoint] &= ~AT91C_UDP_EPEDS;
}


//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_SetState
//* \brief Set UDP Device state
//*----------------------------------------------------------------------------
__inline void AT91F_UDP_SetState (
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned int flag) // \arg new UDP address
{
pUDP->UDP_GLBSTATE &= ~(AT91C_UDP_FADDEN | AT91C_UDP_CONFG);
pUDP->UDP_GLBSTATE |= flag;
}

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_GetState
//* \brief return UDP Device state
//*----------------------------------------------------------------------------
__inline unsigned int AT91F_UDP_GetState ( // \return the UDP device state
AT91PS_UDP pUDP) // \arg pointer to a UDP controller
{
return (pUDP->UDP_GLBSTATE & (AT91C_UDP_FADDEN | AT91C_UDP_CONFG));
}

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_ResetEp
//* \brief Reset UDP endpoint
//*----------------------------------------------------------------------------
__inline void AT91F_UDP_ResetEp ( // \return the UDP device state
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned int flag) // \arg Endpoints to be reset
{
pUDP->UDP_RSTEP = flag;
pUDP->UDP_RSTEP = 0;
}

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_EpStall
//* \brief Endpoint will STALL requests
//*----------------------------------------------------------------------------
__inline void AT91F_UDP_EpStall(
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned char endpoint) // \arg endpoint number
{
pUDP->UDP_CSR[endpoint] |= AT91C_UDP_FORCESTALL;
}

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_EpWrite
//* \brief Write value in the DPR
//*----------------------------------------------------------------------------
__inline void AT91F_UDP_EpWrite(
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned char endpoint, // \arg endpoint number
unsigned char value) // \arg value to be written in the DPR
{
pUDP->UDP_FDR[endpoint] = value;
}

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_EpRead
//* \brief Return value from the DPR
//*----------------------------------------------------------------------------
__inline unsigned int AT91F_UDP_EpRead(
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned char endpoint) // \arg endpoint number
{
return pUDP->UDP_FDR[endpoint];
}

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_EpEndOfWr
//* \brief Notify the UDP that values in DPR are ready to be sent
//*----------------------------------------------------------------------------
__inline void AT91F_UDP_EpEndOfWr(
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned char endpoint) // \arg endpoint number
{
pUDP->UDP_CSR[endpoint] |= AT91C_UDP_TXPKTRDY;
}

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_EpClear
//* \brief Clear flag in the endpoint CSR register
//*----------------------------------------------------------------------------
__inline void AT91F_UDP_EpClear(
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned char endpoint, // \arg endpoint number
unsigned int flag) // \arg flag to be cleared
{
pUDP->UDP_CSR[endpoint] &= ~(flag);
}

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_EpSet
//* \brief Set flag in the endpoint CSR register
//*----------------------------------------------------------------------------
__inline void AT91F_UDP_EpSet(
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned char endpoint, // \arg endpoint number
unsigned int flag) // \arg flag to be cleared
{
pUDP->UDP_CSR[endpoint] |= flag;
}

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_EpStatus
//* \brief Return the endpoint CSR register
//*----------------------------------------------------------------------------
__inline unsigned int AT91F_UDP_EpStatus(
AT91PS_UDP pUDP, // \arg pointer to a UDP controller
unsigned char endpoint) // \arg endpoint number
{
return pUDP->UDP_CSR[endpoint];
}

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_GetInterruptMaskStatus
//* \brief Return UDP Interrupt Mask Status
//*----------------------------------------------------------------------------
__inline unsigned int AT91F_UDP_GetInterruptMaskStatus( // \return UDP Interrupt Mask Status
AT91PS_UDP pUdp) // \arg pointer to a UDP controller
{
return pUdp->UDP_IMR;
}

//*----------------------------------------------------------------------------
//* \fn AT91F_UDP_IsInterruptMasked
//* \brief Test if UDP Interrupt is Masked
//*----------------------------------------------------------------------------
__inline int AT91F_UDP_IsInterruptMasked(
AT91PS_UDP pUdp, // \arg pointer to a UDP controller
unsigned int flag) // \arg flag to be tested
{
return (AT91F_UDP_GetInterruptMaskStatus(pUdp) & flag);
}


// ----------------------------------------------------------------------------
// \fn AT91F_UDP_InterruptStatusRegister
// \brief Return the Interrupt Status Register
// ----------------------------------------------------------------------------
__inline unsigned int AT91F_UDP_InterruptStatusRegister(
AT91PS_UDP pUDP ) // \arg pointer to a UDP controller
{
return pUDP->UDP_ISR;
}

// ----------------------------------------------------------------------------
// \fn AT91F_UDP_InterruptClearRegister
// \brief Clear Interrupt Register
// ----------------------------------------------------------------------------
__inline void AT91F_UDP_InterruptClearRegister (
AT91PS_UDP pUDP, // \arg pointer to UDP controller
unsigned int flag) // \arg IT to be cleat
{
pUDP->UDP_ICR = flag;
}

// ----------------------------------------------------------------------------
// \fn AT91F_UDP_EnableTransceiver
// \brief Enable transceiver
// ----------------------------------------------------------------------------
__inline void AT91F_UDP_EnableTransceiver(
AT91PS_UDP pUDP ) // \arg pointer to a UDP controller
{
pUDP->UDP_TXVC &= ~AT91C_UDP_TXVDIS;
}

// ----------------------------------------------------------------------------
// \fn AT91F_UDP_DisableTransceiver
// \brief Disable transceiver
// ----------------------------------------------------------------------------
__inline void AT91F_UDP_DisableTransceiver(
AT91PS_UDP pUDP ) // \arg pointer to a UDP controller
{
pUDP->UDP_TXVC = AT91C_UDP_TXVDIS;
}

/* *****************************************************************************
SOFTWARE API FOR ST
***************************************************************************** */
Go to the top of the page
 
+Quote Post
sergeeff
сообщение Mar 3 2006, 10:51
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007



Спасибо за отклики на мой вопрос, который мне удалось таки решить.

1. Приведенные исправления в библиотеке мне известны уже как с полгода и я их у себя давно сделал.

2. Эффект с чтением неверных запросов. Проблема оказалась (как часто бывает) совсем не там где сначала казалось. Все дело было во входном фильтре сигналов USB. Плата покупная, не нашей разработки. На входе (pin 2 и 3) сначала стоял L-фильтр (две встречно намотанные обмотки), затем стандартная RC цепочка (27 Ohm + 15 pF). Как только L-фильтр был удален с платы, все сразу же заработало. Думаю, что он приводил с появлению колебательных процессов на фронтах сигналов, которые сбивали внутреннюю работу аппаратной части контроллера USB. Причем это проявлялось при работе только с внешним USB 2.0 hub'ом.

Вот такая, думаю поучительная для embedded программистов, история.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 27th June 2025 - 20:07
Рейтинг@Mail.ru


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