Simplified USBv1 driver.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8656 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
Giovanni Di Sirio 2015-12-30 12:11:29 +00:00
parent 32f4a2999d
commit 01e18c68be
1 changed files with 39 additions and 51 deletions

View File

@ -122,44 +122,71 @@ static uint32_t usb_pm_alloc(USBDriver *usbp, size_t size) {
* *
* @param[in] udp pointer to a @p stm32_usb_descriptor_t * @param[in] udp pointer to a @p stm32_usb_descriptor_t
* @param[out] buf buffer where to copy the packet data * @param[out] buf buffer where to copy the packet data
* @param[in] n maximum number of bytes to copy. This value must * @return The size of the receivee packet.
* not exceed the maximum packet size for this endpoint.
* *
* @notapi * @notapi
*/ */
static void usb_packet_read_to_buffer(stm32_usb_descriptor_t *udp, static size_t usb_packet_read_to_buffer(usbep_t ep, uint8_t *buf) {
uint8_t *buf, size_t n) { size_t i, n;
stm32_usb_descriptor_t *udp = USB_GET_DESCRIPTOR(ep);
stm32_usb_pma_t *pmap = USB_ADDR2PTR(udp->RXADDR0); stm32_usb_pma_t *pmap = USB_ADDR2PTR(udp->RXADDR0);
uint32_t epr = STM32_USB->EPR[ep];
while (n > 1) { /* Double buffering is always enabled for isochronous endpoints, and
although we overlap the two buffers for simplicity, we still need
to read from the right counter. The DTOG_RX bit indicates the buffer
that is currently in use by the USB peripheral, that is, the buffer
in which the next received packet will be stored, so we need to
read the counter of the OTHER buffer, which is where the last
received packet was stored.*/
n = (size_t)udp->RXCOUNT0 & RXCOUNT_COUNT_MASK;
if (EPR_EP_TYPE_IS_ISO(epr) && !(epr & EPR_DTOG_RX))
n = (size_t)udp->RXCOUNT1 & RXCOUNT_COUNT_MASK;
i = n;
while (i > 1) {
uint32_t w = *pmap++; uint32_t w = *pmap++;
*buf++ = (uint8_t)w; *buf++ = (uint8_t)w;
*buf++ = (uint8_t)(w >> 8); *buf++ = (uint8_t)(w >> 8);
n -= 2; i -= 2;
} }
if (n > 0) { if (i > 0) {
*buf = (uint8_t)*pmap; *buf = (uint8_t)*pmap;
} }
return n;
} }
/** /**
* @brief Writes to a dedicated packet buffer. * @brief Writes to a dedicated packet buffer.
* *
* @param[in] udp pointer to a @p stm32_usb_descriptor_t * @param[in] ep endpoint number
* @param[in] buf buffer where to fetch the packet data * @param[in] buf buffer where to fetch the packet data
* @param[in] n maximum number of bytes to copy. This value must * @param[in] n maximum number of bytes to copy. This value must
* not exceed the maximum packet size for this endpoint. * not exceed the maximum packet size for this endpoint.
* *
* @notapi * @notapi
*/ */
static void usb_packet_write_from_buffer(stm32_usb_descriptor_t *udp, static void usb_packet_write_from_buffer(usbep_t ep,
const uint8_t *buf, const uint8_t *buf,
size_t n) { size_t n) {
stm32_usb_descriptor_t *udp = USB_GET_DESCRIPTOR(ep);
stm32_usb_pma_t *pmap = USB_ADDR2PTR(udp->TXADDR0); stm32_usb_pma_t *pmap = USB_ADDR2PTR(udp->TXADDR0);
uint32_t epr = STM32_USB->EPR[ep];
uint32_t w; uint32_t w;
int i = (int)n; int i = (int)n;
/* Double buffering is always enabled for isochronous endpoints, and
although we overlap the two buffers for simplicity, we still need
to write to the right counter. The DTOG_TX bit indicates the buffer
that is currently in use by the USB peripheral, that is, the buffer
from which the next packet will be sent, so we need to write the
counter of that buffer.*/
udp->TXCOUNT0 = (stm32_usb_pma_t)n;
if (EPR_EP_TYPE_IS_ISO(epr) && (epr & EPR_DTOG_TX))
udp->TXCOUNT1 = (stm32_usb_pma_t)n;
while (i > 0) { while (i > 0) {
w = *buf++; w = *buf++;
w |= *buf++ << 8; w |= *buf++ << 8;
@ -204,21 +231,9 @@ static void usb_serve_endpoints(USBDriver *usbp, uint32_t ep) {
if (n > epcp->in_maxsize) if (n > epcp->in_maxsize)
n = epcp->in_maxsize; n = epcp->in_maxsize;
/* Double buffering is always enabled for isochronous endpoints, and
although we overlap the two buffers for simplicity, we still need
to write to the right counter. The DTOG_TX bit indicates the buffer
that is currently in use by the USB peripheral, that is, the buffer
from which the next packet will be sent, so we need to write the
counter of that buffer.*/
USB_GET_DESCRIPTOR(ep)->TXCOUNT0 = (stm32_usb_pma_t)n;
if (EPR_EP_TYPE_IS_ISO(epr) && (epr & EPR_DTOG_TX))
USB_GET_DESCRIPTOR(ep)->TXCOUNT1 = (stm32_usb_pma_t)n;
/* Writes the packet from the defined buffer.*/ /* Writes the packet from the defined buffer.*/
epcp->in_state->txbuf += transmitted; epcp->in_state->txbuf += transmitted;
usb_packet_write_from_buffer(USB_GET_DESCRIPTOR(ep), usb_packet_write_from_buffer(ep, epcp->in_state->txbuf, n);
epcp->in_state->txbuf,
n);
/* Starting IN operation.*/ /* Starting IN operation.*/
EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID); EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID);
@ -237,23 +252,8 @@ static void usb_serve_endpoints(USBDriver *usbp, uint32_t ep) {
_usb_isr_invoke_setup_cb(usbp, ep); _usb_isr_invoke_setup_cb(usbp, ep);
} }
else { else {
stm32_usb_descriptor_t *udp = USB_GET_DESCRIPTOR(ep);
/* Double buffering is always enabled for isochronous endpoints, and
although we overlap the two buffers for simplicity, we still need
to read from the right counter. The DTOG_RX bit indicates the buffer
that is currently in use by the USB peripheral, that is, the buffer
in which the next received packet will be stored, so we need to
read the counter of the OTHER buffer, which is where the last
received packet was stored.*/
n = (size_t)udp->RXCOUNT0 & RXCOUNT_COUNT_MASK;
if (EPR_EP_TYPE_IS_ISO(epr) && !(epr & EPR_DTOG_RX))
n = (size_t)udp->RXCOUNT1 & RXCOUNT_COUNT_MASK;
/* Reads the packet into the defined buffer.*/ /* Reads the packet into the defined buffer.*/
usb_packet_read_to_buffer(udp, n = usb_packet_read_to_buffer(ep, epcp->out_state->rxbuf);
epcp->out_state->rxbuf,
n);
epcp->out_state->rxbuf += n; epcp->out_state->rxbuf += n;
/* Transaction data updated.*/ /* Transaction data updated.*/
@ -688,25 +688,13 @@ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
void usb_lld_start_in(USBDriver *usbp, usbep_t ep) { void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
size_t n; size_t n;
USBInEndpointState *isp = usbp->epc[ep]->in_state; USBInEndpointState *isp = usbp->epc[ep]->in_state;
uint32_t epr = STM32_USB->EPR[ep];
/* Transfer initialization.*/ /* Transfer initialization.*/
n = isp->txsize; n = isp->txsize;
if (n > (size_t)usbp->epc[ep]->in_maxsize) if (n > (size_t)usbp->epc[ep]->in_maxsize)
n = (size_t)usbp->epc[ep]->in_maxsize; n = (size_t)usbp->epc[ep]->in_maxsize;
/* Double buffering is always enabled for isochronous endpoints, and usb_packet_write_from_buffer(ep, isp->txbuf, n);
although we overlap the two buffers for simplicity, we still need
to write to the right counter. The DTOG_TX bit indicates the buffer
that is currently in use by the USB peripheral, that is, the buffer
from which the next packet will be sent, so we need to write the
counter of that buffer.*/
USB_GET_DESCRIPTOR(ep)->TXCOUNT0 = (stm32_usb_pma_t)n;
if (EPR_EP_TYPE_IS_ISO(epr) && (epr & EPR_DTOG_TX))
USB_GET_DESCRIPTOR(ep)->TXCOUNT1 = (stm32_usb_pma_t)n;
usb_packet_write_from_buffer(USB_GET_DESCRIPTOR(ep),
isp->txbuf, n);
EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID); EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID);
} }