Пример #1
0
/**
 * @brief   Waits on the condition variable releasing the mutex lock.
 * @details Releases the currently owned mutex, waits on the condition
 *          variable, and finally acquires the mutex again. All the sequence
 *          is performed atomically.
 * @pre     The invoking thread <b>must</b> have at least one owned mutex.
 * @pre     The configuration option @p CH_USE_CONDVARS_TIMEOUT must be enabled
 *          in order to use this function.
 * @post    Exiting the function because a timeout does not re-acquire the
 *          mutex, the mutex ownership is lost.
 *
 * @param[in] cp        pointer to the @p CondVar structure
 * @param[in] time      the number of ticks before the operation timeouts, the
 *                      special values are handled as follow:
 *                      - @a TIME_INFINITE no timeout.
 *                      - @a TIME_IMMEDIATE this value is not allowed.
 *                      .
 * @return              A message specifying how the invoking thread has been
 *                      released from the condition variable.
 * @retval RDY_OK       if the condvar has been signaled using
 *                      @p chCondSignal().
 * @retval RDY_RESET    if the condvar has been signaled using
 *                      @p chCondBroadcast().
 * @retval RDY_TIMEOUT  if the condvar has not been signaled within the
 *                      specified timeout.
 *
 * @sclass
 */
msg_t chCondWaitTimeoutS(CondVar *cp, systime_t time) {
  Mutex *mp;
  msg_t msg;

  chDbgCheck((cp != NULL) && (time != TIME_IMMEDIATE), "chCondWaitTimeoutS");
  chDbgAssert(currp->p_mtxlist != NULL,
              "chCondWaitTimeoutS(), #1",
              "not owning a mutex");

  mp = chMtxUnlockS();
  currp->p_u.wtobjp = cp;
  prio_insert(currp, &cp->c_queue);
  msg = chSchGoSleepTimeoutS(THD_STATE_WTCOND, time);
  if (msg != RDY_TIMEOUT)
    chMtxLockS(mp);
  return msg;
}
Пример #2
0
/**
 * @brief   Invokes the event handlers associated to an event flags mask.
 *
 * @param[in] mask      mask of the event flags to be dispatched
 * @param[in] handlers  an array of @p evhandler_t. The array must have size
 *                      equal to the number of bits in eventmask_t.
 *
 * @api
 */
void chEvtDispatch(const evhandler_t *handlers, eventmask_t mask) {
  eventid_t eid;

  chDbgCheck(handlers != NULL, "chEvtDispatch");

  eid = 0;
  while (mask) {
    if (mask & EVENT_MASK(eid)) {
      chDbgAssert(handlers[eid] != NULL,
                  "chEvtDispatch(), #1",
                  "null handler");
      mask &= ~EVENT_MASK(eid);
      handlers[eid](eid);
    }
    eid++;
  }
}
/**
 * @brief   Stops any ongoing transmission.
 * @note    Stopping a transmission also suppresses the transmission callbacks.
 *
 * @param[in] uartp     pointer to the @p UARTDriver object
 *
 * @return              The number of data frames not transmitted by the
 *                      stopped transmit operation.
 * @retval 0            There was no transmit operation in progress.
 *
 * @api
 */
size_t uartStopSend(UARTDriver *uartp) {
  size_t n;

  chDbgCheck(uartp != NULL, "uartStopSend");

  chSysLock();
  chDbgAssert(uartp->state == UART_READY, "uartStopSend(), #1", "not active");

  if (uartp->txstate == UART_TX_ACTIVE) {
    n = uart_lld_stop_send(uartp);
    uartp->txstate = UART_TX_IDLE;
  }
  else
    n = 0;
  chSysUnlock();
  return n;
}
Пример #4
0
/**
 * @brief   Disables the MMC peripheral.
 *
 * @param[in] mmcp      pointer to the @p MMCDriver object
 */
void mmcStop(MMCDriver *mmcp) {

  chDbgCheck(mmcp != NULL, "mmcStop");

  chSysLock();
  chDbgAssert((mmcp->mmc_state != MMC_UNINIT) &&
              (mmcp->mmc_state != MMC_READING) &&
              (mmcp->mmc_state != MMC_WRITING),
              "mmcStop(), #1",
              "invalid state");
  if (mmcp->mmc_state != MMC_STOP) {
    mmcp->mmc_state = MMC_STOP;
    chVTResetI(&mmcp->mmc_vt);
  }
  chSysUnlock();
  spiStop(mmcp->mmc_spip);
}
Пример #5
0
/**
 * @brief   Waits for completion.
 * @details If the conversion is not completed or not yet started then the
 *          invoking thread waits for a conversion completion event.
 *
 * @param[in] adcp      pointer to the @p ADCDriver object
 * @param[in] timeout   the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout.
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              The operation result.
 * @retval RDY_OK       conversion finished.
 * @retval RDY_TIMEOUT  conversion not finished within the specified time.
 */
msg_t adcWaitConversion(ADCDriver *adcp, systime_t timeout) {

  chSysLock();
  chDbgAssert((adcp->ad_state == ADC_READY) ||
              (adcp->ad_state == ADC_RUNNING) ||
              (adcp->ad_state == ADC_COMPLETE),
              "adcWaitConversion(), #1",
              "invalid state");
  if (adcp->ad_state != ADC_COMPLETE) {
    if (chSemWaitTimeoutS(&adcp->ad_sem, timeout) == RDY_TIMEOUT) {
      chSysUnlock();
      return RDY_TIMEOUT;
    }
  }
  chSysUnlock();
  return RDY_OK;
}
Пример #6
0
/**
 * @brief   Waits on the condition variable releasing the mutex lock.
 * @details Releases the currently owned mutex, waits on the condition
 *          variable, and finally acquires the mutex again. All the sequence
 *          is performed atomically.
 * @pre     The invoking thread <b>must</b> have at least one owned mutex.
 * @pre     The configuration option @p CH_CFG_USE_CONDVARS_TIMEOUT must be enabled
 *          in order to use this function.
 * @post    Exiting the function because a timeout does not re-acquire the
 *          mutex, the mutex ownership is lost.
 *
 * @param[in] cp        pointer to the @p condition_variable_t structure
 * @param[in] time      the number of ticks before the operation timeouts, the
 *                      special values are handled as follow:
 *                      - @a TIME_INFINITE no timeout.
 *                      - @a TIME_IMMEDIATE this value is not allowed.
 *                      .
 * @return              A message specifying how the invoking thread has been
 *                      released from the condition variable.
 * @retval MSG_OK       if the condition variable has been signaled using
 *                      @p chCondSignal().
 * @retval MSG_RESET    if the condition variable has been signaled using
 *                      @p chCondBroadcast().
 * @retval MSG_TIMEOUT  if the condition variable has not been signaled within
 *                      the specified timeout.
 *
 * @sclass
 */
msg_t chCondWaitTimeoutS(condition_variable_t *cp, systime_t time) {
  mutex_t *mp;
  msg_t msg;

  chDbgCheckClassS();
  chDbgCheck((cp != NULL) && (time != TIME_IMMEDIATE));
  chDbgAssert(currp->p_mtxlist != NULL, "not owning a mutex");

  mp = chMtxGetNextMutexS();
  chMtxUnlockS(mp);
  currp->p_u.wtobjp = cp;
  queue_prio_insert(currp, &cp->c_queue);
  msg = chSchGoSleepTimeoutS(CH_STATE_WTCOND, time);
  if (msg != MSG_TIMEOUT)
    chMtxLockS(mp);
  return msg;
}
Пример #7
0
/**
 * @brief   Performs a wait operation on a semaphore.
 *
 * @param[in] sp        pointer to a @p Semaphore structure
 * @return              A message specifying how the invoking thread has been
 *                      released from the semaphore.
 * @retval RDY_OK       if the thread has not stopped on the semaphore or the
 *                      semaphore has been signaled.
 * @retval RDY_RESET    if the semaphore has been reset using @p chSemReset().
 *
 * @sclass
 */
msg_t chSemWaitS(Semaphore *sp) {

  chDbgCheck(sp != NULL, "chSemWaitS");

  chDbgAssert(((sp->s_cnt >= 0) && isempty(&sp->s_queue)) ||
              ((sp->s_cnt < 0) && notempty(&sp->s_queue)),
              "chSemWaitS(), #1",
              "inconsistent semaphore");

  if (--sp->s_cnt < 0) {
    currp->p_u.wtobjp = sp;
    sem_insert(currp, &sp->s_queue);
    chSchGoSleepS(THD_STATE_WTSEM);
    return currp->p_u.rdymsg;
  }
  return RDY_OK;
}
Пример #8
0
/**
 * @brief   Performs a signal operation on a semaphore.
 * @post    This function does not reschedule so a call to a rescheduling
 *          function must be performed before unlocking the kernel. Note that
 *          interrupt handlers always reschedule on exit so an explicit
 *          reschedule must not be performed in ISRs.
 *
 * @param[in] sp    pointer to a @p Semaphore structure
 *
 * @iclass
 */
void chSemSignalI(Semaphore *sp) {

  chDbgCheck(sp != NULL, "chSemSignalI");

  chDbgAssert(((sp->s_cnt >= 0) && isempty(&sp->s_queue)) ||
              ((sp->s_cnt < 0) && notempty(&sp->s_queue)),
              "chSemSignalI(), #1",
              "inconsistent semaphore");

  if (++sp->s_cnt <= 0) {
    /* note, it is done this way in order to allow a tail call on
             chSchReadyI().*/
    Thread *tp = fifo_remove(&sp->s_queue);
    tp->p_u.rdymsg = RDY_OK;
    chSchReadyI(tp);
  }
}
Пример #9
0
/**
 * @brief   Performs a wait operation on a semaphore.
 *
 * @param[in] sp        pointer to a @p semaphore_t structure
 * @return              A message specifying how the invoking thread has been
 *                      released from the semaphore.
 * @retval MSG_OK       if the thread has not stopped on the semaphore or the
 *                      semaphore has been signaled.
 * @retval MSG_RESET    if the semaphore has been reset using @p chSemReset().
 *
 * @sclass
 */
msg_t chSemWaitS(semaphore_t *sp) {

  chDbgCheckClassS();
  chDbgCheck(sp != NULL);
  chDbgAssert(((sp->s_cnt >= (cnt_t)0) && queue_isempty(&sp->s_queue)) ||
              ((sp->s_cnt < (cnt_t)0) && queue_notempty(&sp->s_queue)),
              "inconsistent semaphore");

  if (--sp->s_cnt < (cnt_t)0) {
    currp->p_u.wtsemp = sp;
    sem_insert(currp, &sp->s_queue);
    chSchGoSleepS(CH_STATE_WTSEM);

    return currp->p_u.rdymsg;
  }

  return MSG_OK;
}
Пример #10
0
/**
 * @brief   Can frame receive.
 * @details The function waits until a frame is received.
 * @note    Trying to receive while in sleep mode simply enqueues the thread.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 * @param[out] crfp     pointer to the buffer where the CAN frame is copied
 * @param[in] timeout   the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout (useful in an
 *                        event driven scenario where a thread never blocks
 *                        for I/O).
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              The operation result.
 * @retval RDY_OK       a frame has been received and placed in the buffer.
 * @retval RDY_TIMEOUT  The operation has timed out.
 * @retval RDY_RESET    The driver has been stopped while waiting.
 *
 * @api
 */
msg_t canReceive(CANDriver *canp, CANRxFrame *crfp, systime_t timeout) {

  chDbgCheck((canp != NULL) && (crfp != NULL), "canReceive");

  chSysLock();
  chDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
              "canReceive(), #1", "invalid state");
  while ((canp->state == CAN_SLEEP) || !can_lld_can_receive(canp)) {
    msg_t msg = chSemWaitTimeoutS(&canp->rxsem, timeout);
    if (msg != RDY_OK) {
      chSysUnlock();
      return msg;
    }
  }
  can_lld_receive(canp, crfp);
  chSysUnlock();
  return RDY_OK;
}
Пример #11
0
/**
 * @brief   Can frame transmission.
 * @details The specified frame is queued for transmission, if the hardware
 *          queue is full then the invoking thread is queued.
 * @note    Trying to transmit while in sleep mode simply enqueues the thread.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 * @param[in] ctfp      pointer to the CAN frame to be transmitted
 * @param[in] timeout   the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout.
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              The operation result.
 * @retval RDY_OK       the frame has been queued for transmission.
 * @retval RDY_TIMEOUT  The operation has timed out.
 * @retval RDY_RESET    The driver has been stopped while waiting.
 *
 * @api
 */
msg_t canTransmit(CANDriver *canp, const CANTxFrame *ctfp, systime_t timeout) {

  chDbgCheck((canp != NULL) && (ctfp != NULL), "canTransmit");

  chSysLock();
  chDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP),
              "canTransmit(), #1", "invalid state");
  while ((canp->state == CAN_SLEEP) || !can_lld_can_transmit(canp)) {
    msg_t msg = chSemWaitTimeoutS(&canp->txsem, timeout);
    if (msg != RDY_OK) {
      chSysUnlock();
      return msg;
    }
  }
  can_lld_transmit(canp, ctfp);
  chSysUnlock();
  return RDY_OK;
}
Пример #12
0
/**
 * @brief   Configures and activates the CAN peripheral.
 * @note    Activating the CAN bus can be a slow operation this this function
 *          is not atomic, it waits internally for the initialization to
 *          complete.
 *
 * @param[in] canp      pointer to the @p CANDriver object
 * @param[in] config    pointer to the @p CANConfig object. Depending on
 *                      the implementation the value can be @p NULL.
 *
 * @api
 */
void canStart(CANDriver *canp, const CANConfig *config) {

  chDbgCheck(canp != NULL, "canStart");

  chSysLock();
  chDbgAssert((canp->state == CAN_STOP) ||
              (canp->state == CAN_STARTING) ||
              (canp->state == CAN_READY),
              "canStart(), #1", "invalid state");
  while (canp->state == CAN_STARTING)
    chThdSleepS(1);
  if (canp->state == CAN_STOP) {
    canp->config = config;
    can_lld_start(canp);
    canp->state = CAN_READY;
  }
  chSysUnlock();
}
Пример #13
0
/**
 * @brief   Waits on the condition variable releasing the mutex lock.
 * @details Releases the currently owned mutex, waits on the condition
 *          variable, and finally acquires the mutex again. All the sequence
 *          is performed atomically.
 * @pre     The invoking thread <b>must</b> have at least one owned mutex.
 *
 * @param[in] cp        pointer to the @p CondVar structure
 * @return              A message specifying how the invoking thread has been
 *                      released from the condition variable.
 * @retval RDY_OK       if the condvar has been signaled using
 *                      @p chCondSignal().
 * @retval RDY_RESET    if the condvar has been signaled using
 *                      @p chCondBroadcast().
 *
 * @sclass
 */
msg_t chCondWaitS(CondVar *cp) {
  Thread *ctp = currp;
  Mutex *mp;
  msg_t msg;

  chDbgCheck(cp != NULL, "chCondWaitS");
  chDbgAssert(ctp->p_mtxlist != NULL,
              "chCondWaitS(), #1",
              "not owning a mutex");

  mp = chMtxUnlockS();
  ctp->p_u.wtobjp = cp;
  prio_insert(ctp, &cp->c_queue);
  chSchGoSleepS(THD_STATE_WTCOND);
  msg = ctp->p_u.rdymsg;
  chMtxLockS(mp);
  return msg;
}
Пример #14
0
msg_t i2c_receive(i2caddr_t addr, uint8_t *rxbuf, size_t rxbytes){
  msg_t status = RDY_OK;
  systime_t tmo = calc_timeout(&I2C_BUS, 0, rxbytes);

  i2cAcquireBus(&I2C_BUS);
  status = i2cMasterReceiveTimeout(&I2C_BUS, addr, rxbuf, rxbytes, tmo);
  i2cReleaseBus(&I2C_BUS);
  chDbgAssert(status == RDY_OK, "i2c_transmit(), #1", "error in driver");
  if (status == RDY_TIMEOUT){
	//chprintf((BaseChannel *)&SD1, "I2C Timeout, restarting...\r\n");
    i2cStop(&I2C_BUS);
    chThdSleepMilliseconds(1);
    i2cStart(&I2C_BUS, &i2cfg1);
    setGlobalFlag(I2C_RESTARTED_FLAG);
    return status;
  }
  return status;
}
Пример #15
0
/**
 * @brief   Releases a DMA stream.
 * @details The stream is freed and, if required, the DMA clock disabled.
 *          Trying to release a unallocated stream is an illegal operation
 *          and is trapped if assertions are enabled.
 * @pre     The stream must have been allocated using @p dmaStreamAllocate().
 * @post    The stream is again available.
 * @note    This function can be invoked in both ISR or thread context.
 *
 * @param[in] dmastp    pointer to a stm32_dma_stream_t structure
 *
 * @special
 */
void dmaStreamRelease(const stm32_dma_stream_t *dmastp) {

  chDbgCheck(dmastp != NULL, "dmaStreamRelease");

  /* Check if the streams is not taken.*/
  chDbgAssert((dma_streams_mask & (1 << dmastp->selfindex)) != 0,
              "dmaStreamRelease(), #1", "not allocated");

  /* Disables the associated IRQ vector.*/
  nvicDisableVector(dmastp->vector);

  /* Marks the stream as not allocated.*/
  dma_streams_mask &= ~(1 << dmastp->selfindex);

  /* Shutting down clocks that are no more required, if any.*/
  if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) == 0)
    rccDisableDMA1(FALSE);
}
Пример #16
0
/**
 * @brief   Terminates the current thread.
 * @details The thread goes in the @p CH_STATE_FINAL state holding the
 *          specified exit status code, other threads can retrieve the
 *          exit status code by invoking the function @p chThdWait().
 * @post    Eventual code after this function will never be executed,
 *          this function never returns. The compiler has no way to
 *          know this so do not assume that the compiler would remove
 *          the dead code.
 *
 * @param[in] msg       thread exit code
 *
 * @sclass
 */
void chThdExitS(msg_t msg) {
  thread_t *tp = currp;

  tp->u.exitcode = msg;
  CH_CFG_THREAD_EXIT_HOOK(tp);
#if CH_CFG_USE_WAITEXIT == TRUE
  while (list_notempty(&tp->waiting)) {
    (void) chSchReadyI(list_remove(&tp->waiting));
  }
#endif
#if CH_CFG_USE_REGISTRY == TRUE
  REG_REMOVE(tp);
#endif
  chSchGoSleepS(CH_STATE_FINAL);

  /* The thread never returns here.*/
  chDbgAssert(false, "zombies apocalypse");
}
Пример #17
0
/**
 * @brief   Enables a DC Motor channel.
 * @pre     The DCMotor unit must have been activated using @p dcmStart().
 *
 * @param[in] dcmp      pointer to a @p DCMotorDriver object
 * @param[in] channel   channel identifier (0..DCM_CHANNELS-1)
 * @param[in] with      pulse width [-1000 .. +1000]
 *
 * @api
 */
void dcmEnableChannel(DCMotorDriver *dcmp,
                      dcmchannel_t channel,
                      dcmwidth_t with) {

  chDbgCheck((dcmp != NULL) && (channel < DCM_CHANNELS),
             "dcmEnableChannel");

  if (with > DCM_MAX)
    with = DCM_MAX;
  else if (with < DCM_MIN)
    with = DCM_MIN;

  //chSysLock();
  chDbgAssert(dcmp->state == DCM_READY,
              "dcmEnableChannel(), #1", "not ready");
  dcm_lld_enable_channel(dcmp, channel, with);
  //chSysUnlock();
}
Пример #18
0
/**
 * @brief   Waits on the condition variable releasing the mutex lock.
 * @details Releases the currently owned mutex, waits on the condition
 *          variable, and finally acquires the mutex again. All the sequence
 *          is performed atomically.
 * @pre     The invoking thread <b>must</b> have at least one owned mutex.
 *
 * @param[in] cp        pointer to the @p condition_variable_t structure
 * @return              A message specifying how the invoking thread has been
 *                      released from the condition variable.
 * @retval MSG_OK       if the condition variable has been signaled using
 *                      @p chCondSignal().
 * @retval MSG_RESET    if the condition variable has been signaled using
 *                      @p chCondBroadcast().
 *
 * @sclass
 */
msg_t chCondWaitS(condition_variable_t *cp) {
  thread_t *ctp = currp;
  mutex_t *mp;
  msg_t msg;

  chDbgCheckClassS();
  chDbgCheck(cp != NULL);
  chDbgAssert(ctp->p_mtxlist != NULL, "not owning a mutex");

  mp = chMtxGetNextMutexS();
  chMtxUnlockS(mp);
  ctp->p_u.wtobjp = cp;
  queue_prio_insert(ctp, &cp->c_queue);
  chSchGoSleepS(CH_STATE_WTCOND);
  msg = ctp->p_u.rdymsg;
  chMtxLockS(mp);
  return msg;
}
Пример #19
0
/**
 * @brief   Writes a value into a register.
 * @pre     The SPI interface must be initialized and the driver started.
 *
 * @param[in] spip      pointer to the SPI initerface
 * @param[in] reg       register number
 * @param[in] value     the value to be written
 */
void l3g4200dWriteRegister(SPIDriver *spip, uint8_t reg, uint8_t value) {

  switch (reg) {
  case L3G4200D_WHO_AM_I:
  case L3G4200D_OUT_TEMP:
  case L3G4200D_STATUS_REG:
  case L3G4200D_OUT_X_L:
  case L3G4200D_OUT_X_H:
  case L3G4200D_OUT_Y_L:
  case L3G4200D_OUT_Y_H:
  case L3G4200D_OUT_Z_L:
  case L3G4200D_OUT_Z_H:
    /* Read only registers cannot be written, the command is ignored.*/
    return;
  case L3G4200D_CTRL_REG1:
  case L3G4200D_CTRL_REG2:
  case L3G4200D_CTRL_REG3:
  case L3G4200D_CTRL_REG4:
  case L3G4200D_CTRL_REG5:
  case L3G4200D_REFERENCE:
  case L3G4200D_FIFO_CTRL_REG:
  case L3G4200D_FIFO_SRC_REG:
  case L3G4200D_INT1_CFG:
  case L3G4200D_INT1_SRC:
  case L3G4200D_INT1_TSH_XH:
  case L3G4200D_INT1_TSH_XL:
  case L3G4200D_INT1_TSH_YH:
  case L3G4200D_INT1_TSH_YL:
  case L3G4200D_INT1_TSH_ZH:
  case L3G4200D_INT1_TSH_ZL:
  case L3G4200D_INT1_DURATION:
    spiSelect(spip);
    txbuf[0] = reg;
    txbuf[1] = value;
    spiSend(spip, 2, txbuf);
    spiUnselect(spip);
    break;
  default:
    /* Reserved register must not be written, according to the datasheet
     this could permanently damage the device.*/
    chDbgAssert(FALSE, "L3G4200DWriteRegister(), #1", "reserved register");
    break;
  }
}
Пример #20
0
/**
 * @brief   Performs a wait operation on a semaphore with timeout specification.
 *
 * @param[in] sp        pointer to a @p semaphore_t structure
 * @param[in] time      the number of ticks before the operation timeouts,
 *                      the following special values are allowed:
 *                      - @a TIME_IMMEDIATE immediate timeout.
 *                      - @a TIME_INFINITE no timeout.
 *                      .
 * @return              A message specifying how the invoking thread has been
 *                      released from the semaphore.
 * @retval MSG_OK       if the thread has not stopped on the semaphore or the
 *                      semaphore has been signaled.
 * @retval MSG_RESET    if the semaphore has been reset using @p chSemReset().
 * @retval MSG_TIMEOUT  if the semaphore has not been signaled or reset within
 *                      the specified timeout.
 *
 * @sclass
 */
msg_t chSemWaitTimeoutS(semaphore_t *sp, systime_t time) {

  chDbgCheckClassS();
  chDbgCheck(sp != NULL);
  chDbgAssert(((sp->s_cnt >= 0) && queue_isempty(&sp->s_queue)) ||
              ((sp->s_cnt < 0) && queue_notempty(&sp->s_queue)),
              "inconsistent semaphore");

  if (--sp->s_cnt < 0) {
    if (TIME_IMMEDIATE == time) {
      sp->s_cnt++;
      return MSG_TIMEOUT;
    }
    currp->p_u.wtobjp = sp;
    sem_insert(currp, &sp->s_queue);
    return chSchGoSleepTimeoutS(CH_STATE_WTSEM, time);
  }
  return MSG_OK;
}
Пример #21
0
/**
 * @brief   Outputs a value directly on a DAC channel.
 *
 * @param[in] dacp      pointer to the @p DACDriver object
 * @param[in] channel   DAC channel number
 * @param[in] sample    value to be output
 *
 * @api
 */
void dac_lld_put_channel(DACDriver *dacp,
                         dacchannel_t channel,
                         dacsample_t sample) {

  switch (dacp->config->datamode) {
  case DAC_DHRM_12BIT_RIGHT:
#if STM32_DAC_DUAL_MODE
  case DAC_DHRM_12BIT_RIGHT_DUAL:
#endif
    if (channel == 0U) {
      dacp->params->dac->DHR12R1 = (uint32_t)sample;
    }
    else {
      dacp->params->dac->DHR12R2 = (uint32_t)sample;
    }
    break;
  case DAC_DHRM_12BIT_LEFT:
#if STM32_DAC_DUAL_MODE
  case DAC_DHRM_12BIT_LEFT_DUAL:
#endif
    if (channel == 0U) {
      dacp->params->dac->DHR12L1 = (uint32_t)sample;
    }
    else {
      dacp->params->dac->DHR12L2 = (uint32_t)sample;
    }
    break;
  case DAC_DHRM_8BIT_RIGHT:
#if STM32_DAC_DUAL_MODE
  case DAC_DHRM_8BIT_RIGHT_DUAL:
#endif
    if (channel == 0U) {
      dacp->params->dac->DHR8R1  = (uint32_t)sample;
    }
    else {
      dacp->params->dac->DHR8R2  = (uint32_t)sample;
    }
    break;
  default:
    chDbgAssert(false, "unexpected DAC mode");
    break;
  }
}
Пример #22
0
/**
 * @brief   Returns the thread next to the specified one.
 * @details The reference counter of the specified thread is decremented and
 *          the reference counter of the returned thread is incremented.
 *
 * @param[in] tp        pointer to the thread
 * @return              A reference to the next thread.
 * @retval NULL         if there is no next thread.
 *
 * @api
 */
thread_t *chRegNextThread(thread_t *tp) {
    thread_t *ntp;

    chSysLock();
    ntp = tp->p_newer;
    if (ntp == (thread_t *)&ch.rlist)
        ntp = NULL;
#if CH_CFG_USE_DYNAMIC
    else {
        chDbgAssert(ntp->p_refs < 255, "too many references");
        ntp->p_refs++;
    }
#endif
    chSysUnlock();
#if CH_CFG_USE_DYNAMIC
    chThdRelease(tp);
#endif
    return ntp;
}
Пример #23
0
/*
 * Return pointer to newly received binary blob
 */
uint16_t sc_cmd_blob_get(uint8_t **blob)
{
  uint16_t len = 0;

  chMtxLock(&blob_mtx);
  if (blob_len > 0 && blob_i == blob_len) {
    len = blob_len;
  }
  chMtxUnlock(&blob_mtx);

  // There might still be a small change that the blob gets restarted between the check above and returning below.
  if (len) {
    *blob = blob_buf;
  } else {
    chDbgAssert(0, "No binary blob available");
    *blob = NULL;
  }
  return len;
}
Пример #24
0
/**
 * @brief   EDMA channel allocation.
 *
 * @param[in] channel   the channel number
 *
 * @special
 */
void edmaChannelRelease(edma_channel_t channel) {

  chDbgCheck((channel < 0) && (channel >= SPC5_EDMA_NCHANNELS),
             "edmaChannelAllocate");
  chDbgAssert(channels[channel] != NULL,
              "edmaChannelRelease(), #1",
              "not allocated");

  /* Enforcing a stop.*/
  edmaChannelStop(channel);

  /* Clearing ISR sources for the channel.*/
  SPC5_EDMA.CIRQR.R = channel;
  SPC5_EDMA.CEEIR.R = channel;
  SPC5_EDMA.CER.R   = channel;

  /* The channels is flagged as available.*/
  channels[channel] = NULL;
}
Пример #25
0
/**
 * @brief   Configures and activates the GPT peripheral.
 *
 * @param[in] gptp      pointer to the @p GPTDriver object
 *
 * @notapi
 */
void gpt_lld_start(GPTDriver *gptp) {
  uint32_t pr;

  if (gptp->state == GPT_STOP) {
    /* Clock activation.*/
#if LPC11xx_GPT_USE_CT16B0
    if (&GPTD1 == gptp) {
      LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 7);
      nvicEnableVector(TIMER_16_0_IRQn, CORTEX_PRIORITY_MASK(2));
    }
#endif
#if LPC11xx_GPT_USE_CT16B1
    if (&GPTD2 == gptp) {
      LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 8);
      nvicEnableVector(TIMER_16_1_IRQn, CORTEX_PRIORITY_MASK(3));
    }
#endif
#if LPC11xx_GPT_USE_CT32B0
    if (&GPTD3 == gptp) {
      LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 9);
      nvicEnableVector(TIMER_32_0_IRQn, CORTEX_PRIORITY_MASK(2));
    }
#endif
#if LPC11xx_GPT_USE_CT32B1
    if (&GPTD4 == gptp) {
      LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 10);
      nvicEnableVector(TIMER_32_1_IRQn, CORTEX_PRIORITY_MASK(2));
    }
#endif
  }

  /* Prescaler value calculation.*/
  pr = (uint16_t)((LPC11xx_SYSCLK / gptp->config->frequency) - 1);
  chDbgAssert(((uint32_t)(pr + 1) * gptp->config->frequency) == LPC11xx_SYSCLK,
              "gpt_lld_start(), #1", "invalid frequency");

  /* Timer configuration.*/
  gptp->tmr->PR  = pr;
  gptp->tmr->IR  = 1;
  gptp->tmr->MCR = 0;
  gptp->tmr->TCR = 0;
}
Пример #26
0
/**
 * @brief   Changes the operation mode of a channel.
 * @note    This function attempts to write over the current configuration
 *          structure that must have been not declared constant. This
 *          violates the @p const qualifier in @p extStart() but it is
 *          intentional.
 * @note    This function cannot be used if the configuration structure is
 *          declared @p const.
 * @note    The effect of this function on constant configuration structures
 *          is not defined.
 *
 * @param[in] extp      pointer to the @p EXTDriver object
 * @param[in] channel   channel to be changed
 * @param[in] extcp     new configuration for the channel
 *
 * @iclass
 */
void extSetChannelModeI(EXTDriver *extp,
                        expchannel_t channel,
                        const EXTChannelConfig *extcp) {
  EXTChannelConfig *oldcp;

  chDbgCheck((extp != NULL) && (channel < EXT_MAX_CHANNELS) &&
             (extcp != NULL), "extSetChannelModeI");

  chDbgAssert(extp->state == EXT_ACTIVE,
              "extSetChannelModeI(), #1", "invalid state");

  /* Note that here the access is enforced as non-const, known access
     violation.*/
  oldcp = (EXTChannelConfig *)&extp->config->channels[channel];

  /* Overwiting the old channels configuration then the channel is reconfigured
     by the low level driver.*/
  *oldcp = *extcp;
  ext_lld_channel_enable(extp, channel);
}
Пример #27
0
Thread *chSchReadyI(Thread *tp) {
  Thread *cp;

  /* Integrity checks.*/
  chDbgAssert((tp->p_state != THD_STATE_READY) &&
              (tp->p_state != THD_STATE_FINAL),
              "chSchReadyI(), #1",
              "invalid state");

  tp->p_state = THD_STATE_READY;
  cp = (Thread *)&rlist.r_queue;
  do {
    cp = cp->p_next;
  } while (cp->p_prio >= tp->p_prio);
  /* Insertion on p_prev.*/
  tp->p_next = cp;
  tp->p_prev = cp->p_prev;
  tp->p_prev->p_next = cp->p_prev = tp;
  return tp;
}
Пример #28
0
/**
 * @brief   Starts a DAC conversion.
 * @details Starts an asynchronous conversion operation.
 * @post    The callbacks associated to the conversion group will be invoked
 *          on buffer fill and error events.
 * @note    The buffer is organized as a matrix of M*N elements where M is the
 *          channels number configured into the conversion group and N is the
 *          buffer depth. The samples are sequentially written into the buffer
 *          with no gaps.
 *
 * @param[in] dacp      pointer to the @p DACDriver object
 * @param[in] grpp      pointer to a @p DACConversionGroup object
 * @param[in] samples   pointer to the samples buffer
 * @param[in] depth     buffer depth (matrix rows number). The buffer depth
 *                      must be one or an even number.
 *
 * @iclass
 */
void dacStartConversionI(DACDriver *dacp,
                         const DACConversionGroup *grpp,
                         const dacsample_t *samples,
                         size_t depth) {

  chDbgCheckClassI();
  chDbgCheck((dacp != NULL) && (grpp != NULL) && (samples != NULL) &&
             ((depth == 1) || ((depth & 1) == 0)),
             "dacStartConversionI");
  chDbgAssert((dacp->state == DAC_READY) ||
              (dacp->state == DAC_COMPLETE) ||
              (dacp->state == DAC_ERROR),
              "dacStartConversionI(), #1", "not ready");

  dacp->samples  = samples;
  dacp->depth    = depth;
  dacp->grpp     = grpp;
  dacp->state    = DAC_ACTIVE;
  dac_lld_start_conversion(dacp);
}
Пример #29
0
/**
 * @brief   Starts an ADC conversion.
 * @details Starts an asynchronous conversion operation.
 * @post    The callbacks associated to the conversion group will be invoked
 *          on buffer fill and error events.
 * @note    The buffer is organized as a matrix of M*N elements where M is the
 *          channels number configured into the conversion group and N is the
 *          buffer depth. The samples are sequentially written into the buffer
 *          with no gaps.
 *
 * @param[in] adcp      pointer to the @p ADCDriver object
 * @param[in] grpp      pointer to a @p ADCConversionGroup object
 * @param[out] samples  pointer to the samples buffer
 * @param[in] depth     buffer depth (matrix rows number). The buffer depth
 *                      must be one or an even number.
 *
 * @iclass
 */
void adcStartConversionI(ADCDriver *adcp,
                         const ADCConversionGroup *grpp,
                         adcsample_t *samples,
                         size_t depth) {

  chDbgCheckClassI();
  chDbgCheck((adcp != NULL) && (grpp != NULL) && (samples != NULL) &&
             ((depth == 1) || ((depth & 1) == 0)),
             "adcStartConversionI");
  chDbgAssert((adcp->state == ADC_READY) ||
              (adcp->state == ADC_COMPLETE) ||
              (adcp->state == ADC_ERROR),
              "adcStartConversionI(), #1", "not ready");

  adcp->samples  = samples;
  adcp->depth    = depth;
  adcp->grpp     = grpp;
  adcp->state    = ADC_ACTIVE;
  adc_lld_start_conversion(adcp);
}
Пример #30
0
/**
 * @brief   Returns the thread next to the specified one.
 * @details The reference counter of the specified thread is decremented and
 *          the reference counter of the returned thread is incremented.
 *
 * @param[in] tp        pointer to the thread
 * @return              A reference to the next thread.
 * @retval NULL         if there is no next thread.
 *
 * @api
 */
Thread *chRegNextThread(Thread *tp) {
  Thread *ntp;

  chSysLock();
  ntp = tp->p_newer;
  if (ntp == (Thread *)&rlist)
    ntp = NULL;
#if CH_USE_DYNAMIC
  else {
    chDbgAssert(ntp->p_refs < 255, "chRegNextThread(), #1",
                "too many references");
    ntp->p_refs++;
  }
#endif
  chSysUnlock();
#if CH_USE_DYNAMIC
  chThdRelease(tp);
#endif
  return ntp;
}