📄 uart.c
字号:
/*************************************************************************
*
* Used with ICCARM and AARM.
*
* (c) Copyright IAR Systems 2006
*
* File name : uart.c
* Description : UARTs module
*
* History :
* 1. Date : July 6, 2006
* Author : Stanimir Bonev
* Description : Create
*
* $Revision: 18137 $
**************************************************************************/
#define UART_GLOBAL
#include "uart.h"
pUartFifo_t pUart0RxFifo; // Pointer to a FIFO Buffer of the UART0 Receive
pUartFifo_t pUart0TxFifo; // Pointer to a FIFO Buffer of the UART0 Transmit
pUartFifo_t pUart1RxFifo; // Pointer to a FIFO Buffer of the UART1 Receive
pUartFifo_t pUart1TxFifo; // Pointer to a FIFO Buffer of the UART1 Transmit
pUartFifo_t pUart2RxFifo; // Pointer to a FIFO Buffer of the UART2 Receive
pUartFifo_t pUart2TxFifo; // Pointer to a FIFO Buffer of the UART2 Transmit
pUartFifo_t pUart3RxFifo; // Pointer to a FIFO Buffer of the UART3 Receive
pUartFifo_t pUart3TxFifo; // Pointer to a FIFO Buffer of the UART3 Transmit
// Hold UART0 Evens (PE, BI, FE, OE)
UartLineEvents_t Uart0LineEvents;
// Hold UART1 Evens (PE, BI, FE, OE)
UartLineEvents_t Uart1LineEvents;
// Hold UART2 Evens (PE, BI, FE, OE)
UartLineEvents_t Uart2LineEvents;
// Hold UART3 Evens (PE, BI, FE, OE)
UartLineEvents_t Uart3LineEvents;
#if UART1_MODEM_STAT_ENA > 0
// Hold the Modem Lines States of UART1
// ( Delta CTS, Delta DSR, Delta RI, Delta DCD,
// CTS, DSR, RI and DCD )
UartModemEvents_t Uart1ModemEvents;
#endif // UART1_MODEM_STAT_ENA > 0
/*************************************************************************
* Function Name: FifoPush
* Parameters: pUartFifo_t Fifo, Int8U Data
*
* Return: Boolean
*
* Description: Push a char in a FIFO. Return TRUE when push is successful
* or FALSE when the FIFO is full.
*
*************************************************************************/
static Boolean FifoPush(pUartFifo_t Fifo, Int8U Data)
{
Int32U IndxTmp;
// calculate next push index
IndxTmp = Fifo->PushIndx + 1;
IndxTmp = IndxTmp % UART_FIFO_SIZE;
// Check FIFO state
if (IndxTmp == Fifo->PopIndx)
{
// The FIFO is full
return(FALSE);
}
// Push the data
Fifo->Buffer[Fifo->PushIndx] = Data;
// Updating the push's index
Fifo->PushIndx = IndxTmp;
return(TRUE);
}
/*************************************************************************
* Function Name: FifoPop
* Parameters: pUartFifo_t Fifo, Int8U Data
*
* Return: Boolean
*
* Description: Pop a char from a FIFO. Return TRUE when pop is successful
* or FALSE when the FIFO is empty.
*
*************************************************************************/
static Boolean FifoPop(pUartFifo_t Fifo, pInt8U pData)
{
Int32U IndxTmp;
// Check FIFO state
if (Fifo->PushIndx == Fifo->PopIndx)
{
// The FIFO is empty
return(FALSE);
}
// Calculate the next pop index
IndxTmp = Fifo->PopIndx + 1;
IndxTmp = IndxTmp % UART_FIFO_SIZE;
// Pop the data
*pData = Fifo->Buffer[Fifo->PopIndx];
// Updating of the pop's index
Fifo->PopIndx = IndxTmp;
return(TRUE);
}
/*************************************************************************
* Function Name: Uart0Isr
* Parameters: none
*
* Return: none
*
* Description: UART 0 interrupt routine
*
*************************************************************************/
static
void Uart0Isr(void)
{
Int32U UartIntId = U0IIR, LineStatus, Counter;
Int8U Data;
// Recognize the interrupt event
switch (UartIntId & 0xF)
{
case RLS_INTR_ID: // Receive Line Status
case CDI_INTR_ID: // Character Time-out Indicator
case RDA_INTR_ID: // Receive Data Available
// Read the line state of the UART
LineStatus = U0LSR;
do
{
if(LineStatus & RLS_OverrunError)
{
// Overrun Error
Uart0LineEvents.bOE = TRUE;
}
Data = U0RBR;
if (LineStatus & RLS_BreakInterruptr)
{
// Break Indicator
Uart0LineEvents.bBI = TRUE;
}
else if (LineStatus & RLS_FramingError)
{
// Framing Error
Uart0LineEvents.bFE = TRUE;
}
else if (LineStatus & RLS_ParityError)
{
// Parity Error
Uart0LineEvents.bPE = TRUE;
}
// Push a new data into the receiver buffer
if(!FifoPush(pUart0RxFifo,Data))
{
// the FIFO is full
Uart0LineEvents.bOE = TRUE;
break;
}
// Read the line state of the UART
LineStatus = U0LSR;
}
while(LineStatus & RLS_ReceiverDataReady); // Is the hardware FIFO is empty?
break;
case THRE_INTR_ID: // THRE Interrupt
// Tx UART FIFO size - 1
// Fill whole hardware transmit FIFO
for (Counter = 15; Counter; --Counter)
{
// Pop a data from the transmit buffer
if(!FifoPop(pUart0TxFifo,&Data))
{
// The tx software FIFO is empty
break;
}
U0THR = Data;
}
break;
}
VICADDRESS = 0; // Clear interrupt in VIC.
}
/*************************************************************************
* Function Name: Uart1Isr
* Parameters: none
*
* Return: none
*
* Description: UART 1 interrupt routine
*
*************************************************************************/
static
void Uart1Isr(void)
{
Int32U UartIntId = U1IIR, LineStatus, Counter;
Int8U Data;
// Same like interrupt routine of UART0
switch (UartIntId & 0xF)
{
case RLS_INTR_ID:
case CDI_INTR_ID:
case RDA_INTR_ID:
LineStatus = U1LSR;
do
{
if(LineStatus & RLS_OverrunError)
{
Uart1LineEvents.bOE = TRUE;
}
Data = U1RBR;
if (LineStatus & RLS_BreakInterruptr)
{
Uart1LineEvents.bBI = TRUE;
}
else if (LineStatus & RLS_FramingError)
{
Uart1LineEvents.bFE = TRUE;
}
else if (LineStatus & RLS_ParityError)
{
Uart1LineEvents.bPE = TRUE;
}
if(!FifoPush(pUart1RxFifo,Data))
{
Uart1LineEvents.bOE = TRUE;
break;
}
LineStatus = U1LSR;
}
while(LineStatus & RLS_ReceiverDataReady);
break;
case THRE_INTR_ID:
// Tx UART FIFO size - 1
for (Counter = 15; Counter; --Counter)
{
if(!FifoPop(pUart1TxFifo,&Data))
{
// The tx software FIFO is empty
break;
}
U1THR = Data;
}
break;
#if UART1_MODEM_STAT_ENA > 0
case MODEM_INTR_ID: // Modem Interrupt
// Read the modem lines status
Uart1ModemEvents.Data = U1MSR;
break;
#endif // UART1_MODEM_STAT_ENA > 0
}
VICADDRESS = 0; // Clear interrupt in VIC.
}
/*************************************************************************
* Function Name: Uart2Isr
* Parameters: none
*
* Return: none
*
* Description: UART2 interrupt routine
*
*************************************************************************/
static
void Uart2Isr(void)
{
Int32U UartIntId = U2IIR, LineStatus, Counter;
Int8U Data;
// Recognize the interrupt event
switch (UartIntId & 0xF)
{
case RLS_INTR_ID: // Receive Line Status
case CDI_INTR_ID: // Character Time-out Indicator
case RDA_INTR_ID: // Receive Data Available
// Read the line state of the UART
LineStatus = U2LSR;
do
{
if(LineStatus & RLS_OverrunError)
{
// Overrun Error
Uart2LineEvents.bOE = TRUE;
}
Data = U2RBR;
if (LineStatus & RLS_BreakInterruptr)
{
// Break Indicator
Uart2LineEvents.bBI = TRUE;
}
else if (LineStatus & RLS_FramingError)
{
// Framing Error
Uart2LineEvents.bFE = TRUE;
}
else if (LineStatus & RLS_ParityError)
{
// Parity Error
Uart2LineEvents.bPE = TRUE;
}
// Push a new data into the receiver buffer
if(!FifoPush(pUart2RxFifo,Data))
{
// the FIFO is full
Uart2LineEvents.bOE = TRUE;
break;
}
// Read the line state of the UART
LineStatus = U2LSR;
}
while(LineStatus & RLS_ReceiverDataReady); // Is the hardware FIFO is empty?
break;
case THRE_INTR_ID: // THRE Interrupt
// Tx UART FIFO size - 1
// Fill whole hardware transmit FIFO
for (Counter = 15; Counter; --Counter)
{
// Pop a data from the transmit buffer
if(!FifoPop(pUart2TxFifo,&Data))
{
// The tx software FIFO is empty
break;
}
U2THR = Data;
}
break;
}
VICADDRESS = 0; // Clear interrupt in VIC.
}
/*************************************************************************
* Function Name: Uart3Isr
* Parameters: none
*
* Return: none
*
* Description: UART3 interrupt routine
*
*************************************************************************/
static
void Uart3Isr(void)
{
Int32U UartIntId = U3IIR, LineStatus, Counter;
Int8U Data;
// Recognize the interrupt event
switch (UartIntId & 0xF)
{
case RLS_INTR_ID: // Receive Line Status
case CDI_INTR_ID: // Character Time-out Indicator
case RDA_INTR_ID: // Receive Data Available
// Read the line state of the UART
LineStatus = U3LSR;
do
{
if(LineStatus & RLS_OverrunError)
{
// Overrun Error
Uart3LineEvents.bOE = TRUE;
}
Data = U3RBR;
if (LineStatus & RLS_BreakInterruptr)
{
// Break Indicator
Uart3LineEvents.bBI = TRUE;
}
else if (LineStatus & RLS_FramingError)
{
// Framing Error
Uart3LineEvents.bFE = TRUE;
}
else if (LineStatus & RLS_ParityError)
{
// Parity Error
Uart3LineEvents.bPE = TRUE;
}
// Push a new data into the receiver buffer
if(!FifoPush(pUart3RxFifo,Data))
{
// the FIFO is full
Uart3LineEvents.bOE = TRUE;
break;
}
// Read the line state of the UART
LineStatus = U3LSR;
}
while(LineStatus & RLS_ReceiverDataReady); // Is the hardware FIFO is empty?
break;
case THRE_INTR_ID: // THRE Interrupt
// Tx UART FIFO size - 1
// Fill whole hardware transmit FIFO
for (Counter = 15; Counter; --Counter)
{
// Pop a data from the transmit buffer
if(!FifoPop(pUart3TxFifo,&Data))
{
// The tx software FIFO is empty
break;
}
U3THR = Data;
}
break;
}
VICADDRESS = 0; // Clear interrupt in VIC.
}
/*************************************************************************
* Function Name: UartInit
* Parameters: UartNum_t Uart, Int32U IrqSlot, UartMode_t UartMode
*
* Return: Boolean
*
* Description: Init UART
*
*************************************************************************/
Boolean UartInit(UartNum_t Uart,Int32U IrqSlot, UartMode_t UartMode)
{
volatile Int8U Tmp;
switch (Uart)
{
case UART_0:
pUart0RxFifo = (pUartFifo_t)malloc(sizeof(UartFifo_t));
if(pUart0RxFifo == NULL)
{
return(FALSE);
}
pUart0TxFifo = (pUartFifo_t)malloc(sizeof(UartFifo_t));
if(pUart0TxFifo == NULL)
{
free(pUart0RxFifo);
return(FALSE);
}
// Init receive and transmit FIFOs
pUart0RxFifo->PopIndx = pUart0RxFifo->PushIndx = \
pUart0TxFifo->PopIndx = pUart0TxFifo->PushIndx = 0;
// Enable UART0
PCONP_bit.PCUART0 = 1;
// Assign Port 0,1 to UART0
// TX
PINSEL0_bit.P0_2 = 1;
// RX
PINSEL0_bit.P0_3 = 1;
U0LCR = 0x03; // Word Length =8, no parity , 1 stop
U0FCR = 0x7; // Enable and Clear the UART0 FIFO, Set RX FIFO interrupt level - 1 char
// Transmit enable
U0TER_bit.TXEN = 1;
Tmp = U0IER; // Clear pending interrupts
// enable RBR Interrupt, THRE Interrupt, RX Line Status Interrupt
U0IER = 0x07;
VIC_SetVectoredIRQ(Uart0Isr,IrqSlot,VIC_UART0);
VICINTENABLE |= 1<<VIC_UART0;
break;
case UART_1:
pUart1RxFifo = (pUartFifo_t)malloc(sizeof(UartFifo_t));
if(pUart1RxFifo == NULL)
{
return(FALSE);
}
pUart1TxFifo = (pUartFifo_t)malloc(sizeof(UartFifo_t));
if(pUart1TxFifo == NULL)
{
free(pUart1RxFifo);
return(FALSE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -