void DRV_USART_BufferAddRead
(
    DRV_HANDLE hClient,
    DRV_USART_BUFFER_HANDLE * bufferHandle,
    void * destination,
    size_t nBytes
)
{
    DRV_USART_CLIENT_OBJ * clientObj;
    DRV_USART_OBJ * hDriver;
    bool interruptWasEnabled = false;
    DRV_USART_BUFFER_OBJ * bufferObj = NULL;
    DRV_USART_BUFFER_OBJ * iterator;
    unsigned int i;

    /* This function adds a buffer to the read queue */

    /* We first check the arguments and initialize the
       buffer handle */

    if(bufferHandle == NULL)
    {
        return;
    }

    *bufferHandle = DRV_USART_BUFFER_HANDLE_INVALID;

    clientObj = _DRV_USART_DriverHandleValidate(hClient);

    if(clientObj == NULL)
    {
        SYS_ASSERT(false, "Invalid driver handle");
        return;
    }

    if((nBytes == 0) || (NULL == destination))
    {
        /* We either got an invalid client handle,
           invalid destination pointer or 0 bytes to
           transfer */

        SYS_ASSERT(false, "Invalid parameters");
        return;
    }

    hDriver = clientObj->hDriver;

    if(hDriver->queueSizeCurrentRead >= hDriver->queueSizeRead)
    {
        /* This means the queue is full. We cannot add
         * this request */

        //SYS_ASSERT(false, "Receive Queue is full");
        return;
    }

    /* We will allow buffers to be added in the interrupt
     * context of this USART driver. But we must make
     * sure that if we are in interrupt, then we should
     * not modify mutexes. */

    if(hDriver->interruptNestingCount == 0)
    {
        /* Grab a mutex. This is okay because we are not in an
         * interrupt context */

        if(OSAL_MUTEX_Lock(&(hDriver->mutexDriverInstance), OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE)
        {
            /* We will disable interrupts so that the queue
             * status does not get updated asynchronously.
             * This code will always execute. */

            interruptWasEnabled = _DRV_USART_InterruptSourceDisable(hDriver->rxInterruptSource);
        }
        else
        {
            /* The mutex acquisition timed out. Return with an
             * invalid handle. This code will not execute
             * if there is no RTOS. */
            return;
        }
    }

    /* Search the buffer pool for a free buffer object */
    for(i = 0 ; i < DRV_USART_QUEUE_DEPTH_COMBINED; i ++)
    {
        if(!gDrvUSARTBufferObj[i].inUse)
        {
            /* This means this object is free.
             * Configure the object and then
             * break */
            bufferObj = &gDrvUSARTBufferObj[i];
            bufferObj->size     = nBytes;
            bufferObj->inUse    = true;
            bufferObj->buffer   = (uint8_t*)destination;
            bufferObj->hClient  = clientObj;
            bufferObj->next     = NULL;
            bufferObj->previous = NULL;
            bufferObj->nCurrentBytes = 0;
            bufferObj->flags = (0 | DRV_USART_BUFFER_OBJ_FLAG_BUFFER_ADD);

            /* Assign a handle to this buffer. The buffer handle must be unique.
             * To do this, we construct the buffer handle out of the
             * gDrvUSARTTokenCount and allocated buffer index. Note that
             * gDrvUSARTTokenCount is incremented and wrapped around when the
             * value reaches OxFFFF. We do avoid a case where the token value
             * becomes 0xFFFF and the buffer index also becomes 0xFFFF */

            bufferObj->bufferHandle = _DRV_USART_MAKE_HANDLE(gDrvUSARTTokenCount, i);
            *bufferHandle = bufferObj->bufferHandle;

            /* Update the token number. */
            _DRV_USART_UPDATE_BUFFER_TOKEN(gDrvUSARTTokenCount);
            break;
        }
    }

    if(i == DRV_USART_QUEUE_DEPTH_COMBINED)
    {
        /* This means we could not find a buffer. This
           will happen if the the DRV_USART_QUEUE_DEPTH_COMBINED
           parameter is configured to be less */

        SYS_ASSERT(false, "Insufficient Combined Queue Depth");

        /* Enable the interrupt if it was enabled */
        if(interruptWasEnabled)
        {
            _DRV_USART_InterruptSourceEnable(hDriver->rxInterruptSource);
        }

        if(hDriver->interruptNestingCount == 0)
        {
            /* Release mutex */
            OSAL_MUTEX_Unlock(&(hDriver->mutexDriverInstance));
        }

        return;
    }

    /* Increment the current queue size*/
    hDriver->queueSizeCurrentRead ++;

    /* Check if the queue is empty */
    if(hDriver->queueRead == NULL)
    {
        /* This is the first buffer in the
           queue */

        hDriver->queueRead = bufferObj;

        /* This is the first item in the queue. Enable
           RX interrupt. */

        _DRV_USART_InterruptSourceEnable(hDriver->rxInterruptSource);

    }
    else
    {
        /* This means the read queue is not empty. We must add
           the buffer object to the end of the queue */

        iterator = hDriver->queueRead;
        while(iterator->next != NULL)
        {
            /* Get the next buffer object */
            iterator = iterator->next;
        }

        /* At this point, iterator will point to the
           last object in the queue. We add the buffer
           object to the linked list. Note that we
           need to set up the previous pointer as well
           because buffer should be deleted when the
           client closes the driver */

        iterator->next = bufferObj;
        bufferObj->previous = iterator;

        /* We are done. Restore the interrupt enable status
           and return. */

        if(interruptWasEnabled)
        {
            _DRV_USART_InterruptSourceEnable(hDriver->rxInterruptSource);
        }

    }
    if(hDriver->interruptNestingCount == 0)
    {
        /* Release mutex */
        OSAL_MUTEX_Unlock(&(hDriver->mutexDriverInstance));
    }
    return;
}
size_t DRV_USART_Read(const DRV_HANDLE hClient, void * destination, size_t nBytes)
{
    DRV_USART_CLIENT_OBJ * clientObj;
    DRV_USART_OBJ * hDriver;
    USART_MODULE_ID plibID;
    DRV_USART_BUFFER_OBJ * iterator, * bufferObj;
    size_t count = 0;
    uint8_t * data;
    bool status;

    /* Validate the driver handle */

    clientObj = _DRV_USART_DriverHandleValidate(hClient);
    if(clientObj == NULL)
    {
        SYS_DEBUG(0, "Invalid driver handle");
        return 0;
    }

    hDriver = (DRV_USART_OBJ *)clientObj->hDriver;
    plibID = hDriver->moduleId;

    if(!(clientObj->ioIntent & DRV_IO_INTENT_READ))
    {
        /* This client did not open the driver for
           reading */
        SYS_DEBUG(0, "Driver not opened for read");
        return 0;
    }

    if((destination == NULL) || (nBytes == 0))
    {
        /* We have a NULL pointer or dont have
           any data to write. */

        SYS_DEBUG(0, "NULL data pointer or no data to write");
        return 0;
    }

    data = (uint8_t *)destination;

    /* Grab he hardware instance mutex */

    if(OSAL_MUTEX_Lock(hDriver->mutexDriverInstance, OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE)
    {
        if(!(clientObj->ioIntent & DRV_IO_INTENT_NONBLOCKING))
        {
            /* This is a blocking implementation. We populate the client buffer
               object and add it to the queue. We then wait till the buffer is
               completely processed. */

            /* Because we are modifying the queue, we should disable the
               interrupt */

            status = _DRV_USART_InterruptSourceDisable(hDriver->rxInterruptSource);

            /* Get the queue head */

            iterator = hDriver->queueRead;

            /* If the queue is not empty, get to the end of the queue */

            if(iterator != NULL)
            {
                while(iterator->next != NULL)
                {
                    iterator = iterator->next;
                }
            }

            /* We should be at the end of the queue now. Populate the client
               buffer object */

            bufferObj = &clientObj->bufferObject;
            bufferObj->buffer = destination;
            bufferObj->nCurrentBytes = 0;
            bufferObj->size = nBytes;
            bufferObj->inUse = true;
            bufferObj->hClient = clientObj;
            bufferObj->flags = (0 | DRV_USART_BUFFER_OBJ_FLAG_READ_WRITE);

            /* Add this object to the queue and enable the RX interrupt */

            bufferObj->previous = iterator;
            bufferObj->next = NULL;

            /* If we are not at the start of the queue, then update the next
               pointer of the last object else set the queue head to point to
               this object */

            if(hDriver->queueRead == NULL)
            {
                hDriver->queueRead = bufferObj;
            }
            else
            {
                iterator->next = bufferObj;
                bufferObj->previous = iterator;
            }

            /* Now enable the interrupt and release the mutex so that the system
               can proceed */

            _DRV_USART_InterruptSourceEnable(hDriver->rxInterruptSource);
            OSAL_ASSERT((OSAL_MUTEX_Unlock(hDriver->mutexDriverInstance)),
                            "Unable to unlock hardware instance mutex");
            
            /* If we are in a bare metal configuration, then wait till the
               buffer is processed. If we are in RTOS configuration then pend on
               the client semaphore. */

            if(OSAL_SEM_Pend(clientObj->semReadDone, OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE)
            {
                /* This is the implementation of the blocking behavior. In a
                   RTOS configuration, if the code reaches here, it means then
                   that buffer has been processed. */ 
                
                while(bufferObj->inUse);
                if(bufferObj->nCurrentBytes != nBytes) 
                {
                    /* This means this buffer was terminated because of an
                       error. */
                    
                    return(DRV_USART_READ_ERROR);
                }
                     
                count = nBytes;
            }
        }
        else if(clientObj->ioIntent & DRV_IO_INTENT_NONBLOCKING)
        {
            /* This is a non blocking implementation*/

            if(hDriver->queueRead != NULL)
            {
                /* This means queue is not empty. We cannot read
                   data now. */
                count = 0;
            }
            else
            {

                while((PLIB_USART_ReceiverDataIsAvailable(plibID)) &&
                        (count < nBytes))
                {
                    /* This is not a blocking implementation. We read
                       the hardware till the FIFO is empty. */

                    data[count] = PLIB_USART_ReceiverByteReceive(plibID);
                    count ++;

                    /* We need to check for errors. Store the error
                       in the client error field. */

                    clientObj->error = PLIB_USART_ErrorsGet(plibID);

                    if(clientObj->error != DRV_USART_ERROR_NONE)
                    {
                        /* This means we have an error. Release the mutex and
                           exit */
                        OSAL_ASSERT((OSAL_MUTEX_Unlock(hDriver->mutexDriverInstance)),
                                "Unable to unlock hardware instance mutex");
                        return(DRV_USART_READ_ERROR);
                    }
                }
            }
        }
    }
    else
    {
        /* Timed out while waiting for read mutex.
         * We simply return 0 */
        count = 0;
    }

    return(count);
}
void DRV_USART_BufferAddRead
(
    DRV_HANDLE hClient,
    DRV_USART_BUFFER_HANDLE * bufferHandle,
    void * destination,
    size_t nBytes
)
{
    DRV_USART_CLIENT_OBJ * clientObj;
    DRV_USART_OBJ * hDriver;
    bool interruptWasEnabled=false;
    DRV_USART_BUFFER_OBJ * bufferObj, * iterator;
    DRV_USART_BUFFER_OBJECT_INDEX usartBufIndex;

    /* This function adds a buffer to the read queue */

    /* We first check the arguments and initialize the
       buffer handle */

    if(bufferHandle == NULL)
    {
        return;
    }

    *bufferHandle = DRV_USART_BUFFER_HANDLE_INVALID;

    clientObj = _DRV_USART_DriverHandleValidate(hClient);

    if(clientObj == NULL)
    {
        SYS_ASSERT(false, "Invalid driver handle");
        return;
    }

    if((nBytes == 0) || (NULL == destination))
    {
        /* We either got an invalid client handle,
           invalid destination pointer or 0 bytes to
           transfer */

        SYS_DEBUG(0, "Invalid parameters");
        return;
    }

    hDriver = clientObj->hDriver;

    if(hDriver->queueSizeCurrentRead >= hDriver->queueSizeRead)
    {
        /* This means the queue is full. We cannot add
         * this request */

        SYS_DEBUG(0, "Receive Queue is full");
        return;
    }

    /* We will allow buffers to be added in the interrupt
     * context of this USART driver. But we must make
     * sure that if we are in interrupt, then we should
     * not modify mutexes. */

    if(hDriver->interruptNestingCount == 0)
    {
        /* Grab a mutex. This is okay because we are not in an
         * interrupt context */

        if(OSAL_MUTEX_Lock(&(hDriver->mutexDriverInstance), OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE)
        {
            /* We will disable interrupts so that the queue
             * status does not get updated asynchronously.
             * This code will always execute. */
            if(SYS_DMA_CHANNEL_HANDLE_INVALID != hDriver->dmaChannelHandleRead)
            {
                interruptWasEnabled = _DRV_USART_InterruptSourceDisable(hDriver->dmaInterruptReceive);
            }
            else
            {
                interruptWasEnabled = _DRV_USART_InterruptSourceDisable(hDriver->rxInterruptSource);
            }

        }
        else
        {
            /* The mutex acquisition timed out. Return with an
             * invalid handle. This code will not execute
             * if there is no RTOS. */
            return;
        }
    }

    usartBufIndex = _DRV_USART_QueueObjectIndexGet();
    if (usartBufIndex != DRV_USART_BUFFER_OBJECT_INDEX_INVALID)
    {
        bufferObj = &gDrvUSARTBufferObj[usartBufIndex];

        bufferObj->bufferHandle = _DRV_USART_DMA_MAKE_HANDLE(gDrvUSARTDMATokenCount, usartBufIndex);
        *bufferHandle = bufferObj->bufferHandle;

        _DRV_USART_DMA_UPDATE_BUFFER_TOKEN(gDrvUSARTDMATokenCount);

        bufferObj->size     = nBytes;
        bufferObj->inUse    = true;
        bufferObj->buffer   = (uint8_t*)destination;
        bufferObj->hClient  = clientObj;
        bufferObj->next     = NULL;
        bufferObj->previous = NULL;
        bufferObj->nCurrentBytes = 0;
        bufferObj->flags = (0 | DRV_USART_BUFFER_OBJ_FLAG_BUFFER_ADD);
    }
    else
    {
        /* This means we could not find a buffer. This
           will happen if the the DRV_USART_QUEUE_DEPTH_COMBINED
           parameter is configured to be less */

        SYS_ASSERT(false, "Insufficient Combined Queue Depth");

        /* Enable the interrupt if it was enabled */
        if(interruptWasEnabled)
        {
            if(SYS_DMA_CHANNEL_HANDLE_INVALID != hDriver->dmaChannelHandleRead)
            {
                _DRV_USART_InterruptSourceEnable(hDriver->dmaInterruptReceive);
            }
            else
            {
                _DRV_USART_InterruptSourceEnable(hDriver->rxInterruptSource);
            }
        }
        /* Release mutex */
        OSAL_MUTEX_Unlock(&(hDriver->mutexDriverInstance));

        return;
    }

    /* Increment the current queue size*/
    hDriver->queueSizeCurrentRead ++;

    /* Check if the queue is empty */
    if(hDriver->queueRead == NULL)
    {
        /* This is the first buffer in the queue */
        hDriver->queueRead = bufferObj;

        /* This is the first item in the queue. Enable RX interrupt. */
        if(SYS_DMA_CHANNEL_HANDLE_INVALID != hDriver->dmaChannelHandleRead)
        {
            /* Since this is the first buffer in the queue Add it immediately
              to DMA for processing */
            size_t srcSize, cellSize;
            srcSize = 1;
            cellSize = 1;
            SYS_DMA_ChannelTransferAdd(hDriver->dmaChannelHandleRead,
                                       PLIB_USART_ReceiverAddressGet(hDriver->moduleId),
                                       srcSize,bufferObj->buffer, bufferObj->size,
                                       cellSize);
            _SYS_DMA_ChannelForceStart(hDriver->dmaChannelHandleRead);
            _DRV_USART_InterruptSourceEnable(hDriver->dmaInterruptReceive);
        }
        else
        {
            _DRV_USART_InterruptSourceEnable(hDriver->rxInterruptSource);
        }
    }
    else
    {
        /* This means the read queue is not empty. We must add
           the buffer object to the end of the queue */

        iterator = hDriver->queueRead;
        while(iterator->next != NULL)
        {
            /* Get the next buffer object */
            iterator = iterator->next;
        }

        /* At this point, iterator will point to the
           last object in the queue. We add the buffer
           object to the linked list. Note that we
           need to set up the previous pointer as well
           because buffer should be deleted when the
           client closes the driver */

        iterator->next = bufferObj;
        bufferObj->previous = iterator;

        /* We are done. Restore the interrupt enable status
           and return. */
        if(interruptWasEnabled)
        {
            if(SYS_DMA_CHANNEL_HANDLE_INVALID != hDriver->dmaChannelHandleRead)
            {
                /* There is already a buffer under processing in the queue.
                   This buffer will be added to DMA for processing immediately
                   after the processing of the buffer prior to this buffer completes.
                   (This functionality is implemented in _DRV_USART_BufferQueueRxTasks)*/
                _SYS_DMA_ChannelForceStart(hDriver->dmaChannelHandleRead);
                _DRV_USART_InterruptSourceEnable(hDriver->dmaInterruptReceive);
            }
            else
            {
                _DRV_USART_InterruptSourceEnable(hDriver->rxInterruptSource);
            }
        }
    }

    /* Release mutex */
    OSAL_MUTEX_Unlock(&(hDriver->mutexDriverInstance));
    return;
}
void DRV_USART_BufferAddWrite
(
    DRV_HANDLE hClient,
    DRV_USART_BUFFER_HANDLE * bufferHandle, 
    void * source,
    size_t nBytes
)
{
    DRV_USART_CLIENT_OBJ * clientObj;
    DRV_USART_OBJ * hDriver;
    bool interruptWasEnabled = false;
    DRV_USART_BUFFER_OBJ * bufferObj, * iterator;
    unsigned int i;

    /* This function adds a buffer to the write queue */

    /* We first check the arguments and initialize the 
       buffer handle */ 

    if(bufferHandle != NULL)
    {
        *bufferHandle = DRV_USART_BUFFER_HANDLE_INVALID;
    }

    /* Validate the driver handle */
    clientObj = _DRV_USART_DriverHandleValidate(hClient);
    if(clientObj == NULL)
    {
        SYS_DEBUG(0, "Invalid Driver Handle");
        return;
    }

    if((nBytes == 0) || (NULL == source) || (bufferHandle == NULL))
    {
        /* We either got an invalid client handle,
           invalid source pointer or 0 bytes to
           transfer */

        SYS_DEBUG(0, "Invalid parameters");
        return;
    }

    hDriver = clientObj->hDriver;

    if(hDriver->queueSizeCurrentWrite >= hDriver->queueSizeWrite)
    {
        /* This means the queue is full. We cannot add
           this request */

        SYS_DEBUG(0, "Transmit Queue is full");
        return;
    }

    /* We will allow buffers to be added in the interrupt
       context of this USART driver. But we must make 
       sure that if we are in interrupt, then we should 
       not modify mutexes. */

    if(hDriver->interruptNestingCount == 0)
    {
        /* Grab a mutex. This is okay because we are not in an
           interrupt context */

        if(OSAL_MUTEX_Lock(hDriver->mutexDriverInstance, OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE)
        {
            /* We will disable interrupts so that the queue
               status does not get updated asynchronously. 
               This code will always execute. */

            interruptWasEnabled = _DRV_USART_InterruptSourceDisable(hDriver->txInterruptSource);
        }
        else
        {
            /* The mutex acquisition timed out. Return with an 
               invalid handle. This code will not execute
               if there is no RTOS. */
            return;
        }
    }

    /* Search the buffer pool for a free buffer object */
    for(i = 0 ; i < DRV_USART_QUEUE_DEPTH_COMBINED; i ++)
    {
        if(!gDrvUSARTBufferObj[i].inUse)
        {
            /* This means this object is free. 
             * Configure the object and then
             * break */
            bufferObj = &gDrvUSARTBufferObj[i];
            bufferObj->size     = nBytes;
            bufferObj->inUse    = true;
            bufferObj->buffer   = (uint8_t*)source;
            bufferObj->hClient  = clientObj;
            bufferObj->nCurrentBytes = 0;
            bufferObj->next = NULL;
            bufferObj->previous = NULL;
            bufferObj->flags = (0 | DRV_USART_BUFFER_OBJ_FLAG_BUFFER_ADD);

            /* Assign a handle to this buffer */
            *bufferHandle = (DRV_USART_BUFFER_HANDLE)bufferObj;
            break;
        }
    }

    if(i == DRV_USART_QUEUE_DEPTH_COMBINED)
    {
        /* This means we could not find a buffer. This
           will happen if the the DRV_USART_QUEUE_DEPTH_COMBINED
           parameter is configured to be less */

        SYS_DEBUG(0, "Insufficient Combined Queue Depth");

        /* Enable the interrupt if it was enabled */
        if(interruptWasEnabled)
        {
            _DRV_USART_InterruptSourceEnable(hDriver->txInterruptSource);
        }

        /* Release mutex */
        OSAL_ASSERT((OSAL_MUTEX_Unlock(hDriver->mutexDriverInstance)),
                "Unable to unlock buffer add write mutex");
        
        return;
    }

    /* Increment the current queue size*/
    hDriver->queueSizeCurrentWrite ++;

    /* Check if the queue is empty */
    if(hDriver->queueWrite == NULL)
    {
        /* This is the first buffer in the
           queue */

        hDriver->queueWrite = bufferObj;
        
        /* Enabling the interrupt here will cause the task
           routine to start processing this buffer. If this
           function is being called in an ISR, then this
           statement will not have any effect. */

        _DRV_USART_InterruptSourceEnable(hDriver->txInterruptSource);
    }
    else
    {
        /* This means the write queue is not empty. We must add
         * the buffer object to the end of the queue */

        iterator = hDriver->queueWrite;
        while(iterator->next != NULL)
        {
            /* Get the next buffer object */
            iterator = iterator->next;
        }

        /* At this point, iterator will point to the
           last object in the queue. We add the buffer
           object to the linked list. Note that we
           need to set up the previous pointer as well
           because buffer should be deleted when the 
           client closes the driver */

        iterator->next = bufferObj;
        bufferObj->previous = iterator;

        /* We are done. Restore the interrupt enable status
           and return. */

        if(interruptWasEnabled)
        {
            _DRV_USART_InterruptSourceEnable(hDriver->txInterruptSource);
        }

    }
    
    /* Release mutex */
    OSAL_ASSERT((OSAL_MUTEX_Unlock(hDriver->mutexDriverInstance)),
            "Unable to unlock buffer add write mutex");
    return;
}
Exemple #5
0
bool _DRV_USART_ClientBufferQueueObjectsRemove(DRV_USART_CLIENT_OBJ * clientObj)
{
    DRV_USART_OBJ * dObj = clientObj->hDriver;
    bool interruptWasEnabled = false;
    DRV_USART_BUFFER_OBJ * iterator = NULL;

    if(OSAL_MUTEX_Lock(dObj->mutexDriverInstance, OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE)
    {
        /* Disable the transmit interrupt */
        interruptWasEnabled = _DRV_USART_InterruptSourceDisable(dObj->txInterruptSource);
        iterator = dObj->queueWrite;
        while(iterator != NULL)
        {
            if(clientObj == (DRV_USART_CLIENT_OBJ *)iterator->hClient)
            {
                /* That means this buffer object is owned
                   by this client. This buffer object should
                   be removed. The following code removes
                   the object from a doubly linked list queue. */

                iterator->inUse = false;
                if(iterator->previous != NULL)
                {
                    iterator->previous->next = iterator->next;
                }
                if(iterator->next != NULL)
                {
                    iterator->next->previous = iterator->previous;
                }
            }
            iterator = iterator->next;
        }

        /* Re-enable the interrupt if it was enabled */
        if(interruptWasEnabled)
        {
            _DRV_USART_InterruptSourceEnable(dObj->txInterruptSource);
        }

        /* Now check the receive buffer queue. Start by disabling the 
           receive interrupt */

        interruptWasEnabled = _DRV_USART_InterruptSourceDisable(dObj->rxInterruptSource);
        iterator = dObj->queueRead;
        while(iterator != NULL)
        {
            if(clientObj == (DRV_USART_CLIENT_OBJ *)iterator->hClient)
            {
                /* That means this buffer object is owned
                   by this client. This buffer object should
                   be removed. The following code removed
                   the object from a doubly linked list queue. */

                iterator->inUse = false;
                if(iterator->previous != NULL)
                {
                    iterator->previous->next = iterator->next;
                }
                if(iterator->next != NULL)
                {
                    iterator->next->previous = iterator->previous;
                }
            }
            iterator = iterator->next;
        }
        
        if(interruptWasEnabled)
        {
            _DRV_USART_InterruptSourceEnable(dObj->rxInterruptSource);
        }
        
        /* Unlock the mutex */

        OSAL_ASSERT((OSAL_MUTEX_Unlock(dObj->mutexDriverInstance)),
                "Unable to unlock Driver instance mutex");
    }
    else
    {
        /* The case where the mutex lock timed out and the
           client buffer objects could not be removed from
           the driver queue, the close function should fail. */

        return false;
    }

    return true;

} 
Exemple #6
0
SYS_MODULE_OBJ DRV_USART_Initialize
(
    const SYS_MODULE_INDEX drvIndex,
    const SYS_MODULE_INIT * const init
)
{
    DRV_USART_OBJ *dObj = (DRV_USART_OBJ*)NULL;
    DRV_USART_INIT *usartInit = NULL ;

    /* Check if the specified driver index is in valid range */
    if(drvIndex >= DRV_USART_INSTANCES_NUMBER)
    {
        SYS_DEBUG(0, "Invalid driver index");
        return SYS_MODULE_OBJ_INVALID;
    }

    /* Check if this hardware instance was already initialized */
    if(gDrvUSARTObj[drvIndex].inUse != false)
    {
        SYS_DEBUG(0, "Instance already in use");
        return SYS_MODULE_OBJ_INVALID;
    }

    /* Assign to the local pointer the init data passed */
    usartInit = ( DRV_USART_INIT * ) init ;

    /* Disable the USART module */
    PLIB_USART_Disable (usartInit->usartID) ;

    /* Allocate the driver object and set the operation flag to be in use */
    dObj = &gDrvUSARTObj[drvIndex];
    dObj->inUse = true;

    /* Update the USART PLIB Id and other parameters. */

    dObj->nClients              = 0;
    dObj->moduleId              = usartInit->usartID;
    dObj->brgClock              = usartInit->brgClock;
    dObj->isExclusive           = false;
    dObj->queueSizeRead         = usartInit->queueSizeReceive;
    dObj->queueSizeWrite        = usartInit->queueSizeTransmit;
    dObj->dmaChannelRead        = usartInit->dmaReceive;
    dObj->dmaChannelWrite       = usartInit->dmaTransmit;
    dObj->txInterruptSource     = usartInit->interruptTransmit;
    dObj->rxInterruptSource     = usartInit->interruptReceive;
    dObj->errorInterruptSource  = usartInit->interruptError;
    dObj->dmaInterruptTransmit  = usartInit->dmaInterruptTransmit;
    dObj->dmaInterruptReceive   = usartInit->dmaInterruptReceive;
    dObj->interruptNestingCount = 0;
    dObj->queueSizeCurrentRead  = 0; 
    dObj->queueSizeCurrentWrite = 0;

    /* Setup the Hardware */
    _DRV_USART_HardwareSetup(usartInit->usartID, usartInit ) ;

    /* Clear the interrupts */
    SYS_INT_SourceStatusClear(dObj->txInterruptSource);
    SYS_INT_SourceStatusClear(dObj->rxInterruptSource);
    SYS_INT_SourceStatusClear(dObj->errorInterruptSource);

    /* Enable the interrupt source in case of interrupt mode */
    _DRV_USART_InterruptSourceEnable(dObj->errorInterruptSource);

    /* TODO: Enable DMA interrupts if the DMA channel is selected */

    /* Create the hardware instance mutex. */
     OSAL_ASSERT((OSAL_MUTEX_Create(&(dObj->mutexDriverInstance)) == OSAL_RESULT_TRUE),
                 "Unable to create hardware instance mutex");


    /* Check if the global mutexes have been created. If not
       then create these. */

     if(!gDrvUSARTCommonDataObj.membersAreInitialized)
     {
         /* This means that mutexes where not created. Create them. */
         OSAL_ASSERT((OSAL_MUTEX_Create(&(gDrvUSARTCommonDataObj.mutexClientObjects)) == OSAL_RESULT_TRUE),
                     "Unable to create client instance mutex");
         OSAL_ASSERT((OSAL_MUTEX_Create(&(gDrvUSARTCommonDataObj.mutexBufferQueueObjects)) == OSAL_RESULT_TRUE),
                     "Unable to create buffer queue objects mutex");

         /* Set this flag so that global mutexes get allocated only once */
         gDrvUSARTCommonDataObj.membersAreInitialized = true;
     }

    /* Enable the USART module */
    PLIB_USART_Enable(usartInit->usartID) ;

    /* Update the status */
    dObj->status = SYS_STATUS_READY;

    /* Return the object structure */
    return ( (SYS_MODULE_OBJ)drvIndex );
}