Beispiel #1
0
// Called from TX interrupt. Read from transmit message queue and 
// output byte by byte to the transmit buffer
void receiveDataFromISR() {
    BaseType_t xTaskWokenByReceive = pdFALSE;
    char readChar;

    // Temporarily disable the transmit interrupt
    PLIB_INT_SourceDisable(INT_ID_0, INT_SOURCE_USART_1_TRANSMIT);
        
    // While the queue has available messages, read bytes and transmit
    while (uxQueueMessagesWaitingFromISR(sendData.transmitQ_CD) != 0){
        while (xQueueReceiveFromISR(sendData.transmitQ_CD, (void *) &readChar, &xTaskWokenByReceive) ) 
        {
            // A character was received.  Transmit the character now.
            if (sendData.testCount % BREAK_MESSAGE_DIV != 2) // Error simulation constant (missing byte)
                PLIB_USART_TransmitterByteSend(USART_ID_1, readChar);
            
            // Duplicate data error simulation constant
            if (sendData.testCount % ADD_MESSAGE_DIV == 1)
                PLIB_USART_TransmitterByteSend(USART_ID_1, readChar);
            
            // If removing the character from the queue woke the task that was
            // posting onto the queue cTaskWokenByReceive will have been set to
            // pdTRUE.  No matter how many times this loop iterates only one
            // task will be woken.
            sendData.testCount++;
        }
    }
}
Beispiel #2
0
/*******************************************************************************
  Function:
    bool WriteString (void)

  Summary:
    Writes a string to the console
*/
bool WriteString(void)
{
    if(*appData.stringPointer == '\0')
    {
        return true;
    }

    /* Write a character at a time, only if transmitter is empty */
    while (PLIB_USART_TransmitterIsEmpty(USART_ID_2))
    {
       int i=0;
 	/* Send measured values */
	for(i0;i<10;i++)
	{
        	PLIB_USART_TransmitterByteSend(USART_ID_2, *appData.stringPointer);

       		 /* Increment to address of next character */
        	appData.stringPointer++;
	}
       // if(*appData.stringPointer == '\0')
      //  {
       //     return true;
       // }
    }
    return true;
}
void DRV_USART0_WriteByte(const uint8_t byte)
{
   while(PLIB_USART_TransmitterBufferIsFull(USART_ID_1))
   {
   }

   PLIB_USART_TransmitterByteSend(USART_ID_1, byte);
}
Beispiel #4
0
/*******************************************************************************
  Function:
    bool PutCharacter (const char character)

  Summary:
    Sends a character to the console
*/
bool PutCharacter(const char character)
{
    /* Check if buffer is empty for a new transmission */
    if(PLIB_USART_TransmitterIsEmpty(USART_ID_2))
    {
        /* Send character */
        PLIB_USART_TransmitterByteSend(USART_ID_2, character);
        return true;
    }
    else
        return false;
}
Beispiel #5
0
bool STIMULUS_USART_DRV_PutCharacter(const char character)
{
    /* Check if buffer is empty for a new transmission */
    if(PLIB_USART_TransmitterIsEmpty(configData->usartId))
    {
        /* Send character */
        PLIB_USART_TransmitterByteSend(configData->usartId, character);
        return true;
    }
    else
    {
        return false;
    }
}
Beispiel #6
0
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
    {
        
    }
}
Beispiel #7
0
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();
}
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 = NULL;
    DRV_USART_BUFFER_OBJ * 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)
    {
        return;
    }

    *bufferHandle = DRV_USART_BUFFER_HANDLE_INVALID;

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

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

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

    hDriver = clientObj->hDriver;

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

        SYS_ASSERT(false, "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. 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->txInterruptSource);
        }
        if(hDriver->interruptNestingCount == 0)
        {
            /* Release mutex */
            OSAL_MUTEX_Unlock(&(hDriver->mutexDriverInstance));
        }

        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;

        /* Because this is the first buffer in the queue, we need to send the
         first byte so that we trigger the transmit interrupt generation. The
         rest of the buffer then gets processed in the task routine, which
         may or may not be called from the interrupt service routine. */

        /* Check if TX FIFO is full before sending a byte even though it is a
         first buffer in the queue, because FIFO may be full when using 
         Read/Write model along with the Buffer queue model */

        while(PLIB_USART_TransmitterBufferIsFull(hDriver->moduleId));
        bufferObj->nCurrentBytes ++;
        PLIB_USART_TransmitterByteSend(hDriver->moduleId, bufferObj->buffer[0]);

        /* If the driver is configured for interrupt mode, then the following
         statement should enable the interrupt. */

        _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);
        }

    }
    if(hDriver->interruptNestingCount == 0)
    {
        /* Release mutex */
        OSAL_MUTEX_Unlock(&(hDriver->mutexDriverInstance));
    }
    return;
}
size_t DRV_USART_Write(DRV_HANDLE hClient, void * source, size_t nBytes)
{
    DRV_USART_CLIENT_OBJ * clientObj;
    DRV_USART_OBJ * hDriver;
    DRV_USART_BUFFER_OBJ * iterator, * bufferObj;
    USART_MODULE_ID plibID;
    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_WRITE))
    {
        /* This client did not open the driver for
           writing */
        SYS_DEBUG(0, "Driver not opened for write");
        return 0;
    }

    if((source == 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 *)source;

    /* Grab the write 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->txInterruptSource);

            /* Get the queue head */

            iterator = hDriver->queueWrite;

            /* If the queue is not empty, then 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 = source;
            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->queueWrite == NULL)
            {
                hDriver->queueWrite = 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->txInterruptSource);
            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->semWriteDone, 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_WRITE_ERROR);
                }
                     
                count = nBytes;
            }
        }
        else if(clientObj->ioIntent & DRV_IO_INTENT_NONBLOCKING)
        {
            /* This is a non blocking implementation*/

            if(hDriver->queueWrite != NULL)
            {
                /* This means queue is not empty. We cannot send
                   data now. */
                count = 0;
            }
            else
            {
                while((!PLIB_USART_TransmitterBufferIsFull(plibID)) &&
                        (count < nBytes))
                {
                    /* This is not a blocking implementation. We write
                       to the hardware till the FIFO is full. */

                    PLIB_USART_TransmitterByteSend(plibID, data[count]);
                    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 driver instance mutex");
                        return(DRV_USART_WRITE_ERROR);
                    }
                }
            }
        }

        /* Release mutex */
        OSAL_ASSERT((OSAL_MUTEX_Unlock(hDriver->mutexDriverInstance)),
                "Unable to unlock driver instance mutex");
    }
    else
    {
        /* Write mutex timed out. Set the return count to zero. */
        count = 0;
    }

    return(count);
}
Beispiel #10
0
void _DRV_USART_BufferQueueTxTasks(DRV_USART_OBJ * hDriver)
{
    /* Start by getting the buffer at the head of queue. */

    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))
        {
            /* 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;
        }
    }

    if(bufferObj != NULL)
    {
        /* This means the queue is not empty. 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))
            {
                /* Before calling the event handler, the interrupt nesting
                   counter is incremented. This will allow driver routine that
                   are called from the event handler to know the interrupt
                   nesting level. Events are only generated for buffers that
                   were submitted using the buffer add routine */

                hDriver->interruptNestingCount ++;

                client->eventHandler(DRV_USART_BUFFER_EVENT_COMPLETE,
                        (DRV_USART_BUFFER_HANDLE)bufferObj,
                        client->context);

                /* Decrement the nesting count */
                hDriver->interruptNestingCount -- ;
            }
           
            /* Get the next buffer in the queue and deallocate
             * this buffer */
           
            hDriver->queueWrite = bufferObj->next;
            bufferObj->inUse = false;
            hDriver->queueSizeCurrentWrite --;
           
            if(bufferObj->flags & DRV_USART_BUFFER_OBJ_FLAG_READ_WRITE)
            {
                /* This means we should post the semaphore */
                OSAL_ASSERT(_DRV_USART_SEM_POST(client->semWriteDone) == OSAL_RESULT_TRUE,
                        "Unable to post write buffer queue empty semaphore");

            }
        }
    }

    /* Check if the queue is still not empty and process
       the buffer */

    if(hDriver->queueWrite != NULL)
    {
        bufferObj = hDriver->queueWrite;

        /* Fill up the FIFO with data till the FIFO is full
           and we have data to send */
        while((!PLIB_USART_TransmitterBufferIsFull(plibID))
                && (bufferObj->nCurrentBytes < bufferObj->size ))
        {
            PLIB_USART_TransmitterByteSend(plibID, bufferObj->buffer[bufferObj->nCurrentBytes]);
            bufferObj->nCurrentBytes ++;
        }
    }
    else 
    {
        /* If the queue is empty, then disable the TX interrupt */
        status = _DRV_USART_InterruptSourceDisable(hDriver->txInterruptSource);
    }
    
    /* Release the mutex */
    OSAL_ASSERT(_DRV_USART_RELEASE_MUTEX(hDriver->mutexDriverInstance),
                            "Unable to release Hardware Instance Mutex");
  
}
Beispiel #11
0
// called by printf
void _mon_putc (char c)
{
    while (!PLIB_USART_TransmitterIsEmpty(APP_DEBUG_USART_ID));
    PLIB_USART_TransmitterByteSend(APP_DEBUG_USART_ID, c);;
}