Пример #1
0
// ---------------------------------------------------------------------------
void USART_IRQHandler(int ComPortNum, int Direction)
{
    LPC_USART_T *usart = USART_REG(ComPortNum);
    char c;

    switch (Direction)
    {
        case 1: // Transmit
            if (USART_RemoveCharFromTxBuffer(ComPortNum, c))
            {
                usart->THR = c;  // Write data
            } else {
                CPU_USART_TxBufferEmptyInterruptEnable(ComPortNum, FALSE); // Disable interrupt
            }
            Events_Set(SYSTEM_EVENT_FLAG_COM_OUT);
            break;

        case 2: // Receive
            c = (char)(usart->RBR); // Read data
            USART_AddCharToRxBuffer(ComPortNum, c);
            Events_Set(SYSTEM_EVENT_FLAG_COM_IN);
            break;

        default:
            break;
    }
}
void USART_TxISR( UINT32 port )
{
    char c;
    GLOBAL_LOCK(irq);

    if(USART_RemoveCharFromTxBuffer( port, c ))
    {
        CPU_USART_WriteCharToTxBuffer( port, c );
        Events_Set( SYSTEM_EVENT_FLAG_COM_OUT );
        
    }
    else
    {
        CPU_USART_TxBufferEmptyInterruptEnable( port, FALSE );
    }

}
Пример #3
0
void USART_Driver::SendXOFF( INT32 ComPortNum, const UINT32 Flag )
{
    ASSERT_IRQ_MUST_BE_OFF();

    HAL_USART_STATE& State = Hal_Usart_State[ComPortNum];

    if(IS_POWERSAVE_ENABLED(State)) return;

    if(RX_XOFF_STATE(State) == 0)
    {
        // send the XOFF if we are the first to add the XOFF state
        SET_USART_FLAG(State, HAL_USART_STATE::c_TX_BUFFERXOFF);

        // enable interrupts to send the XOFF, but be expedient about it to improve response time
        CPU_USART_TxBufferEmptyInterruptEnable( ComPortNum, TRUE );
    }

    SET_RX_XOFF_STATE(State,Flag);
}
Пример #4
0
void USART_Driver::SendXON( INT32 ComPortNum, const UINT32 Flag )
{
    ASSERT_IRQ_MUST_BE_OFF();

    HAL_USART_STATE& State = Hal_Usart_State[ComPortNum];

    if(IS_POWERSAVE_ENABLED(State)) return;

    // clear our XOFF state
    CLEAR_RX_XOFF_STATE(State, Flag);

    if(RX_XOFF_STATE(State) == 0)
    {
        // send the XON if we are the last to remove the XOFF state
        SET_USART_FLAG(State, HAL_USART_STATE::c_TX_BUFFERXON);
            
        // enable interrupts to send the XON
        CPU_USART_TxBufferEmptyInterruptEnable( ComPortNum, TRUE );

        // coming out of XON doesn't benefit from a priority inversion like XOFF does
    }
}
Пример #5
0
int USART_Driver::Write( int ComPortNum, const char* Data, size_t size )
{
    NATIVE_PROFILE_PAL_COM();
    int         totWrite = 0;
    const char* ptr      = Data;
    int j;

    if((ComPortNum < 0) || (ComPortNum >= TOTAL_USART_PORT)) {ASSERT(FALSE); return -1;}
    if(0    == size                                        )                 return -1;
    if(NULL == Data                                        ) {ASSERT(FALSE); return -1;}

    HAL_USART_STATE& State = Hal_Usart_State[ComPortNum];

    if (IS_POWERSAVE_ENABLED(State) || (!IS_USART_INITIALIZED(State)))return -1;

    if (USART_FLAG_STATE(State, HAL_USART_STATE::c_TX_SWFLOW_CTRL) && (!USART_FLAG_STATE(State, HAL_USART_STATE::c_TX_XON_STATE)))
    {   
        // A timeout is used for XOFF incase the XOFF value was lost or never sent.
        // USART_TX_XOFF_TIMEOUT_TICKS is defined in the platform selector file
        if((USART_TX_XOFF_TIMEOUT_INFINITE != USART_TX_XOFF_TIMEOUT_TICKS              ) &&
           (HAL_Time_CurrentTicks() - State.TicksStartTxXOFF) > USART_TX_XOFF_TIMEOUT_TICKS)
        {
            SET_USART_FLAG(State, HAL_USART_STATE::c_TX_XON_STATE);
        }
        else
        {
            return 0;
        }
    }

    // loop twice if needed because of our implementaition of a circular buffered QUEUE
    for(j=0; (j < 2) && (totWrite < size); j++)
    {
        // Keep interrupts off to keep queue access atomic
        GLOBAL_LOCK(irq);
        UINT8 *Dst;
        size_t nWritten;

        nWritten = size - totWrite;
        Dst = State.TxQueue.Push( nWritten );
        if( Dst != NULL )
        {
            memcpy(Dst, ptr, nWritten); // Move characters to transmit queue from buffer
            totWrite += nWritten;
            ptr      += nWritten;
        }
        else if(!USART_FLAG_STATE(State, HAL_USART_STATE::c_RX_HWFLOW_CTRL))
        {
            SetEvent( ComPortNum, USART_EVENT_ERROR_TXFULL );
            break;
        }
    }

    // we need to be atomic on PowerSave/USART_TxBufferEmptyInterruptEnable
    // since it gets set/cleared from ISR, and disables the clock, but
    // USART_TxBufferEmptyInterruptEnable turns the clock back on!
    // We don't want to turn on the USART clock if in power save mode
    {
        GLOBAL_LOCK(irq);

        if(size && !IS_POWERSAVE_ENABLED(State))
        {
            // if we added chars, enable interrupts so characters will actually start flowing
            // we could do this early, then we race each iteration, and could cause a stall,
            // so we do this once to be efficient in the common case (buffer has room for all chars)
            CPU_USART_TxBufferEmptyInterruptEnable( ComPortNum, TRUE );
        }
    }

    return totWrite;
}