From d094e348c5d1a3785289c69c5185bbaca1257de8 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 11 Jun 2012 16:54:35 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@4266 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/src/serial.c | 4 +- os/hal/src/serial_usb.c | 115 ++++++++++++++++++++---------------------------- 2 files changed, 49 insertions(+), 70 deletions(-) (limited to 'os/hal/src') diff --git a/os/hal/src/serial.c b/os/hal/src/serial.c index 3f06025c6..5b883e16a 100644 --- a/os/hal/src/serial.c +++ b/os/hal/src/serial.c @@ -149,8 +149,8 @@ void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify) { chEvtInit(&sdp->event); sdp->flags = CHN_NO_ERROR; sdp->state = SD_STOP; - chIQInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, inotify); - chOQInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify); + chIQInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, inotify, sdp); + chOQInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify, sdp); } /** diff --git a/os/hal/src/serial_usb.c b/os/hal/src/serial_usb.c index 7f1658812..5fec52a68 100644 --- a/os/hal/src/serial_usb.c +++ b/os/hal/src/serial_usb.c @@ -117,59 +117,47 @@ static const struct SerialUSBDriverVMT vmt = { * @brief Notification of data removed from the input queue. */ static void inotify(GenericQueue *qp) { - SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_wrptr; + size_t n, maxsize; + SerialUSBDriver *sdup = chQGetLink(qp); -#if 0 - /* Writes to the input queue can only happen when the queue has been - emptied, then a whole packet is loaded in the queue.*/ + /* If there is in the queue enough space to hold at least one packet and + a transaction is not yet started then a new transaction is started for + the available space.*/ + maxsize = sdup->config->usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize; if (!usbGetReceiveStatusI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP) && - chIQIsEmptyI(&sdup->iqueue)) { + ((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize)) { chSysUnlock(); - /* Unlocked to make the potentially long read operation preemptable.*/ - size_t n = usbReadPacketBuffer(sdup->config->usbp, - USB_CDC_DATA_AVAILABLE_EP, - sdup->iqueue.q_buffer, - SERIAL_USB_BUFFERS_SIZE); + n = (n / maxsize) * maxsize; + usbPrepareQueuedReceive(sdup->config->usbp, + USB_CDC_DATA_AVAILABLE_EP, + &sdup->iqueue, n); chSysLock(); usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP); - chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE); - sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; - sdup->iqueue.q_counter = n; - while (notempty(&sdup->iqueue.q_waiting)) - chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; } -#endif } /** * @brief Notification of data inserted into the output queue. */ static void onotify(GenericQueue *qp) { - SerialUSBDriver *sdup = (SerialUSBDriver *)qp->q_rdptr; size_t n; + SerialUSBDriver *sdup = chQGetLink(qp); -#if 0 - /* If there is any data in the output queue then it is sent within a - single packet and the queue is emptied.*/ - n = chOQGetFullI(&sdup->oqueue); - if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP)) { + /* If there is not an ongoing transaction and the output queue contains + data then a new transaction is started.*/ + if (!usbGetTransmitStatusI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP) && + ((n = chOQGetFullI(&sdup->oqueue)) > 0)) { chSysUnlock(); - /* Unlocked to make the potentially long write operation preemptable.*/ - usbWritePacketBuffer(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP, - sdup->oqueue.q_buffer, n); + usbPrepareQueuedTransmit(sdup->config->usbp, + USB_CDC_DATA_REQUEST_EP, + &sdup->oqueue, n); chSysLock(); usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP); - chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY); - sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; - 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; } -#endif } /*===========================================================================*/ @@ -201,12 +189,8 @@ void sduObjectInit(SerialUSBDriver *sdup) { chEvtInit(&sdup->event); sdup->flags = CHN_NO_ERROR; sdup->state = SDU_STOP; - chIQInit(&sdup->iqueue, sdup->ib, SERIAL_USB_BUFFERS_SIZE, inotify); - chOQInit(&sdup->oqueue, sdup->ob, SERIAL_USB_BUFFERS_SIZE, onotify); - /* This is a dirty trick but those pointers are never used because queues - are accessed in block mode from the low level.*/ - sdup->iqueue.q_wrptr = (uint8_t *)sdup; - sdup->oqueue.q_rdptr = (uint8_t *)sdup; + chIQInit(&sdup->iqueue, sdup->ib, SERIAL_USB_BUFFERS_SIZE, inotify, sdup); + chOQInit(&sdup->oqueue, sdup->ob, SERIAL_USB_BUFFERS_SIZE, onotify, sdup); } /** @@ -299,32 +283,28 @@ bool_t sduRequestsHook(USBDriver *usbp) { * @param[in] ep endpoint number */ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { - SerialUSBDriver *sdup = usbp->param; size_t n; + SerialUSBDriver *sdup = usbp->param; + + (void)ep; -#if 0 + chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY); chSysLockFromIsr(); - /* If there is any data in the output queue then it is sent within a - single packet and the queue is emptied.*/ - n = chOQGetFullI(&sdup->oqueue); - if (n > 0) { + + if ((n = chOQGetFullI(&sdup->oqueue)) > 0) { /* The endpoint cannot be busy, we are in the context of the callback, so it is safe to transmit without a check.*/ chSysUnlockFromIsr(); - /* Unlocked to make the potentially long write operation preemptable.*/ - usbWritePacketBuffer(usbp, ep, sdup->oqueue.q_buffer, n); + usbPrepareQueuedTransmit(sdup->config->usbp, + USB_CDC_DATA_REQUEST_EP, + &sdup->oqueue, n); chSysLockFromIsr(); - usbStartTransmitI(usbp, ep); - chnAddFlagsI(sdup, CHN_OUTPUT_EMPTY); - sdup->oqueue.q_wrptr = sdup->oqueue.q_buffer; - 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; + usbStartTransmitI(sdup->config->usbp, USB_CDC_DATA_REQUEST_EP); } + chSysUnlockFromIsr(); -#endif } /** @@ -336,33 +316,32 @@ void sduDataTransmitted(USBDriver *usbp, usbep_t ep) { * @param[in] ep endpoint number */ void sduDataReceived(USBDriver *usbp, usbep_t ep) { + size_t n, maxsize; SerialUSBDriver *sdup = usbp->param; -#if 0 + (void)ep; + + chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE); chSysLockFromIsr(); - /* Writes to the input queue can only happen when the queue has been - emptied, then a whole packet is loaded in the queue.*/ - if (chIQIsEmptyI(&sdup->iqueue)) { + + /* Writes to the input queue can only happen when there is enough space + to hold at least one packet.*/ + maxsize = sdup->config->usbp->epc[USB_CDC_DATA_AVAILABLE_EP]->out_maxsize; + if ((n = chIQGetEmptyI(&sdup->iqueue)) >= maxsize) { /* The endpoint cannot be busy, we are in the context of the callback, so a packet is in the buffer for sure.*/ - size_t n; - chSysUnlockFromIsr(); - /* Unlocked to make the potentially long write operation preemptable.*/ - n = usbReadPacketBuffer(usbp, ep, sdup->iqueue.q_buffer, - SERIAL_USB_BUFFERS_SIZE); + n = (n / maxsize) * maxsize; + usbPrepareQueuedReceive(sdup->config->usbp, + USB_CDC_DATA_AVAILABLE_EP, + &sdup->iqueue, n); chSysLockFromIsr(); - usbStartReceiveI(usbp, ep); - chnAddFlagsI(sdup, CHN_INPUT_AVAILABLE); - sdup->iqueue.q_rdptr = sdup->iqueue.q_buffer; - sdup->iqueue.q_counter = n; - while (notempty(&sdup->iqueue.q_waiting)) - chSchReadyI(fifo_remove(&sdup->iqueue.q_waiting))->p_u.rdymsg = Q_OK; + usbStartReceiveI(sdup->config->usbp, USB_CDC_DATA_AVAILABLE_EP); } + chSysUnlockFromIsr(); -#endif } /** -- cgit v1.2.3