Цитата(taoga @ Jul 11 2011, 14:36)

Здравствуйте!
После включения d-cache перестали передаваться пакеты длиной больше 64 байт (не работает "ping-pong endpoint"). Для работы с USB использую код из проекта (примеров) для sam7, код в архиве.
Отвечаю сам себе, может кому-нибудь понадобится.
При использовании ping-pong endpoint после заполнения второго банка нужно ждать пока будет установлен TXCOMP, затем установить TXPKTRDY, только после этого очистить TXCOMP.
С помощью анализатора заметил, что один буфер передался полностью без ошибок, а на следующем произошел сбой.
Поэтому переделал код так, чтобы TXPKTRDY всегда устанавливался вперед TXCOMP.
Код работает как для передачи пакетов <=64 байт, так и больших размеров:
CODE
//#define REG_NO_EFFECT_1_ALL AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \
|AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP \
|AT91C_UDP_TXCOMP
#define REG_NO_EFFECT_1_ALL 0
/// Clears the specified bit(s) in the UDP_CSR register.
/// \param endpoint The endpoint number of the CSR to process.
/// \param flags The bitmap to set to 1.
#define SET_CSR(endpoint, flags) \
{ \
volatile unsigned int reg; \
reg = AT91C_BASE_UDP->UDP_CSR[endpoint] ; \
reg |= REG_NO_EFFECT_1_ALL; \
reg |= (flags); \
AT91C_BASE_UDP->UDP_CSR[endpoint] = reg; \
while ( (AT91C_BASE_UDP->UDP_CSR[endpoint] & (flags)) != (flags)); \
}
/// Sets the specified bit(s) in the UDP_CSR register.
/// \param endpoint The endpoint number of the CSR to process.
/// \param flags The bitmap to clear to 0.
#define CLEAR_CSR(endpoint, flags) \
{ \
volatile unsigned int reg; \
reg = AT91C_BASE_UDP->UDP_CSR[endpoint]; \
reg |= REG_NO_EFFECT_1_ALL; \
reg &= ~(flags); \
AT91C_BASE_UDP->UDP_CSR[endpoint] = reg; \
while ( (AT91C_BASE_UDP->UDP_CSR[endpoint] & (flags)) == (flags)); \
}
//*----------------------------------------------------------------------------
//* \fn AT91F_CDC_Write
//* \brief Send through endpoint 2
//*----------------------------------------------------------------------------
static uint AT91F_UDP_Write(AT91PS_CDC pCdc, const char *pData, uint length)
{
uint cpt = 0;
while ( (AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) );
// Send the first packet
cpt = MIN(length, AT91C_EP_IN_SIZE);
length -= cpt;
while (cpt--) AT91C_BASE_UDP->UDP_FDR[AT91C_EP_IN] = *pData++;
SET_CSR(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
if ( AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP )
CLEAR_CSR(AT91C_EP_IN, AT91C_UDP_TXCOMP);
while (length) {
// Fill the second bank
cpt = MIN(length, AT91C_EP_IN_SIZE);
length -= cpt;
while (cpt--) AT91C_BASE_UDP->UDP_FDR[AT91C_EP_IN] = *pData++;
// Enable interrupt on endpoint
AT91C_BASE_UDP->UDP_IER = 1 << AT91C_EP_IN;
// Wait for the the first bank to be sent
while ( !(AT91C_BASE_UDP->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) )
if ( !AT91F_UDP_IsConfigured(pCdc) ) return length;
SET_CSR(AT91C_EP_IN, AT91C_UDP_TXPKTRDY);
CLEAR_CSR(AT91C_EP_IN, AT91C_UDP_TXCOMP);
}
return length;
}