📄 sausb.c
字号:
*/
static
void showStats(DM_Function_T * funcP, void * arg)
{
DM_ClearScreen();
/* Global stats
*/
DM_PrintfPaged("Int: %d, Cmd: %d",
udcStats.usbIntCount,
udcStats.commandCount);
/* DMA stats
*/
DM_PrintfPaged("RcvDma: %d, XmitDma: %d",
udcStats.rcvDmaCount,
udcStats.xmitDmaCount);
/* Loopback stats
*/
DM_PrintfPaged("Loop: %d, RxCmp: %d/%d",
udcStats.loopCount,
udcStats.rxCompareError,
udcStats.rxCompareCount);
/* Endpoint 1 (IN) stats
*/
DM_PrintfPaged("RcvPkt: %d, AcptPkt: %d",
udcStats.readPacketCount,
udcStats.acceptPacketCount);
DM_PrintfPaged("FifoRd: %d, FifoOvr: %d",
udcStats.extraFIFOReads,
udcStats.fifoReadOverrun);
DM_PrintfPaged("BadPkt: %d, DmaBsy: %d",
udcStats.badRdPacketCount,
udcStats.dmaReadPending);
DM_PrintfPaged("NpRPC: %d, RejectPkt: %d",
udcStats.noRPC,
udcStats.rejectPacket);
/* Endpoint 2 (OUT) count
*/
DM_PrintfPaged("XmitPkt: %d/%d, WrtPkt: %d",
udcStats.badWrPacketCount,
udcStats.goodWrPacketCount,
udcStats.writePacketCount);
DM_PrintfPaged("NoDMA: %d",
udcStats.noDMA);
/* Endpoint 0 (control) stats
*/
DM_PrintfPaged("Send: %d/%d, Fail: %d",
udcStats.reSendCount,
udcStats.sendCount,
udcStats.sendFailCount);
DM_PrintfPaged("WriteCnt: %d/%d",
udcStats.reWriteCount,
udcStats.writeCount);
DM_PrintfPaged("ReadCnt: %d/%d, Fail: %d",
udcStats.reReadCount,
udcStats.readCount,
udcStats.readFailCount);
/* Register read/write stats
*/
DM_PrintfPaged("UDD: %d/%d, RIM: %d/%d",
udcStats.uddRewrites, udcStats.uddWrites,
udcStats.rimRewrites, udcStats.rimWrites);
DM_PrintfPaged("Comp: %d/%d, Cimp: %d/%d",
udcStats.compRewrites, udcStats.compWrites,
udcStats.cimpRewrites, udcStats.cimpWrites);
DM_PrintfPaged("SSE: %d/%d, SO: %d/%d",
udcStats.sseRewrites, udcStats.sseWrites,
udcStats.soRewrites, udcStats.soWrites);
DM_PrintfPaged("SST: %d/%d, FST: %d/%d",
udcStats.sstRewrites, udcStats.sstWrites,
udcStats.fstRewrites, udcStats.fstWrites);
DM_PrintfPaged("IPR: %d/%d",
udcStats.iprRewrites, udcStats.iprWrites);
DM_PrintfPaged("SST1: %d/%d, FST1: %d/%d",
udcStats.sst1Rewrites, udcStats.sst1Writes,
udcStats.fst1Rewrites, udcStats.fst1Writes);
DM_PrintfPaged("SST2: %d/%d, FST2: %d/%d",
udcStats.sst2Rewrites, udcStats.sst2Writes,
udcStats.fst2Rewrites, udcStats.fst2Writes);
DM_PrintfPaged("RPC: %d/%d, TPC: %d/%d",
udcStats.rpcRewrites, udcStats.rpcWrites,
udcStats.tpcRewrites, udcStats.tpcWrites);
DM_PrintfPaged("RIR: %d/%d, MisRIR: %d",
udcStats.rirRewrites, udcStats.rirWrites,
udcStats.missedRIR);
DM_PrintfPaged("TIR: %d/%d, MisTIR: %d",
udcStats.tirRewrites, udcStats.tirWrites,
udcStats.missedTIR);
DM_PrintfPaged("EIR: %d/%d, RSTIR: %d/%d",
udcStats.eirRewrites, udcStats.eirWrites,
udcStats.rstirRewrites, udcStats.rstirWrites);
DM_PrintfPaged("SUSIR: %d/%d, RESIR: %d/%d",
udcStats.susirRewrites, udcStats.susirWrites,
udcStats.resirRewrites, udcStats.resirWrites);
DM_AnyKeyToContinue(NULL);
}
/*----------------------------------------------------------------------
* Clear statistics
*/
static
void clearStats(DM_Function_T * funcP, void * arg)
{
clearUdcStats();
}
/*----------------------------------------------------------------------
* Compare the receive buffer
*/
static
void compareRx(void)
{
int i, j;
udcStats.rxCompareCount++;
for (i=0; i < RX_BUFSIZE/maxPacketSize; i++) {
for (j=0; j < maxPacketSize; j++) {
if (rxDataP[i*maxPacketSize+j] != i) {
DM_WarnPrintf("Mismatch buf %d, index %d\n",
udcStats.rxCompareCount,
i*maxPacketSize+j);
udcStats.rxCompareError++;
return;
}
}
}
}
/*----------------------------------------------------------------------
* Loopback data received to data transmit
*/
static
void loopDma(int reason, char * buf, void * param)
{
udcStats.loopCount++;
compareRx();
memset(rxDataP,0xff,RX_BUFSIZE);
}
/*----------------------------------------------------------------------
* Receive interrupt handler. This is called on DMA channel buffer
* completion. Dispatch the callback function (if any) and keep track of
* which buffer is active. Make sure the channel is cleared in case the
* callback is not active so we don't continue to get interrupts.
*/
static
void rcvHandler(void * arg)
{
void * buf = rcvBufs[whichGetRcvBuf].buf;
udcStats.rcvDmaCount++;
SA_ClearDMA(rcvDmaP,whichGetRcvBuf);
rcvBufs[whichGetRcvBuf].buf = NULL;
rcvBufs[whichGetRcvBuf].dmaP = NULL;
DM_DbgPrintf("Rcv done %d bufs", rcvPacketCount);
if (rcvCallback)
rcvCallback(DM_SerialReceiveDone,
(char*)buf,
rcvBufs[whichGetRcvBuf].param);
whichGetRcvBuf ^= 1;
}
/*----------------------------------------------------------------------
* Transmit interrupt service handler. This is called on DMA channel
* buffer completion. Dispatch the callback function (if any) and keep
* track of which buffer is active. Make sure the channel is cleared in
* case the callback is not active so we don't continue to get interrupts.
*/
static
void xmitHandler(void * arg)
{
void * buf = xmitBufs[whichGetXmitBuf].buf;
udcStats.xmitDmaCount++;
SA_ClearDMA(xmitDmaP,whichGetXmitBuf);
xmitBufs[whichGetXmitBuf].buf = NULL;
xmitBufs[whichGetXmitBuf].dmaP = NULL;
if (xmitCallback)
xmitCallback(DM_SerialTransmitDone,
(char*)buf,
xmitBufs[whichGetXmitBuf].param);
whichGetXmitBuf ^= 1;
}
/*----------------------------------------------------------------------
* Find the requested descriptor
*/
static
char * getDescriptor(int type, int index, int * length)
{
switch (type) {
case UsbDescTypeDevice:
*length = SA11x0_USB_DeviceDesc[0];
return SA11x0_USB_DeviceDesc;
break;
case UsbDescTypeConfiguration:
*length = SA11x0_USB_ConfigDesc[2]; /* Total length */
return SA11x0_USB_ConfigDesc;
break;
}
return NULL;
}
/*----------------------------------------------------------------------
* Read the command from the endpoint 0 FIFO
*/
static
int getCommand(void * argP)
{
unsigned char * bufP = (unsigned char*)argP;
int length = udcP->udcwc.wc;
int reReadAttempts = 10;
char wcBuf[16];
char tcBuf[16];
int count[16];
int attempts[16];
int i;
if (timerFuncP)
timerFuncP->stop(timerP, 0, reSendTimerInterval, reSendProc, NULL);
memset(bufP,0x55,8);
for (i=0; i < length; i++) {
int oldwc = udcP->udcwc.wc;
int retryCount = readRetryCount;
bufP[i] = udcP->udcd0.data;
udcStats.readCount++;
/* Make sure the read actually worked by polling the FIFO count.
* When it decrements the read has been done, otherwise the read was
* ignored.
*/
wcBuf[i] = oldwc;
tcBuf[i] = udcP->udcwc.wc;
while (oldwc == tcBuf[i]) {
if (--retryCount < 0) { /* Looks like we missed a read */
bufP[i] = udcP->udcd0.data;
udcStats.reReadCount++;
retryCount = readRetryCount;
/* If we get stuck here abort the command.
*/
if (--reReadAttempts < 0) {
udcStats.readFailCount++;
return 1;
}
}
tcBuf[i] = udcP->udcwc.wc;
}
count[i] = readRetryCount - retryCount;
attempts[i] = 10 - reReadAttempts;
#if 0
#if 0
{
int dummy, x;
/* We have finished the write, now wait a bit to let things propagate.
*/
for (x=0; x < 10; x++)
dummy += *(volatile unsigned int *)&udcP->udcwc;
}
#else
DM_WaitUs(2);
#endif
#endif
}
/* All setup commands are 8 bytes in length
*/
if (length != 8) {
DM_WarnPrintf("UDC bad command length %d\n", length);
return 1;
}
if (udcP->udcwc.wc != 0) {
DM_WarnPrintf("UDC EP0 FIFO not empty %d\n", udcP->udcwc.wc);
DM_WarnPrintf("%02X %02X %02X %02X %02X %02X %02X %02X",
bufP[0], bufP[1], bufP[2], bufP[3],
bufP[4], bufP[5], bufP[6], bufP[7]);
DM_WarnPrintf("%02X %02X %02X %02X %02X %02X %02X %02X",
wcBuf[0], wcBuf[1], wcBuf[2], wcBuf[3],
wcBuf[4], wcBuf[5], wcBuf[6], wcBuf[7]);
DM_WarnPrintf("%02X %02X %02X %02X %02X %02X %02X %02X",
tcBuf[0], tcBuf[1], tcBuf[2], tcBuf[3],
tcBuf[4], tcBuf[5], tcBuf[6], tcBuf[7]);
DM_WarnPrintf("%2d %2d %2d %2d %2d %2d %2d %2d",
count[0], count[1], count[2], count[3],
count[4], count[5], count[6], count[7]);
DM_WarnPrintf("%2d %2d %2d %2d %2d %2d %2d %2d",
attempts[0], attempts[1], attempts[2], attempts[3],
attempts[4], attempts[5], attempts[6], attempts[7]);
return 1;
}
return 0;
}
/*----------------------------------------------------------------------
* Command response with data packets
*/
static
void sendData(void * argP, int length, int totalLen)
{
unsigned char * bufP = (unsigned char*)argP;
struct udccs0Bits udccs0;
int i;
DM_DbgPrintf("UDC send %d bytes\n", length);
/* Send the data back. The FIFO should be turned around for
* us already. Just blast away ...
*/
for (i=0; (i < length) && (i < USBR_MAX_PACKET_SIZE_CTL); i++) {
int oldwc = udcP->udcwc.wc;
int retryCount = writeRetryCount;
int retryAttempts = 10;
int wc;
IOW_REG_FIELD(struct udcdBits,&udcP->udcd0,data,bufP[i]);
udcStats.writeCount++;
IOW_REG_GET(struct udcwcBits, &udcP->udcwc,wc,wc);
while (oldwc == wc) {
if (--retryCount < 0) { /* Looks like we missed a write */
IOW_REG_FIELD(struct udcdBits,&udcP->udcd0,data,bufP[i]);
udcStats.reWriteCount++;
retryCount = writeRetryCount;
/* If the FIFO did not detect a command requiring return
* data we will get stuck here. Abort the command.
*/
if (--retryAttempts < 0) {
UDC_REG_BITSET(struct udccs0Bits,&udcP->udccs0,fst,1,
udcP->udccs0.fst != 1,
fst);
udcStats.sendFailCount++;
return;
}
}
IOW_REG_GET(struct udcwcBits, &udcP->udcwc,wc,wc);
}
#if 1
{
int dummy, x;
/* We have finished the write, now wait a bit to let things propagate.
*/
for (x=0; x < 10; x++)
dummy += *(volatile unsigned int *)&udcP->udcwc;
}
#endif
}
/* Form the register update. Always set IPR.
*/
udccs0 = udcP->udccs0;
udccs0.ipr = 1;
/* We can not complete on a packet which is full only if
* the request allowed for more data. We need to wait till
* next time and generate a zero length packet, so only complete
* if we're at the end and it is not the max packet size.
*/
if ((i == length) && ((i != USBR_MAX_PACKET_SIZE_CTL) || (i == totalLen))) {
savSendPacket = sendPacket;
savSendPacketLength = sendPacketLength;
sendPacket = NULL;
sendPacketLength = length - i;
sendTotalLength = totalLen - i;
udccs0.de = 1;
}
/* Need to send another packet.
*/
else {
sendPacket = (char*)&bufP[i];
sendPacketLength = length - i;
sendTotalLength = totalLen - i;
savSendPacket = sendPacket;
savSendPacketLength = sendPacketLength;
}
/* Update the register
*/
UDC_REG_WRITEX(*(volatile unsigned *)&udcP->udccs0,*(unsigned *)&udccs0,
udcP->udccs0.ipr != 1,
ipr);
udcStats.sendCount++;
DM_DbgPrintf("UDC send packet done\n");
}
/*----------------------------------------------------------------------
* Send command done
*/
static
void sendCommandDone(void)
{
/* Release the command FIFO and start the data phase
*/
UDC_REG_BITSET(struct udccs0Bits,&udcP->udccs0,so,1,
udcP->udccs0.opr != 0,
so);
}
/*----------------------------------------------------------------------
* Command response with no data packets
*/
static
void sendDone(int err)
{
struct udccs0Bits udccs0 = udcP->udccs0;
DM_DbgPrintf("UDC send done\n");
udccs0.so = 1;
udccs0.de = 1;
udccs0.fst = err;
UDC_REG_WRITEX(udcP->udccs0,udccs0,
udcP->udccs0.opr != 0,
so);
}
/*----------------------------------------------------------------------
* Timer handler. If there is still a transmit pending restart it
*/
static
void reSendProc(void * arg)
{
struct udccs0Bits udccs0 = udcP->udccs0;
/* If IPR and DE are both zero we have sent the last packet.
*/
if ((udccs0.ipr == 0) && (udccs0.de == 0) && (sendPacket == NULL))
savSendPacket = NULL;
/* If there is still data to send we have missed a write to IPR. Resend
*/
if ((udccs0.ipr == 0) && (savSendPacket)) {
sendData(sendPacket, sendPacketLength, sendTotalLength);
udcStats.reSendCount++;
}
}
/*----------------------------------------------------------------------
* Set the device address
*/
static
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -