/** * @brief Input queue read with timeout. * @details This function reads a byte value from an input queue. If the queue * is empty then the calling thread is suspended until a byte arrives * in the queue or a timeout occurs. * @note The callback is invoked before reading the character from the * buffer or before entering the state @p THD_STATE_WTQUEUE. * * @param[in] iqp pointer to an @p input_queue_t structure * @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 A byte value from the queue. * @retval Q_TIMEOUT if the specified time expired. * @retval Q_RESET if the queue has been reset. * * @api */ msg_t iqGetTimeout(input_queue_t *iqp, systime_t timeout) { uint8_t b; osalSysLock(); if (iqp->q_notify != NULL) { iqp->q_notify(iqp); } while (iqIsEmptyI(iqp)) { msg_t msg = osalThreadEnqueueTimeoutS(&iqp->q_waiting, timeout); if (msg < Q_OK) { osalSysUnlock(); return msg; } } iqp->q_counter--; b = *iqp->q_rdptr++; if (iqp->q_rdptr >= iqp->q_top) { iqp->q_rdptr = iqp->q_buffer; } osalSysUnlock(); return (msg_t)b; }
/** * @brief Output queue write with timeout. * @details The function writes data from a buffer to an output queue. The * operation completes when the specified amount of data has been * transferred or after the specified timeout or if the queue has * been reset. * @note The function is not atomic, if you need atomicity it is suggested * to use a semaphore or a mutex for mutual exclusion. * @note The callback is invoked after writing each character into the * buffer. * * @param[in] oqp pointer to an @p output_queue_t structure * @param[in] bp pointer to the data buffer * @param[in] n the maximum amount of data to be transferred, the * value 0 is reserved * @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 number of bytes effectively transferred. * * @api */ size_t oqWriteTimeout(output_queue_t *oqp, const uint8_t *bp, size_t n, systime_t timeout) { qnotify_t nfy = oqp->q_notify; size_t w = 0; osalDbgCheck(n > 0U); osalSysLock(); while (true) { while (oqIsFullI(oqp)) { if (osalThreadEnqueueTimeoutS(&oqp->q_waiting, timeout) != Q_OK) { osalSysUnlock(); return w; } } oqp->q_counter--; *oqp->q_wrptr++ = *bp++; if (oqp->q_wrptr >= oqp->q_top) { oqp->q_wrptr = oqp->q_buffer; } if (nfy != NULL) { nfy(oqp); } osalSysUnlock(); /* Gives a preemption chance in a controlled point.*/ w++; if (--n == 0U) { return w; } osalSysLock(); } }
/** * @brief Input queue read with timeout. * @details The function reads data from an input queue into a buffer. The * operation completes when the specified amount of data has been * transferred or after the specified timeout or if the queue has * been reset. * @note The function is not atomic, if you need atomicity it is suggested * to use a semaphore or a mutex for mutual exclusion. * @note The callback is invoked before reading each character from the * buffer or before entering the state @p THD_STATE_WTQUEUE. * * @param[in] iqp pointer to an @p input_queue_t structure * @param[out] bp pointer to the data buffer * @param[in] n the maximum amount of data to be transferred, the * value 0 is reserved * @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 number of bytes effectively transferred. * * @api */ size_t iqReadTimeout(input_queue_t *iqp, uint8_t *bp, size_t n, systime_t timeout) { qnotify_t nfy = iqp->q_notify; size_t r = 0; osalDbgCheck(n > 0U); osalSysLock(); while (true) { if (nfy != NULL) { nfy(iqp); } while (iqIsEmptyI(iqp)) { if (osalThreadEnqueueTimeoutS(&iqp->q_waiting, timeout) != Q_OK) { osalSysUnlock(); return r; } } iqp->q_counter--; *bp++ = *iqp->q_rdptr++; if (iqp->q_rdptr >= iqp->q_top) { iqp->q_rdptr = iqp->q_buffer; } osalSysUnlock(); /* Gives a preemption chance in a controlled point.*/ r++; if (--n == 0U) { return r; } osalSysLock(); } }
/** * @brief Waits for a received frame. * @details Stops until a frame is received and buffered. If a frame is * not immediately available then the invoking thread is queued * until one is received. * * @param[in] macp pointer to the @p MACDriver object * @param[out] rdp pointer to a @p MACReceiveDescriptor structure * @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 status. * @retval MSG_OK the descriptor was obtained. * @retval MSG_TIMEOUT the operation timed out, descriptor not initialized. * * @api */ msg_t macWaitReceiveDescriptor(MACDriver *macp, MACReceiveDescriptor *rdp, systime_t timeout) { msg_t msg; systime_t now; osalDbgCheck((macp != NULL) && (rdp != NULL)); osalDbgAssert(macp->state == MAC_ACTIVE, "not active"); while (((msg = mac_lld_get_receive_descriptor(macp, rdp)) != MSG_OK) && (timeout > (systime_t)0)) { osalSysLock(); now = osalOsGetSystemTimeX(); msg = osalThreadEnqueueTimeoutS(&macp->rdqueue, timeout); if (msg == MSG_TIMEOUT) { osalSysUnlock(); break; } if (timeout != TIME_INFINITE) { timeout -= (osalOsGetSystemTimeX() - now); } osalSysUnlock(); } return msg; }
/** * @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[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox * @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 MSG_OK a frame has been received and placed in the buffer. * @retval MSG_TIMEOUT The operation has timed out. * @retval MSG_RESET The driver has been stopped while waiting. * * @api */ msg_t canReceiveTimeout(CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp, systime_t timeout) { osalDbgCheck((canp != NULL) && (crfp != NULL) && (mailbox <= (canmbx_t)CAN_RX_MAILBOXES)); osalSysLock(); osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), "invalid state"); /*lint -save -e9007 [13.5] Right side is supposed to be pure.*/ while ((canp->state == CAN_SLEEP) || !can_lld_is_rx_nonempty(canp, mailbox)) { /*lint -restore*/ msg_t msg = osalThreadEnqueueTimeoutS(&canp->rxqueue, timeout); if (msg != MSG_OK) { osalSysUnlock(); return msg; } } can_lld_receive(canp, mailbox, crfp); osalSysUnlock(); return MSG_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] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox * @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 MSG_OK the frame has been queued for transmission. * @retval MSG_TIMEOUT The operation has timed out. * @retval MSG_RESET The driver has been stopped while waiting. * * @api */ msg_t canTransmitTimeout(CANDriver *canp, canmbx_t mailbox, const CANTxFrame *ctfp, sysinterval_t timeout) { osalDbgCheck((canp != NULL) && (ctfp != NULL) && (mailbox <= (canmbx_t)CAN_TX_MAILBOXES)); osalSysLock(); osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), "invalid state"); /*lint -save -e9007 [13.5] Right side is supposed to be pure.*/ while ((canp->state == CAN_SLEEP) || !can_lld_is_tx_empty(canp, mailbox)) { /*lint -restore*/ msg_t msg = osalThreadEnqueueTimeoutS(&canp->txqueue, timeout); if (msg != MSG_OK) { osalSysUnlock(); return msg; } } can_lld_transmit(canp, mailbox, ctfp); osalSysUnlock(); 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[in] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox * @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 MSG_OK a frame has been received and placed in the buffer. * @retval MSG_TIMEOUT The operation has timed out. * @retval MSG_RESET The driver has been stopped while waiting. * * @api */ msg_t canReceive(CANDriver *canp, canmbx_t mailbox, CANRxFrame *crfp, systime_t timeout) { osalDbgCheck((canp != NULL) && (crfp != NULL) && (mailbox < CAN_RX_MAILBOXES)); osalSysLock(); osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), "invalid state"); while ((canp->state == CAN_SLEEP) || !can_lld_is_rx_nonempty(canp, mailbox)) { msg_t msg = osalThreadEnqueueTimeoutS(&canp->rxqueue, timeout); if (msg != MSG_OK) { osalSysUnlock(); return msg; } } can_lld_receive(canp, mailbox, crfp); osalSysUnlock(); return MSG_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] mailbox mailbox number, @p CAN_ANY_MAILBOX for any mailbox * @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 MSG_OK the frame has been queued for transmission. * @retval MSG_TIMEOUT The operation has timed out. * @retval MSG_RESET The driver has been stopped while waiting. * * @api */ msg_t canTransmit(CANDriver *canp, canmbx_t mailbox, const CANTxFrame *ctfp, systime_t timeout) { osalDbgCheck((canp != NULL) && (ctfp != NULL) && (mailbox <= CAN_TX_MAILBOXES)); osalSysLock(); osalDbgAssert((canp->state == CAN_READY) || (canp->state == CAN_SLEEP), "invalid state"); while ((canp->state == CAN_SLEEP) || !can_lld_is_tx_empty(canp, mailbox)) { msg_t msg = osalThreadEnqueueTimeoutS(&canp->txqueue, timeout); if (msg != MSG_OK) { osalSysUnlock(); return msg; } } can_lld_transmit(canp, mailbox, ctfp); osalSysUnlock(); return MSG_OK; }
/** * @brief Output queue write with timeout. * @details This function writes a byte value to an output queue. If the queue * is full then the calling thread is suspended until there is space * in the queue or a timeout occurs. * @note The callback is invoked after writing the character into the * buffer. * * @param[in] oqp pointer to an @p output_queue_t structure * @param[in] b the byte value to be written in the queue * @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 status. * @retval Q_OK if the operation succeeded. * @retval Q_TIMEOUT if the specified time expired. * @retval Q_RESET if the queue has been reset. * * @api */ msg_t oqPutTimeout(output_queue_t *oqp, uint8_t b, systime_t timeout) { osalSysLock(); while (oqIsFullI(oqp)) { msg_t msg = osalThreadEnqueueTimeoutS(&oqp->q_waiting, timeout); if (msg < Q_OK) { osalSysUnlock(); return msg; } } oqp->q_counter--; *oqp->q_wrptr++ = b; if (oqp->q_wrptr >= oqp->q_top) { oqp->q_wrptr = oqp->q_buffer; } if (oqp->q_notify != NULL) { oqp->q_notify(oqp); } osalSysUnlock(); return Q_OK; }