New USB API finalized, updated OTGv1, USBv1 not yet updated.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8653 35acf78f-673a-0410-8e92-d51de3d6d3f4master
parent
d93fdcd424
commit
de202dd376
|
@ -412,9 +412,9 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
|
|||
* @param[in] usbp pointer to the @p USBDriver object
|
||||
* @return The current frame number.
|
||||
*
|
||||
* @api
|
||||
* @xclass
|
||||
*/
|
||||
#define usbGetFrameNumber(usbp) usb_lld_get_frame_number(usbp)
|
||||
#define usbGetFrameNumberX(usbp) usb_lld_get_frame_number(usbp)
|
||||
|
||||
/**
|
||||
* @brief Returns the status of an IN endpoint.
|
||||
|
@ -454,9 +454,9 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
|
|||
* @param[in] ep endpoint number
|
||||
* @return Received data size.
|
||||
*
|
||||
* @iclass
|
||||
* @xclass
|
||||
*/
|
||||
#define usbGetReceiveTransactionSizeI(usbp, ep) \
|
||||
#define usbGetReceiveTransactionSizeX(usbp, ep) \
|
||||
usb_lld_get_transaction_size(usbp, ep)
|
||||
|
||||
/**
|
||||
|
@ -469,7 +469,7 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
|
|||
* @param[in] n number of bytes to be transferred
|
||||
* @param[in] endcb callback to be invoked after the transfer or @p NULL
|
||||
*
|
||||
* @api
|
||||
* @special
|
||||
*/
|
||||
#define usbSetupTransfer(usbp, buf, n, endcb) { \
|
||||
(usbp)->ep0next = (buf); \
|
||||
|
@ -580,7 +580,7 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
|
|||
} \
|
||||
osalSysLockFromISR(); \
|
||||
osalThreadResumeI(&(usbp)->epc[ep]->out_state->thread, \
|
||||
usbGetReceiveTransactionSizeI(usbp, ep)); \
|
||||
usbGetReceiveTransactionSizeX(usbp, ep)); \
|
||||
osalSysUnlockFromISR(); \
|
||||
}
|
||||
#else
|
||||
|
@ -608,12 +608,10 @@ extern "C" {
|
|||
const USBEndpointConfig *epcp);
|
||||
void usbDisableEndpointsI(USBDriver *usbp);
|
||||
void usbReadSetupI(USBDriver *usbp, usbep_t ep, uint8_t *buf);
|
||||
void usbPrepareReceive(USBDriver *usbp, usbep_t ep,
|
||||
uint8_t *buf, size_t n);
|
||||
void usbPrepareTransmit(USBDriver *usbp, usbep_t ep,
|
||||
const uint8_t *buf, size_t n);
|
||||
bool usbStartReceiveI(USBDriver *usbp, usbep_t ep);
|
||||
bool usbStartTransmitI(USBDriver *usbp, usbep_t ep);
|
||||
void usbStartReceiveI(USBDriver *usbp, usbep_t ep,
|
||||
uint8_t *buf, size_t n);
|
||||
void usbStartTransmitI(USBDriver *usbp, usbep_t ep,
|
||||
const uint8_t *buf, size_t n);
|
||||
#if USB_USE_WAIT == TRUE
|
||||
msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n);
|
||||
msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n);
|
||||
|
|
|
@ -369,7 +369,6 @@ static void otg_epin_handler(USBDriver *usbp, usbep_t ep) {
|
|||
cover the remaining.*/
|
||||
isp->txsize = isp->totsize - isp->txsize;
|
||||
isp->txcnt = 0;
|
||||
usb_lld_prepare_transmit(usbp, ep);
|
||||
osalSysLockFromISR();
|
||||
usb_lld_start_in(usbp, ep);
|
||||
osalSysUnlockFromISR();
|
||||
|
@ -415,13 +414,14 @@ static void otg_epout_handler(USBDriver *usbp, usbep_t ep) {
|
|||
/* Receive transfer complete.*/
|
||||
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
|
||||
|
||||
if (osp->rxsize < osp->totsize) {
|
||||
/* A short packet always terminates a transaction.*/
|
||||
if (((osp->rxcnt % usbp->epc[ep]->out_maxsize) == 0) &&
|
||||
(osp->rxsize < osp->totsize)) {
|
||||
/* In case the transaction covered only part of the total transfer
|
||||
then another transaction is immediately started in order to
|
||||
cover the remaining.*/
|
||||
osp->rxsize = osp->totsize - osp->rxsize;
|
||||
osp->rxcnt = 0;
|
||||
usb_lld_prepare_receive(usbp, ep);
|
||||
osalSysLockFromISR();
|
||||
usb_lld_start_out(usbp, ep);
|
||||
osalSysUnlockFromISR();
|
||||
|
@ -476,7 +476,6 @@ static void otg_isoc_in_failed_handler(USBDriver *usbp) {
|
|||
*
|
||||
* @notapi
|
||||
*/
|
||||
|
||||
static void otg_isoc_out_failed_handler(USBDriver *usbp) {
|
||||
usbep_t ep;
|
||||
stm32_otg_t *otgp = usbp->otg;
|
||||
|
@ -1134,60 +1133,6 @@ void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf) {
|
|||
memcpy(buf, usbp->epc[ep]->setup_buf, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepares for a receive operation.
|
||||
*
|
||||
* @param[in] usbp pointer to the @p USBDriver object
|
||||
* @param[in] ep endpoint number
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep) {
|
||||
uint32_t pcnt;
|
||||
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
|
||||
|
||||
/* Transfer initialization.*/
|
||||
osp->totsize = osp->rxsize;
|
||||
if ((ep == 0) && (osp->rxsize > EP0_MAX_OUTSIZE))
|
||||
osp->rxsize = EP0_MAX_OUTSIZE;
|
||||
|
||||
pcnt = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1) /
|
||||
usbp->epc[ep]->out_maxsize;
|
||||
usbp->otg->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
|
||||
DOEPTSIZ_XFRSIZ(osp->rxsize);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepares for a transmit operation.
|
||||
*
|
||||
* @param[in] usbp pointer to the @p USBDriver object
|
||||
* @param[in] ep endpoint number
|
||||
*
|
||||
* @notapi
|
||||
*/
|
||||
void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) {
|
||||
USBInEndpointState *isp = usbp->epc[ep]->in_state;
|
||||
|
||||
/* Transfer initialization.*/
|
||||
isp->totsize = isp->txsize;
|
||||
if (isp->txsize == 0) {
|
||||
/* Special case, sending zero size packet.*/
|
||||
usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0);
|
||||
}
|
||||
else {
|
||||
if ((ep == 0) && (isp->txsize > EP0_MAX_INSIZE))
|
||||
isp->txsize = EP0_MAX_INSIZE;
|
||||
|
||||
/* Normal case.*/
|
||||
uint32_t pcnt = (isp->txsize + usbp->epc[ep]->in_maxsize - 1) /
|
||||
usbp->epc[ep]->in_maxsize;
|
||||
/* TODO: Support more than one packet per frame for isochronous transfers.*/
|
||||
usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_MCNT(1) | DIEPTSIZ_PKTCNT(pcnt) |
|
||||
DIEPTSIZ_XFRSIZ(isp->txsize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts a receive operation on an OUT endpoint.
|
||||
*
|
||||
|
@ -1197,7 +1142,28 @@ void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep) {
|
|||
* @notapi
|
||||
*/
|
||||
void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
|
||||
uint32_t pcnt, rxsize;
|
||||
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
|
||||
|
||||
/* Transfer initialization.*/
|
||||
osp->totsize = osp->rxsize;
|
||||
if ((ep == 0) && (osp->rxsize > EP0_MAX_OUTSIZE))
|
||||
osp->rxsize = EP0_MAX_OUTSIZE;
|
||||
|
||||
/* Transaction size is rounded to a multiple of packet size because the
|
||||
following requirement in the RM:
|
||||
"For OUT transfers, the transfer size field in the endpoint's transfer
|
||||
size register must be a multiple of the maximum packet size of the
|
||||
endpoint, adjusted to the Word boundary".*/
|
||||
pcnt = (osp->rxsize + usbp->epc[ep]->out_maxsize - 1U) /
|
||||
usbp->epc[ep]->out_maxsize;
|
||||
rxsize = (pcnt * usbp->epc[ep]->out_maxsize + 3U) & 0xFFFFFFFCU;
|
||||
|
||||
/*Setting up transaction parameters in DOEPTSIZ.*/
|
||||
usbp->otg->oe[ep].DOEPTSIZ = DOEPTSIZ_STUPCNT(3) | DOEPTSIZ_PKTCNT(pcnt) |
|
||||
DOEPTSIZ_XFRSIZ(rxsize);
|
||||
|
||||
/* Special case of isochronous endpoint.*/
|
||||
if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) {
|
||||
/* Odd/even bit toggling for isochronous endpoint.*/
|
||||
if (usbp->otg->DSTS & DSTS_FNSOF_ODD)
|
||||
|
@ -1206,6 +1172,7 @@ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
|
|||
usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_SODDFRM;
|
||||
}
|
||||
|
||||
/* Starting operation.*/
|
||||
usbp->otg->oe[ep].DOEPCTL |= DOEPCTL_EPENA | DOEPCTL_CNAK;
|
||||
}
|
||||
|
||||
|
@ -1218,7 +1185,27 @@ void usb_lld_start_out(USBDriver *usbp, usbep_t ep) {
|
|||
* @notapi
|
||||
*/
|
||||
void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
|
||||
USBInEndpointState *isp = usbp->epc[ep]->in_state;
|
||||
|
||||
/* Transfer initialization.*/
|
||||
isp->totsize = isp->txsize;
|
||||
if (isp->txsize == 0) {
|
||||
/* Special case, sending zero size packet.*/
|
||||
usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_PKTCNT(1) | DIEPTSIZ_XFRSIZ(0);
|
||||
}
|
||||
else {
|
||||
if ((ep == 0) && (isp->txsize > EP0_MAX_INSIZE))
|
||||
isp->txsize = EP0_MAX_INSIZE;
|
||||
|
||||
/* Normal case.*/
|
||||
uint32_t pcnt = (isp->txsize + usbp->epc[ep]->in_maxsize - 1) /
|
||||
usbp->epc[ep]->in_maxsize;
|
||||
/* TODO: Support more than one packet per frame for isochronous transfers.*/
|
||||
usbp->otg->ie[ep].DIEPTSIZ = DIEPTSIZ_MCNT(1) | DIEPTSIZ_PKTCNT(pcnt) |
|
||||
DIEPTSIZ_XFRSIZ(isp->txsize);
|
||||
}
|
||||
|
||||
/* Special case of isochronous endpoint.*/
|
||||
if ((usbp->epc[ep]->ep_mode & USB_EP_MODE_TYPE) == USB_EP_MODE_TYPE_ISOC) {
|
||||
/* Odd/even bit toggling.*/
|
||||
if (usbp->otg->DSTS & DSTS_FNSOF_ODD)
|
||||
|
@ -1227,6 +1214,7 @@ void usb_lld_start_in(USBDriver *usbp, usbep_t ep) {
|
|||
usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_SODDFRM;
|
||||
}
|
||||
|
||||
/* Starting operation.*/
|
||||
usbp->otg->ie[ep].DIEPCTL |= DIEPCTL_EPENA | DIEPCTL_CNAK;
|
||||
usbp->otg->DIEPEMPMSK |= DIEPEMPMSK_INEPTXFEM(ep);
|
||||
}
|
||||
|
|
|
@ -540,8 +540,6 @@ extern "C" {
|
|||
usbepstatus_t usb_lld_get_status_in(USBDriver *usbp, usbep_t ep);
|
||||
usbepstatus_t usb_lld_get_status_out(USBDriver *usbp, usbep_t ep);
|
||||
void usb_lld_read_setup(USBDriver *usbp, usbep_t ep, uint8_t *buf);
|
||||
void usb_lld_prepare_receive(USBDriver *usbp, usbep_t ep);
|
||||
void usb_lld_prepare_transmit(USBDriver *usbp, usbep_t ep);
|
||||
void usb_lld_start_out(USBDriver *usbp, usbep_t ep);
|
||||
void usb_lld_start_in(USBDriver *usbp, usbep_t ep);
|
||||
void usb_lld_stall_out(USBDriver *usbp, usbep_t ep);
|
||||
|
|
|
@ -146,13 +146,8 @@ static void ibnotify(io_buffers_queue_t *bqp) {
|
|||
uint8_t *buf = ibqGetEmptyBufferI(&sdup->ibqueue);
|
||||
if (buf != NULL) {
|
||||
/* Buffer found, starting a new transaction.*/
|
||||
osalSysUnlock();
|
||||
|
||||
usbPrepareReceive(sdup->config->usbp, sdup->config->bulk_out,
|
||||
buf, SERIAL_USB_BUFFERS_SIZE);
|
||||
|
||||
osalSysLock();
|
||||
(void) usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out);
|
||||
usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out,
|
||||
buf, SERIAL_USB_BUFFERS_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -179,12 +174,7 @@ static void obnotify(io_buffers_queue_t *bqp) {
|
|||
uint8_t *buf = obqGetFullBufferI(&sdup->obqueue, &n);
|
||||
if (buf != NULL) {
|
||||
/* Buffer found, starting a new transaction.*/
|
||||
osalSysUnlock();
|
||||
|
||||
usbPrepareTransmit(sdup->config->usbp, sdup->config->bulk_in, buf, n);
|
||||
|
||||
osalSysLock();
|
||||
(void) usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in);
|
||||
usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in, buf, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -319,9 +309,8 @@ void sduConfigureHookI(SerialUSBDriver *sdup) {
|
|||
|
||||
osalDbgAssert(buf != NULL, "no free buffer");
|
||||
|
||||
usbPrepareReceive(sdup->config->usbp, sdup->config->bulk_out,
|
||||
buf, SERIAL_USB_BUFFERS_SIZE);
|
||||
(void) usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out);
|
||||
usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out,
|
||||
buf, SERIAL_USB_BUFFERS_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -392,12 +381,7 @@ void sduSOFHookI(SerialUSBDriver *sdup) {
|
|||
|
||||
osalDbgAssert(buf != NULL, "queue is empty");
|
||||
|
||||
osalSysUnlockFromISR();
|
||||
|
||||
usbPrepareTransmit(sdup->config->usbp, sdup->config->bulk_in, buf, n);
|
||||
|
||||
osalSysLockFromISR();
|
||||
(void) usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in);
|
||||
usbStartTransmitI(sdup->config->usbp, sdup->config->bulk_in, buf, n);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -431,13 +415,10 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
|
|||
/* Checking if there is a buffer ready for transmission.*/
|
||||
buf = obqGetFullBufferI(&sdup->obqueue, &n);
|
||||
|
||||
/* Unlocking the critical zone.*/
|
||||
osalSysUnlockFromISR();
|
||||
|
||||
if (buf != NULL) {
|
||||
/* The endpoint cannot be busy, we are in the context of the callback,
|
||||
so it is safe to transmit without a check.*/
|
||||
usbPrepareTransmit(usbp, ep, buf, n);
|
||||
usbStartTransmitI(usbp, ep, buf, n);
|
||||
}
|
||||
else if ((usbp->epc[ep]->in_state->txsize > 0U) &&
|
||||
((usbp->epc[ep]->in_state->txsize &
|
||||
|
@ -446,17 +427,13 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) {
|
|||
size. Otherwise the recipient may expect more data coming soon and
|
||||
not return buffered data to app. See section 5.8.3 Bulk Transfer
|
||||
Packet Size Constraints of the USB Specification document.*/
|
||||
usbPrepareTransmit(usbp, ep, usbp->setup, 0);
|
||||
usbStartTransmitI(usbp, ep, usbp->setup, 0);
|
||||
|
||||
}
|
||||
else {
|
||||
/* Nothing to transmit.*/
|
||||
return;
|
||||
}
|
||||
|
||||
/* Locking again and starting transmission.*/
|
||||
osalSysLockFromISR();
|
||||
(void) usbStartTransmitI(usbp, ep);
|
||||
osalSysUnlockFromISR();
|
||||
}
|
||||
|
||||
|
@ -483,7 +460,7 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) {
|
|||
|
||||
/* Posting the filled buffer in the queue.*/
|
||||
ibqPostFullBufferI(&sdup->ibqueue,
|
||||
usbGetReceiveTransactionSizeI(sdup->config->usbp,
|
||||
usbGetReceiveTransactionSizeX(sdup->config->usbp,
|
||||
sdup->config->bulk_out));
|
||||
|
||||
/* The endpoint cannot be busy, we are in the context of the callback,
|
||||
|
@ -492,11 +469,8 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) {
|
|||
buf = ibqGetEmptyBufferI(&sdup->ibqueue);
|
||||
if (buf != NULL) {
|
||||
/* Buffer found, starting a new transaction.*/
|
||||
osalSysUnlockFromISR();
|
||||
usbPrepareReceive(sdup->config->usbp, sdup->config->bulk_out,
|
||||
buf, SERIAL_USB_BUFFERS_SIZE);
|
||||
osalSysLockFromISR();
|
||||
(void) usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out);
|
||||
usbStartReceiveI(sdup->config->usbp, sdup->config->bulk_out,
|
||||
buf, SERIAL_USB_BUFFERS_SIZE);
|
||||
}
|
||||
osalSysUnlockFromISR();
|
||||
}
|
||||
|
|
159
os/hal/src/usb.c
159
os/hal/src/usb.c
|
@ -401,22 +401,31 @@ void usbDisableEndpointsI(USBDriver *usbp) {
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Prepares for a receive transaction on an OUT endpoint.
|
||||
* @post The endpoint is ready for @p usbStartReceiveI().
|
||||
* @note This function can be called both in ISR and thread context.
|
||||
* @brief Starts a receive transaction on an OUT endpoint.
|
||||
* @note This function is meant to be called from ISR context outside
|
||||
* critical zones because there is a potentially slow operation
|
||||
* inside.
|
||||
*
|
||||
* @param[in] usbp pointer to the @p USBDriver object
|
||||
* @param[in] ep endpoint number
|
||||
* @param[out] buf buffer where to copy the received data
|
||||
* @param[in] n transaction size
|
||||
* @param[in] n transaction size. It is recommended a multiple of
|
||||
* the packet size because the excess is discarded.
|
||||
*
|
||||
* @special
|
||||
* @iclass
|
||||
*/
|
||||
void usbPrepareReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
|
||||
void usbStartReceiveI(USBDriver *usbp, usbep_t ep,
|
||||
uint8_t *buf, size_t n) {
|
||||
USBOutEndpointState *osp;
|
||||
|
||||
osalDbgCheckClassI();
|
||||
osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS));
|
||||
osalDbgAssert(!usbGetReceiveStatusI(usbp, ep), "already receiving");
|
||||
|
||||
/* Marking the endpoint as active.*/
|
||||
usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep);
|
||||
|
||||
/* Setting up the transfer.*/
|
||||
osp = usbp->epc[ep]->out_state;
|
||||
osp->rxbuf = buf;
|
||||
osp->rxsize = n;
|
||||
|
@ -425,29 +434,35 @@ void usbPrepareReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
|
|||
osp->thread = NULL;
|
||||
#endif
|
||||
|
||||
usb_lld_prepare_receive(usbp, ep);
|
||||
/* Starting transfer.*/
|
||||
usb_lld_start_out(usbp, ep);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Prepares for a transmit transaction on an IN endpoint.
|
||||
* @post The endpoint is ready for @p usbStartTransmitI().
|
||||
* @note This function can be called both in ISR and thread context.
|
||||
* @note The queue must contain at least the amount of data specified
|
||||
* as transaction size.
|
||||
* @brief Starts a transmit transaction on an IN endpoint.
|
||||
* @note This function is meant to be called from ISR context outside
|
||||
* critical zones because there is a potentially slow operation
|
||||
* inside.
|
||||
*
|
||||
* @param[in] usbp pointer to the @p USBDriver object
|
||||
* @param[in] ep endpoint number
|
||||
* @param[in] buf buffer where to fetch the data to be transmitted
|
||||
* @param[in] n transaction size
|
||||
*
|
||||
* @special
|
||||
* @iclass
|
||||
*/
|
||||
void usbPrepareTransmit(USBDriver *usbp, usbep_t ep,
|
||||
const uint8_t *buf, size_t n) {
|
||||
void usbStartTransmitI(USBDriver *usbp, usbep_t ep,
|
||||
const uint8_t *buf, size_t n) {
|
||||
USBInEndpointState *isp;
|
||||
|
||||
osalDbgCheckClassI();
|
||||
osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS));
|
||||
osalDbgAssert(!usbGetTransmitStatusI(usbp, ep), "already transmitting");
|
||||
|
||||
/* Marking the endpoint as active.*/
|
||||
usbp->transmitting |= (uint16_t)((unsigned)1U << (unsigned)ep);
|
||||
|
||||
/* Setting up the transfer.*/
|
||||
isp = usbp->epc[ep]->in_state;
|
||||
isp->txbuf = buf;
|
||||
isp->txsize = n;
|
||||
|
@ -456,63 +471,8 @@ void usbPrepareTransmit(USBDriver *usbp, usbep_t ep,
|
|||
isp->thread = NULL;
|
||||
#endif
|
||||
|
||||
usb_lld_prepare_transmit(usbp, ep);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts a receive transaction on an OUT endpoint.
|
||||
* @post The endpoint callback is invoked when the transfer has been
|
||||
* completed.
|
||||
*
|
||||
* @param[in] usbp pointer to the @p USBDriver object
|
||||
* @param[in] ep endpoint number
|
||||
*
|
||||
* @return The operation status.
|
||||
* @retval false Operation started successfully.
|
||||
* @retval true Endpoint busy, operation not started.
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
bool usbStartReceiveI(USBDriver *usbp, usbep_t ep) {
|
||||
|
||||
osalDbgCheckClassI();
|
||||
osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS));
|
||||
|
||||
if (usbGetReceiveStatusI(usbp, ep)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
usbp->receiving |= (uint16_t)((unsigned)1U << (unsigned)ep);
|
||||
usb_lld_start_out(usbp, ep);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts a transmit transaction on an IN endpoint.
|
||||
* @post The endpoint callback is invoked when the transfer has been
|
||||
* completed.
|
||||
*
|
||||
* @param[in] usbp pointer to the @p USBDriver object
|
||||
* @param[in] ep endpoint number
|
||||
*
|
||||
* @return The operation status.
|
||||
* @retval false Operation started successfully.
|
||||
* @retval true Endpoint busy, operation not started.
|
||||
*
|
||||
* @iclass
|
||||
*/
|
||||
bool usbStartTransmitI(USBDriver *usbp, usbep_t ep) {
|
||||
|
||||
osalDbgCheckClassI();
|
||||
osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS));
|
||||
|
||||
if (usbGetTransmitStatusI(usbp, ep)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
usbp->transmitting |= (uint16_t)((unsigned)1U << (unsigned)ep);
|
||||
/* Starting transfer.*/
|
||||
usb_lld_start_in(usbp, ep);
|
||||
return false;
|
||||
}
|
||||
|
||||
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
|
||||
|
@ -527,18 +487,23 @@ bool usbStartTransmitI(USBDriver *usbp, usbep_t ep) {
|
|||
*
|
||||
* @return The received effective data size, it can be less than
|
||||
* the amount specified.
|
||||
* @retval MSG_RESET operation aborted by a reset.
|
||||
* @retval MSG_TIMEOUT operation aborted by a suspend.
|
||||
* @retval MSG_RESET driver not in @p USB_ACTIVE state or the operation
|
||||
* has been aborted by an USB reset or a transition to
|
||||
* the @p USB_SUSPENDED state.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
|
||||
msg_t msg;
|
||||
|
||||
usbPrepareReceive(usbp, ep, buf, n);
|
||||
|
||||
osalSysLock();
|
||||
usbStartReceiveI(usbp, ep);
|
||||
|
||||
if (usbGetDriverStateI(usbp) != USB_ACTIVE) {
|
||||
osalSysUnlock();
|
||||
return MSG_RESET;
|
||||
}
|
||||
|
||||
usbStartReceiveI(usbp, ep, buf, n);
|
||||
msg = osalThreadSuspendS(&usbp->epc[ep]->out_state->thread);
|
||||
osalSysUnlock();
|
||||
|
||||
|
@ -555,18 +520,23 @@ msg_t usbReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
|
|||
*
|
||||
* @return The operation status.
|
||||
* @retval MSG_OK operation performed successfully.
|
||||
* @retval MSG_RESET operation aborted by a reset.
|
||||
* @retval MSG_TIMEOUT operation aborted by a suspend.
|
||||
* @retval MSG_RESET driver not in @p USB_ACTIVE state or the operation
|
||||
* has been aborted by an USB reset or a transition to
|
||||
* the @p USB_SUSPENDED state.
|
||||
*
|
||||
* @api
|
||||
*/
|
||||
msg_t usbTransmit(USBDriver *usbp, usbep_t ep, const uint8_t *buf, size_t n) {
|
||||
msg_t msg;
|
||||
|
||||
usbPrepareTransmit(usbp, ep, buf, n);
|
||||
|
||||
osalSysLock();
|
||||
usbStartTransmitI(usbp, ep);
|
||||
|
||||
if (usbGetDriverStateI(usbp) != USB_ACTIVE) {
|
||||
osalSysUnlock();
|
||||
return MSG_RESET;
|
||||
}
|
||||
|
||||
usbStartTransmitI(usbp, ep, buf, n);
|
||||
msg = osalThreadSuspendS(&usbp->epc[ep]->in_state->thread);
|
||||
osalSysUnlock();
|
||||
|
||||
|
@ -700,10 +670,10 @@ void _usb_suspend(USBDriver *usbp) {
|
|||
if (usbp->epc[i] != NULL) {
|
||||
osalSysLockFromISR();
|
||||
if (usbp->epc[i]->in_state != NULL) {
|
||||
osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_TIMEOUT);
|
||||
osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET);
|
||||
}
|
||||
if (usbp->epc[i]->out_state != NULL) {
|
||||
osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_TIMEOUT);
|
||||
osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET);
|
||||
}
|
||||
osalSysUnlockFromISR();
|
||||
}
|
||||
|
@ -787,9 +757,8 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
|
|||
if (usbp->ep0n != 0U) {
|
||||
/* Starts the transmit phase.*/
|
||||
usbp->ep0state = USB_EP0_TX;
|
||||
usbPrepareTransmit(usbp, 0, usbp->ep0next, usbp->ep0n);
|
||||
osalSysLockFromISR();
|
||||
(void) usbStartTransmitI(usbp, 0);
|
||||
usbStartTransmitI(usbp, 0, usbp->ep0next, usbp->ep0n);
|
||||
osalSysUnlockFromISR();
|
||||
}
|
||||
else {
|
||||
|
@ -797,9 +766,8 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
|
|||
packet.*/
|
||||
usbp->ep0state = USB_EP0_WAITING_STS;
|
||||
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
|
||||
usbPrepareReceive(usbp, 0, NULL, 0);
|
||||
osalSysLockFromISR();
|
||||
(void) usbStartReceiveI(usbp, 0);
|
||||
usbStartReceiveI(usbp, 0, NULL, 0);
|
||||
osalSysUnlockFromISR();
|
||||
#else
|
||||
usb_lld_end_setup(usbp, ep);
|
||||
|
@ -811,9 +779,8 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
|
|||
if (usbp->ep0n != 0U) {
|
||||
/* Starts the receive phase.*/
|
||||
usbp->ep0state = USB_EP0_RX;
|
||||
usbPrepareReceive(usbp, 0, usbp->ep0next, usbp->ep0n);
|
||||
osalSysLockFromISR();
|
||||
(void) usbStartReceiveI(usbp, 0);
|
||||
usbStartReceiveI(usbp, 0, usbp->ep0next, usbp->ep0n);
|
||||
osalSysUnlockFromISR();
|
||||
}
|
||||
else {
|
||||
|
@ -821,9 +788,8 @@ void _usb_ep0setup(USBDriver *usbp, usbep_t ep) {
|
|||
packet.*/
|
||||
usbp->ep0state = USB_EP0_SENDING_STS;
|
||||
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
|
||||
usbPrepareTransmit(usbp, 0, NULL, 0);
|
||||
osalSysLockFromISR();
|
||||
(void) usbStartTransmitI(usbp, 0);
|
||||
usbStartTransmitI(usbp, 0, NULL, 0);
|
||||
osalSysUnlockFromISR();
|
||||
#else
|
||||
usb_lld_end_setup(usbp, ep);
|
||||
|
@ -854,9 +820,8 @@ void _usb_ep0in(USBDriver *usbp, usbep_t ep) {
|
|||
transmitted.*/
|
||||
if ((usbp->ep0n < max) &&
|
||||
((usbp->ep0n % usbp->epc[0]->in_maxsize) == 0U)) {
|
||||
usbPrepareTransmit(usbp, 0, NULL, 0);
|
||||
osalSysLockFromISR();
|
||||
(void) usbStartTransmitI(usbp, 0);
|
||||
usbStartTransmitI(usbp, 0, NULL, 0);
|
||||
osalSysUnlockFromISR();
|
||||
usbp->ep0state = USB_EP0_WAITING_TX0;
|
||||
return;
|
||||
|
@ -866,9 +831,8 @@ void _usb_ep0in(USBDriver *usbp, usbep_t ep) {
|
|||
/* Transmit phase over, receiving the zero sized status packet.*/
|
||||
usbp->ep0state = USB_EP0_WAITING_STS;
|
||||
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
|
||||
usbPrepareReceive(usbp, 0, NULL, 0);
|
||||
osalSysLockFromISR();
|
||||
(void) usbStartReceiveI(usbp, 0);
|
||||
usbStartReceiveI(usbp, 0, NULL, 0);
|
||||
osalSysUnlockFromISR();
|
||||
#else
|
||||
usb_lld_end_setup(usbp, ep);
|
||||
|
@ -919,9 +883,8 @@ void _usb_ep0out(USBDriver *usbp, usbep_t ep) {
|
|||
/* Receive phase over, sending the zero sized status packet.*/
|
||||
usbp->ep0state = USB_EP0_SENDING_STS;
|
||||
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
|
||||
usbPrepareTransmit(usbp, 0, NULL, 0);
|
||||
osalSysLockFromISR();
|
||||
(void) usbStartTransmitI(usbp, 0);
|
||||
usbStartTransmitI(usbp, 0, NULL, 0);
|
||||
osalSysUnlockFromISR();
|
||||
#else
|
||||
usb_lld_end_setup(usbp, ep);
|
||||
|
@ -931,7 +894,7 @@ void _usb_ep0out(USBDriver *usbp, usbep_t ep) {
|
|||
/* Status packet received, it must be zero sized, invoking the callback
|
||||
if defined.*/
|
||||
#if (USB_EP0_STATUS_STAGE == USB_EP0_STATUS_STAGE_SW)
|
||||
if (usbGetReceiveTransactionSizeI(usbp, 0) != 0U) {
|
||||
if (usbGetReceiveTransactionSizeX(usbp, 0) != 0U) {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
# Compiler options here.
|
||||
ifeq ($(USE_OPT),)
|
||||
USE_OPT = -O0 -ggdb -fomit-frame-pointer -falign-functions=16
|
||||
USE_OPT = -O2 -ggdb -fomit-frame-pointer -falign-functions=16
|
||||
endif
|
||||
|
||||
# C specific options here (added to USE_OPT).
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
|
||||
#include "usbcfg.h"
|
||||
|
||||
/* Can be measured using dd if=/dev/xxxx of=/dev/null bs=512 count=10000.*/
|
||||
static uint8_t buf[] =
|
||||
static const uint8_t txbuf[] =
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
|
@ -42,8 +41,12 @@ static uint8_t buf[] =
|
|||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
|
||||
|
||||
static uint8_t rxbuf[1024];
|
||||
|
||||
/*
|
||||
* Red LED blinker thread, times are in milliseconds.
|
||||
* USB writer. This thread writes data to the USB at maximum rate.
|
||||
* Can be measured using:
|
||||
* dd if=/dev/xxxx of=/dev/null bs=512 count=10000
|
||||
*/
|
||||
static THD_WORKING_AREA(waWriter, 128);
|
||||
static THD_FUNCTION(Writer, arg) {
|
||||
|
@ -51,13 +54,28 @@ static THD_FUNCTION(Writer, arg) {
|
|||
(void)arg;
|
||||
chRegSetThreadName("writer");
|
||||
while (true) {
|
||||
if (USBD2.state == USB_ACTIVE) {
|
||||
msg_t msg = usbTransmit(&USBD2, USBD2_DATA_REQUEST_EP,
|
||||
buf, sizeof (buf) - 1);
|
||||
if (msg == MSG_OK)
|
||||
continue;
|
||||
}
|
||||
chThdSleepMilliseconds(500);
|
||||
msg_t msg = usbTransmit(&USBD2, USBD2_DATA_REQUEST_EP,
|
||||
txbuf, sizeof (txbuf) - 1);
|
||||
if (msg == MSG_RESET)
|
||||
chThdSleepMilliseconds(500);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* USB reader. This thread reads data from the USB at maximum rate.
|
||||
* Can be measured using:
|
||||
* dd if=bigfile of=/dev/xxx bs=512 count=10000
|
||||
*/
|
||||
static THD_WORKING_AREA(waReader, 128);
|
||||
static THD_FUNCTION(Reader, arg) {
|
||||
|
||||
(void)arg;
|
||||
chRegSetThreadName("reader");
|
||||
while (true) {
|
||||
msg_t msg = usbReceive(&USBD2, USBD2_DATA_AVAILABLE_EP,
|
||||
rxbuf, sizeof (rxbuf) - 1);
|
||||
if (msg == MSG_RESET)
|
||||
chThdSleepMilliseconds(500);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,6 +134,7 @@ int main(void) {
|
|||
*/
|
||||
chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);
|
||||
chThdCreateStatic(waWriter, sizeof(waWriter), NORMALPRIO, Writer, NULL);
|
||||
chThdCreateStatic(waReader, sizeof(waReader), NORMALPRIO, Reader, NULL);
|
||||
|
||||
/*
|
||||
* Normal main() thread activity, in this demo it does nothing except
|
||||
|
|
Loading…
Reference in New Issue