Beispiel #1
0
/**
 * @brief   Deactivates the USB peripheral.
 *
 * @param[in] usbp      pointer to the @p USBDriver object
 *
 * @api
 */
void usbStop(USBDriver *usbp) {
  unsigned i;

  osalDbgCheck(usbp != NULL);

  osalSysLock();

  osalDbgAssert((usbp->state == USB_STOP) || (usbp->state == USB_READY) ||
                (usbp->state == USB_SELECTED) || (usbp->state == USB_ACTIVE) ||
                (usbp->state == USB_SUSPENDED),
                "invalid state");

  usb_lld_stop(usbp);
  usbp->config = NULL;
  usbp->state  = USB_STOP;

  /* Resetting all ongoing synchronous operations.*/
  for (i = 0; i <= (unsigned)USB_MAX_ENDPOINTS; i++) {
#if USB_USE_WAIT == TRUE
    if (usbp->epc[i] != NULL) {
      if (usbp->epc[i]->in_state != NULL) {
        osalThreadResumeI(&usbp->epc[i]->in_state->thread, MSG_RESET);
      }
      if (usbp->epc[i]->out_state != NULL) {
        osalThreadResumeI(&usbp->epc[i]->out_state->thread, MSG_RESET);
      }
    }
#endif
    usbp->epc[i] = NULL;
  }
  osalOsRescheduleS();

  osalSysUnlock();
}
Beispiel #2
0
/**
 * @brief   Writes to a TX FIFO fetching data from a queue.
 *
 * @param[in] fifop     pointer to the FIFO register
 * @param[in] oqp       pointer to an @p output_queue_t object
 * @param[in] n         maximum number of bytes to copy
 *
 * @notapi
 */
static void otg_fifo_write_from_queue(volatile uint32_t *fifop,
                                      output_queue_t *oqp,
                                      size_t n) {
  uint32_t w;
  size_t i;

  /* Pushing all complete words.*/
  i = 0;
  w = 0;
  while (i < n) {
    w |= (uint32_t)*oqp->q_rdptr << ((i & 3) * 8);
    oqp->q_rdptr++;
    if (oqp->q_rdptr >= oqp->q_top) {
      oqp->q_rdptr = oqp->q_buffer;
    }
    i++;
    if ((i & 3) == 0) {
      *fifop = w;
      w = 0;
    }
  }

  /* Remaining bytes.*/
  if ((i & 3) != 0) {
    *fifop = w;
  }

  /* Updating queue.*/
  osalSysLock();
  oqp->q_counter += n;
  osalThreadDequeueAllI(&oqp->q_waiting, Q_OK);
  osalOsRescheduleS();
  osalSysUnlock();
}
Beispiel #3
0
/**
 * @brief   Aborts the ongoing SPI operation, if any.
 *
 * @param[in] spip      pointer to the @p SPIDriver object
 *
 * @api
 */
void spiAbort(SPIDriver *spip) {

  osalSysLock();
  osalDbgAssert((spip->state == SPI_READY) || (spip->state == SPI_ACTIVE),
                "invalid state");
  if (spip->state == SPI_ACTIVE) {
    spiAbortI(spip);
    osalOsRescheduleS();
  }
  osalSysUnlock();
}
Beispiel #4
0
/**
 * @brief   Stops the driver.
 * @details Any thread waiting on the driver's queues will be awakened with
 *          the message @p Q_RESET.
 *
 * @param[in] sdp       pointer to a @p SerialDriver object
 *
 * @api
 */
void sdStop(SerialDriver *sdp) {

  osalDbgCheck(sdp != NULL);

  osalSysLock();
  osalDbgAssert((sdp->state == SD_STOP) || (sdp->state == SD_READY),
                "invalid state");
  sd_lld_stop(sdp);
  sdp->state = SD_STOP;
  oqResetI(&sdp->oqueue);
  iqResetI(&sdp->iqueue);
  osalOsRescheduleS();
  osalSysUnlock();
}
Beispiel #5
0
/**
 * @brief   Deactivates the CAN peripheral.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 *
 * @api
 */
void canStop(CANDriver *canp) {

  osalDbgCheck(canp != NULL);

  osalSysLock();
  osalDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY),
                "invalid state");
  can_lld_stop(canp);
  canp->state  = CAN_STOP;
  osalThreadDequeueAllI(&canp->rxqueue, MSG_RESET);
  osalThreadDequeueAllI(&canp->txqueue, MSG_RESET);
  osalOsRescheduleS();
  osalSysUnlock();
}
Beispiel #6
0
/**
 * @brief   Enforces leaving the sleep mode.
 * @note    The sleep mode is supposed to be usually exited automatically by
 *          an hardware event.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 */
void canWakeup(CANDriver *canp) {

  osalDbgCheck(canp != NULL);

  osalSysLock();
  osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
                "invalid state");
  if (canp->state == CAN_SLEEP) {
    can_lld_wakeup(canp);
    canp->state = CAN_READY;
    osalEventBroadcastFlagsI(&canp->wakeup_event, (eventflags_t)0);
    osalOsRescheduleS();
  }
  osalSysUnlock();
}
Beispiel #7
0
/**
 * @brief   Writes to a TX FIFO fetching data from a queue.
 *
 * @param[in] fifop     pointer to the FIFO register
 * @param[in] oqp       pointer to an @p output_queue_t object
 * @param[in] n         maximum number of bytes to copy
 *
 * @notapi
 */
static void otg_fifo_write_from_queue(volatile uint32_t *fifop,
                                      output_queue_t *oqp,
                                      size_t n) {
  size_t ntogo;

  ntogo = n;
  while (ntogo > 0) {
    uint32_t w, i;
    size_t nw = ntogo / 4;

    if (nw > 0) {
      size_t streak;
      uint32_t nw2end = (oqp->q_top - oqp->q_rdptr) / 4;

      ntogo -= (streak = nw <= nw2end ? nw : nw2end) * 4;
      oqp->q_rdptr = otg_do_push(fifop, oqp->q_rdptr, streak);
      if (oqp->q_rdptr >= oqp->q_top) {
        oqp->q_rdptr = oqp->q_buffer;
        continue;
      }
    }

    /* If this condition is not satisfied then there is a word lying across
       queue circular buffer boundary or there are some remaining bytes.*/
    if (ntogo <= 0)
      break;

    /* One byte at time.*/
    w = 0;
    i = 0;
    while ((ntogo > 0) && (i < 4)) {
      w |= (uint32_t)*oqp->q_rdptr++ << (i * 8);
      if (oqp->q_rdptr >= oqp->q_top)
        oqp->q_rdptr = oqp->q_buffer;
      ntogo--;
      i++;
    }
    *fifop = w;
  }

  /* Updating queue.*/
  osalSysLock();
  oqp->q_counter += n;
  osalThreadDequeueAllI(&oqp->q_waiting, Q_OK);
  osalOsRescheduleS();
  osalSysUnlock();
}
Beispiel #8
0
/**
 * @brief   Reads a packet from the RXFIFO.
 *
 * @param[in] fifop     pointer to the FIFO register
 * @param[in] iqp       pointer to an @p input_queue_t object
 * @param[in] n         number of bytes to pull from the FIFO
 *
 * @notapi
 */
static void otg_fifo_read_to_queue(volatile uint32_t *fifop,
                                   input_queue_t *iqp,
                                   size_t n) {
  size_t ntogo;

  ntogo = n;
  while (ntogo > 0) {
    uint32_t w, i;
    size_t nw = ntogo / 4;

    if (nw > 0) {
      size_t streak;
      uint32_t nw2end = (iqp->q_wrptr - iqp->q_wrptr) / 4;

      ntogo -= (streak = nw <= nw2end ? nw : nw2end) * 4;
      iqp->q_wrptr = otg_do_pop(fifop, iqp->q_wrptr, streak);
      if (iqp->q_wrptr >= iqp->q_top) {
        iqp->q_wrptr = iqp->q_buffer;
        continue;
      }
    }

    /* If this condition is not satisfied then there is a word lying across
       queue circular buffer boundary or there are some remaining bytes.*/
    if (ntogo <= 0)
      break;

    /* One byte at time.*/
    w = *fifop;
    i = 0;
    while ((ntogo > 0) && (i < 4)) {
      *iqp->q_wrptr++ = (uint8_t)(w >> (i * 8));
      if (iqp->q_wrptr >= iqp->q_top)
        iqp->q_wrptr = iqp->q_buffer;
      ntogo--;
      i++;
    }
  }

  /* Updating queue.*/
  osalSysLock();
  iqp->q_counter += n;
  osalThreadDequeueAllI(&iqp->q_waiting, Q_OK);
  osalOsRescheduleS();
  osalSysUnlock();
}
Beispiel #9
0
/**
 * @brief   Enters the sleep mode.
 * @details This function puts the CAN driver in sleep mode and broadcasts
 *          the @p sleep_event event source.
 * @pre     In order to use this function the option @p CAN_USE_SLEEP_MODE must
 *          be enabled and the @p CAN_SUPPORTS_SLEEP mode must be supported
 *          by the low level driver.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 *
 * @api
 */
void canSleep(CANDriver *canp) {

  osalDbgCheck(canp != NULL);

  osalSysLock();
  osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
                "invalid state");
  if (canp->state == CAN_READY) {
    can_lld_sleep(canp);
    canp->state = CAN_SLEEP;
#if CAN_ENFORCE_USE_CALLBACKS == FALSE
    osalEventBroadcastFlagsI(&canp->sleep_event, (eventflags_t)0);
    osalOsRescheduleS();
#endif
  }
  osalSysUnlock();
}
Beispiel #10
0
/**
 * @brief   Deactivates the CAN peripheral.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 *
 * @api
 */
void canStop(CANDriver *canp) {

  osalDbgCheck(canp != NULL);

  osalSysLock();
  osalDbgAssert((canp->state == CAN_STOP) || (canp->state == CAN_READY),
                "invalid state");

  /* The low level driver is stopped.*/
  can_lld_stop(canp);
  canp->state  = CAN_STOP;

  /* Threads waiting on CAN APIs are notified that the driver has been
     stopped in order to not have stuck threads.*/
  osalThreadDequeueAllI(&canp->rxqueue, MSG_RESET);
  osalThreadDequeueAllI(&canp->txqueue, MSG_RESET);
  osalOsRescheduleS();
  osalSysUnlock();
}
Beispiel #11
0
/**
 * @brief   Stops the driver.
 * @details Any thread waiting on the driver's queues will be awakened with
 *          the message @p MSG_RESET.
 *
 * @param[in] uhdp      pointer to a @p USBHIDDriver object
 *
 * @api
 */
void hidStop(USBHIDDriver *uhdp) {
  USBDriver *usbp = uhdp->config->usbp;

  osalDbgCheck(uhdp != NULL);

  osalSysLock();
  osalDbgAssert((uhdp->state == HID_STOP) || (uhdp->state == HID_READY),
                "invalid state");

  /* Driver in stopped state.*/
  usbp->in_params[uhdp->config->int_in - 1U]   = NULL;
  usbp->out_params[uhdp->config->int_out - 1U] = NULL;
  uhdp->state = HID_STOP;

  /* Enforces a disconnection.*/
  hidDisconnectI(uhdp);
  osalOsRescheduleS();
  osalSysUnlock();
}
/**
 * @brief   Stops the driver.
 * @details Any thread waiting on the driver's queues will be awakened with
 *          the message @p Q_RESET.
 *
 * @param[in] hiddp      pointer to a @p HIDDebugDriver object
 *
 * @api
 */
void hidDebugStop(HIDDebugDriver *hiddp) {
  USBDriver *usbp = hiddp->config->usbp;

  osalDbgCheck(hiddp != NULL);

  osalSysLock();
  osalDbgAssert((hiddp->state == HIDDEBUG_STOP) || (hiddp->state == HIDDEBUG_READY),
                "invalid state");

  /* Driver in stopped state.*/
  usbp->in_params[hiddp->config->ep_in - 1U] = NULL;
  hiddp->state = HIDDEBUG_STOP;

  /* Stop the flush timer */
  chVTResetI(&hid_debug_flush_timer);

  /* Queues reset in order to signal the driver stop to the application.*/
  chnAddFlagsI(hiddp, CHN_DISCONNECTED);
  iqResetI(&hiddp->oqueue);
  osalOsRescheduleS();
  osalSysUnlock();
}
Beispiel #13
0
/**
 * @brief   Stops the driver.
 * @details Any thread waiting on the driver's queues will be awakened with
 *          the message @p Q_RESET.
 *
 * @param[in] sdup      pointer to a @p SerialUSBDriver object
 *
 * @api
 */
void sduStop(SerialUSBDriver *sdup) {
  USBDriver *usbp = sdup->config->usbp;

  osalDbgCheck(sdup != NULL);

  osalSysLock();
  osalDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY),
                "invalid state");

  /* Driver in stopped state.*/
  usbp->in_params[sdup->config->bulk_in - 1U]   = NULL;
  usbp->out_params[sdup->config->bulk_out - 1U] = NULL;
  if (sdup->config->int_in > 0U) {
    usbp->in_params[sdup->config->int_in - 1U]  = NULL;
  }
  sdup->state = SDU_STOP;

  /* Enforces a disconnection.*/
  sduDisconnectI(sdup);
  osalOsRescheduleS();
  osalSysUnlock();
}
/**
 * @brief   Stops the driver.
 * @details Any thread waiting on the driver's queues will be awakened with
 *          the message @p Q_RESET.
 *
 * @param[in] sdup      pointer to a @p SerialUSBDriver object
 *
 * @api
 */
void sduStop(SerialUSBDriver *sdup) {
  USBDriver *usbp = sdup->config->usbp;

  osalDbgCheck(sdup != NULL);

  osalSysLock();
  osalDbgAssert((sdup->state == SDU_STOP) || (sdup->state == SDU_READY),
                "invalid state");

  /* Driver in stopped state.*/
  usbp->in_params[sdup->config->bulk_in - 1U]   = NULL;
  usbp->out_params[sdup->config->bulk_out - 1U] = NULL;
  if (sdup->config->int_in > 0U) {
    usbp->in_params[sdup->config->int_in - 1U]  = NULL;
  }
  sdup->state = SDU_STOP;

  /* Queues reset in order to signal the driver stop to the application.*/
  chnAddFlagsI(sdup, CHN_DISCONNECTED);
  iqResetI(&sdup->iqueue);
  oqResetI(&sdup->oqueue);
  osalOsRescheduleS();
  osalSysUnlock();
}