aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2015-12-26 13:29:09 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2015-12-26 13:29:09 +0000
commiteb0c1ac0c3a3544366b7be5014a23d96ec4e9c9e (patch)
treebab95b57ba0de647a19fdd35d920922d6db3160a
parentae70b0edcea8b466894e140839371fb122a4aa92 (diff)
downloadChibiOS-eb0c1ac0c3a3544366b7be5014a23d96ec4e9c9e.tar.gz
ChibiOS-eb0c1ac0c3a3544366b7be5014a23d96ec4e9c9e.tar.bz2
ChibiOS-eb0c1ac0c3a3544366b7be5014a23d96ec4e9c9e.zip
USB synchronous API, to be completed.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8648 35acf78f-673a-0410-8e92-d51de3d6d3f4
-rw-r--r--os/hal/include/usb.h45
-rw-r--r--os/hal/ports/STM32/LLD/OTGv1/usb_lld.c8
-rw-r--r--os/hal/ports/STM32/LLD/OTGv1/usb_lld.h20
-rw-r--r--os/hal/src/usb.c84
4 files changed, 136 insertions, 21 deletions
diff --git a/os/hal/include/usb.h b/os/hal/include/usb.h
index 896aa31cd..4aed90a08 100644
--- a/os/hal/include/usb.h
+++ b/os/hal/include/usb.h
@@ -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)); \
+ 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)); \
- (usbp)->epc[ep]->out_cb(usbp, 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);
diff --git a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c
index 4ec8fd976..ab735b903 100644
--- a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c
+++ b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.c
@@ -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)
diff --git a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h
index 544d5aecd..f59685c43 100644
--- a/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h
+++ b/os/hal/ports/STM32/LLD/OTGv1/usb_lld.h
@@ -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;
/**
diff --git a/os/hal/src/usb.c b/os/hal/src/usb.c
index cea90b32e..14d345b09 100644
--- a/os/hal/src/usb.c
+++ b/os/hal/src/usb.c
@@ -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.
*