|
SAM7x256 & USB |
|
|
|
Jul 19 2009, 07:40
|
Частый гость
 
Группа: Участник
Сообщений: 119
Регистрация: 3-07-06
Пользователь №: 18 528

|
Код на прием такой Код uint AT91F_UDP_Read(AT91PS_CDC pCdc, char *pData, uint length) { AT91PS_UDP pUdp = pCdc->pUdp; uint packetSize, nbBytesRcv = 0, currentReceiveBank = pCdc->currentRcvBank; if ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RX_DATA_BK0)||(pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RX_DATA_BK1)) { return 0;//то есть, если не было ни одного пакета принято, то просто выходим } while (length) { if ( !AT91F_UDP_IsConfigured(pCdc) ) break; if ( pUdp->UDP_CSR[AT91C_EP_OUT] & currentReceiveBank ) { packetSize = MIN(pUdp->UDP_CSR[AT91C_EP_OUT] >> 16, length); length -= packetSize; if (packetSize < AT91C_EP_OUT_SIZE) length = 0; while(packetSize--) pData[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT]; pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(currentReceiveBank); if (currentReceiveBank == AT91C_UDP_RX_DATA_BK0) currentReceiveBank = AT91C_UDP_RX_DATA_BK1; else currentReceiveBank = AT91C_UDP_RX_DATA_BK0;</P> <P> } } pUdp->UDP_CSR[AT91C_EP_OUT] &= ~(AT91C_UDP_TXCOMP); pCdc->currentRcvBank = currentReceiveBank; return nbBytesRcv;</P> <P>} код на передачу Код uint AT91F_UDP_Write(AT91PS_CDC pCdc, const char *pData, uint length) { AT91PS_UDP pUdp = pCdc->pUdp; uint cpt = 0;</P> <P> if ((pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY)) { return 0;//если усб готово к передаче, то начинаем её } pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP); cpt = MIN(length, AT91C_EP_IN_SIZE); length -= cpt; while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *pData++; pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY;</P> <P> while (length) { cpt = MIN(length, AT91C_EP_IN_SIZE); length -= cpt; while (cpt--) pUdp->UDP_FDR[AT91C_EP_IN] = *pData++; while ( !(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) ) if ( !AT91F_UDP_IsConfigured(pCdc) ) return length; pUdp->UDP_CSR[AT91C_EP_IN] &= ~(AT91C_UDP_TXCOMP); while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP); pUdp->UDP_CSR[AT91C_EP_IN] |= AT91C_UDP_TXPKTRDY; } return length; } в основном цикле я поочередно вызываю сначала чтение, потом запись. И получается, что посылка отправляется только тогда, когда произойдет прием посылки. Если убрать чтение в основном цикле, то передача идет всегда. Почему так? Мне нужно принимать контроллером всего 2 байта, а передавать 256, друг за другом. Причем 2 байта могут быть посланы контроллеру не всегда. получается следующее Код pCDC.Read(&pCDC, ((char *) &data_comp), 2); if ((length>256)) { pCDC.Write(&pCDC, data, length); } обнаружилось, что данные все таки доходят до микроконтроллера, а вот он на комп ничего не отправляет. убирая строчку чтения, получаем, что данные на комп все таки идут
|
|
|
|
|
 |
Ответов
(30 - 44)
|
Oct 31 2009, 15:42
|
дятел
    
Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065

|
Цитата(overloaded @ Oct 31 2009, 17:59)  Вот и интересно где тот вариант встречается). Например вот так в атмеловском Framework: Код /// /// !Macros /// - CLEAR_CSR /// - SET_CSR
/// Bitmap for all status bits in CSR. #define REG_NO_EFFECT_1_ALL UDP_CSR_RX_DATA_BK0 | UDP_CSR_RX_DATA_BK1 \ |UDP_CSR_STALLSENT | UDP_CSR_RXSETUP \ |UDP_CSR_TXCOMP
/// 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 = UDP_CSR(UDP_BASE,endpoint); \ reg |= REG_NO_EFFECT_1_ALL; \ reg |= (flags); \ UDP_CSR(UDP_BASE,endpoint) = reg; \ while ( (UDP_CSR(UDP_BASE,endpoint) & (flags)) != (flags)); \ } SET_CSR(...) вызываемая без запрета всех(или только нужных) прерываний гарантированно когда-нить зависнет...
|
|
|
|
|
Dec 12 2009, 06:36
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Продолжение темы. Решил оптимизировать прием данных от хоста. Ранее я выгребал полностью данные из точки в софтовый ФИФО, а из него задача выгребала данных столько, сколько ей нужно. Решил избавиться от софтового буфера и забирать данные, сколько необходимо, сразу из конечной точки. При этом, если нужно данных меньше, чем находится в буфере точки, то не сбрасывать флаг приема (AT91C_UDP_RX_DATA_BK0/1) а просто запрещать прерывания. Что то опять туплю к выходным, ни как не выходит... Описание конечной точки: Код /* Endpoint status setup */ typedef struct __UDP_EP_STATUS { INT size; /* EP FIFO size */ UINT32 type; /* EP type (for store in CSR register) */ UINT32 imask; /* Interrupt flag in the IMR register (for enable/disable interrupt) */ UINT32 banks; /* Current receive bank for OUT endpoint, number of TX FIFO's for IN endpoint */ P_UINT8 data; /* Data buffer pointer */ INT len; /* Data size in buffer */ INT inbuf; /* For RX data count of buffered data */ void (*fcbk)(void); /* Optional transfer complete callback function */ } UDP_EP_STATUS, *P_UDP_EP_STATUS; Обработчик прерывания по приему Код /* Receive Data from host host complete */ if((AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1) & csr) { DBG_OUT("CSR%d RX: ", ep); if(p_eps->data) /* Endpoint is in read state */ { if(p_eps->inbuf > 0) /* Old EP FIFO not be fully readed */ cnt = p_eps->inbuf; else cnt = (AT91C_UDP_RXBYTECNT & csr) >> 16; /* Get data counter */ if(p_eps->len >= cnt) /* Room for new data exist */ { p_eps->len -= cnt; /* Add data to be readed */ for(i = 0; i < cnt; i++) /* Read new data */ *p_eps->data++ = AT91C_BASE_UDP->UDP_FDR[ep]; p_eps->inbuf = 0; /* No data in FIFO */ ClrRxFlag(ep, p_eps); /* Notify USB peripheral device that data have been read */ } else /* No room for all received bank */ { p_eps->inbuf = cnt - p_eps->len; /* Store number of bytes in EP FIFO */ for(i = 0; i < p_eps->len; i++) /* Read new data */ *p_eps->data++ = AT91C_BASE_UDP->UDP_FDR[ep]; p_eps->len = 0; } /* Check read complete */ if(!p_eps->len || cnt < p_eps->size) /* OK */ { p_eps->data = NULL; AT91C_BASE_UDP->UDP_IDR = p_eps->imask; /* disable interrupt */ if(p_eps->fcbk) /* Call Rx Complete application callback */ p_eps->fcbk(); } } else /* Data buffer not set - application not wating data */ { DBG_OUT("NAK! Data buffer not set.\r\n"); AT91C_BASE_UDP->UDP_IDR = p_eps->imask; } } Собственно попытка чтения Код /******************************************************************************* Read data from endpoint *******************************************************************************/ INT UDP_EP_Read(UINT8 ep, void *data, INT len, void (*fcbk)(void)) { P_UDP_EP_STATUS p_eps; DBG_OUT("UDP_EP%d_Read: ", ep); if(!g_State.curr_cfg) /* Check UDP device state */ { DBG_OUT("Device not configured!\r\n"); return FALSE; /* Not configured */ } if(!ep || ep >= UDP_NUM_EP) /* Check enpoint number */ { DBG_OUT("Invalid number %d!\r\n", ep); return FALSE; } p_eps = g_State.ep[ep]; /* Get endpoint status */ if(!p_eps) /* Check endpoint parameters */ { DBG_OUT("ep not inited!\r\n"); return FALSE; } if(p_eps->data) { DBG_OUT("ep busy!\r\n"); return FALSE; } /* Set data fields */ p_eps->data = data; p_eps->len = len; p_eps->fcbk = fcbk; AT91C_BASE_UDP->UDP_IER = p_eps->imask; /* Enable interrupts from endpoint */ DBG_OUT("\r\n"); return TRUE; /* Success */ }
--------------------
|
|
|
|
|
Dec 12 2009, 15:03
|

Гуру
     
Группа: Свой
Сообщений: 2 720
Регистрация: 24-03-05
Пользователь №: 3 659

|
Цитата(aaarrr @ Dec 12 2009, 20:01)  Напишите, как оно по-вашему должно работать, и как работает на самом деле. Спасибо, уже разобрался. Опять косяк с палочками был  . Собственно, то что хотел, описал постом выше. Когда я написал первый вариант драйвера - вычитывал все из буфера точки в буфер драйвера. А из буфера задача читала байт столько, сколько ей нужно было. Теперь решил оптимизировать и убрать буфер между драйвером UDP и задачей. Т.е. драйвер напрямую отдавал из хардварного FIFO конечной точки столько, сколько нужно задаче. Если в FIFO данные кончались, то флаг RX_BK0(1) очищался. Не работало в очередной раз по моей невнимательности. Надеюсь понятно объяснил.
--------------------
|
|
|
|
|
Dec 15 2009, 06:22
|

Любитель
    
Группа: Свой
Сообщений: 1 864
Регистрация: 20-08-06
Из: Тольятти
Пользователь №: 19 695

|
Цитата(ZiB @ Dec 15 2009, 07:28)  Если я правильно понимаю, то для режима Bulk максимальная частота опроса (для full speed) составляет 1 кГц, а максимальная длина пакета 64 байта. Устройства "Mass Storage Class Device" используют тип передачи Bulk, каким образом получается "900 килобайт в секунду"? У STM32 High Speed USB? Транзакции bulk могут занимать всю свободную ширину шины USB. За один фрейм (1мс) будет несколько передач. 900 килобайт - это Full Speed. High Speed - это десятки мегабайт/сек.
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|