/** * @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; }
/** * @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; }
/** * @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); }
/** * @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; }
/** * @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; }
/** * @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; }
/** * @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); } }
/** * @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; }
/** * @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; }
/** * @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; }
/** * @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(); }
/** * @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; }
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; }
/** * @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); }
/** * @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"); }
/** * @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(); }
/** * @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; }
/** * @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; } }
/** * @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; }
/** * @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; } }
/** * @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; }
/* * 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; }
/** * @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; }
/** * @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; }
/** * @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); }
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; }
/** * @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); }
/** * @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); }
/** * @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; }