Пример #1
0
/**
 * @brief   Generic endpoint OUT handler.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 *
 * @notapi
 */
static void otg_epout_handler(USBDriver *usbp, usbep_t ep) {
  stm32_otg_t *otgp = usbp->otg;
  uint32_t epint = otgp->oe[ep].DOEPINT;

  /* Resets all EP IRQ sources.*/
  otgp->oe[ep].DOEPINT = epint;

  if ((epint & DOEPINT_STUP) && (otgp->DOEPMSK & DOEPMSK_STUPM)) {
    /* Setup packets handling, setup packets are handled using a
       specific callback.*/
    _usb_isr_invoke_setup_cb(usbp, ep);

  }
  if ((epint & DOEPINT_XFRC) && (otgp->DOEPMSK & DOEPMSK_XFRCM)) {
    /* Receive transfer complete.*/
    USBOutEndpointState *osp = usbp->epc[ep]->out_state;

    if (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);
      chSysLockFromIsr();
      usb_lld_start_out(usbp, ep);
      chSysUnlockFromIsr();
    }
    else {
      /* End on OUT transfer.*/
      _usb_isr_invoke_out_cb(usbp, ep);
    }
  }
}
Пример #2
0
/**
 * @brief   Generic endpoint OUT handler.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 *
 * @notapi
 */
static void otg_epout_handler(USBDriver *usbp, usbep_t ep) {
  stm32_otg_t *otgp = usbp->otg;
  uint32_t epint = otgp->oe[ep].DOEPINT;

  /* Resets all EP IRQ sources.*/
  otgp->oe[ep].DOEPINT = 0xFFFFFFFF;

  if ((epint & DOEPINT_STUP) && (otgp->DOEPMSK & DOEPMSK_STUPM)) {
    /* Setup packets handling, setup packets are handled using a
       specific callback.*/
    _usb_isr_invoke_setup_cb(usbp, ep);

  }
  if ((epint & DOEPINT_XFRC) && (otgp->DOEPMSK & DOEPMSK_XFRCM)) {
    /* Receive transfer complete.*/
    _usb_isr_invoke_out_cb(usbp, ep);
  }
}
Пример #3
0
static void ep_isr(USBDriver *usbp, usbep_t ep) {
  const USBEndpointConfig *epcp = usbp->epc[ep];
  size_t n;
  UENUM = ep & 0xf;

  /* TODO: if stalling is needed/expected remove this check */
  osalDbgAssert(!(UEINTX & (1 << STALLEDI)), "Endpoint stalled!");

  if ((UEIENX & (1 << TXINE)) && (UEINTX & (1 << TXINI))) {
    /* Ready to accept more IN data to transmit to host */
    /* Disable TXIN interrupt for now, will be re-enabled below if we
     * send more data */
    UEIENX &= ~(1 << TXINE);

    /* Update transaction counts to reflect newly transmitted bytes */
    epcp->in_state->txcnt += epcp->in_state->last_tx_size;
    n = epcp->in_state->txsize - epcp->in_state->txcnt;
    if (n > 0) {
      /* Transfer not completed, there are more packets to send. */
      usb_fifo_write(usbp, ep, n);

      osalSysLockFromISR();
      usb_lld_start_in(usbp, ep);
      osalSysUnlockFromISR();
    } else {
      UEINTX &= ~(1 << TXINI);
      _usb_isr_invoke_in_cb(usbp, ep);
    }
  }

  if ((UEIENX & (1 << RXSTPE)) && (UEINTX & (1 << RXSTPI))) {
    /* Received SETUP data */
    /* Reset transaction state for endpoint */
    epcp->in_state->txcnt = 0;
    epcp->in_state->txsize = 0;
    epcp->in_state->last_tx_size = 0;
    /* Setup packets handling, setup packets are handled using a
       specific callback.*/
    _usb_isr_invoke_setup_cb(usbp, ep);
  } else if (UEINTX & (1 << RXOUTI)) {
    /* Received OUT data from host */
    if (ep == 0 && usbp->ep0state == USB_EP0_WAITING_STS) {
      /* SETUP/control transaction complete, invoke the callback. */
      n = 0;
      UEINTX &= ~((1 << RXOUTI) | (1 << FIFOCON));
      _usb_isr_invoke_out_cb(usbp, ep);
    } else {
      /* Check the FIFO byte count to see how many bytes were received */
      n = UEBCX;
    }
    if (n > 0) {
      usb_fifo_read(usbp, ep, n);

      /* Mark OUT FIFO processed to allow more data to be received */
      UEINTX &= ~((1 << RXOUTI) | (1 << FIFOCON));

      /* Transaction state update */
      epcp->out_state->rxcnt += n;
      epcp->out_state->rxsize -= n;
      epcp->out_state->rxpkts -= 1;
      if (n < epcp->out_maxsize || epcp->out_state->rxpkts == 0) {
        /* Transfer complete, invokes the callback.*/
        _usb_isr_invoke_out_cb(usbp, ep);
      }
    }
  }
}
Пример #4
0
/**
 * @brief   Common ISR code, serves the EP-related interrupts.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 * @param[in] ep        endpoint number
 *
 * @notapi
 */
static void usb_serve_endpoints(USBDriver *usbp, uint32_t ep) {
  size_t n;
  uint32_t epr = STM32_USB->EPR[ep];
  const USBEndpointConfig *epcp = usbp->epc[ep];

  if (epr & EPR_CTR_TX) {
    /* IN endpoint, transmission.*/
    USBInEndpointState *isp = epcp->in_state;

    EPR_CLEAR_CTR_TX(ep);

    isp->txcnt += isp->txlast;
    n = isp->txsize - isp->txcnt;
    if (n > 0) {
      /* Transfer not completed, there are more packets to send.*/
      if (n > epcp->in_maxsize)
        n = epcp->in_maxsize;

      /* Writes the packet from the defined buffer.*/
      isp->txbuf += isp->txlast;
      isp->txlast = n;
      usb_packet_write_from_buffer(ep, isp->txbuf, n);

      /* Starting IN operation.*/
      EPR_SET_STAT_TX(ep, EPR_STAT_TX_VALID);
    }
    else {
      /* Transfer completed, invokes the callback.*/
      _usb_isr_invoke_in_cb(usbp, ep);
    }
  }
  if (epr & EPR_CTR_RX) {
    /* OUT endpoint, receive.*/

    EPR_CLEAR_CTR_RX(ep);

    if (epr & EPR_SETUP) {
      /* Setup packets handling, setup packets are handled using a
         specific callback.*/
      _usb_isr_invoke_setup_cb(usbp, ep);
    }
    else {
      USBOutEndpointState *osp = epcp->out_state;

      /* Reads the packet into the defined buffer.*/
      n = usb_packet_read_to_buffer(ep, osp->rxbuf);
      osp->rxbuf += n;

      /* Transaction data updated.*/
      osp->rxcnt  += n;
      osp->rxsize -= n;
      osp->rxpkts -= 1;

      /* The transaction is completed if the specified number of packets
         has been received or the current packet is a short packet.*/
      if ((n < epcp->out_maxsize) || (osp->rxpkts == 0)) {
        /* Transfer complete, invokes the callback.*/
        _usb_isr_invoke_out_cb(usbp, ep);
      }
      else {
        /* Transfer not complete, there are more packets to receive.*/
        EPR_SET_STAT_RX(ep, EPR_STAT_RX_VALID);
      }
    }
  }
}