diff options
| author | Giovanni Di Sirio <gdisirio@gmail.com> | 2015-12-26 13:29:09 +0000 | 
|---|---|---|
| committer | Giovanni Di Sirio <gdisirio@gmail.com> | 2015-12-26 13:29:09 +0000 | 
| commit | eb0c1ac0c3a3544366b7be5014a23d96ec4e9c9e (patch) | |
| tree | bab95b57ba0de647a19fdd35d920922d6db3160a | |
| parent | ae70b0edcea8b466894e140839371fb122a4aa92 (diff) | |
| download | ChibiOS-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.h | 45 | ||||
| -rw-r--r-- | os/hal/ports/STM32/LLD/OTGv1/usb_lld.c | 8 | ||||
| -rw-r--r-- | os/hal/ports/STM32/LLD/OTGv1/usb_lld.h | 20 | ||||
| -rw-r--r-- | os/hal/src/usb.c | 84 | 
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.
   *
  | 
