From f4ec81ae144ef2ae7ddd9a0e56082970420c0464 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Fri, 20 May 2011 12:46:24 +0000 Subject: [PATCH] USB CDC functionality restored, more improvements to the I/O queues. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@2983 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial_usb.c | 14 ++++++-------- os/kernel/src/chqueues.c | 41 ++++++++++++++++++++++------------------ readme.txt | 2 ++ 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 7fecd5f30..3f53d7df0 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -126,9 +126,8 @@ static void inotify(GenericQueue *qp) { chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; sdup->iqueue.q_counter = n; - if (notempty(&sdup->iqueue.q_waiting)) + while (notempty(&sdup->iqueue.q_waiting)) chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; - chSchRescheduleS(); } } } @@ -148,10 +147,9 @@ static void onotify(GenericQueue *qp) { if (w != USB_ENDPOINT_BUSY) { chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; - sdup->oqueue.q_counter = n; - if (notempty(&sdup->oqueue.q_waiting)) + sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue); + while (notempty(&sdup->oqueue.q_waiting)) chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK; - chSchRescheduleS(); } } @@ -294,8 +292,8 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { if (w != USB_ENDPOINT_BUSY) { chIOAddFlagsI(sdup, IO_OUTPUT_EMPTY); sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; - sdup->oqueue.q_counter = n; - if (notempty(&sdup->oqueue.q_waiting)) + sdup->oqueue.q_counter = chQSizeI(&sdup->oqueue); + while (notempty(&sdup->oqueue.q_waiting)) chSchReadyI(fifo_remove(&sdup->oqueue.q_waiting))->p_u.rdymsg = Q_OK; } } @@ -325,7 +323,7 @@ void sduDataReceived(USBDriver *usbp, usbep_t ep) { chIOAddFlagsI(sdup, IO_INPUT_AVAILABLE); sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; sdup->iqueue.q_counter = n; - if (notempty(&sdup->iqueue.q_waiting)) + while (notempty(&sdup->iqueue.q_waiting)) chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; } } diff --git a/os/kernel/src/chqueues.c b/os/kernel/src/chqueues.c index 767a36e63..8532f8307 100644 --- a/os/kernel/src/chqueues.c +++ b/os/kernel/src/chqueues.c @@ -136,8 +136,10 @@ msg_t chIQPutI(InputQueue *iqp, uint8_t b) { *iqp->q_wrptr++ = b; if (iqp->q_wrptr >= iqp->q_top) iqp->q_wrptr = iqp->q_buffer; + if (notempty(&iqp->q_waiting)) chSchReadyI(fifo_remove(&iqp->q_waiting))->p_u.rdymsg = Q_OK; + return Q_OK; } @@ -146,6 +148,9 @@ msg_t chIQPutI(InputQueue *iqp, uint8_t b) { * @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 if the queue is empty before entering the + * @p THD_STATE_WTQUEUE state in order to solicit the low level to + * start queue filling. * * @param[in] iqp pointer to an @p InputQueue structure * @param[in] time the number of ticks before the operation timeouts, @@ -192,8 +197,9 @@ msg_t chIQGetTimeout(InputQueue *iqp, systime_t time) { * 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 queue callback is invoked before entering a sleep state and at - * the end of the transfer. + * @note The callback is invoked if the queue is empty before entering the + * @p THD_STATE_WTQUEUE state in order to solicit the low level to + * start queue filling. * * @param[in] iqp pointer to an @p InputQueue structure * @param[out] bp pointer to the data buffer @@ -220,6 +226,7 @@ size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp, while (chIQIsEmptyI(iqp)) { if (nfy) nfy(iqp); + if (qwait((GenericQueue *)iqp, time) != Q_OK) { chSysUnlock(); return r; @@ -230,15 +237,12 @@ size_t chIQReadTimeout(InputQueue *iqp, uint8_t *bp, *bp++ = *iqp->q_rdptr++; if (iqp->q_rdptr >= iqp->q_top) iqp->q_rdptr = iqp->q_buffer; + chSysUnlock(); /* Gives a preemption chance in a controlled point.*/ r++; - if (--n == 0) { - chSysLock(); - if (nfy) - nfy(iqp); - chSysUnlock(); + if (--n == 0) return r; - } + chSysLock(); } } @@ -291,6 +295,8 @@ void chOQResetI(OutputQueue *oqp) { * @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 OutputQueue structure * @param[in] b the byte value to be written in the queue @@ -350,8 +356,10 @@ msg_t chOQGetI(OutputQueue *oqp) { b = *oqp->q_rdptr++; if (oqp->q_rdptr >= oqp->q_top) oqp->q_rdptr = oqp->q_buffer; + if (notempty(&oqp->q_waiting)) chSchReadyI(fifo_remove(&oqp->q_waiting))->p_u.rdymsg = Q_OK; + return b; } @@ -363,8 +371,8 @@ msg_t chOQGetI(OutputQueue *oqp) { * 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 queue callback is invoked before entering a sleep state and at - * the end of the transfer. + * @note The callback is invoked after writing each character into the + * buffer. * * @param[in] oqp pointer to an @p OutputQueue structure * @param[out] bp pointer to the data buffer @@ -389,8 +397,6 @@ size_t chOQWriteTimeout(OutputQueue *oqp, const uint8_t *bp, chSysLock(); while (TRUE) { while (chOQIsFullI(oqp)) { - if (nfy) - nfy(oqp); if (qwait((GenericQueue *)oqp, time) != Q_OK) { chSysUnlock(); return w; @@ -400,15 +406,14 @@ size_t chOQWriteTimeout(OutputQueue *oqp, const uint8_t *bp, *oqp->q_wrptr++ = *bp++; if (oqp->q_wrptr >= oqp->q_top) oqp->q_wrptr = oqp->q_buffer; + + if (nfy) + nfy(oqp); + chSysUnlock(); /* Gives a preemption chance in a controlled point.*/ w++; - if (--n == 0) { - chSysLock(); - if (nfy) - nfy(oqp); - chSysUnlock(); + if (--n == 0) return w; - } chSysLock(); } } diff --git a/readme.txt b/readme.txt index b8e11b162..03541aa30 100644 --- a/readme.txt +++ b/readme.txt @@ -95,6 +95,8 @@ reimplemented as a port-specific option. - CHANGE: chiQGetFullI() and chOQGetFullI() become macros. The queues subsystem has been optimized and is no more dependent on semaphores. + Note that the queues callbacks invocation policy has been slightly + changed, see the documentation. *** 2.3.2 *** - FIX: Fixed invalid BRR() macro in AVR serial driver (bug 3299306)(backported