?? uart.c
字號:
/*******************************************************************************
*
* UART.C
*
* This module allows to use the UARTs of chipset 1.5 in interrupt mode for
* the Receive side and in polling mode for the Transmit side.
* The driver calls a user's function when characters are received.
*
* (C) Texas Instruments 1999
*
******************************************************************************/
#include "chipset.cfg"
#include "sys_types.h"
#include "traceswitch.h"
#include "uart.h"
#include <string.h>
#include "mem.h"
/*
* Needed to reset and restart the sleep timer in case of incoming characters.
*/
#include "serialswitch.h"
extern SYS_BOOL uart_sleep_timer_enabled;
#define BUFFER_SIZE (512) /* In bytes. */
#define FIFO_SIZE (64) /* In bytes. */
#define STX 0x02
#define DLE 0x10
/*
* TLR is used to program the RX FIFO trigger levels. FCR[7:4] are not used.
*/
#define RX_FIFO_TRIGGER_LEVEL (12 << 4)
/*
* 16750 addresses. Registers accessed when LCR[7] = 0.
*/
#define RHR (0x00) /* Rx buffer register - Read access */
#define THR (0x00) /* Tx holding register - Write access */
#define IER (0x01) /* Interrupt enable register */
/*
* 16750 addresses. Registers accessed when LCR[7] = 1.
*/
#define DLL (0x00) /* Divisor latch (LSB) */
#define DLM (0x01) /* Divisor latch (MSB) */
/*
* EFR is accessed when LCR[7:0] = 0xBF.
*/
#define EFR (0x02) /* Enhanced feature register */
/*
* 16750 addresses. Bit 5 of the FCR register is accessed when LCR[7] = 1.
*/
#define IIR (0x02) /* Interrupt ident. register - Read only */
#define FCR (0x02) /* FIFO control register - Write only */
#define LCR (0x03) /* Line control register */
#define MCR (0x04) /* Modem control register */
#define LSR (0x05) /* Line status register */
#define MSR (0x06) /* Modem status register */
#define TCR (0x06) /* Transmission control register */
#define TLR (0x07) /* Trigger level register */
#define MDR1 (0x08) /* Mode definition register 1 */
#define SCR (0x10) /* Supplementary Control register */
#define SSR (0x11) /* Supplementary Status register */
/*
* Supplementary control register.
*/
#define TX_EMPTY_CTL_IT (0x08)
#define RX_CTS_WAKE_UP_ENABLE_BIT (4) /* Use RESET_BIT and SET_BIT macros. */
/*
* Enhanced feature register.
*/
#define ENHANCED_FEATURE_BIT (4) /* Use RESET_BIT and SET_BIT macros. */
/*
* Mode definition register 1.
*/
#define UART_MODE (0x00)
#define SIR_MODE (0x01)
#define UART_MODE_AUTOBAUDING (0x02) /* Reserved in UART/IrDA. */
#define RESET_DEFAULT_STATE (0x07)
#define IR_SLEEP_DISABLED (0x00)
#define IR_SLEEP_ENABLED (0x08)
#define SIR_TX_WITHOUT_ACREG2 (0x00) /* Reserved in UART/modem. */
#define SIR_TX_WITH_ACREG2 (0x20) /* Reserved in UART/modem. */
#define FRAME_LENGTH_METHOD (0x00) /* Reserved in UART/modem. */
#define EOT_BIT_METHOD (0x80) /* Reserved in UART/modem. */
/*
* Supplementary Status Register
*/
#define TX_FIFO_FULL (0x01)
/*
* Interrupt enable register.
*/
#define ERBI (0x01) /* Enable received data available interrupt */
#define ETBEI (0x02) /* Enable transmitter holding register empty interrupt */
#define ELSI (0x04) /* Enable receiver line status interrupt */
#define EDSSI (0x08) /* Enable modem status interrupt */
#define IER_SLEEP (0x10) /* Enable sleep mode */
/*
* Modem control register.
*/
#define MDTR (0x01) /* Data terminal ready. */
#define MRTS (0x02) /* Request to send. */
#define TCR_TLR_BIT (6)
/*
* Line status register.
*/
#define DR (0x01) /* Data ready */
#define OE (0x02) /* Overrun error */
#define PE (0x04) /* Parity error */
#define FE (0x08) /* Framing error */
#define BI (0x10) /* Break interrupt */
#define THRE (0x20) /* Transmitter holding register (FIFO empty) */
#define TEMT (0x40) /* Transmitter empty (FIFO and TSR both empty) */
/*
* Interrupt identification register.
* Bit 0 is set to 0 if an IT is pending.
* Bits 1 and 2 are used to identify the IT.
*/
#define IIR_BITS_USED (0x07)
#define IT_NOT_PENDING (0x01)
#define RX_DATA (0x04)
#define TX_EMPTY (0x02)
#define MODEM_STATUS (0x00)
/*
* Line control register.
*/
#define WLS_5 (0x00) /* Word length: 5 bits */
#define WLS_6 (0x01) /* Word length: 6 bits */
#define WLS_7 (0x02) /* Word length: 7 bits */
#define WLS_8 (0x03) /* Word length: 8 bits */
#define STB (0x04) /* Number of stop bits: 0: 1, 1: 1,5 or 2 */
#define PEN (0x08) /* Parity enable */
#define EPS (0x10) /* Even parity select */
#define BREAK_CONTROL (0x40) /* Enable a break condition */
#define DLAB (0x80) /* Divisor latch access bit */
#define DIV_EN_BIT (7)
/*
* FIFO control register.
*/
#define FIFO_ENABLE (0x01)
#define RX_FIFO_RESET (0x02)
#define TX_FIFO_RESET (0x04)
/*
* These macros allow to read and write a UART register.
*/
#define READ_UART_REGISTER(UART,REG) \
*((volatile SYS_UWORD8 *) ((UART)->base_address + (REG)))
#define WRITE_UART_REGISTER(UART,REG,VALUE) \
*((volatile SYS_UWORD8 *) ((UART)->base_address + (REG))) = (VALUE)
#define RESET_BIT(UART,REG,BIT) \
(WRITE_UART_REGISTER ( \
UART, REG, READ_UART_REGISTER (UART, REG) & ~(1 << (BIT))))
#define SET_BIT(UART,REG,BIT) \
(WRITE_UART_REGISTER ( \
UART, REG, READ_UART_REGISTER (UART, REG) | (1 << (BIT))))
/*
* These macros allow to enable or disable the wake-up interrupt.
*/
#define ENABLE_WAKEUP_INTERRUPT(UART) \
SET_BIT(UART, SCR, RX_CTS_WAKE_UP_ENABLE_BIT);
#define DISABLE_WAKEUP_INTERRUPT(UART) \
RESET_BIT(UART, SCR, RX_CTS_WAKE_UP_ENABLE_BIT);
/*
* This macro allows to know if the RX buffer is full. It must be called only
* from the RX interrupt handler. If it is called from the application, the
* rx_in pointer may be updated if a RX interrupt occurs.
*/
#define RX_BUFFER_FULL(UART) \
(((UART)->rx_in == (UART)->rx_out - 1) || \
((UART)->rx_in == (UART)->rx_out + BUFFER_SIZE - 1))
typedef struct s_uart {
SYS_UWORD32 base_address;
/*
* Buffers management.
*/
char rx_buffer[BUFFER_SIZE + 1];
char *rx_in;
char *rx_out;
void (*callback_function) (void);
/*
* Errors counters.
*/
SYS_UWORD32 framing_error;
SYS_UWORD32 parity_error;
SYS_UWORD32 overrun_error;
/*
* Framing flags.
*/
SYS_BOOL dle_detected;
SYS_BOOL inframe;
SYS_BOOL encapsulation_flag;
unsigned char frame_length;
} t_uart;
static t_uart uart_parameter[NUMBER_OF_TR_UART];
static const SYS_UWORD32 base_address[NUMBER_OF_TR_UART] =
{
MEM_UART_IRDA,
MEM_UART_MODEM
#if (CHIPSET == 12)
, MEM_UART_MODEM2
#endif
};
/*
* DLL (LSB) and DLH (MSB) registers values using the 13 MHz clock.
*/
static const SYS_UWORD8 dll[] =
{
7, /* 115200 baud. */
14, /* 57600 baud. */
21, /* 38400 baud. */
24, /* 33900 baud. */
28, /* 28800 baud. */
42, /* 19200 baud. */
56, /* 14400 baud. */
84, /* 9600 baud. */
169, /* 4800 baud. */
83, /* 2400 baud. */
165, /* 1200 baud. */
74, /* 600 baud. */
148, /* 300 baud. */
40, /* 150 baud. */
81 /* 75 baud. */
};
static const SYS_UWORD8 dlh[] =
{
0, /* 115200 baud. */
0, /* 57600 baud. */
0, /* 38400 baud. */
0, /* 33900 baud. */
0, /* 28800 baud. */
0, /* 19200 baud. */
0, /* 14400 baud. */
0, /* 9600 baud. */
0, /* 4800 baud. */
1, /* 2400 baud. */
2, /* 1200 baud. */
5, /* 600 baud. */
10, /* 300 baud. */
21, /* 150 baud. */
42 /* 75 baud. */
};
/*******************************************************************************
*
* read_rx_fifo
*
* Purpose : Check the bytes written into the RX FIFO. Characters are not
* written in the RX buffer if it is full. The HISR is called if
* enough characters are received.
*
* Arguments: In : uart: pointer on UART structure.
* Out: none
*
* Returns : none
*
******************************************************************************/
static void
read_rx_fifo (t_uart *uart)
{
volatile SYS_UWORD8 status;
int error_detected;
SYS_UWORD8 char_received;
/*
* Since new characters have been received, the sleep timer is reset then
* restarted preventing the system to enter deep-sleep for a new period of
* time.
*/
SER_activate_timer_hisr ();
uart_sleep_timer_enabled = 1;
status = READ_UART_REGISTER (uart, LSR);
while (status & DR) { /* While RX FIFO is not empty... */
error_detected = 0;
char_received = READ_UART_REGISTER (uart, RHR);
/*
* Check if an error (overrun, parity, framing or break) is associated with the
* received data. If there is an error the byte is not copied into the
* RX buffer.
*/
if (status & (OE | PE | FE | BI)) {
if (status & PE)
uart->parity_error++;
if (status & FE)
uart->framing_error++;
if (status & OE)
uart->overrun_error++;
error_detected = 1;
}
/*
* If there is no error the byte is copied into the RX
* buffer if it is not full.
*/
if (!error_detected && !RX_BUFFER_FULL (uart)) {
*(uart->rx_in++) = char_received;
if (uart->rx_in == &(uart->rx_buffer[0]) + BUFFER_SIZE + 1)
uart->rx_in = &(uart->rx_buffer[0]);
}
status = READ_UART_REGISTER (uart, LSR);
}
/*
* Call the user's function.
*/
if (uart->callback_function != NULL)
(*(uart->callback_function)) ();
}
/*******************************************************************************
*
* initialize_uart_sleep
*
* Purpose : Performs basic UART hardware initialization including sleep mode.
*
* Arguments: In : uart_id : UART id.
* Out: none
*
* Returns: none
*
* Warning: Parameters are not verified.
*
******************************************************************************/
void
initialize_uart_sleep (T_tr_UartId uart_id)
{
t_uart *uart;
int index;
SYS_UWORD8 dummy;
for (index = 0; index < NUMBER_OF_TR_UART; index++)
uart_parameter[index].base_address = base_address[index];
uart = &(uart_parameter[uart_id]);
/*
* Mask all interrupts causes and disable sleep mode.
*/
WRITE_UART_REGISTER (uart, IER, 0x00);
/*
* Reset UART mode configuration.
*/
WRITE_UART_REGISTER (uart, MDR1, RESET_DEFAULT_STATE);
/*
* LCR[7:0] = 0xBF to allow to access EFR
* EFR[4] = 1 to allow to program IER[4].
*/
WRITE_UART_REGISTER (uart, LCR, 0xBF);
SET_BIT (uart, EFR, ENHANCED_FEATURE_BIT);
WRITE_UART_REGISTER (uart, LCR, 0x83);
/*
* Enable FIFO and reset them.
*/
WRITE_UART_REGISTER (uart, FCR, FIFO_ENABLE |
RX_FIFO_RESET |
TX_FIFO_RESET);
/*
* Program the baud generator (dummy 115200).
*/
WRITE_UART_REGISTER (uart, DLL, 0x07);
WRITE_UART_REGISTER (uart, DLM, 0x00);
/*
* LCR[7] = 0 to allow to access IER and RHR - normal mode.
*/
RESET_BIT (uart, LCR, DIV_EN_BIT);
/*
* Select UART mode.
*/
WRITE_UART_REGISTER (uart, MDR1, UART_MODE);
/*
* Clear Interrupt and check that Rx FIFO is empty.
*/
dummy = READ_UART_REGISTER (uart, IIR);
while (READ_UART_REGISTER (uart, LSR) & DR)
dummy = READ_UART_REGISTER (uart, RHR);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -