📄 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 "board.cfg"#include "sys_types.h"#include "uart/traceswitch.h"#include "uart/uart.h"#include <string.h>#include "memif/mem.h"/* * Needed to reset and restart the sleep timer in case of incoming characters. */#if (OP_L1_STANDALONE == 1) #include "uart/serialswitch_core.h"#else #include "uart/serialswitch.h" #endifextern 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))/* * This allows monitor the last 32 inbound buffers gotten from the RX FIFO. *///#define UART_RX_BUFFER_DUMP#ifdef UART_RX_BUFFER_DUMPstruct { char rx_buffer[(BUFFER_SIZE + 1) << 5]; char *rx_in; int errors_count; int wrong_interrupt_status;} uart_rx_buffer_dump = {0};#endiftypedef 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] ={#if (((BOARD != 35) && (BOARD != 46)) || (GSM_IDLE_RAM == 0)) MEM_UART_IRDA,#endif 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[] ={ 2, /* 406250 baud. */ 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, /* 406250 baud. */ 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 voidread_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]);#ifdef UART_RX_BUFFER_DUMP *(uart_rx_buffer_dump.rx_in)++ = char_received; if (uart_rx_buffer_dump.rx_in == uart_rx_buffer_dump.rx_buffer + sizeof (uart_rx_buffer_dump.rx_buffer)) uart_rx_buffer_dump.rx_in = uart_rx_buffer_dump.rx_buffer; } else { uart_rx_buffer_dump.errors_count++;#endif } 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. * ******************************************************************************/voidinitialize_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); /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -