1. the size of the receiver packet buffer must be packet size + 2 bytes to account for the 2 bytes of crc the usb controller slave will read. when there is no space for it it will send a STALL to the host
/*
**********************************************************************
*description: usb routine to enable a particular endpoint
*
*inputs: unsigned int wdEndPNum = endpoint number
* unsigned int wdEndPType= endpoint type
* STM32_USB_EPR_EP_TYPE_BULK
* STM32_USB_EPR_EP_TYPE_CONTROL
* STM32_USB_EPR_EP_TYPE_ISO
* STM32_USB_EPR_EP_TYPE_INTERRUPT
* unsigned int wdEndPSize= 8,16,32,64 etc
*output: wdLclPktAddr = usb local packet address
*NOTE: packet descriptor size must be pktsize+2 to account for
* the two byte crc the host writes
**********************************************************************
*/
int stm32_usb_endp_enable(unsigned int wdEndPNum,\
unsigned int wdEndPType,\
unsigned int wdEndPSize,\
unsigned int *ptrDescAddr,\
unsigned int wdLclPktAddr)
{
volatile unsigned int wdTemp;
/*set tx buffer addr*/
(*ptrDescAddr++) = wdLclPktAddr;
wdLclPktAddr += wdEndPSize;
/*set tx count*/
(*ptrDescAddr++) = wdEndPSize;
/*adjust wdEndPSize to account for extra 2 bytes of crc*/
/*set rx buffer addr*/
wdEndPSize += 2;
(*ptrDescAddr++) = wdLclPktAddr;
wdLclPktAddr += wdEndPSize;
if(wdEndPSize >= 64)
{
wdTemp = STM32_USB_COUNT_RX_BL_SIZE_32BYTE;
wdTemp |= ((wdEndPSize >> 6) << STM32_USB_COUNT_RX_NUM_BLOCK_OFFSET);
}
else
{
wdTemp = STM32_USB_COUNT_RX_BL_SIZE_2BYTE;
wdTemp |= ((wdEndPSize >> 1) << STM32_USB_COUNT_RX_NUM_BLOCK_OFFSET);
}
/*set rx count*/
(*ptrDescAddr++) = wdTemp;
/*set rx and tx status bits*/
wdTemp = (STM32_USB_EPR_STAT_RX_VALID << STM32_USB_EPR_STAT_RX_OFFSET);
wdTemp |= (wdEndPType << STM32_USB_EPR_EP_TYPE_OFFSET);
wdTemp |= (STM32_USB_EPR_STAT_TX_NAK << STM32_USB_EPR_STAT_TX_OFFSET);
wdTemp |= wdEndPNum;
/*these bits be written as 1 to not clear*/
wdTemp |= (STM32_USB_EPR_CTR_RX|STM32_USB_EPR_CTR_TX);
*(PTR_STM32_USB_EP0R + wdEndPNum) = wdTemp;
return wdLclPktAddr;
}
2. the access of the packet buffer in stm32_usb_get/send_packet() must be made as words even though only the two bytes are relevant
/*
**********************************************************************
*description: usb endpoint send packet routine
*
*inputs: unsigned int wdEndPNum = endpoint number
* unsigned int wdEndPSize= 8,16,32,64 etc
* char *ptrBuffer= pointer to buffer
* unsigned int wdBytelen = byte length
*output: 0 on success -1 on error (timeout)
**********************************************************************
*/
int stm32_usb_endp_send_packet(unsigned int wdEndPNum,\
unsigned char *ptrBuffer,\
unsigned int wdEndPSize,\
unsigned int wdBytelen)
{
volatile unsigned int wdTemp, *ptrTemp, wdCount, *ptrDst;
volatile unsigned int wdFlag=FALSE, wdZlp=FALSE;
unsigned short int *ptrSrc;
ptrSrc = (unsigned short int *)ptrBuffer;
while(wdBytelen != 0)
{
if(wdBytelen > wdEndPSize)
wdCount = wdEndPSize;
else
wdCount = wdBytelen;
/*
**************************************************************
*copy the data into the buffer - retrieve address
*update transmission count
*now enable transmission control reg - retrieve value
*prepare for transmission - set status bits
**************************************************************
*/
ptrTemp = (volatile unsigned int *)PTR_STM32_USB_EPRAM;
ptrTemp += (4 * wdEndPNum);
wdTemp = (*ptrTemp);
wdTemp = (PTR_STM32_USB_EPRAM + (wdTemp << 1));
ptrTemp += 1; /*tx count descriptor*/
(*ptrTemp) = wdCount;
/*
**************************************************************
*adjust wdBytelen before starting data xfer
**************************************************************
*/
wdBytelen -= wdCount;
if(wdBytelen == 0 && (wdCount == wdEndPSize))
wdZlp = TRUE;
else
wdZlp = FALSE;
ptrDst = (unsigned int *)wdTemp;
while(wdCount > 0)
{
*(ptrDst++) = (int)(*(ptrSrc++));
if(wdCount >= 2)
wdCount -= 2;
else
wdCount -= 1;
}
ptrTemp = PTR_STM32_USB_EP0R;
ptrTemp += wdEndPNum;
wdTemp = (*ptrTemp);
/*invariants - values that will not modify these reg bits*/
wdTemp &= ~(STM32_USB_EPR_STAT_TX_MASK | \
STM32_USB_EPR_STAT_RX_MASK | \
STM32_USB_EPR_DTOG_TX | \
STM32_USB_EPR_DTOG_RX);
wdTemp |= (STM32_USB_EPR_CTR_TX | STM32_USB_EPR_CTR_RX);
/*user settings*/
wdTemp |= (STM32_USB_EPR_STAT_TX_VALID << \
STM32_USB_EPR_STAT_TX_OFFSET);
(*ptrTemp) = wdTemp;
/*
**************************************************************
*continue until done (do it for 1ms then bail on error)
*wait for CTR_TX to be set
*clear it and restart
**************************************************************
*/
wdCount = 10;
do
{
stm32_timer_uS_delay(100);
wdCount--;
wdTemp = (*PTR_STM32_USB_ISTR);
if((wdTemp & STM32_USB_ISTR_RESET) == STM32_USB_ISTR_RESET)
{
wdFlag = TRUE;
break;
}
wdTemp = (*ptrTemp);
#ifdef IGNORE_FOR_NOW
if((wdTemp & STM32_USB_EPR_CTR_RX) == STM32_USB_EPR_CTR_RX)
{
wdFlag = TRUE;
break;
}
#endif
}while(((wdTemp & STM32_USB_EPR_CTR_TX) == 0) &&\
(wdCount > 0));
/*invariants - values that will not modify these reg bits*/
wdTemp &= ~(STM32_USB_EPR_STAT_TX_MASK | \
STM32_USB_EPR_STAT_RX_MASK | \
STM32_USB_EPR_DTOG_TX | \
STM32_USB_EPR_DTOG_RX);
wdTemp |= (STM32_USB_EPR_CTR_TX | STM32_USB_EPR_CTR_RX);
/*user settings*/
wdTemp &= ~(STM32_USB_EPR_CTR_TX);
(*ptrTemp) = wdTemp;
}
/*
**********************************************************************
*should we send a zlp ?
**********************************************************************
*/
if(wdZlp == TRUE)
{
ptrTemp = (volatile unsigned int *)PTR_STM32_USB_EPRAM;
ptrTemp += (4 * wdEndPNum);
ptrTemp += 1; /*tx count descriptor*/
(*ptrTemp) = 0;
ptrTemp = PTR_STM32_USB_EP0R;
ptrTemp += wdEndPNum;
wdTemp = (*ptrTemp);
/*invariants - values that will not modify these reg bits*/
wdTemp &= ~(STM32_USB_EPR_STAT_TX_MASK | \
STM32_USB_EPR_STAT_RX_MASK | \
STM32_USB_EPR_DTOG_TX | \
STM32_USB_EPR_DTOG_RX);
wdTemp |= (STM32_USB_EPR_CTR_TX | STM32_USB_EPR_CTR_RX);
/*user settings*/
wdTemp |= (STM32_USB_EPR_STAT_TX_VALID << \
STM32_USB_EPR_STAT_TX_OFFSET);
(*ptrTemp) = wdTemp;
}
return 0;
}
/*
**********************************************************************
*description: usb endpoint get packet routine
*
*inputs: unsigned int wdEndPNum = endpoint number
* char *ptrBuffer= pointer to buffer
* unsigned int wdBytelen = byte length
*output: int = size of data posted
**********************************************************************
*/
int stm32_usb_endp_get_packet(unsigned int wdEndPNum,\
unsigned char *ptrBuffer,\
unsigned int wdBytelen)
{
volatile unsigned int wdTemp, *ptrTemp, wdCount, wdSize ,*ptrSrc;
unsigned short int *ptrDst;
/*
**********************************************************************
*get byte size
*copy over data
**********************************************************************
*/
ptrTemp = (volatile unsigned int *)PTR_STM32_USB_EPRAM;
ptrTemp += (4 * wdEndPNum);
ptrTemp += 2;
wdTemp = (*ptrTemp);
wdTemp = (PTR_STM32_USB_EPRAM + (wdTemp << 1));
wdCount = *(ptrTemp +1);
wdCount &= STM32_USB_COUNT_RX_MASK;
wdSize = wdCount;
if(wdCount > wdBytelen)
wdCount = wdBytelen;
ptrSrc = (unsigned int *)wdTemp;
ptrDst = (unsigned short int *)ptrBuffer;
while(wdCount > 0)
{
*(ptrDst++) = (short int)(*(ptrSrc++));
if(wdCount >= 2)
wdCount -= 2;
else
wdCount -= 1;
}
/*
**********************************************************************
*prepare for new transmission at a later date
*set valid bits
**********************************************************************
*/
ptrTemp = PTR_STM32_USB_EP0R;
ptrTemp += wdEndPNum;
wdTemp = (*ptrTemp);
/*invariants - values that will not modify these reg bits*/
wdTemp &= ~(STM32_USB_EPR_STAT_RX_MASK | \
STM32_USB_EPR_STAT_TX_MASK | \
STM32_USB_EPR_DTOG_RX | \
STM32_USB_EPR_DTOG_TX);
wdTemp |= (STM32_USB_EPR_CTR_TX | STM32_USB_EPR_CTR_RX);
/*user settings*/
wdTemp |= (STM32_USB_EPR_STAT_RX_VALID << \
STM32_USB_EPR_STAT_RX_OFFSET);
(*ptrTemp) = wdTemp;
return wdSize;
}