DRV_USART_TRANSFER_STATUS DRV_USART_TransferStatus(const DRV_HANDLE handle) { DRV_USART_CLIENT_OBJ * client; DRV_USART_OBJ * hDriver; DRV_USART_TRANSFER_STATUS result = 0; client = _DRV_USART_DriverHandleValidate(handle); /* Validate the handle */ if(client == NULL) { SYS_DEBUG(0, "Invalid Driver handle"); return 0; } hDriver = client->hDriver; /* If the Rx interrupt flag is set then there is data available else there isn't */ result |= (SYS_INT_SourceStatusGet(hDriver->rxInterruptSource)) ? DRV_USART_TRANSFER_STATUS_RECEIVER_DATA_PRESENT : DRV_USART_TRANSFER_STATUS_RECEIVER_EMPTY; /* If the TX interrupt flag is set, then the Tx Buffer is empty */ result |= (SYS_INT_SourceStatusGet(hDriver->txInterruptSource)) ? DRV_USART_TRANSFER_STATUS_TRANSMIT_EMPTY : 0; /* Check if the TX buffer is full */ result |= (PLIB_USART_TransmitterBufferIsFull(hDriver->moduleId)) ? DRV_USART_TRANSFER_STATUS_TRANSMIT_FULL : 0; return(result); }
DRV_USART_BAUD_SET_RESULT DRV_USART_BaudSet(DRV_HANDLE handle, uint32_t baud) { DRV_USART_OBJ * hDriver; DRV_USART_CLIENT_OBJ * client; USART_MODULE_ID plibID; /* Validate the handle */ client = _DRV_USART_DriverHandleValidate(handle); if(client == NULL) { /* Driver handle is not valid. Return error */ SYS_DEBUG(0, "Invalid client handle"); return DRV_USART_BAUD_SET_ERROR; } hDriver = (DRV_USART_OBJ*)client->hDriver; plibID = hDriver->moduleId; if(OSAL_MUTEX_Lock(hDriver->mutexDriverInstance, OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE) { /* Set the baud rate */ PLIB_USART_BaudRateSet(plibID, hDriver->brgClock, baud); } else { /* The mutex timed out */ SYS_DEBUG(0, "Hardware instance mutex time out in DRV_USART_BaudSet() function"); return(DRV_USART_BAUD_SET_ERROR); } /* Return success */ return(DRV_USART_BAUD_SET_SUCCESS); }
void DRV_USART_Close ( DRV_HANDLE handle) { /* This function closes the client, The client object is de-allocated and returned to the pool. */ DRV_USART_CLIENT_OBJ * clientObj; DRV_USART_OBJ * dObj; /* Validate the handle */ clientObj = _DRV_USART_DriverHandleValidate(handle); if(clientObj == NULL) { /* Driver handle is not valid */ SYS_DEBUG(0, "Invalid Driver Handle"); return; } dObj = (DRV_USART_OBJ *)clientObj->hDriver; /* Remove all buffers that this client owns from the driver queue. This function will map to _DRV_USART_ClientBufferQueueObjectsRemove() if the driver was built for buffer queue support. Else this condition always maps to true. */ if(!_DRV_USART_CLIENT_BUFFER_QUEUE_OBJECTS_REMOVE(clientObj)) { /* The function could fail if the mutex time out occurred */ SYS_DEBUG(0, "Could not remove client buffer objects"); clientObj->status = DRV_USART_CLIENT_STATUS_ERROR; return; } /* Deallocate all semaphores */ OSAL_ASSERT((OSAL_SEM_Delete(&(clientObj->semWriteDone)) == OSAL_RESULT_TRUE), "Unable to delete client write done semaphore"); OSAL_ASSERT((OSAL_SEM_Delete(&(clientObj->semReadDone)) == OSAL_RESULT_TRUE), "Unable to delete client read done semaphore"); /* Reduce the number of clients */ dObj->nClients --; /* De-allocate the object */ clientObj->status = DRV_USART_CLIENT_STATUS_CLOSED; clientObj->inUse = false; return; }
DRV_USART_CLIENT_STATUS DRV_USART_ClientStatus(DRV_HANDLE handle) { DRV_USART_CLIENT_OBJ * client; /* Validate the driver handle */ client = _DRV_USART_DriverHandleValidate(handle); if(client == NULL) { /* Driver handle is not valid */ SYS_DEBUG(0, "Invalid driver handle"); return DRV_USART_CLIENT_STATUS_CLOSED; } /* Return the client status */ return(client->status); }
DRV_USART_ERROR DRV_USART_ErrorGet(DRV_HANDLE hClient) { DRV_USART_CLIENT_OBJ * clientObj; DRV_USART_ERROR error; /* Validate the handle */ clientObj = _DRV_USART_DriverHandleValidate(hClient); if(clientObj == NULL) { /* Driver handle is not valid. Return error */ SYS_DEBUG(0, "Invalid client handle"); return DRV_USART_BAUD_SET_ERROR; } /* Return the error. Clear the error before returning. */ error = clientObj->error; clientObj->error = DRV_USART_ERROR_NONE; return(error); }
DRV_USART_LINE_CONTROL_SET_RESULT DRV_USART_LineControlSet ( DRV_HANDLE handle, DRV_USART_LINE_CONTROL lineControlMode ) { DRV_USART_OBJ * hDriver; DRV_USART_CLIENT_OBJ * client; USART_MODULE_ID plibID; /* Validate the driver handle */ client = _DRV_USART_DriverHandleValidate(handle); if(client == NULL) { /* Driver handle is not valid. Return error */ SYS_DEBUG(0, "Invalid driver handle"); return DRV_USART_LINE_CONTROL_SET_ERROR; } hDriver = (DRV_USART_OBJ*)client->hDriver; plibID = hDriver->moduleId; if(OSAL_MUTEX_Lock(hDriver->mutexDriverInstance, OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE) { /* Set the Line Control Mode */ PLIB_USART_LineControlModeSelect(plibID, lineControlMode); } else { SYS_DEBUG(0, "Hardware Instance Mutex time out in DRV_USART_LineControlSet() function"); return DRV_USART_LINE_CONTROL_SET_ERROR; } /* Return success */ return(DRV_USART_LINE_CONTROL_SET_SUCCESS); }
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; }