Simplified USBv1 driver.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8656 35acf78f-673a-0410-8e92-d51de3d6d3f4
master
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[out] buf buffer where to copy the packet data
* @param[in] n maximum number of bytes to copy. This value must
* not exceed the maximum packet size for this endpoint.
* @return The size of the receivee packet.
*
* @notapi
*/
static void usb_packet_read_to_buffer(stm32_usb_descriptor_t *udp,
uint8_t *buf, size_t n) {
static size_t usb_packet_read_to_buffer(usbep_t ep, uint8_t *buf) {
size_t i, n;
stm32_usb_descriptor_t *udp = USB_GET_DESCRIPTOR(ep);
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++;
*buf++ = (uint8_t)w;
*buf++ = (uint8_t)(w >> 8);
n -= 2;
i -= 2;
}
if (n > 0) {
if (i > 0) {
*buf = (uint8_t)*pmap;
}
return n;
}
/**
* @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] n maximum number of bytes to copy. This value must
* not exceed the maximum packet size for this endpoint.
*
* @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,
size_t n) {
stm32_usb_descriptor_t *udp = USB_GET_DESCRIPTOR(ep);
stm32_usb_pma_t *pmap = USB_ADDR2PTR(udp->TXADDR0);
uint32_t epr = STM32_USB->EPR[ep];
uint32_t w;
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) {
w = *buf++;
w |= *buf++ << 8;
@ -204,21 +231,9 @@ static void usb_serve_endpoints(USBDriver *usbp, uint32_t ep) {
if (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.*/
epcp->in_state->txbuf += transmitted;
usb_packet_write_from_buffer(USB_GET_DESCRIPTOR(ep),
epcp->in_state->txbuf,
n);
usb_packet_write_from_buffer(ep, epcp->in_state->txbuf, n);
/* Starting IN operation.*/
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);
}
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.*/
usb_packet_read_to_buffer(udp,
epcp->out_state->rxbuf,
n);
n = usb_packet_read_to_buffer(ep, epcp->out_state->rxbuf);
epcp->out_state->rxbuf += n;
/* 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) {
size_t n;
USBInEndpointState *isp = usbp->epc[ep]->in_state;
uint32_t epr = STM32_USB->EPR[ep];
/* Transfer initialization.*/
n = isp->txsize;
if (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
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);
usb_packet_write_from_buffer(ep, isp->txbuf, n);
EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID);
}