USB synchronous API, to be completed.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8648 35acf78f-673a-0410-8e92-d51de3d6d3f4
master
Giovanni Di Sirio 2015-12-26 13:29:09 +00:00
parent ae70b0edce
commit eb0c1ac0c3
4 changed files with 136 additions and 21 deletions

View File

@ -236,6 +236,14 @@
/* Driver pre-compile time settings. */
/*===========================================================================*/
/**
* @brief Enables synchronous APIs.
* @note Disabling this option saves both code and data space.
*/
#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
#define USB_USE_WAIT TRUE
#endif
/*===========================================================================*/
/* Derived constants and error checks. */
/*===========================================================================*/
@ -537,10 +545,24 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
*
* @notapi
*/
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
#define _usb_isr_invoke_in_cb(usbp, ep) { \
(usbp)->transmitting &= ~(1 << (ep)); \
(usbp)->epc[ep]->in_cb(usbp, ep); \
if ((usbp)->epc[ep]->in_cb != NULL) { \
(usbp)->epc[ep]->in_cb(usbp, ep); \
} \
osalSysLockFromISR(); \
osalThreadResumeI(&(usbp)->epc[ep]->in_state->thread, MSG_OK); \
osalSysUnlockFromISR(); \
}
#else
#define _usb_isr_invoke_in_cb(usbp, ep) { \
(usbp)->transmitting &= ~(1 << (ep)); \
if ((usbp)->epc[ep]->in_cb != NULL) { \
(usbp)->epc[ep]->in_cb(usbp, ep); \
} \
}
#endif
/**
* @brief Common ISR code, OUT endpoint event.
@ -550,10 +572,25 @@ typedef const USBDescriptor * (*usbgetdescriptor_t)(USBDriver *usbp,
*
* @notapi
*/
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
#define _usb_isr_invoke_out_cb(usbp, ep) { \
(usbp)->receiving &= ~(1 << (ep)); \
(usbp)->epc[ep]->out_cb(usbp, ep); \
if ((usbp)->epc[ep]->out_cb != NULL) { \
(usbp)->epc[ep]->out_cb(usbp, ep); \
} \
osalSysLockFromISR(); \
osalThreadResumeI(&(usbp)->epc[ep]->out_state->thread, \
usbGetReceiveTransactionSizeI(usbp, ep)); \
osalSysUnlockFromISR(); \
}
#else
#define _usb_isr_invoke_out_cb(usbp, ep) { \
(usbp)->receiving &= ~(1 << (ep)); \
if ((usbp)->epc[ep]->out_cb != NULL) { \
(usbp)->epc[ep]->out_cb(usbp, ep); \
} \
}
#endif
/** @} */
/*===========================================================================*/
@ -577,6 +614,10 @@ extern "C" {
const uint8_t *buf, size_t n);
bool usbStartReceiveI(USBDriver *usbp, usbep_t ep);
bool usbStartTransmitI(USBDriver *usbp, usbep_t ep);
#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);
#endif
bool usbStallReceiveI(USBDriver *usbp, usbep_t ep);
bool usbStallTransmitI(USBDriver *usbp, usbep_t ep);
void _usb_reset(USBDriver *usbp);

View File

@ -422,9 +422,9 @@ static void otg_epout_handler(USBDriver *usbp, usbep_t ep) {
osp->rxsize = osp->totsize - osp->rxsize;
osp->rxcnt = 0;
usb_lld_prepare_receive(usbp, ep);
chSysLockFromISR();
osalSysLockFromISR();
usb_lld_start_out(usbp, ep);
chSysUnlockFromISR();
osalSysUnlockFromISR();
}
else {
/* End on OUT transfer.*/
@ -1005,7 +1005,7 @@ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
/* OUT endpoint activation or deactivation.*/
otgp->oe[ep].DOEPTSIZ = 0;
if (usbp->epc[ep]->out_cb != NULL) {
if (usbp->epc[ep]->out_maxsize != 0) {
otgp->oe[ep].DOEPCTL = ctl | DOEPCTL_MPSIZ(usbp->epc[ep]->out_maxsize);
otgp->DAINTMSK |= DAINTMSK_OEPM(ep);
}
@ -1016,7 +1016,7 @@ void usb_lld_init_endpoint(USBDriver *usbp, usbep_t ep) {
/* IN endpoint activation or deactivation.*/
otgp->ie[ep].DIEPTSIZ = 0;
if (usbp->epc[ep]->in_cb != NULL) {
if (usbp->epc[ep]->in_maxsize != 0) {
/* FIFO allocation for the IN endpoint.*/
fsize = usbp->epc[ep]->in_maxsize / 4;
if (usbp->epc[ep]->in_multiplier > 1)

View File

@ -226,6 +226,12 @@ typedef struct {
* @brief Pointer to the transmission linear buffer.
*/
const uint8_t *txbuf;
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Waiting thread.
*/
thread_reference_t thread;
#endif
/* End of the mandatory fields.*/
/**
* @brief Total transmit transfer size.
@ -249,6 +255,12 @@ typedef struct {
* @brief Pointer to the receive linear buffer.
*/
uint8_t *rxbuf;
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Waiting thread.
*/
thread_reference_t thread;
#endif
/* End of the mandatory fields.*/
/**
* @brief Total transmit transfer size.
@ -278,14 +290,14 @@ typedef struct {
usbepcallback_t setup_cb;
/**
* @brief IN endpoint notification callback.
* @details This field must be set to @p NULL if the IN endpoint is not
* used.
* @details This field must can be set to @p NULL if callback is not
* required.
*/
usbepcallback_t in_cb;
/**
* @brief OUT endpoint notification callback.
* @details This field must be set to @p NULL if the OUT endpoint is not
* used.
* @details This field must can be set to @p NULL if callback is not
* required.
*/
usbepcallback_t out_cb;
/**

View File

@ -345,13 +345,6 @@ void usbInitEndpointI(USBDriver *usbp, usbep_t ep,
osalDbgAssert(usbp->epc[ep] == NULL, "already initialized");
/* Logically enabling the endpoint in the USBDriver structure.*/
if (epcp->in_state != NULL) {
memset(epcp->in_state, 0, sizeof(USBInEndpointState));
}
if (epcp->out_state != NULL) {
memset(epcp->out_state, 0, sizeof(USBOutEndpointState));
}
usbp->epc[ep] = epcp;
/* Low level endpoint activation.*/
@ -399,11 +392,17 @@ void usbDisableEndpointsI(USBDriver *usbp) {
* @special
*/
void usbPrepareReceive(USBDriver *usbp, usbep_t ep, uint8_t *buf, size_t n) {
USBOutEndpointState *osp = usbp->epc[ep]->out_state;
USBOutEndpointState *osp;
osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS));
osp = usbp->epc[ep]->out_state;
osp->rxbuf = buf;
osp->rxsize = n;
osp->rxcnt = 0;
#if USB_USE_WAIT == TRUE
osp->thread = NULL;
#endif
usb_lld_prepare_receive(usbp, ep);
}
@ -424,11 +423,17 @@ 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) {
USBInEndpointState *isp = usbp->epc[ep]->in_state;
USBInEndpointState *isp;
osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS));
isp = usbp->epc[ep]->in_state;
isp->txbuf = buf;
isp->txsize = n;
isp->txcnt = 0;
#if USB_USE_WAIT == TRUE
isp->thread = NULL;
#endif
usb_lld_prepare_transmit(usbp, ep);
}
@ -450,7 +455,7 @@ void usbPrepareTransmit(USBDriver *usbp, usbep_t ep,
bool usbStartReceiveI(USBDriver *usbp, usbep_t ep) {
osalDbgCheckClassI();
osalDbgCheck(usbp != NULL);
osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS));
if (usbGetReceiveStatusI(usbp, ep)) {
return true;
@ -478,7 +483,7 @@ bool usbStartReceiveI(USBDriver *usbp, usbep_t ep) {
bool usbStartTransmitI(USBDriver *usbp, usbep_t ep) {
osalDbgCheckClassI();
osalDbgCheck(usbp != NULL);
osalDbgCheck((usbp != NULL) && (ep <= USB_MAX_ENDPOINTS));
if (usbGetTransmitStatusI(usbp, ep)) {
return true;
@ -489,6 +494,63 @@ bool usbStartTransmitI(USBDriver *usbp, usbep_t ep) {
return false;
}
#if (USB_USE_WAIT == TRUE) || defined(__DOXYGEN__)
/**
* @brief Performs a receive transaction on an OUT endpoint.
*
* @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. It is recommended a multiple of
* the packet size because the excess is discarded.
*
* @return The received data effective size, it can be less than
* the amount specified.
* @retval MSG_RESET operation aborted by a reset.
*
* @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);
msg = osalThreadSuspendS(&usbp->epc[ep]->out_state->thread);
osalSysUnlock();
return msg;
}
/**
* @brief Performs a transmit transaction on an IN endpoint.
*
* @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
*
* @return The operation status.
* @retval MSG_OK operation performed successfully.
* @retval MSG_RESET operation aborted by a reset.
*
* @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();
usbStartReceiveI(usbp, ep);
msg = osalThreadSuspendS(&usbp->epc[ep]->in_state->thread);
osalSysUnlock();
return msg;
}
#endif /* USB_USE_WAIT == TRUE */
/**
* @brief Stalls an OUT endpoint.
*