uint8_t DRV_USART0_ReadByte(void) { if(PLIB_USART_ReceiverOverrunHasOccurred(USART_ID_1)) { PLIB_USART_ReceiverOverrunErrorClear(USART_ID_1); } return (PLIB_USART_ReceiverByteReceive(USART_ID_1)); }
////////////////////////////////// // DN Communications Interrupts // ////////////////////////////////// void __ISR(_UART2_RX_VECTOR, ipl7) _InterruptHandler_RS485_RX(void) { /* Clear the interrupt flag */ PLIB_INT_SourceFlagClear(INT_ID_0, INT_SOURCE_USART_2_RECEIVE); /* Make sure receive buffer has data availible */ if (PLIB_USART_ReceiverDataIsAvailable(USART_ID_2)) { char data; /* Get the data from the buffer */ data = PLIB_USART_ReceiverByteReceive(USART_ID_2); /* Echo what we just received */ PutCharacter(data); } usartIntTriggered = true; }
void STIMULUS_USART_DRV_ReceiveTask() { /* Make sure receive buffer has data available */ if (PLIB_USART_ReceiverDataIsAvailable(configData->usartId)) { if(gStimulusBuffObj.nBytesReceived < gStimulusBuffObj.nBytestoReceive) { /* Get the data from the buffer */ rxStimulusBuff[gStimulusBuffObj.nBytesReceived] = PLIB_USART_ReceiverByteReceive(configData->usartId); gStimulusBuffObj.nBytesReceived++; } else { } if(gStimulusBuffObj.nBytesReceived == gStimulusBuffObj.nBytestoReceive) { Console_Usart_Write_String("Data Rx:"); Console_Usart_Write_Data(&rxStimulusBuff[0],gStimulusBuffObj.nBytesReceived); TestCaseInfo.TCResult = TM_TC_PASS; STIMULUS_Callback(); } else { } } else { } if(!PLIB_USART_TransmitterIsEmpty(configData->usartId)) { /* Send character */ PLIB_USART_TransmitterByteSend(configData->usartId, *gStimulusBuffObj.pTxBuffer); gStimulusBuffObj.pTxBuffer++; } else { } }
void BTSTACK_Tasks(void){ if (bytes_to_read && PLIB_USART_ReceiverDataIsAvailable(BT_USART_ID)) { *rx_buffer_ptr++ = PLIB_USART_ReceiverByteReceive(BT_USART_ID); bytes_to_read--; if (bytes_to_read == 0){ (*rx_done_handler)(); } } if (bytes_to_write && PLIB_USART_TransmitterIsEmpty(BT_USART_ID)){ PLIB_USART_TransmitterByteSend(BT_USART_ID, *tx_buffer_ptr++); bytes_to_write--; if (bytes_to_write == 0){ (*tx_done_handler)(); } } // BTstack Run Loop btstack_run_loop_embedded_execute_once(); }
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_BufferQueueRxTasks(DRV_USART_OBJ * hDriver) { DRV_USART_BUFFER_OBJ * bufferObj; DRV_USART_CLIENT_OBJ * client; USART_MODULE_ID plibID; bool status; bufferObj = hDriver->queueWrite; plibID = hDriver->moduleId; /* If this driver is configured for polled mode in an RTOS, the tasks routine would be called from another thread. We need to get the driver instance mutex before updating the queue. If the driver is configured for interrupt mode, then _DRV_USART_TAKE_MUTEX will compile to true */ if(DRV_USART_INTERRUPT_MODE == false) { if(OSAL_MUTEX_Lock(hDriver->mutexDriverInstance, OSAL_WAIT_FOREVER) == OSAL_RESULT_TRUE) { /* We were able to take the mutex */ } else { /* The mutex acquisition timed out. Return with an invalid handle. This code will not execute if there is no RTOS. */ return; } } /* In this function, the driver checks if there are any buffers in queue. If so the buffer is serviced. A buffer that is serviced completely is removed from the queue. Start by getting the buffer at the head of the queue */ bufferObj = hDriver->queueRead; if(bufferObj != NULL) { /* The USART driver is configured to generate an interrupt when the FIFO is not empty. Additionally the queue is not empty. Which means there is work to done in this routine. Read data from the FIFO till either the FIFO is empty or till we have read the requested number of bytes. */ while((PLIB_USART_ReceiverDataIsAvailable(plibID)) && (bufferObj->nCurrentBytes < bufferObj->size )) { bufferObj->buffer[bufferObj->nCurrentBytes] = PLIB_USART_ReceiverByteReceive(plibID); bufferObj->nCurrentBytes ++; } /* Check if this buffer is done */ if(bufferObj->nCurrentBytes >= bufferObj->size) { /* This means the buffer is completed. If there is a callback registered with client, then call it */ client = (DRV_USART_CLIENT_OBJ *)bufferObj->hClient; if((client->eventHandler != NULL) && (bufferObj->flags & DRV_USART_BUFFER_OBJ_FLAG_BUFFER_ADD)) { /* Call the event handler. We additionally increment the interrupt nesting count which lets the driver functions that are called from the event handler know that an interrupt context is active. */ hDriver->interruptNestingCount ++; client->eventHandler(DRV_USART_BUFFER_EVENT_COMPLETE, (DRV_USART_BUFFER_HANDLE)bufferObj, client->context); hDriver->interruptNestingCount --; } /* Get the next buffer in the queue and deallocate this buffer */ hDriver->queueRead = bufferObj->next; bufferObj->inUse = false; hDriver->queueSizeCurrentRead --; if(bufferObj->flags & DRV_USART_BUFFER_OBJ_FLAG_READ_WRITE) { /* This means we should post the semaphore */ OSAL_ASSERT(_DRV_USART_SEM_POST(client->semReadDone) == OSAL_RESULT_TRUE, "Unable to post write buffer queue empty semaphore"); } } } if(hDriver->queueRead == NULL) { /* The queue is empty. We can disable the interrupt */ status = _DRV_USART_InterruptSourceDisable(hDriver->rxInterruptSource); } /* Release the mutex */ OSAL_ASSERT(_DRV_USART_RELEASE_MUTEX(hDriver->mutexDriverInstance), "Unable to release Hardware Instance Mutex"); }