line source
+ − /*******************************************************************************
+ − *
+ − * UARTFAX.C
+ − *
+ − * This driver allows to control the UARTs of chipset 1.5 for fax and data
+ − * services. It performs flow control: RTS/CTS, XON/XOFF.
+ − *
+ − * (C) Texas Instruments 1999
+ − *
+ − ******************************************************************************/
+ −
+ − /*
+ − * DB9 16750
+ − *
+ − * 1 DCD DTR output
+ − * 2 RX SOUT output
+ − * 3 TX SIN input
+ − * 4 DTR DSR input
+ − * 5 GND
+ − * 6 DSR (connected to DTR (DB9) if J1 is used)
+ − * 7 RTS CTS input
+ − * 8 CTS RTS output
+ − * 9 nc
+ − */
+ − #include <string.h>
+ − #include "nucleus.h"
+ −
+ − #include "config/chipset.cfg"
+ − #include "config/board.cfg"
+ −
+ − #include "main/sys_types.h"
+ − #include "uart/faxdata.h"
+ − #include "uart/uartfax.h"
+ − #include "memif/mem.h"
+ −
+ −
+ − short uart_initialized = 0;
+ −
+ −
+ − /*
+ − * Maximal value for an unsigned 32 bits.
+ − */
+ −
+ − #define MAX_UNSIGNED_32 (4294967295)
+ −
+ − #define FIFO_SIZE (64) /* In bytes. */
+ −
+ −
+ − /*
+ − * TLR is used to program the RX FIFO trigger levels. FCR[7:4] are not used.
+ − * No trigger level used for TX FIFO. THR_IT generated on TX FIFO empty.
+ − */
+ −
+ − #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 (0x00) /* 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) */
+ −
+ − #define BYTE_ERROR (OE | PE | FE | BI)
+ −
+ − /*
+ − * 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_PENDING (0x01)
+ − #define RX_DATA (0x04)
+ − #define TX_EMPTY (0x02)
+ − #define MODEM_STATUS (0x00)
+ −
+ − /*
+ − * Modem status register.
+ − */
+ −
+ − #define DELTA_CTS (0x01)
+ − #define DELTA_DSR (0x02)
+ − #define MCTS (0x10) /* Clear to send */
+ − #define MDSR (0x20) /* Data set ready */
+ −
+ − /*
+ − * 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 */
+ −
+ − /*
+ − * FIFO control register.
+ − */
+ −
+ − #define FIFO_ENABLE (0x01)
+ − #define RX_FIFO_RESET (0x02)
+ − #define TX_FIFO_RESET (0x04)
+ −
+ − /*
+ − * These constants define the states of the escape sequence detection.
+ − */
+ −
+ − #define INITIALIZATION (0)
+ − #define NO_ESCAPE_SEQUENCE (1)
+ − #define ONE_CHAR_DETECTED (2)
+ − #define TWO_CHARS_DETECTED (3)
+ − #define THREE_CHARS_DETECTED (4)
+ −
+ − #define CHARACTERS_IN_ESC_SEQ (3)
+ − #define DEFAULT_ESC_SEQ_CHARACTER '+'
+ − #define DEFAULT_GUARD_PERIOD (1000) /* 1 second. */
+ −
+ − /*
+ − * 3 HISR are used to avoid to execute operations from the LISR.
+ − */
+ −
+ − #define RX_HISR_PRIORITY (2)
+ − #define RX_HISR_STACK_SIZE (512) /* Bytes. */
+ − #define TX_HISR_PRIORITY (2)
+ − #define TX_HISR_STACK_SIZE (512) /* Bytes. */
+ − #define V24_HISR_PRIORITY (2)
+ − #define V24_HISR_STACK_SIZE (512) /* Bytes. */
+ −
+ − /*
+ − * When the break interrupt indicator (BI) is set in the line status register
+ − * (LSR), it indicates that the received data input was held in the low state
+ − * for longer than a full-word transmission time. In the FIFO mode, when a break
+ − * occurs, only one 0 character is loaded into the FIFO. The next character
+ − * transfer is enabled after SIN goes to the marking state for at least two RCLK
+ − * samples and then receives the next valid start bit.
+ − * This constant defined a defined break length returned by the US_GetLineState
+ − * function.
+ − */
+ −
+ − #define MINIMAL_BREAK_LENGTH (2)
+ −
+ − #define BREAK_HISR_PRIORITY (2)
+ − #define BREAK_HISR_STACK_SIZE (512) /* Bytes. */
+ −
+ − /*
+ − * 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 is used to simplify the code in detect_escape_sequence.
+ − */
+ −
+ − #define CHECK_RX_FIFO_OUT_WRAP_AROUND(UART) \
+ − { \
+ − if (rx_fifo_out == \
+ − &((UART)->rx_fifo_byte[0]) + (UART)->rx_fifo_buffer_size + 1) \
+ − rx_fifo_out = &((UART)->rx_fifo_byte[0]); \
+ − }
+ −
+ − /*
+ − * This macro is created to simplify the code. It allows to write a byte from
+ − * the TX buffer to the TX FIFO.
+ − * The tx_out pointer is incremented before to write the character into the
+ − * TX FIFO because an interrupt may occur between the two operations.
+ − */
+ −
+ − #define WRITE_ONE_TX_BUFFER_BYTE_IN_TX_FIFO(UART) \
+ − { \
+ − SYS_UWORD8 buffer_byte; \
+ − \
+ − if (get_bytes_in_tx_buffer (UART)) { \
+ − \
+ − buffer_byte = *((UART)->tx_out++); \
+ − WRITE_UART_REGISTER (UART, THR, buffer_byte); \
+ − \
+ − if ((UART)->tx_out == \
+ − &((UART)->tx_buffer[0]) + (UART)->buffer_size + 1) \
+ − \
+ − (UART)->tx_out = &((UART)->tx_buffer[0]); \
+ − } \
+ − }
+ −
+ − /*
+ − * The transmitter is disabled only when the application disables the driver.
+ − * To disable the driver, the receiver and the transmitter are disabled by the
+ − * application. The transmitter is disabled first to test if the driver is
+ − * disabled.
+ − */
+ −
+ − #define DRIVER_DISABLED(UART) ((UART)->tx_stopped_by_application)
+ −
+ − #define DISABLE_DRIVER(UART) \
+ − { \
+ − (UART)->tx_stopped_by_application = 1; \
+ − (UART)->rx_stopped_by_application = 1; \
+ − }
+ −
+ − #define ENABLE_DRIVER(UART) \
+ − { \
+ − (UART)->rx_stopped_by_application = 0; \
+ − (UART)->tx_stopped_by_application = 0; \
+ − }
+ −
+ − /*
+ − * Low and high watermarks for the RX buffer. If it is enabled, the flow
+ − * control is activated or deactivated according to these values.
+ − * The high watermark value allows to copy an array filled with the RX FIFO
+ − * into the RX buffer.
+ − */
+ −
+ − #define RX_LOW_WATERMARK(RX_BUFFER_SIZE) (FIFO_SIZE)
+ − #define RX_HIGH_WATERMARK(RX_BUFFER_SIZE) ((RX_BUFFER_SIZE) - 2 * FIFO_SIZE)
+ −
+ − /*
+ − * This macro allows to know if the RX buffer is full. It must be called only
+ − * from the RX HISR. If it is called from the application, the rx_in and
+ − * rx_fifo_in pointers may be updated if a RX interrupt occurs or if the
+ − * RX HISR is activated.
+ − */
+ −
+ − #define RX_BUFFER_FULL(UART) \
+ − (((UART)->rx_in == (UART)->rx_out - 1) || \
+ − ((UART)->rx_in == (UART)->rx_out + (UART)->buffer_size))
+ −
+ − /*
+ − * This macro allows to know if the TX buffer is empty.
+ − */
+ −
+ − #define TX_BUFFER_EMPTY(UART) \
+ − ((UART)->tx_in == (UART)->tx_out)
+ −
+ − /*
+ − * This macro is used to convert a time (unit: ms) into a number of TDMA.
+ − * 1 TDMA = 4.6 ms (23/5).
+ − */
+ −
+ − #define CONVERT_TIME_IN_TDMA(TIME) (((TIME) * 5) / 23)
+ −
+ − /*
+ − * Size of the intermediate circular buffer used to store RX FIFO bytes before
+ − * to analyze them from the RX HISR.
+ − */
+ −
+ − #define RX_FIFO_BUFFER_SIZE (2 * FIFO_SIZE)
+ −
+ −
+ −
+ − typedef void (*T_HISR_ENTRY)(void);
+ − typedef void (*T_TIMER_FUNCTION)(UNSIGNED);
+ −
+ − static void hisr_execute_rx_entry_point_1(void);
+ − static void hisr_execute_rx_entry_point_2(void);
+ − static void hisr_execute_tx_entry_point_1(void);
+ − static void hisr_execute_tx_entry_point_2(void);
+ − static void hisr_execute_v24_entry_point_1(void);
+ − static void hisr_execute_v24_entry_point_2(void);
+ − static void hisr_start_break_entry_point_1(void);
+ − static void hisr_start_break_entry_point_2(void);
+ − static void stop_break_entry_point_1(UNSIGNED);
+ − static void stop_break_entry_point_2(UNSIGNED);
+ − static void analyze_guard_period_timer_expiration_entry_1(UNSIGNED);
+ − static void analyze_guard_period_timer_expiration_entry_2(UNSIGNED);
+ −
+ −
+ − const T_TIMER_FUNCTION analyze_guard_period_timer_expiration_tab[NUMBER_OF_FD_UART] =
+ − {
+ − analyze_guard_period_timer_expiration_entry_1,
+ − analyze_guard_period_timer_expiration_entry_2
+ − };
+ −
+ − const T_TIMER_FUNCTION stop_break_tab[NUMBER_OF_FD_UART] =
+ − {
+ − stop_break_entry_point_1,
+ − stop_break_entry_point_2
+ − };
+ −
+ − const T_HISR_ENTRY hisr_execute_rx_tab[NUMBER_OF_FD_UART] =
+ − {
+ − hisr_execute_rx_entry_point_1,
+ − hisr_execute_rx_entry_point_2
+ − };
+ −
+ − const T_HISR_ENTRY hisr_execute_tx_tab[NUMBER_OF_FD_UART] =
+ − {
+ − hisr_execute_tx_entry_point_1,
+ − hisr_execute_tx_entry_point_2
+ − };
+ −
+ − const T_HISR_ENTRY hisr_execute_v24_tab[NUMBER_OF_FD_UART] =
+ − {
+ − hisr_execute_v24_entry_point_1,
+ − hisr_execute_v24_entry_point_2
+ − };
+ −
+ − const T_HISR_ENTRY hisr_start_break_tab[NUMBER_OF_FD_UART] =
+ − {
+ − hisr_start_break_entry_point_1,
+ − hisr_start_break_entry_point_2
+ − };
+ −
+ −
+ −
+ − /*
+ − * This structure describes an UART compatible with the UART 16750 and
+ − * contains some fields to manage this UART.
+ − */
+ −
+ − typedef struct s_uart {
+ −
+ − SYS_UWORD32 base_address;
+ −
+ − /*
+ − * HISR executed from the RX/TX interrupt handler.
+ − */
+ −
+ − NU_HISR rx_hisr_ctrl_block;
+ − NU_HISR tx_hisr_ctrl_block;
+ − NU_HISR v24_hisr_ctrl_block;
+ − char rx_hisr_stack[RX_HISR_STACK_SIZE];
+ − char tx_hisr_stack[TX_HISR_STACK_SIZE];
+ − char v24_hisr_stack[V24_HISR_STACK_SIZE];
+ −
+ − /*
+ − * 2 arrays are used to store bytes read in RX FIFO. A UART RX interrupt
+ − * may occur while executing RX operations in RX HISR. To avoid overwriting
+ − * the array in which received bytes are stored, a second array is used.
+ − */
+ −
+ − SYS_UWORD8 *rx_buffer_used_by_rx_lisr;
+ − SYS_UWORD8 *rx_buffer_used_by_rx_hisr;
+ − SYS_UWORD8 rx_fifo_byte_1[FIFO_SIZE];
+ − SYS_UWORD8 rx_fifo_byte_2[FIFO_SIZE];
+ − SYS_UWORD16 bytes_in_rx_buffer_1;
+ − SYS_UWORD16 bytes_in_rx_buffer_2;
+ −
+ − /*
+ − * RX and TX buffers.
+ − * One character is not used in each buffer to allow to know if the buffer
+ − * is empty or not (See macro RX_BUFFER_FULL). If buffers are empty,
+ − * rx_in = rx_out and tx_in = tx_out. It is impossible to use fields to
+ − * count the number of bytes in each buffer because these fields may be
+ − * updated from the application and from the interrupt handlers. That avoids
+ − * to have conflicts.
+ − */
+ −
+ − SYS_UWORD16 buffer_size;
+ − SYS_UWORD16 rx_threshold_level;
+ − SYS_UWORD16 tx_threshold_level;
+ − SYS_UWORD8 rx_buffer[FD_MAX_BUFFER_SIZE + 1];
+ − SYS_UWORD8 tx_buffer[FD_MAX_BUFFER_SIZE + 1];
+ − SYS_UWORD8 *rx_in;
+ − SYS_UWORD8 *rx_out;
+ − SYS_UWORD8 *tx_in;
+ − SYS_UWORD8 *tx_out;
+ −
+ − /*
+ − * Escape sequence.
+ − * the field esc_seq_modified may have 2 values:
+ − * - 0: No modification.
+ − * - 1: Parameters are in the process of modification: The detection
+ − * is stopped.
+ − */
+ −
+ − NU_TIMER guard_period_timer_ctrl_block;
+ − SYS_UWORD8 esc_seq_modified;
+ − SYS_UWORD8 esc_seq_detection_state;
+ − SYS_UWORD8 esc_seq_character;
+ − UNSIGNED guard_period;
+ − UNSIGNED current_time;
+ − UNSIGNED previous_time;
+ −
+ − /*
+ − * Flow control.
+ − */
+ −
+ − T_flowCtrlMode flow_control_mode;
+ − SYS_BOOL send_xon_xoff;
+ − SYS_UWORD8 xon_xoff_to_send;
+ − SYS_UWORD8 xon_character;
+ − SYS_UWORD8 xoff_character;
+ − SYS_BOOL rx_stopped_by_application;
+ − SYS_BOOL rx_stopped_by_driver;
+ − SYS_BOOL tx_stopped_by_application;
+ − SYS_BOOL tx_stopped_by_driver;
+ −
+ − /*
+ − * Break.
+ − */
+ −
+ − SYS_BOOL break_received;
+ − SYS_BOOL break_to_send;
+ − SYS_BOOL break_in_progress;
+ − NU_HISR break_hisr_ctrl_block;
+ − char break_hisr_stack[BREAK_HISR_STACK_SIZE];
+ − NU_TIMER break_timer_ctrl_block;
+ − UNSIGNED baudrate;
+ − UNSIGNED bits_per_char; /* Including start, stop and parity bits. */
+ − UNSIGNED break_length; /* In bytes. */
+ − UNSIGNED time_without_character;
+ −
+ − /*
+ − * Callback (UAF_ReadData and UAF_WriteData).
+ − * rd: read, wr: write.
+ − */
+ −
+ − SYS_UWORD8 cts_level; /* 1: The RS232 line is deactivated (low). */
+ − SYS_BOOL esc_seq_received;
+ −
+ − SYS_BOOL reading_suspended;
+ − SYS_BOOL writing_suspended;
+ − SYS_BOOL rd_call_from_hisr_in_progress;
+ − SYS_BOOL wr_call_from_hisr_in_progress;
+ − T_reInstMode rd_call_setup;
+ − T_reInstMode wr_call_setup;
+ − SYS_UWORD8 *rd_address[2];
+ − SYS_UWORD8 *wr_address[2];
+ − SYS_UWORD16 rd_size_before_call[2];
+ − SYS_UWORD16 rd_size_after_call[2];
+ − SYS_UWORD16 wr_size_before_call[2];
+ − SYS_UWORD16 wr_size_after_call[2];
+ −
+ − void (*readOutFunc) (SYS_BOOL cldFromIrq,
+ − T_reInstMode *reInstall,
+ − SYS_UWORD8 nsource,
+ − SYS_UWORD8 *source[],
+ − SYS_UWORD16 size[],
+ − SYS_UWORD32 state);
+ −
+ − void (*writeInFunc) (SYS_BOOL cldFromIrq,
+ − T_reInstMode *reInstall,
+ − SYS_UWORD8 ndest,
+ − SYS_UWORD8 *dest[],
+ − SYS_UWORD16 size[]);
+ −
+ − /*
+ − * These fields are used to store the state defined in UAF_GetLineState.The
+ − * first field is used when UAF_GetLineState and UAF_ReadData are not called.
+ − * When one of these functions is called the second field is used. That
+ − * avoids to lose events when UAF_GetLineState or UAF_ReadData resets the
+ − * first field.
+ − */
+ −
+ − SYS_UWORD32 state_1;
+ − SYS_UWORD32 state_2;
+ − SYS_UWORD32 *state;
+ −
+ − /*
+ − * Errors counters.
+ − */
+ −
+ − SYS_UWORD32 framing_error;
+ − SYS_UWORD32 parity_error;
+ − SYS_UWORD32 overrun_error;
+ − SYS_UWORD32 spurious_interrupts;
+ −
+ − SYS_UWORD16 max_rx_fifo_level;
+ −
+ − } t_uart;
+ −
+ − static t_uart uart_parameters[NUMBER_OF_FD_UART];
+ −
+ − static const SYS_UWORD32 base_address[NUMBER_OF_FD_UART] =
+ − {
+ − MEM_UART_IRDA,
+ − MEM_UART_MODEM
+ − };
+ −
+ −
+ − /*
+ − * DLL (LSB) and DLH (MSB) registers values using the 13 MHz clock.
+ − */
+ −
+ − static const SYS_UWORD8 dll[] =
+ − {
+ − 0, /* Auto baud: not supported. */
+ − 81, /* 75 baud. */
+ − 40, /* 150 baud. */
+ − 148, /* 300 baud. */
+ − 74, /* 600 baud. */
+ − 165, /* 1200 baud. */
+ − 83, /* 2400 baud. */
+ − 169, /* 4800 baud. */
+ − 113, /* 7200 baud. */
+ − 84, /* 9600 baud. */
+ − 56, /* 14400 baud. */
+ − 42, /* 19200 baud. */
+ − 28, /* 28800 baud. */
+ − 24, /* 33900 baud: not supported. */
+ − 21, /* 38400 baud. */
+ − 14, /* 57600 baud. */
+ − 7, /* 115200 baud. */
+ − 0, /* 203125 baud: not supported. */
+ − 0, /* 406250 baud: not supported. */
+ − 0 /* 812500 baud: not supported. */
+ − };
+ −
+ − static const SYS_UWORD8 dlh[] =
+ − {
+ − 0, /* Auto baud: not supported. */
+ − 42, /* 75 baud. */
+ − 21, /* 150 baud. */
+ − 10, /* 300 baud. */
+ − 5, /* 600 baud. */
+ − 2, /* 1200 baud. */
+ − 1, /* 2400 baud. */
+ − 0, /* 4800 baud. */
+ − 0, /* 7200 baud. */
+ − 0, /* 9600 baud. */
+ − 0, /* 14400 baud. */
+ − 0, /* 19200 baud. */
+ − 0, /* 28800 baud. */
+ − 0, /* 33900 baud: not supported. */
+ − 0, /* 38400 baud. */
+ − 0, /* 57600 baud. */
+ − 0, /* 115200 baud. */
+ − 0, /* 203125 baud: not supported. */
+ − 0, /* 406250 baud: not supported. */
+ − 0 /* 812500 baud: not supported. */
+ − };
+ −
+ − static const UNSIGNED baudrate_value[] =
+ − {
+ − 0, /* Not supported. */
+ − 75,
+ − 150,
+ − 300,
+ − 600,
+ − 1200,
+ − 2400,
+ − 4800,
+ − 7200,
+ − 9600,
+ − 14400,
+ − 19200,
+ − 28800,
+ − 0, /* Not supported. */
+ − 38400,
+ − 57600,
+ − 115200,
+ − 0, /* Not supported. */
+ − 0, /* Not supported. */
+ − 0 /* Not supported. */
+ − };
+ −
+ − /*******************************************************************************
+ − *
+ − * get_bytes_in_rx_buffer
+ − *
+ − * Purpose : Gets the number of bytes in the RX buffer.
+ − *
+ − * Arguments: In : uart: Pointer on the UART structure.
+ − * Out: none
+ − *
+ − * Returns : The number of bytes in the RX buffer.
+ − *
+ − ******************************************************************************/
+ −
+ − static SYS_UWORD16
+ − get_bytes_in_rx_buffer (t_uart *uart)
+ − {
+ − SYS_UWORD16 bytes_in_rx_buffer;
+ − volatile SYS_UWORD8 *rx_in;
+ −
+ − rx_in = uart->rx_in;
+ −
+ − if (uart->rx_out <= rx_in)
+ − bytes_in_rx_buffer = (SYS_UWORD16) (rx_in - uart->rx_out);
+ − else
+ − bytes_in_rx_buffer =
+ − (SYS_UWORD16) (rx_in - uart->rx_out + uart->buffer_size + 1);
+ −
+ − return (bytes_in_rx_buffer);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * get_bytes_in_tx_buffer
+ − *
+ − * Purpose : Gets the number of bytes in the TX buffer.
+ − *
+ − * Arguments: In : uart: Pointer on the UART structure.
+ − * Out: none
+ − *
+ − * Returns : The number of bytes in the TX buffer.
+ − *
+ − ******************************************************************************/
+ −
+ − static SYS_UWORD16
+ − get_bytes_in_tx_buffer (t_uart *uart)
+ − {
+ − SYS_UWORD16 bytes_in_tx_buffer;
+ − volatile SYS_UWORD8 *tx_out;
+ −
+ − tx_out = uart->tx_out;
+ −
+ − if (tx_out <= uart->tx_in)
+ − bytes_in_tx_buffer = (SYS_UWORD16) (uart->tx_in - tx_out);
+ − else
+ − bytes_in_tx_buffer =
+ − (SYS_UWORD16) (uart->tx_in - tx_out + uart->buffer_size + 1);
+ −
+ − return (bytes_in_tx_buffer);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * compute_break_time
+ − *
+ − * Purpose : Computes a number of TDMA from 3 parameters:
+ − * - baudrate,
+ − * - bits per character including start bit, stop bits and parity,
+ − * - number of characters.
+ − * Due to the TDMA value (4.6 ms), a minimal value is sent: 2 TDMA.
+ − *
+ − * Arguments: In : baudrate
+ − * bits_per_char
+ − * number_of_chars
+ − * Out: none
+ − *
+ − * Returns : The number of TDMA.
+ − *
+ − ******************************************************************************/
+ −
+ − static UNSIGNED
+ − compute_break_time (UNSIGNED baudrate,
+ − UNSIGNED bits_per_char,
+ − UNSIGNED number_of_chars)
+ − {
+ − UNSIGNED number_of_tdma;
+ −
+ − number_of_tdma = CONVERT_TIME_IN_TDMA (
+ − 1000 * bits_per_char * number_of_chars / baudrate);
+ −
+ − if (number_of_tdma == 0)
+ − number_of_tdma = 1;
+ −
+ − number_of_tdma++;
+ −
+ − return (number_of_tdma);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * update_reading_callback
+ − *
+ − * Purpose : Updates the sizes array and the addresses array and get and builds
+ − * the state parameter defined in UAF_GetLineState to call the
+ − * readOutFunc function.
+ − *
+ − * Arguments: In : uart : Pointer on the UART structure.
+ − * call_source: 0: LISR, 1: application.
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ −
+ − static void
+ − update_reading_callback (t_uart *uart,
+ − SYS_BOOL call_source)
+ − {
+ − SYS_UWORD32 state;
+ − SYS_UWORD8 fragments_number;
+ − SYS_UWORD16 bytes_in_rx_buffer;
+ − volatile SYS_UWORD8 *rx_in;
+ −
+ − /*
+ − * Update the sizes array and the addresses array.
+ − * A copy of rx_in is used because it may be updated by the interrupt
+ − * handler if this function is called from the application.
+ − */
+ −
+ − rx_in = uart->rx_in;
+ −
+ − if (uart->rx_out < rx_in) {
+ −
+ − fragments_number = 1;
+ −
+ − uart->rd_address[0] = uart->rx_out;
+ − uart->rd_size_before_call[0] = (SYS_UWORD16) (rx_in - uart->rx_out);
+ − uart->rd_size_after_call[0] = uart->rd_size_before_call[0];
+ −
+ − uart->rd_size_before_call[1] = 0;
+ − uart->rd_size_after_call[1] = 0;
+ −
+ − bytes_in_rx_buffer = uart->rd_size_before_call[0];
+ −
+ − } else if (rx_in == uart->rx_out) { /* RX buffer empty. */
+ −
+ − fragments_number = 1;
+ −
+ − uart->rd_address[0] = uart->rx_out;
+ − uart->rd_size_before_call[0] = 0;
+ − uart->rd_size_after_call[0] = 0;
+ −
+ − uart->rd_size_before_call[1] = 0;
+ − uart->rd_size_after_call[1] = 0;
+ −
+ − bytes_in_rx_buffer = 0;
+ −
+ − } else {
+ −
+ − fragments_number = 2;
+ −
+ − uart->rd_address[0] = uart->rx_out;
+ − uart->rd_size_before_call[0] =
+ − uart->buffer_size + 1 - (SYS_UWORD16) (uart->rx_out -
+ − &(uart->rx_buffer[0]));
+ − uart->rd_size_after_call[0] = uart->rd_size_before_call[0];
+ −
+ − uart->rd_address[1] = &(uart->rx_buffer[0]);
+ − uart->rd_size_before_call[1] = (SYS_UWORD16) (rx_in -
+ − &(uart->rx_buffer[0]));
+ − uart->rd_size_after_call[1] = uart->rd_size_before_call[1];
+ −
+ − bytes_in_rx_buffer =
+ − uart->rd_size_before_call[0] + uart->rd_size_before_call[1];
+ −
+ − if (!uart->rd_size_before_call[1])
+ − fragments_number = 1;
+ − }
+ −
+ − /*
+ − * Build the state parameter defined in UAF_GetLineState.
+ − * The field state_2 is used when state_1 is set to 0 to avoid to
+ − * lose events detected in the RX interrupt handler.
+ − */
+ −
+ − state = uart->state_2;
+ − uart->state_2 = 0;
+ − uart->state = &(uart->state_2);
+ −
+ − state |= uart->state_1;
+ − uart->state_1 = 0;
+ − uart->state = &(uart->state_1);
+ −
+ − state |= ((((SYS_UWORD32) uart->cts_level) << RTS) |
+ −
+ − (((SYS_UWORD32) (uart->tx_stopped_by_application |
+ − uart->tx_stopped_by_driver)) << TXSTP) |
+ −
+ − (((SYS_UWORD32) (uart->rx_stopped_by_application |
+ − uart->rx_stopped_by_driver)) << RXSTP) |
+ −
+ − (((SYS_UWORD32) (uart->buffer_size - bytes_in_rx_buffer)) << RXBLEV));
+ −
+ − /*
+ − * Fields SA, SB and X are set according to the flow control:
+ − *
+ − * None RTS/CTS XON/XOFF
+ − * SA 0 (ns) 0 (ns) 0 (ns)
+ − * SB RTS 0 RTS
+ − * X 0 RTS XON:0 XOFF:1 (transmitter)
+ − *
+ − * ns: signal not supported.
+ − * DTR/DSR flow control is not supported.
+ − */
+ −
+ − if (uart->flow_control_mode != fc_rts)
+ − state |= (((SYS_UWORD32) uart->cts_level) << SB);
+ −
+ − if (uart->flow_control_mode == fc_rts)
+ − state |= (((SYS_UWORD32) uart->cts_level) << X);
+ −
+ − else if ((uart->flow_control_mode == fc_xoff) &&
+ − (uart->tx_stopped_by_application ||
+ − uart->tx_stopped_by_driver))
+ − state |= (1 << X);
+ −
+ − /*
+ − * Call the readOutFunc function with these parameters.
+ − */
+ −
+ − uart->rd_call_setup = rm_notDefined;
+ −
+ − (*(uart->readOutFunc)) (call_source & 0x01, /* From HISR or application */
+ − &(uart->rd_call_setup),
+ − fragments_number,
+ − &(uart->rd_address[0]),
+ − &(uart->rd_size_after_call[0]),
+ − state);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * update_writing_callback
+ − *
+ − * Purpose : Updates the sizes array and the addresses array to call the
+ − * writeInFunc function.
+ − *
+ − * Arguments: In : uart : Pointer on the UART structure.
+ − * call_source: 0: LISR, 1: application.
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ −
+ − static void
+ − update_writing_callback (t_uart *uart,
+ − SYS_BOOL call_source)
+ − {
+ − SYS_UWORD8 fragments_number;
+ − volatile SYS_UWORD8 *tx_out;
+ −
+ − /*
+ − * Update the sizes array and the addresses array.
+ − * A copy of tx_out is used because it may be updated by the interrupt
+ − * handler if this function is called from the application.
+ − */
+ −
+ − tx_out = uart->tx_out;
+ −
+ − if (uart->tx_in < tx_out) {
+ −
+ − fragments_number = 1;
+ −
+ − uart->wr_address[0] = uart->tx_in;
+ − uart->wr_size_before_call[0] =
+ − (SYS_UWORD16) (tx_out - uart->tx_in - 1);
+ − uart->wr_size_after_call[0] = uart->wr_size_before_call[0];
+ −
+ − uart->wr_size_before_call[1] = 0;
+ − uart->wr_size_after_call[1] = 0;
+ −
+ − } else if (tx_out == &(uart->tx_buffer[0])) {
+ −
+ − fragments_number = 1;
+ −
+ − uart->wr_address[0] = uart->tx_in;
+ − uart->wr_size_before_call[0] =
+ − uart->buffer_size -
+ − (SYS_UWORD16) (uart->tx_in - &(uart->tx_buffer[0]));
+ − uart->wr_size_after_call[0] = uart->wr_size_before_call[0];
+ −
+ − uart->wr_size_before_call[1] = 0;
+ − uart->wr_size_after_call[1] = 0;
+ −
+ − } else {
+ −
+ − fragments_number = 2;
+ −
+ − uart->wr_address[0] = uart->tx_in;
+ − uart->wr_size_before_call[0] =
+ − uart->buffer_size + 1 -
+ − (SYS_UWORD16) (uart->tx_in - &(uart->tx_buffer[0]));
+ − uart->wr_size_after_call[0] = uart->wr_size_before_call[0];
+ −
+ − uart->wr_address[1] = &(uart->tx_buffer[0]);
+ − uart->wr_size_before_call[1] =
+ − (SYS_UWORD16) (tx_out - &(uart->tx_buffer[0]) - 1);
+ − uart->wr_size_after_call[1] = uart->wr_size_before_call[1];
+ −
+ − if (!uart->wr_size_before_call[1])
+ − fragments_number = 1;
+ − }
+ −
+ − /*
+ − * Call the writeInFunc function with these parameters;
+ − */
+ −
+ − uart->wr_call_setup = rm_notDefined;
+ −
+ − (*(uart->writeInFunc)) (call_source,
+ − &(uart->wr_call_setup),
+ − fragments_number,
+ − &(uart->wr_address[0]),
+ − &(uart->wr_size_after_call[0]));
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * stop_break
+ − *
+ − * Purpose : The timer is activated to expire when a time corresponding to the
+ − * sending time of 2 characters at least has elapsed. After a break,
+ − * no character may be sent during this period.
+ − *
+ − * Arguments: In : uartNo: Irda or Modem
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ −
+ − static VOID
+ − stop_break (T_fd_UartId uartNo)
+ − {
+ − t_uart *uart;
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − uart->break_to_send = 0;
+ − uart->break_in_progress = 0;
+ −
+ − /*
+ − * Disable sleep mode then unmask Tx interrupt.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI);
+ − }
+ −
+ − static VOID
+ − stop_break_entry_point_1(UNSIGNED id)
+ − {
+ − stop_break( UAF_UART_0 ); // uart Irda
+ − }
+ − static VOID
+ − stop_break_entry_point_2(UNSIGNED id)
+ − {
+ − stop_break( UAF_UART_1 ); // uart Modem
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * hisr_start_break
+ − *
+ − * Purpose : Enables the timer used to control the time without character.
+ − *
+ − * Arguments: In : none
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ − static VOID
+ − hisr_start_break (T_fd_UartId uartNo)
+ − {
+ − t_uart *uart;
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − (void) NU_Control_Timer (&(uart->break_timer_ctrl_block),
+ − NU_DISABLE_TIMER);
+ −
+ −
+ − (void) NU_Reset_Timer (&(uart->break_timer_ctrl_block),
+ − stop_break_tab[uartNo],
+ − uart->time_without_character,
+ − 0, /* The timer expires once. */
+ − NU_DISABLE_TIMER);
+ −
+ − (void) NU_Control_Timer (&(uart->break_timer_ctrl_block),
+ − NU_ENABLE_TIMER);
+ − }
+ − static VOID
+ − hisr_start_break_entry_point_1( VOID )
+ − {
+ − hisr_start_break( UAF_UART_0 ); // uart Irda
+ − }
+ −
+ − static VOID
+ − hisr_start_break_entry_point_2( VOID )
+ − {
+ − hisr_start_break( UAF_UART_1 ); // uart Modem
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * stop_receiver
+ − *
+ − * Purpose : Activates DTR or RTS or sends XOFF.
+ − *
+ − * Arguments: In : uart: Pointer on the UART structure.
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ −
+ − static void
+ − stop_receiver (t_uart *uart)
+ − {
+ − /*
+ − * Disable sleep mode.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
+ −
+ − switch (uart->flow_control_mode) {
+ −
+ − case fc_rts:
+ −
+ − /*
+ − * CTS (RTS on UART side) is deactivated (high).
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, MCR, READ_UART_REGISTER (uart, MCR) & ~MRTS);
+ − break;
+ −
+ − case fc_xoff:
+ −
+ − uart->xon_xoff_to_send = uart->xoff_character;
+ − uart->send_xon_xoff = 1;
+ −
+ − /*
+ − * Unmask Tx interrupt.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI);
+ − break;
+ − }
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * start_receiver
+ − *
+ − * Purpose : Deactivates DTR or RTS or sends XON.
+ − *
+ − * Arguments: In : uart: Pointer on the UART structure.
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ −
+ − static void
+ − start_receiver (t_uart *uart)
+ − {
+ − /*
+ − * Disable sleep mode.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
+ −
+ − switch (uart->flow_control_mode) {
+ −
+ − case fc_rts:
+ −
+ − /*
+ − * CTS (RTS on UART side) is activated (low).
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, MCR, READ_UART_REGISTER (uart, MCR) | MRTS);
+ − break;
+ −
+ − case fc_xoff:
+ −
+ − uart->xon_xoff_to_send = uart->xon_character;
+ − uart->send_xon_xoff = 1;
+ −
+ − /*
+ − * Unmask Tx interrupt.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI);
+ − break;
+ − }
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * add_esc_seq_char_in_rx_buffer
+ − *
+ − * Purpose : Writes one escape sequence character in the RX buffer.
+ − *
+ − * Arguments: In : uart: Pointer on the UART structure.
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ −
+ − static void
+ − add_esc_seq_char_in_rx_buffer (t_uart *uart)
+ − {
+ − /*
+ − * IF the RX buffer is not full, write an escape sequence character in the
+ − * RX buffer and check wrap-around.
+ − */
+ −
+ − if (!RX_BUFFER_FULL (uart)) {
+ −
+ − *(uart->rx_in++) = uart->esc_seq_character;
+ −
+ − if (uart->rx_in == &(uart->rx_buffer[0]) + uart->buffer_size + 1)
+ − uart->rx_in = &(uart->rx_buffer[0]);
+ − }
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * analyze_guard_period_timer_expiration
+ − *
+ − * Purpose : According to the state of the escape sequence detection, 1 or 2
+ − * escape sequence characters may be written into the TX buffer or
+ − * the escape sequence is declared as detected.
+ − * If 1 or 2 escape sequence characters have been detected the
+ − * guard period must not expire.
+ − * If 3 characters have been detected the escape sequence must
+ − * expire.
+ − *
+ − * Arguments: In : id: parameter not used.
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ −
+ − static VOID
+ − analyze_guard_period_timer_expiration (T_fd_UartId uartNo)
+ − {
+ − t_uart *uart;
+ − SYS_UWORD16 bytes_in_rx_buffer;
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − switch (uart->esc_seq_detection_state) {
+ −
+ − case ONE_CHAR_DETECTED:
+ −
+ − /*
+ − * 1 escape sequence character has been detected. The guard period has
+ − * ellapsed. This character is written into the TX buffer.
+ − */
+ −
+ − add_esc_seq_char_in_rx_buffer (uart);
+ − break;
+ −
+ − case TWO_CHARS_DETECTED:
+ −
+ − /*
+ − * 2 escape sequence characters have been detected. The guard period has
+ − * ellapsed. These characters are written into the TX buffer.
+ − */
+ −
+ − add_esc_seq_char_in_rx_buffer (uart);
+ − add_esc_seq_char_in_rx_buffer (uart);
+ −
+ − break;
+ −
+ − case THREE_CHARS_DETECTED:
+ −
+ − /*
+ − * 3 escape sequence characters have been detected and the guard period
+ − * has ellapsed. The escape sequence is detected.
+ − */
+ −
+ − uart->esc_seq_received = 1;
+ − *(uart->state) |= (1 << ESC);
+ −
+ − break;
+ − }
+ −
+ − uart->esc_seq_detection_state = NO_ESCAPE_SEQUENCE;
+ −
+ − /*
+ − * If the high watermark is reached, RTS is activated or XOFF is sent
+ − * according to the flow control mode.
+ − */
+ −
+ − bytes_in_rx_buffer = get_bytes_in_rx_buffer (uart);
+ −
+ − if ((uart->flow_control_mode != fc_none) &&
+ − (bytes_in_rx_buffer >= RX_HIGH_WATERMARK (uart->buffer_size))) {
+ −
+ − /*
+ − * Check if receipt must be stopped.
+ − */
+ −
+ − if (!uart->rx_stopped_by_driver) {
+ −
+ − uart->rx_stopped_by_driver = 1;
+ − if (!uart->rx_stopped_by_application)
+ − stop_receiver (uart);
+ − }
+ − }
+ −
+ − /*
+ − * If a reading was suspended or if the callback function is installed,
+ − * it is called if one of these conditions is fulfiled:
+ − * - the RX threshold level is reached,
+ − * - a break has been detected,
+ − * - an escape sequence has been detected,
+ − */
+ −
+ − if ((!uart->rd_call_from_hisr_in_progress) &&
+ − (uart->reading_suspended ||
+ − (uart->rd_call_setup == rm_reInstall))) {
+ −
+ − if ((bytes_in_rx_buffer >= uart->rx_threshold_level) ||
+ − uart->break_received ||
+ − uart->esc_seq_received) {
+ −
+ − uart->rd_call_from_hisr_in_progress = 1;
+ − update_reading_callback (uart, 1); /* 1: call from HISR. */
+ −
+ − uart->reading_suspended = 0;
+ − uart->break_received = 0;
+ − uart->esc_seq_received = 0;
+ − }
+ − }
+ − }
+ − static VOID
+ − analyze_guard_period_timer_expiration_entry_1(UNSIGNED id)
+ − {
+ − analyze_guard_period_timer_expiration( UAF_UART_0 ); // uart Irda
+ − }
+ −
+ − static VOID
+ − analyze_guard_period_timer_expiration_entry_2(UNSIGNED id)
+ − {
+ − analyze_guard_period_timer_expiration( UAF_UART_1 ); // uart Modem
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * stop_guard_period_timer
+ − *
+ − * Purpose : Stops the timer used to detect the guard period expiration.
+ − *
+ − * Arguments: In : uart: Pointer on the UART structure.
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ −
+ − static void
+ − stop_guard_period_timer (t_uart *uart)
+ − {
+ − (void) NU_Control_Timer (&(uart->guard_period_timer_ctrl_block),
+ − NU_DISABLE_TIMER);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * start_guard_period_timer
+ − *
+ − * Purpose : Starts a timer which expires if the guard period has ellapsed.
+ − *
+ − * Arguments: In : uart: Pointer on the UART structure.
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ −
+ − static void
+ − start_guard_period_timer (T_fd_UartId uartNo)
+ − {
+ − t_uart *uart;
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − (void) NU_Control_Timer (&(uart->guard_period_timer_ctrl_block),
+ − NU_DISABLE_TIMER);
+ −
+ − (void) NU_Reset_Timer (&(uart->guard_period_timer_ctrl_block),
+ − analyze_guard_period_timer_expiration_tab[uartNo],
+ − uart->guard_period,
+ − 0, /* The timer expires once. */
+ − NU_DISABLE_TIMER);
+ −
+ − (void) NU_Control_Timer (&(uart->guard_period_timer_ctrl_block),
+ − NU_ENABLE_TIMER);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * detect_escape_sequence
+ − *
+ − * Purpose : The state machine used to detect an escape sequence is updated
+ − * according to the array of bytes to analyse. If the state machine
+ − * goes to the initial state due to a break in the sequence
+ − * detection, the previous characters are put into the RX buffer.
+ − *
+ − * Arguments: In : uart: Pointer on the UART structure.
+ − * Out: none
+ − *
+ − * Returns : 0: Break in detection or a sequence has been detected.
+ − * 1: A sequence may be detected.
+ − *
+ − ******************************************************************************/
+ −
+ − static int
+ − detect_escape_sequence (T_fd_UartId uartNo)
+ − {
+ − t_uart *uart;
+ − int detection_result;
+ − SYS_UWORD8 *rx_fifo_byte;
+ − SYS_UWORD16 bytes_in_rx_buffer;
+ − UNSIGNED elapsed_time;
+ −
+ − uart = &(uart_parameters[uartNo]);
+ − detection_result = 0;
+ −
+ − rx_fifo_byte = uart->rx_buffer_used_by_rx_hisr;
+ − if (rx_fifo_byte == &(uart->rx_fifo_byte_1[0]))
+ − bytes_in_rx_buffer = uart->bytes_in_rx_buffer_1;
+ − else
+ − bytes_in_rx_buffer = uart->bytes_in_rx_buffer_2;
+ −
+ − if (uart->current_time > uart->previous_time)
+ − elapsed_time = uart->current_time - uart->previous_time;
+ − else
+ − elapsed_time =
+ − MAX_UNSIGNED_32 - uart->previous_time + uart->current_time;
+ −
+ − switch (uart->esc_seq_detection_state) {
+ −
+ − case INITIALIZATION:
+ −
+ − /*
+ − * It is the first character received. It may be the first character
+ − * of an escape sequence. The elapsed_time variable is set to the
+ − * guard period value to consider this character as the first character
+ − * of an escape sequence.
+ − */
+ −
+ − if (!uart->esc_seq_modified) {
+ −
+ − elapsed_time = uart->guard_period;
+ − uart->esc_seq_detection_state = NO_ESCAPE_SEQUENCE;
+ − }
+ −
+ − /* No break! */
+ −
+ − case NO_ESCAPE_SEQUENCE:
+ −
+ − /*
+ − * To go to the next state (one, two or three characters detected):
+ − * - a guard period must have elapsed since the last receipt,
+ − * - the characters must belong to the escape sequence.
+ − */
+ −
+ − if ((elapsed_time >= uart->guard_period) &&
+ − (!uart->esc_seq_modified)) {
+ −
+ − switch (bytes_in_rx_buffer) {
+ −
+ − case 1:
+ −
+ − if (*rx_fifo_byte++ == uart->esc_seq_character) {
+ −
+ − uart->esc_seq_detection_state = ONE_CHAR_DETECTED;
+ − start_guard_period_timer(uartNo);
+ − detection_result = 1;
+ − }
+ −
+ − break;
+ −
+ − case 2:
+ −
+ − if ((*rx_fifo_byte++ == uart->esc_seq_character) &&
+ − (*rx_fifo_byte++ == uart->esc_seq_character)) {
+ −
+ − uart->esc_seq_detection_state = TWO_CHARS_DETECTED;
+ − start_guard_period_timer (uartNo);
+ − detection_result = 1;
+ − }
+ −
+ − break;
+ −
+ − case 3:
+ −
+ − if ((*rx_fifo_byte++ == uart->esc_seq_character) &&
+ − (*rx_fifo_byte++ == uart->esc_seq_character) &&
+ − (*rx_fifo_byte++ == uart->esc_seq_character)) {
+ −
+ − uart->esc_seq_detection_state = THREE_CHARS_DETECTED;
+ − start_guard_period_timer (uartNo);
+ − detection_result = 1;
+ − }
+ −
+ − break;
+ −
+ − default:
+ −
+ − /*
+ − * No action.
+ − */
+ −
+ − break;
+ − }
+ − }
+ −
+ − uart->previous_time = uart->current_time;
+ −
+ − break;
+ −
+ − case ONE_CHAR_DETECTED:
+ −
+ − /*
+ − * To go to the next state (two or three characters detected):
+ − * - the difference between the current time and the previous time
+ − * must be less than the guard period,
+ − * - the characters must belong to the escape sequence.
+ − * Otherwise, an escape sequence character is written in the RX buffer.
+ − */
+ −
+ − if (!uart->esc_seq_modified) {
+ −
+ − switch (bytes_in_rx_buffer) {
+ −
+ − case 1:
+ −
+ − if (*rx_fifo_byte++ == uart->esc_seq_character) {
+ −
+ − uart->esc_seq_detection_state = TWO_CHARS_DETECTED;
+ − detection_result = 1;
+ − }
+ −
+ − break;
+ −
+ − case 2:
+ −
+ − if ((*rx_fifo_byte++ == uart->esc_seq_character) &&
+ − (*rx_fifo_byte++ == uart->esc_seq_character)) {
+ −
+ − start_guard_period_timer (uartNo); /* Reset the timer. */
+ −
+ − uart->esc_seq_detection_state = THREE_CHARS_DETECTED;
+ − detection_result = 1;
+ − }
+ −
+ − break;
+ −
+ − default:
+ −
+ − /*
+ − * No action.
+ − */
+ −
+ − break;
+ − }
+ − }
+ −
+ − if (!detection_result) {
+ −
+ − add_esc_seq_char_in_rx_buffer (uart);
+ −
+ − uart->previous_time = uart->current_time;
+ − uart->esc_seq_detection_state = NO_ESCAPE_SEQUENCE;
+ − }
+ −
+ − break;
+ −
+ − case TWO_CHARS_DETECTED:
+ −
+ − /*
+ − * To go to the next state (three chars detected):
+ − * - the difference between the current time and the previous time
+ − * must be less than the guard period,
+ − * - the character must belong to the escape sequence.
+ − * Otherwise, 2 escape sequence characters are written in the RX buffer.
+ − */
+ −
+ − if (!uart->esc_seq_modified) {
+ −
+ − switch (bytes_in_rx_buffer) {
+ −
+ − case 1:
+ −
+ − if (*rx_fifo_byte++ == uart->esc_seq_character) {
+ −
+ − start_guard_period_timer (uartNo); /* Reset the timer. */
+ −
+ − uart->esc_seq_detection_state = THREE_CHARS_DETECTED;
+ − detection_result = 1;
+ − }
+ −
+ − break;
+ −
+ − default:
+ −
+ − /*
+ − * No action.
+ − */
+ −
+ − break;
+ − }
+ − }
+ −
+ − if (!detection_result) {
+ −
+ − add_esc_seq_char_in_rx_buffer (uart);
+ − add_esc_seq_char_in_rx_buffer (uart);
+ −
+ − uart->previous_time = uart->current_time;
+ − uart->esc_seq_detection_state = NO_ESCAPE_SEQUENCE;
+ − }
+ −
+ − break;
+ −
+ − case THREE_CHARS_DETECTED:
+ −
+ − /*
+ − * An escape sequence is detected if a guard period has elapsed since
+ − * the last receipt. Otherwise, 3 escape sequence characters are
+ − * written in the RX buffer.
+ − */
+ −
+ − stop_guard_period_timer (uart);
+ −
+ − add_esc_seq_char_in_rx_buffer (uart);
+ − add_esc_seq_char_in_rx_buffer (uart);
+ − add_esc_seq_char_in_rx_buffer (uart);
+ −
+ − uart->previous_time = uart->current_time;
+ − uart->esc_seq_detection_state = NO_ESCAPE_SEQUENCE;
+ −
+ − break;
+ − }
+ −
+ − return (detection_result);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * send_break
+ − *
+ − * Purpose : This function may only called if the TX FIFO is empty.
+ − * Null characters are written in the TX FIFO. The number of bytes to
+ − * write has been defined with UAF_SetLineState. Enables the break
+ − * condition.
+ − *
+ − * Arguments: In : uart: Pointer on the UART structure.
+ − * Out: none
+ − *
+ − * Returns : Number of bytes sent.
+ − *
+ − ******************************************************************************/
+ −
+ − static SYS_UWORD16
+ − send_break (t_uart *uart)
+ − {
+ − SYS_UWORD16 bytes_in_tx_fifo;
+ −
+ − bytes_in_tx_fifo = 0;
+ − uart->break_in_progress = 1;
+ −
+ − /*
+ − * Disable sleep mode.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
+ −
+ − WRITE_UART_REGISTER (
+ − uart, LCR, READ_UART_REGISTER (uart, LCR) | BREAK_CONTROL);
+ −
+ − /*
+ − * Re-enable sleep mode.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
+ −
+ − while (uart->break_length) {
+ −
+ − WRITE_UART_REGISTER (uart, THR, 0x00);
+ − uart->break_length--;
+ − bytes_in_tx_fifo++;
+ − }
+ −
+ − return (bytes_in_tx_fifo);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * build_rx_fifo_array
+ − *
+ − * Purpose : Reads the RX FIFO to build an array with bytes read.
+ − * A byte is written in this array if no error is detected.
+ − *
+ − * Arguments: In : uart: Pointer on the UART structure.
+ − * Out: none
+ − *
+ − * Returns : The number of bytes in RX FIFO.
+ − *
+ − ******************************************************************************/
+ −
+ − static SYS_UWORD16
+ − build_rx_fifo_array (t_uart *uart)
+ − {
+ − SYS_UWORD8 status;
+ − SYS_UWORD8 *first_byte;
+ − SYS_UWORD8 *current_byte;
+ − SYS_UWORD16 *bytes_in_rx_buffer;
+ − SYS_UWORD16 bytes_received;
+ −
+ − bytes_received = 0;
+ −
+ − /*
+ − * Switch to the other buffer.
+ − */
+ −
+ − first_byte = uart->rx_buffer_used_by_rx_lisr;
+ − if (first_byte == &(uart->rx_fifo_byte_1[0])) {
+ −
+ − first_byte = &(uart->rx_fifo_byte_2[0]);
+ − bytes_in_rx_buffer = &(uart->bytes_in_rx_buffer_2);
+ −
+ − } else {
+ −
+ − first_byte = &(uart->rx_fifo_byte_1[0]);
+ − bytes_in_rx_buffer = &(uart->bytes_in_rx_buffer_1);
+ − }
+ −
+ − current_byte = first_byte;
+ − uart->rx_buffer_used_by_rx_lisr = first_byte;
+ −
+ − status = READ_UART_REGISTER (uart, LSR);
+ −
+ − /*
+ − * Build an array with the bytes contained in the RX FIFO.
+ − */
+ −
+ − while (status & DR) { /* While RX FIFO is not empty... */
+ −
+ − *current_byte = READ_UART_REGISTER (uart, RHR);
+ −
+ − /*
+ − * Check if a parity error or a framing error is associated with the
+ − * received data. If there is an error the byte is not copied into the
+ − * bytes array.
+ − */
+ −
+ − if (status & BYTE_ERROR) {
+ −
+ − if (status & OE)
+ − uart->overrun_error++;
+ −
+ − if (status & PE)
+ − uart->parity_error++;
+ −
+ − if (status & FE)
+ − uart->framing_error++;
+ −
+ − /*
+ − * Check break detection.
+ − */
+ −
+ − if (status & BI) {
+ −
+ − uart->break_received = 1;
+ − *(uart->state) |=
+ − ((1 << BRK) | (MINIMAL_BREAK_LENGTH << BRKLEN));
+ − }
+ −
+ − } else
+ − current_byte++;
+ −
+ − status = READ_UART_REGISTER (uart, LSR);
+ − }
+ −
+ − bytes_received = (SYS_UWORD16) (current_byte - first_byte);
+ − *bytes_in_rx_buffer = bytes_received;
+ −
+ − /*
+ − * Re-switch to the other buffer if no valid character has been received.
+ − */
+ −
+ − if (!bytes_received) {
+ −
+ − if (uart->rx_buffer_used_by_rx_lisr == &(uart->rx_fifo_byte_1[0]))
+ − uart->rx_buffer_used_by_rx_lisr = &(uart->rx_fifo_byte_2[0]);
+ −
+ − else
+ − uart->rx_buffer_used_by_rx_lisr = &(uart->rx_fifo_byte_1[0]);
+ − }
+ −
+ − if (bytes_received > uart->max_rx_fifo_level)
+ − uart->max_rx_fifo_level = bytes_received;
+ −
+ − return (bytes_received);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * empty_rx_fifo
+ − *
+ − * Purpose : Read the RX FIFO.
+ − *
+ − * Arguments: In : uart: Pointer on the UART structure.
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ −
+ − static void
+ − empty_rx_fifo (t_uart *uart)
+ − {
+ − SYS_UWORD16 bytes_in_rx_fifo;
+ − volatile SYS_UWORD8 dummy_byte;
+ −
+ − bytes_in_rx_fifo = 0;
+ −
+ − while (READ_UART_REGISTER (uart, LSR) & DR) {
+ −
+ − dummy_byte = READ_UART_REGISTER (uart, RHR);
+ − bytes_in_rx_fifo++;
+ − }
+ −
+ − if (bytes_in_rx_fifo > uart->max_rx_fifo_level)
+ − uart->max_rx_fifo_level = bytes_in_rx_fifo;
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * hisr_execute_rx_operations
+ − *
+ − * Purpose : If an escape sequence is detected or if a break in the detection
+ − * has occured RX FIFO bytes are written in the RX buffer.
+ − * If the software flow control is used bytes are analyzed to know
+ − * if a XON or a XOFF character is received to stop or start the
+ − * transmitter.
+ − * If a flow control is used and if the high watermark of the RX
+ − * buffer is reached the receiver is stopped.
+ − * If the RX threshold level is reached the callback mechanism is
+ − * activated.
+ − *
+ − * Arguments: In : none
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ − static VOID
+ − hisr_execute_rx_operations ( T_fd_UartId uartNo )
+ − {
+ − SYS_UWORD16 bytes_free_in_rx_buffer;
+ − SYS_UWORD16 wrap_around_counter;
+ − SYS_UWORD16 bytes_in_rx_buffer;
+ − SYS_UWORD16 bytes_read;
+ − SYS_UWORD8 *current_byte;
+ − SYS_UWORD8 xon_xoff_detected;
+ − t_uart *uart;
+ −
+ − xon_xoff_detected = 0;
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − /*
+ − * Switch to the other buffer.
+ − */
+ −
+ − current_byte = uart->rx_buffer_used_by_rx_hisr;
+ − if (current_byte == &(uart->rx_fifo_byte_1[0])) {
+ −
+ − current_byte = &(uart->rx_fifo_byte_2[0]);
+ − bytes_read = uart->bytes_in_rx_buffer_2;
+ −
+ − } else {
+ −
+ − current_byte = &(uart->rx_fifo_byte_1[0]);
+ − bytes_read = uart->bytes_in_rx_buffer_1;
+ − }
+ −
+ − uart->rx_buffer_used_by_rx_hisr = current_byte;
+ −
+ − /*
+ − * All bytes are copied into the RX buffer only if an escape sequence has
+ − * been detected or a break in the detection has occured.
+ − */
+ −
+ − if (!detect_escape_sequence (uartNo)) {
+ −
+ − if (uart->rx_out > uart->rx_in)
+ − bytes_free_in_rx_buffer = (SYS_UWORD16) (uart->rx_out - uart->rx_in - 1);
+ − else
+ − bytes_free_in_rx_buffer =
+ − (SYS_UWORD16) (uart->buffer_size + uart->rx_out - uart->rx_in);
+ −
+ − wrap_around_counter = uart->buffer_size + 1 -
+ − (SYS_UWORD16) (uart->rx_in - &(uart->rx_buffer[0]));
+ −
+ − if (uart->flow_control_mode == fc_xoff) {
+ −
+ − while (bytes_read && bytes_free_in_rx_buffer) {
+ −
+ − /*
+ − * If the data received is XON or XOFF, the transmitter is
+ − * enabled (XON) or disabled (XOFF).
+ − */
+ −
+ − if (*current_byte == uart->xoff_character) {
+ −
+ − uart->tx_stopped_by_driver = 1;
+ − xon_xoff_detected = 1;
+ −
+ − } else if (*current_byte == uart->xon_character) {
+ −
+ − uart->tx_stopped_by_driver = 0;
+ − xon_xoff_detected = 1;
+ −
+ − /*
+ − * Disable sleep mode then unmask Tx interrupt.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI);
+ −
+ − } else {
+ −
+ − *(uart->rx_in++) = *current_byte;
+ −
+ − wrap_around_counter--;
+ − if (!wrap_around_counter) {
+ −
+ − uart->rx_in = &(uart->rx_buffer[0]);
+ − wrap_around_counter = uart->buffer_size + 1;
+ − }
+ −
+ − bytes_free_in_rx_buffer--;
+ − }
+ −
+ − current_byte++;
+ − bytes_read--;
+ − }
+ −
+ − } else {
+ −
+ − while (bytes_read && bytes_free_in_rx_buffer) {
+ −
+ − *(uart->rx_in++) = *current_byte++;
+ −
+ − wrap_around_counter--;
+ − if (!wrap_around_counter) {
+ −
+ − uart->rx_in = &(uart->rx_buffer[0]);
+ − wrap_around_counter = uart->buffer_size;
+ − }
+ −
+ − bytes_free_in_rx_buffer--;
+ − bytes_read--;
+ − }
+ − }
+ −
+ − /*
+ − * If the high watermark is reached, RTS is activated or XOFF is
+ − * sent according to the flow control mode.
+ − */
+ −
+ − bytes_in_rx_buffer = get_bytes_in_rx_buffer (uart);
+ −
+ − if ((uart->flow_control_mode != fc_none) &&
+ − (bytes_in_rx_buffer >= RX_HIGH_WATERMARK (uart->buffer_size))) {
+ −
+ − /*
+ − * Check if receipt must be stopped.
+ − */
+ −
+ − if (!uart->rx_stopped_by_driver) {
+ −
+ − uart->rx_stopped_by_driver = 1;
+ − if (!uart->rx_stopped_by_application)
+ − stop_receiver (uart);
+ − }
+ − }
+ −
+ − /*
+ − * If a reading was suspended or if the callback function is installed,
+ − * it is called if one of these conditions is fulfiled:
+ − * - the RX threshold level is reached,
+ − * - a break has been detected,
+ − */
+ −
+ − if ((!uart->rd_call_from_hisr_in_progress) &&
+ − (uart->reading_suspended ||
+ − (uart->rd_call_setup == rm_reInstall))) {
+ −
+ − if ((bytes_in_rx_buffer >= uart->rx_threshold_level) ||
+ − uart->break_received ||
+ − xon_xoff_detected) {
+ −
+ − uart->rd_call_from_hisr_in_progress = 1;
+ − update_reading_callback (uart, 3); /* 3: call from Rx HISR. */
+ −
+ − uart->reading_suspended = 0;
+ − uart->break_received = 0;
+ − uart->esc_seq_received = 0;
+ − }
+ − }
+ − }
+ − }
+ −
+ − static VOID
+ − hisr_execute_rx_entry_point_1 ( VOID )
+ − {
+ − hisr_execute_rx_operations( UAF_UART_0 ); //uart Irda
+ − }
+ − static VOID
+ − hisr_execute_rx_entry_point_2 ( VOID )
+ − {
+ − hisr_execute_rx_operations( UAF_UART_1 ); //uart Modem
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * hisr_execute_v24_operations
+ − *
+ − * Purpose : The user's function is called if all conditions to call it are
+ − * fulfiled.
+ − *
+ − * Arguments: In : none
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ − static VOID
+ − hisr_execute_v24_operations (T_fd_UartId uartNo)
+ − {
+ − t_uart *uart;
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − /*
+ − * If a reading was suspended or if the callback function is installed,
+ − * it is called.
+ − */
+ −
+ − if ((!DRIVER_DISABLED (uart)) &&
+ − (!uart->rd_call_from_hisr_in_progress) &&
+ − (uart->reading_suspended || (uart->rd_call_setup == rm_reInstall))) {
+ −
+ − uart->rd_call_from_hisr_in_progress = 1;
+ − update_reading_callback (uart, 1); /* 1: call from HISR. */
+ −
+ − uart->reading_suspended = 0;
+ − uart->break_received = 0;
+ − uart->esc_seq_received = 0;
+ − }
+ − }
+ −
+ − static VOID
+ − hisr_execute_v24_entry_point_1( VOID )
+ − {
+ − hisr_execute_v24_operations( UAF_UART_0 ); // uart Irda
+ − }
+ −
+ − static VOID
+ − hisr_execute_v24_entry_point_2( VOID )
+ − {
+ − hisr_execute_v24_operations( UAF_UART_1 ); // uart Modem
+ − }
+ −
+ −
+ − /*******************************************************************************
+ − *
+ − * hisr_execute_tx_operations
+ − *
+ − * Purpose : Writes bytes from the TX buffer to the TX FIFO.
+ − * The user's function is called if all conditions to call it are
+ − * fulfiled.
+ − *
+ − * Arguments: In : none
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ − static VOID
+ − hisr_execute_tx_operations (T_fd_UartId uartNo)
+ − {
+ − SYS_UWORD16 bytes_in_tx_buffer;
+ − SYS_UWORD16 bytes_in_tx_fifo;
+ − SYS_UWORD16 wrap_around_counter;
+ − t_uart *uart;
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − /*
+ − * A TX interrupt may have occured during the previous TX HISR. This case
+ − * may appear when a HISR having a higher priority has been activated when
+ − * the TX HISR was activated. When the next TX HISR is activated, the TX
+ − * FIFO may not be empty. Nothing is done until a TX interrupt will occur.
+ − * The RX HISR will be activated again and the TX FIFO will be empty.
+ − */
+ −
+ − if (READ_UART_REGISTER (uart, LSR) & THRE) {
+ −
+ − bytes_in_tx_fifo = 0;
+ −
+ − /*
+ − * A request to send a XON/XOFF character may have been done by the
+ − * RX interrupt handler. The byte can be written because we are sure
+ − * that the TX FIFO is not full.
+ − */
+ −
+ − if (uart->send_xon_xoff) {
+ −
+ − WRITE_UART_REGISTER (uart, THR, uart->xon_xoff_to_send);
+ − uart->send_xon_xoff = 0;
+ − bytes_in_tx_fifo++;
+ − }
+ −
+ − if ((!uart->tx_stopped_by_application) &&
+ − (!uart->tx_stopped_by_driver)) {
+ −
+ − bytes_in_tx_buffer = get_bytes_in_tx_buffer (uart);
+ − wrap_around_counter =
+ − uart->buffer_size + 1 - (SYS_UWORD16) (uart->tx_out -
+ − &(uart->tx_buffer[0]));
+ −
+ − /*
+ − * Loading of only (FIFO_SIZE - 1) characters in the Tx FIFO to
+ − * avoid the generation of a spurious Tx FIFO almost empty
+ − * interrupt (Ulysse bug report #35), instead of checking SSR[0].
+ − * In normal mode for THR interrupt (i.e. use of trigger level)
+ − * must only load (FIFO_SIZE - Trigger_Level - 1)
+ − */
+ −
+ − while (bytes_in_tx_buffer &&
+ − //!(READ_UART_REGISTER (uart, SSR) & TX_FIFO_FULL)) {
+ − (bytes_in_tx_fifo < FIFO_SIZE)) {
+ −
+ − WRITE_UART_REGISTER (uart, THR, *(uart->tx_out++));
+ − bytes_in_tx_buffer--;
+ − bytes_in_tx_fifo++;
+ −
+ − wrap_around_counter--;
+ − if (!wrap_around_counter) {
+ −
+ − uart->tx_out = &(uart->tx_buffer[0]);
+ − wrap_around_counter = uart->buffer_size + 1;
+ − }
+ − }
+ −
+ − /*
+ − * If a writing was suspended or if the callback function is
+ − * installed, it is called if the TX threshold level is reached.
+ − */
+ −
+ − if ((!DRIVER_DISABLED (uart)) &&
+ − (!uart->wr_call_from_hisr_in_progress) &&
+ − (bytes_in_tx_buffer <= uart->tx_threshold_level) &&
+ − ((uart->wr_call_setup == rm_reInstall) ||
+ − uart->writing_suspended)) {
+ −
+ − uart->writing_suspended = 0;
+ −
+ − uart->wr_call_from_hisr_in_progress = 1;
+ − update_writing_callback (uart, 1); /* 1: call from HISR. */
+ − }
+ − }
+ −
+ − if (bytes_in_tx_fifo)
+ −
+ − /*
+ − * Unmask Tx interrupt.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI);
+ −
+ − if ((!bytes_in_tx_fifo) && (uart->break_to_send))
+ − bytes_in_tx_fifo = send_break (uart);
+ −
+ − /*
+ − * Re-enable the sleep mode.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
+ −
+ − }
+ − }
+ −
+ −
+ − static VOID
+ − hisr_execute_tx_entry_point_1 ( VOID )
+ − {
+ − hisr_execute_tx_operations( UAF_UART_0 ); //uart Irda
+ − }
+ −
+ − static VOID
+ − hisr_execute_tx_entry_point_2 ( VOID )
+ − {
+ − hisr_execute_tx_operations( UAF_UART_1 ); //uart Modem
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * read_rx_fifo
+ − *
+ − * Purpose : Reads the RX FIFO. If the driver is enabled bytes are written in
+ − * an array to be analyzed by the RX HISR.
+ − *
+ − * Arguments: In : uart: Pointer on the UART structure.
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ −
+ − static void
+ − read_rx_fifo (t_uart *uart)
+ − {
+ −
+ − /*
+ − * If the driver is disabled the RX FIFO is read to acknoledge the
+ − * interrupt else bytes received are written into an array which will be
+ − * analyzed from the RX HISR.
+ − */
+ − if (DRIVER_DISABLED (uart))
+ − empty_rx_fifo (uart);
+ − #if (BOARD == 31)
+ − else if ((*((volatile SYS_UWORD16 *) ARMIO_IN) & 0x0100) == 0x0000)
+ − empty_rx_fifo (uart);
+ − #endif
+ − else if (build_rx_fifo_array (uart))
+ − (void) NU_Activate_HISR (&(uart->rx_hisr_ctrl_block));
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * check_v24_input_lines
+ − *
+ − * Purpose : Check the V.24 input lines. According to the states of the input
+ − * lines and to the flow control mode selected, the transmitter is
+ − * enabled or disabled. The reading callback function is called if
+ − * it is installed and if all conditions are fulfiled.
+ − *
+ − * Arguments: In : uart: Pointer on the UART structure.
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ −
+ − static void
+ − check_v24_input_lines (t_uart *uart)
+ − {
+ − SYS_BOOL v24_input_line_changed;
+ − volatile SYS_UWORD8 modem_status;
+ −
+ − modem_status = READ_UART_REGISTER (uart, MSR);
+ − v24_input_line_changed = 0;
+ −
+ − if (modem_status & DELTA_CTS) {
+ −
+ − v24_input_line_changed = 1;
+ −
+ − if (modem_status & MCTS)
+ − uart->cts_level = 0;
+ − else
+ − uart->cts_level = 1;
+ − }
+ −
+ − /*
+ − * When the hardware flow control is selected, if the RS 232 input signal is
+ − * deactivated (low), the transmitter is stopped.
+ − */
+ −
+ − if (uart->flow_control_mode == fc_rts) {
+ −
+ − if (uart->cts_level)
+ − uart->tx_stopped_by_driver = 1;
+ −
+ − else {
+ −
+ − uart->tx_stopped_by_driver = 0;
+ −
+ − /*
+ − * Disable sleep mode then unmask Tx interrupt.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI);
+ −
+ − }
+ − }
+ −
+ − if (v24_input_line_changed)
+ − (void) NU_Activate_HISR (&(uart->v24_hisr_ctrl_block));
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * fill_tx_fifo
+ − *
+ − * Purpose : If the TX buffer is not empty, and if there is no break in
+ − * progress, bytes are written into the TX FIFO until the TX FIFO is
+ − * full or the TX buffer is empty. Else, if there is a break to send
+ − * an all 0s character is written into the TX FIFO and a break is
+ − * declared in progress to avoid to fill the TX FIFO on the next
+ − * interrupt.
+ − * When the TX FIFO is empty and if a break is in progress, the break
+ − * length is programmed: all 0s characters are written into the TX
+ − * FIFO. The number of bytes has been defined previously with the
+ − * UAF_SetLineState function. The break condition is enabled.
+ − * When the TX FIFO and the transmitter shift register (TSR) are both
+ − * empty and if a break is in progress, the break condition is
+ − * disabled.
+ − * When bytes are written from the TX buffer to the TX FIFO, the
+ − * writing callback function is called if it is installed and if all
+ − * conditions are fulfiled.
+ − *
+ − * Arguments: In : uart: Pointer on the UART structure.
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ −
+ − static void
+ − fill_tx_fifo (t_uart *uart)
+ − {
+ −
+ − /*
+ − * Disable sleep mode then mask Tx interrupt.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) & ~ETBEI);
+ −
+ − /*
+ − * If a break is in progress, bytes of the TX buffer are not written into
+ − * the TX FIFO.
+ − */
+ −
+ − if (!uart->break_in_progress)
+ − (void) NU_Activate_HISR (&(uart->tx_hisr_ctrl_block));
+ −
+ − else {
+ −
+ − /*
+ − * The break HISR is activated and the break condition is cleared.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, LCR, READ_UART_REGISTER (uart, LCR) & ~BREAK_CONTROL);
+ −
+ − (void) NU_Activate_HISR (&(uart->break_hisr_ctrl_block));
+ − }
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_Init
+ − *
+ − * Purpose : Initializes the UART hardware and installs interrupt handlers.
+ − * The parameters are set to the default values:
+ − * - 19200 baud,
+ − * - 8 bits / character,
+ − * - no parity,
+ − * - 1 stop bit,
+ − * - no flow control.
+ − * All functionalities of the UART driver are disabled.
+ − *
+ − * Arguments: In : uartNo: Used UART.
+ − * Out: none
+ − *
+ − * Returns : FD_OK : Successful operation.
+ − * FD_NOT_SUPPORTED: Wrong UART number.
+ − * FD_INTERNAL_ERR : Internal problem.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_Init (T_fd_UartId uartNo)
+ − {
+ − t_uart *uart;
+ − volatile SYS_UWORD8 status;
+ − int index;
+ −
+ − #if ((CHIPSET == 2) || (CHIPSET == 3) || (CHIPSET == 4))
+ − /*
+ − * Check UART number.
+ − * A return is used to simplify the code.
+ − * UART IrDA (UAF_UART_0) can't be used for F&D on Ulysse because hardware
+ − * flow control is not supported.
+ − * DCD and DTR are not supported on UART Irda on C-Sample.
+ − */
+ −
+ − if ( (uartNo != UAF_UART_1) && (uartNo != UAF_UART_0) )
+ − return (FD_NOT_SUPPORTED);
+ − #endif
+ −
+ − for (index = 0; index < NUMBER_OF_FD_UART; index++)
+ − uart_parameters[index].base_address = base_address[index];
+ −
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − /*
+ − * Create the 3 HISR actived in the RX/TX and V24 interrupt handlers.
+ − * A return is used to simplify the code if an error occurs.
+ − * All stacks are entirely filled with the pattern 0xFE.
+ − */
+ −
+ − if (uart_initialized==0){
+ − memset (&(uart->rx_hisr_stack[0]), 0xFE, RX_HISR_STACK_SIZE);
+ − memset (&(uart->tx_hisr_stack[0]), 0xFE, TX_HISR_STACK_SIZE);
+ − memset (&(uart->v24_hisr_stack[0]), 0xFE, V24_HISR_STACK_SIZE);
+ − memset (&(uart->break_hisr_stack[0]), 0xFE, BREAK_HISR_STACK_SIZE);
+ − uart_initialized = 1;
+ − }
+ −
+ −
+ − if (NU_Create_HISR (&(uart->rx_hisr_ctrl_block),
+ − "Rx",
+ − hisr_execute_rx_tab[uartNo],
+ − RX_HISR_PRIORITY,
+ − &(uart->rx_hisr_stack[0]),
+ − RX_HISR_STACK_SIZE) != NU_SUCCESS)
+ −
+ − return (FD_INTERNAL_ERR);
+ −
+ − if (NU_Create_HISR (&(uart->tx_hisr_ctrl_block),
+ − "Tx",
+ − hisr_execute_tx_tab[uartNo],
+ − TX_HISR_PRIORITY,
+ − &(uart->tx_hisr_stack[0]),
+ − TX_HISR_STACK_SIZE) != NU_SUCCESS)
+ −
+ − return (FD_INTERNAL_ERR);
+ −
+ − if (NU_Create_HISR (&(uart->v24_hisr_ctrl_block),
+ − "UAF_V24",
+ − hisr_execute_v24_tab[uartNo],
+ − V24_HISR_PRIORITY,
+ − &(uart->v24_hisr_stack[0]),
+ − V24_HISR_STACK_SIZE) != NU_SUCCESS)
+ −
+ − return (FD_INTERNAL_ERR);
+ −
+ − /*
+ − * Create the HISR used to send a break.
+ − * A return is used to simplify the code if an error occurs.
+ − * The stack is entirely filled with the pattern 0xFE.
+ − */
+ −
+ − if (NU_Create_HISR (&(uart->break_hisr_ctrl_block),
+ − "UAF_Brk",
+ − hisr_start_break_tab[uartNo],
+ − BREAK_HISR_PRIORITY,
+ − &(uart->break_hisr_stack[0]),
+ − BREAK_HISR_STACK_SIZE) != NU_SUCCESS)
+ −
+ − return (FD_INTERNAL_ERR);
+ −
+ − /*
+ − * Create a timer used in the break HISR.
+ − * A return is used to simplify the code if an error occurs.
+ − */
+ −
+ − if (NU_Create_Timer (&(uart->break_timer_ctrl_block),
+ − "Break",
+ − stop_break_tab[uartNo],
+ − 0, /* Parameter supplied to the routine: not used. */
+ − 0, /* This parameter is set when the timer is reset. */
+ − 0, /* The timer expires once. */
+ − NU_DISABLE_TIMER) != NU_SUCCESS)
+ −
+ − return (FD_INTERNAL_ERR);
+ −
+ − /*
+ − * Create a timer used in the detection of the escape sequence.
+ − * A return is used to simplify the code if an error occurs.
+ − */
+ −
+ − if (NU_Create_Timer (&(uart->guard_period_timer_ctrl_block),
+ − "Esc seq",
+ − analyze_guard_period_timer_expiration_tab[uartNo],
+ − 0, /* Parameter supplied to the routine: not used. */
+ − 0, /* This parameter is set when the timer is reset. */
+ − 0, /* The timer expires once. */
+ − NU_DISABLE_TIMER) != NU_SUCCESS)
+ −
+ − return (FD_INTERNAL_ERR);
+ −
+ − /*
+ − * These data are used to send a break.
+ − * A character has: 8 data bits + 1 start bit + 1 stop bit = 10 bits.
+ − */
+ −
+ − uart->baudrate = baudrate_value[FD_BAUD_115200];
+ − uart->bits_per_char = 10;
+ −
+ − /*
+ − * UART base address.
+ − */
+ −
+ − uart->base_address = base_address[uartNo];
+ −
+ − /*
+ − * Select the current array used to store received bytes.
+ − */
+ −
+ − uart->rx_buffer_used_by_rx_lisr = &(uart->rx_fifo_byte_2[0]);
+ − uart->rx_buffer_used_by_rx_hisr = &(uart->rx_fifo_byte_2[0]);
+ −
+ − /*
+ − * RX and TX buffers.
+ − */
+ −
+ − uart->buffer_size = FD_MAX_BUFFER_SIZE;
+ − uart->rx_threshold_level = 1;
+ − uart->tx_threshold_level = 0;
+ − uart->rx_in = &(uart->rx_buffer[0]);
+ − uart->rx_out = &(uart->rx_buffer[0]);
+ − uart->tx_in = &(uart->tx_buffer[0]);
+ − uart->tx_out = &(uart->tx_buffer[0]);
+ −
+ − /*
+ − * Escape sequence.
+ − */
+ −
+ − uart->esc_seq_modified = 0;
+ − uart->esc_seq_detection_state = INITIALIZATION;
+ − uart->esc_seq_character = DEFAULT_ESC_SEQ_CHARACTER;
+ − uart->guard_period = CONVERT_TIME_IN_TDMA (
+ − DEFAULT_GUARD_PERIOD);
+ −
+ − /*
+ − * Flow control.
+ − */
+ −
+ − uart->flow_control_mode = fc_none;
+ − uart->send_xon_xoff = 0;
+ − uart->rx_stopped_by_application = 1;
+ − uart->rx_stopped_by_driver = 0;
+ − uart->tx_stopped_by_application = 1;
+ − uart->tx_stopped_by_driver = 0;
+ −
+ − /*
+ − * Break.
+ − */
+ −
+ − uart->break_received = 0;
+ − uart->break_to_send = 0;
+ − uart->break_in_progress = 0;
+ −
+ − /*
+ − * Callback (UAF_ReadData and UAF_WriteData).
+ − */
+ −
+ − uart->esc_seq_received = 0;
+ −
+ − uart->reading_suspended = 0;
+ − uart->writing_suspended = 0;
+ − uart->rd_call_from_hisr_in_progress = 0;
+ − uart->wr_call_from_hisr_in_progress = 0;
+ − uart->rd_call_setup = rm_noInstall;
+ − uart->wr_call_setup = rm_noInstall;
+ −
+ − /*
+ − * State defined in UAF_GetLineState.
+ − */
+ −
+ − uart->state_1 = 0;
+ − uart->state_2 = 0;
+ − uart->state = &(uart->state_1);
+ −
+ − /*
+ − * Errors counters.
+ − */
+ −
+ − uart->framing_error = 0;
+ − uart->parity_error = 0;
+ − uart->overrun_error = 0;
+ − uart->spurious_interrupts = 0;
+ −
+ − uart->max_rx_fifo_level = 0;
+ −
+ − /*
+ − * Mask all interrupts causes and disable sleep mode and low power mode.
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, IER, 0x00);
+ −
+ − /*
+ − * Reset UART mode configuration.
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, MDR1, RESET_DEFAULT_STATE |
+ − IR_SLEEP_DISABLED |
+ − SIR_TX_WITHOUT_ACREG2 |
+ − FRAME_LENGTH_METHOD);
+ −
+ − /*
+ − * FIFO configuration.
+ − * EFR[4] = 1 to allow to program FCR[5:4] and MCR[7:5].
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, LCR, 0xBF);
+ − SET_BIT (uart, EFR, ENHANCED_FEATURE_BIT);
+ −
+ − /*
+ − * Select the word length, the number of stop bits , the parity and set
+ − * LCR[7] (DLAB) to allow to program FCR, DLL and DLM.
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, LCR, WLS_8 | DLAB);
+ −
+ − /*
+ − * Program the trigger levels.
+ − * MCR[6] must be set to 1.
+ − */
+ −
+ − SET_BIT (uart, MCR, TCR_TLR_BIT);
+ − WRITE_UART_REGISTER (uart, TCR, 0x0F);
+ − WRITE_UART_REGISTER (uart, TLR, RX_FIFO_TRIGGER_LEVEL);
+ − RESET_BIT (uart, MCR, TCR_TLR_BIT);
+ −
+ − /*
+ − * Force the generation of THR_IT on TX FIFO empty: SCR[3] = 1.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, SCR, READ_UART_REGISTER (uart, SCR) | TX_EMPTY_CTL_IT);
+ −
+ − /*
+ − * Program the FIFO control register. Bit 0 must be set when other FCR bits
+ − * are written to or they are not programmed.
+ − * FCR is a write-only register. It will not be modified.
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, FCR, FIFO_ENABLE |
+ − RX_FIFO_RESET | /* self cleared */
+ − TX_FIFO_RESET); /* self cleared */
+ −
+ − /*
+ − * Program the baud generator.
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, DLL, dll[FD_BAUD_115200]);
+ − WRITE_UART_REGISTER (uart, DLM, dlh[FD_BAUD_115200]);
+ −
+ − /*
+ − * Reset LCR[7] (DLAB) to have access to the RBR, THR and IER registers.
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, LCR, READ_UART_REGISTER (uart, LCR) & ~DLAB);
+ −
+ − /*
+ − * Select UART mode.
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, MDR1, UART_MODE |
+ − IR_SLEEP_DISABLED |
+ − SIR_TX_WITHOUT_ACREG2 |
+ − FRAME_LENGTH_METHOD);
+ −
+ − /*
+ − * Read the state of CTS, DSR and DCD.
+ − */
+ −
+ − status = READ_UART_REGISTER (uart, MSR);
+ −
+ − if (status & MCTS)
+ − uart->cts_level = 0;
+ − else
+ − uart->cts_level = 1;
+ −
+ − /*
+ − * Unmask RX interrupt and the modem status interrupt.
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, IER, ERBI | EDSSI);
+ −
+ − return (FD_OK);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_Enable
+ − *
+ − * Purpose : The functionalities of the UART driver are disabled or enabled.
+ − * In the deactivated state, all information about the communication
+ − * parameters should be stored and recalled if the driver is again
+ − * enabled. When the driver is enabled the RX and TX buffers are
+ − * cleared.
+ − *
+ − * Arguments: In : enable: 1: enable the driver
+ − * 0: disable the driver
+ − * Out: none
+ − *
+ − * Returns : FD_OK : Successful operation.
+ − * FD_INTERNAL_ERR : Internal problem with the hardware.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_Enable (T_fd_UartId uartNo, SYS_BOOL enable)
+ − {
+ − t_uart *uart;
+ −
+ − /*
+ − * There is no case where FD_INTERNAL_ERR may be returned.
+ − */
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − if (enable) {
+ −
+ − uart->rx_stopped_by_driver = 0;
+ −
+ − ENABLE_DRIVER (uart);
+ − start_receiver (uart);
+ −
+ − } else {
+ −
+ − DISABLE_DRIVER (uart);
+ − stop_receiver (uart);
+ −
+ − uart->tx_in = &(uart->tx_buffer[0]);
+ − uart->rx_in = &(uart->rx_buffer[0]);
+ − uart->tx_out = uart->tx_in;
+ − uart->rx_out = uart->rx_in;
+ − }
+ −
+ − return (FD_OK);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_SetComPar
+ − *
+ − * Purpose : Sets up the communication parameters: baud rate, bits per
+ − * character, number of stop bits, parity.
+ − *
+ − * Arguments: In : baudrate: Used baud rate.
+ − * bpc : Used bits per character.
+ − * sb : Used stop bits.
+ − * parity : Used parity.
+ − * Out: none
+ − *
+ − * Returns : FD_OK : Successful operation.
+ − * FD_NOT_SUPPORTED: The specified parameters don't fit to the
+ − * capabilities of the UART.
+ − * FD_INTERNAL_ERR : Internal problem with the hardware.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_SetComPar (T_fd_UartId uartNo,
+ − T_baudrate baudrate,
+ − T_bitsPerCharacter bpc,
+ − T_stopBits sb,
+ − T_parity parity)
+ − {
+ − t_uart *uart;
+ − volatile SYS_UWORD8 mcr_value;
+ − volatile SYS_UWORD8 status;
+ −
+ − /*
+ − * There is no case where FD_INTERNAL_ERR may be returned.
+ − * pa_space is not supported. Some baudrates are not supported too.
+ − * A return is used to simplify the code.
+ − */
+ − baudrate = FD_BAUD_115200;
+ −
+ − if ((!baudrate_value[baudrate]) ||
+ − (parity == pa_space))
+ −
+ − return (FD_NOT_SUPPORTED);
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − /*
+ − * Mask all interrupts causes and disable sleep mode and low power mode.
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, IER, 0x00);
+ −
+ − /*
+ − * Reset UART mode configuration.
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, MDR1, RESET_DEFAULT_STATE |
+ − IR_SLEEP_DISABLED |
+ − SIR_TX_WITHOUT_ACREG2 |
+ − FRAME_LENGTH_METHOD);
+ −
+ − /*
+ − * FIFO configuration.
+ − * EFR[4] = 1 to allow to program FCR[5:4] and MCR[7:5].
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, LCR, 0xBF);
+ − SET_BIT (uart, EFR, ENHANCED_FEATURE_BIT);
+ −
+ − /*
+ − * Select the word length, the number of stop bits , the parity and set
+ − * LCR[7] (DLAB) to allow to program FCR, DLL and DLM.
+ − */
+ −
+ − uart->baudrate = baudrate_value[baudrate];
+ − uart->bits_per_char = 1; /* Start bit. */
+ − mcr_value = DLAB;
+ −
+ − if (bpc == bpc_7) {
+ −
+ − mcr_value |= WLS_7;
+ − uart->bits_per_char += 7;
+ −
+ − } else {
+ −
+ − mcr_value |= WLS_8;
+ − uart->bits_per_char += 8;
+ − }
+ −
+ − if (sb == sb_2) {
+ −
+ − mcr_value |= STB;
+ − uart->bits_per_char += 2;
+ −
+ − } else
+ − uart->bits_per_char += 1;
+ −
+ − switch (parity) {
+ −
+ − case pa_even:
+ −
+ − mcr_value |= (PEN | EPS);
+ − uart->bits_per_char += 1;
+ −
+ − break;
+ −
+ − case pa_odd:
+ −
+ − mcr_value |= PEN;
+ − uart->bits_per_char += 1;
+ −
+ − break;
+ −
+ − default:
+ −
+ − /*
+ − * There is nothing to do.
+ − */
+ −
+ − break;
+ − }
+ −
+ − WRITE_UART_REGISTER (uart, LCR, mcr_value);
+ −
+ − /*
+ − * Program the trigger levels.
+ − * MCR[6] must be set to 1.
+ − */
+ −
+ − SET_BIT (uart, MCR, TCR_TLR_BIT);
+ − WRITE_UART_REGISTER (uart, TCR, 0x0F);
+ − WRITE_UART_REGISTER (
+ − uart, TLR, RX_FIFO_TRIGGER_LEVEL);
+ − RESET_BIT (uart, MCR, TCR_TLR_BIT);
+ −
+ − /*
+ − * Force the generation of THR_IT on TX FIFO empty: SCR[3] = 1.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, SCR, READ_UART_REGISTER (uart, SCR) | TX_EMPTY_CTL_IT);
+ −
+ − /*
+ − * Program the FIFO control register. Bit 0 must be set when other FCR bits
+ − * are written to or they are not programmed.
+ − * FCR is a write-only register. It will not be modified.
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, FCR, FIFO_ENABLE |
+ − RX_FIFO_RESET | /* self cleared */
+ − TX_FIFO_RESET); /* self cleared */
+ −
+ − /*
+ − * Program the baud generator.
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, DLL, dll[baudrate]);
+ − WRITE_UART_REGISTER (uart, DLM, dlh[baudrate]);
+ −
+ − /*
+ − * Reset LCR[7] (DLAB) to have access to the RBR, THR and IER registers.
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, LCR, READ_UART_REGISTER (uart, LCR) & ~DLAB);
+ −
+ − /*
+ − * Select UART mode.
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, MDR1, UART_MODE |
+ − IR_SLEEP_DISABLED |
+ − SIR_TX_WITHOUT_ACREG2 |
+ − FRAME_LENGTH_METHOD);
+ −
+ − /*
+ − * Read the state of CTS, DSR and DCD.
+ − */
+ −
+ − status = READ_UART_REGISTER (uart, MSR);
+ −
+ − if (status & MCTS)
+ − uart->cts_level = 0;
+ − else
+ − uart->cts_level = 1;
+ −
+ − /*
+ − * Unmask RX and TX interrupts and the modem status interrupt
+ − * and allow sleep mode.
+ − */
+ −
+ − WRITE_UART_REGISTER (uart, IER, ERBI | ETBEI | EDSSI | IER_SLEEP);
+ − WRITE_UART_REGISTER (uart, IER, ERBI | ETBEI | EDSSI);
+ −
+ − return (FD_OK);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_SetBuffer
+ − *
+ − * Purpose : Sets up the size of the circular buffers to be used in the UART
+ − * driver. This function may be called only if the UART is disabled
+ − * with UAF_Enable.
+ − *
+ − * Arguments: In : bufSize : Specifies the size of the circular buffer.
+ − * rxThreshold: Amount of received bytes that leads to a call
+ − * to suspended read-out function which is passed
+ − * to the function UAF_ReadData.
+ − * txThreshold: Amount of bytes in the TX buffer to call the
+ − * suspended write-in function which is passed to
+ − * the function UAF_WriteData
+ − * Out: none
+ − *
+ − * Returns : FD_OK : Successful operation.
+ − * FD_NOT_SUPPORTED: bufSize exceeds the maximal possible
+ − * capabilities of the driver or the threshold
+ − * values don't correspond to the bufSize.
+ − * FD_INTERNAL_ERR : Internal problem with the hardware or the
+ − * function has been called while the UART is
+ − * enabled.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_SetBuffer (T_fd_UartId uartNo,
+ − SYS_UWORD16 bufSize,
+ − SYS_UWORD16 rxThreshold,
+ − SYS_UWORD16 txThreshold)
+ − {
+ − T_FDRET result;
+ − t_uart *uart;
+ −
+ − if ((bufSize > FD_MAX_BUFFER_SIZE) ||
+ − (rxThreshold > FD_MAX_BUFFER_SIZE) ||
+ − (txThreshold > FD_MAX_BUFFER_SIZE))
+ −
+ − result = FD_NOT_SUPPORTED;
+ −
+ − else {
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − if (!DRIVER_DISABLED (uart))
+ − result = FD_INTERNAL_ERR;
+ −
+ − else if (RX_HIGH_WATERMARK (bufSize) < RX_LOW_WATERMARK (bufSize))
+ − result = FD_NOT_SUPPORTED;
+ −
+ − else {
+ −
+ − uart->buffer_size = bufSize;
+ − uart->rx_threshold_level = rxThreshold;
+ − uart->tx_threshold_level = txThreshold;
+ −
+ − result = FD_OK;
+ − }
+ − }
+ −
+ − return (result);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_SetFlowCtrl
+ − *
+ − * Purpose : Changes the flow control mode of the UART driver.
+ − * If a flow control is activated, DTR is activated or XOFF is sent
+ − * if the RX buffer is not able to store the received characters else
+ − * DTR is deactivated or XON is sent.
+ − *
+ − * Arguments: In : fcMode: flow control mode (none, DTR/DSR, RTS/CTS, XON/XOFF).
+ − * XON : ASCII code of the XON character.
+ − * XOFF : ASCII code of the XOFF character.
+ − * Out: none
+ − *
+ − * Returns : FD_OK : Successful operation.
+ − * FD_NOT_SUPPORTED: The flow control mode is not supported.
+ − * FD_INTERNAL_ERR : Internal problem with the hardware.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_SetFlowCtrl (T_fd_UartId uartNo,
+ − T_flowCtrlMode fcMode,
+ − SYS_UWORD8 XON,
+ − SYS_UWORD8 XOFF)
+ − {
+ − T_FDRET result;
+ − t_uart *uart;
+ −
+ − /*
+ − * There is no case where FD_INTERNAL_ERR may be returned.
+ − * The DTR/DSR protocol is not supported.
+ − */
+ −
+ − if (fcMode == fc_dtr)
+ − result = FD_NOT_SUPPORTED;
+ −
+ − else {
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − uart->tx_stopped_by_driver = 0;
+ −
+ −
+ − uart->xon_character = XON;
+ − uart->xoff_character = XOFF;
+ − uart->flow_control_mode = fcMode;
+ −
+ − /*
+ − * Disable sleep mode.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
+ −
+ − WRITE_UART_REGISTER (
+ − uart, MCR, READ_UART_REGISTER (uart, MCR) | MRTS);
+ −
+ − /*
+ − * Re-enable sleep mode.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
+ −
+ − if (fcMode == fc_rts) {
+ −
+ − if (uart->cts_level)
+ − uart->tx_stopped_by_driver = 1;
+ − }
+ −
+ − /*
+ − * If the high watermark is reached, DTR or RTS is activated or XOFF is
+ − * sent according to the flow control mode. Else, DTR is deactivated or
+ − * XON is sent.
+ − */
+ −
+ − if (fcMode != fc_none) {
+ −
+ − if (get_bytes_in_rx_buffer (uart) >= RX_HIGH_WATERMARK (
+ − uart->buffer_size)) {
+ −
+ − uart->rx_stopped_by_driver = 1;
+ − stop_receiver (uart);
+ −
+ − } else if (!DRIVER_DISABLED (uart)) {
+ −
+ − uart->rx_stopped_by_driver = 0;
+ − start_receiver (uart);
+ − }
+ −
+ − } else {
+ −
+ − uart->rx_stopped_by_driver = 0;
+ − uart->tx_stopped_by_driver = 0;
+ − }
+ −
+ − result = FD_OK;
+ − }
+ −
+ − return (result);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_SetEscape
+ − *
+ − * Purpose : To return to the command mode at the ACI while a data connection
+ − * is established, an escape sequence has to be detected.
+ − * To distinguish between user data and the escape sequence a
+ − * defined guard period is necessary before and after this sequence.
+ − *
+ − * Arguments: In : escChar : ASCII character which could appear three times
+ − * as an escape sequence.
+ − * guardPeriod: Denotes the minimal duration of the rest before
+ − * the first and after the last character of the
+ − * escape sequence, and the maximal receiving
+ − * duration of the whole escape string. This value
+ − * is expressed in ms.
+ − * Out: none
+ − *
+ − * Returns : FD_OK : Successful operation.
+ − * FD_INTERNAL_ERR : Internal problem with the hardware.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_SetEscape (T_fd_UartId uartNo,
+ − SYS_UWORD8 escChar,
+ − SYS_UWORD16 guardPeriod)
+ − {
+ − t_uart *uart;
+ −
+ − /*
+ − * There is no case where FD_INTERNAL_ERR may be returned.
+ − */
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − uart->esc_seq_modified = 1;
+ − uart->esc_seq_character = escChar;
+ − uart->guard_period = CONVERT_TIME_IN_TDMA ((UNSIGNED) guardPeriod);
+ − uart->esc_seq_modified = 0; /* Set to 0 by the RX interrupt handler. */
+ −
+ − return (FD_OK);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_InpAvail
+ − *
+ − * Purpose : Returns the number of characters available in the RX buffer of the
+ − * driver. If the driver is disabled the function returns 0.
+ − *
+ − * Arguments: In : none
+ − * Out: none
+ − *
+ − * Returns : >= 0 : The returned value is the amount of data in the
+ − * RX buffer.
+ − * FD_NOT_READY : The function is called while the callback of the
+ − * readOutFunc function is activated and still not
+ − * terminated.
+ − * FD_INTERNAL_ERR : Internal problem with the hardware.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_InpAvail (T_fd_UartId uartNo)
+ − {
+ − T_FDRET result;
+ − t_uart *uart;
+ − SYS_UWORD16 bytes_read;
+ − SYS_UWORD16 bytes_in_rx_buffer;
+ −
+ − /*
+ − * There is no case where FD_INTERNAL_ERR may be returned.
+ − */
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − if (uart->rd_call_setup == rm_notDefined)
+ − result = FD_NOT_READY;
+ −
+ − else if (DRIVER_DISABLED (uart))
+ − result = 0;
+ −
+ − else {
+ −
+ − bytes_in_rx_buffer = get_bytes_in_rx_buffer (uart);
+ −
+ − /*
+ − * Update reading pointer of the RX buffer if a callback from LISR
+ − * has been done.
+ − */
+ −
+ − if (uart->rd_call_from_hisr_in_progress) {
+ −
+ − bytes_read = uart->rd_size_before_call[0] -
+ − uart->rd_size_after_call[0] +
+ − uart->rd_size_before_call[1] -
+ − uart->rd_size_after_call[1];
+ −
+ − uart->rx_out += bytes_read;
+ −
+ − if (uart->rx_out >= &(uart->rx_buffer[0]) + uart->buffer_size + 1)
+ − uart->rx_out = uart->rx_out - uart->buffer_size - 1;
+ −
+ − /*
+ − * Check if the low watermark is reached to enable the receiver.
+ − */
+ −
+ − bytes_in_rx_buffer = get_bytes_in_rx_buffer (uart);
+ −
+ − if ((uart->flow_control_mode != fc_none) &&
+ − (bytes_in_rx_buffer <= RX_LOW_WATERMARK (uart->buffer_size))) {
+ −
+ − if ((!uart->rx_stopped_by_application) &&
+ − uart->rx_stopped_by_driver)
+ − start_receiver (uart);
+ −
+ − uart->rx_stopped_by_driver = 0;
+ − }
+ −
+ − uart->rd_call_from_hisr_in_progress = 0;
+ − }
+ −
+ − result = (T_FDRET) bytes_in_rx_buffer;
+ − }
+ −
+ − return (result);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_OutpAvail
+ − *
+ − * Purpose : Returns the number of free characters in TX buffer of the driver.
+ − * If the driver is disabled the function returns 0.
+ − *
+ − * Arguments: In : none
+ − * Out: none
+ − *
+ − * Returns : >= 0 : The returned value is the amount of data in the
+ − * TX buffer.
+ − * FD_NOT_READY : The function is called while the callback of the
+ − * writeInFunc function is activated and still not
+ − * terminated.
+ − * FD_INTERNAL_ERR : Internal problem with the hardware.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_OutpAvail (T_fd_UartId uartNo)
+ − {
+ − T_FDRET result;
+ − t_uart *uart;
+ − SYS_UWORD16 bytes_written;
+ −
+ − /*
+ − * There is no case where FD_INTERNAL_ERR may be returned.
+ − */
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − if (uart->wr_call_setup == rm_notDefined)
+ − result = FD_NOT_READY;
+ −
+ − else if (DRIVER_DISABLED (uart))
+ − result = 0;
+ −
+ − else {
+ −
+ − /*
+ − * Update reading pointer of the TX buffer if a callback from LISR
+ − * has been done.
+ − */
+ −
+ − if (uart->wr_call_from_hisr_in_progress) {
+ −
+ − bytes_written = uart->wr_size_before_call[0] -
+ − uart->wr_size_after_call[0] +
+ − uart->wr_size_before_call[1] -
+ − uart->wr_size_after_call[1];
+ −
+ − uart->tx_in += bytes_written;
+ −
+ − if (uart->tx_in >= &(uart->tx_buffer[0]) + uart->buffer_size + 1)
+ − uart->tx_in = uart->tx_in - uart->buffer_size - 1;
+ −
+ − uart->wr_call_from_hisr_in_progress = 0;
+ −
+ − /*
+ − * if the TX FIFO is empty, unmask TX empty interrupt.
+ − */
+ −
+ − if (!uart->tx_stopped_by_driver &&
+ − (READ_UART_REGISTER (uart, LSR) & THRE))
+ − {
+ − /*
+ − * Disable sleep mode then unmask Tx interrupt.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI);
+ − }
+ − }
+ −
+ − result = (T_FDRET) (uart->buffer_size - get_bytes_in_tx_buffer (uart));
+ − }
+ −
+ − return (result);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_EnterSleep
+ − *
+ − * Purpose : Checks if UART is ready to enter Deep Sleep. If ready, enables
+ − * wake-up interrupt.
+ − *
+ − * Arguments: In : none
+ − * Out: none
+ − *
+ − * Returns: 0 : Deep Sleep is not possible.
+ − * >= 1 : Deep Sleep is possible.
+ − *
+ − * Warning: Parameters are not verified.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_EnterSleep (T_fd_UartId uartNo)
+ − {
+ − t_uart *uart;
+ − SYS_BOOL deep_sleep;
+ − volatile SYS_UWORD8 status;
+ −
+ − uart = &(uart_parameters[uartNo]);
+ − deep_sleep = 0;
+ −
+ − /*
+ − * Check if RX & TX FIFOs are both empty
+ − */
+ −
+ − status = READ_UART_REGISTER (uart, LSR);
+ −
+ − if (!(status & DR) &&
+ − (status & TEMT)) {
+ −
+ − /*
+ − * Disable sleep mode.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
+ −
+ − /*
+ − * Mask RX, TX and the modem status interrupts.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) &
+ − ~(ERBI | ETBEI | EDSSI));
+ −
+ − /*
+ − * Enable the wake-up interrupt.
+ − */
+ −
+ − ENABLE_WAKEUP_INTERRUPT (uart);
+ −
+ − deep_sleep = 1;
+ − }
+ −
+ − return (deep_sleep);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_WakeUp
+ − *
+ − * Purpose : Wakes up UART after Deep Sleep.
+ − *
+ − * Arguments: In : none
+ − * Out: none
+ − *
+ − * Returns: FD_OK : Successful operation.
+ − *
+ − * Warning: Parameters are not verified.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_WakeUp (T_fd_UartId uartNo)
+ − {
+ − t_uart *uart;
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − /*
+ − * Disable the wake-up interrupt.
+ − */
+ −
+ − DISABLE_WAKEUP_INTERRUPT (uart);
+ −
+ − /*
+ − * Unmask RX and modem status interrupts then allow sleep mode.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) | (ERBI | EDSSI));
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
+ −
+ − return (FD_OK);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_ReadData
+ − *
+ − * Purpose : To read the received characters out of the RX buffer the address
+ − * of a function is passed. If characters are available, the driver
+ − * calls this function and pass the address and the amount of
+ − * readable characters. Because the RX buffer is circular, the
+ − * callback function may be called with more than one address of
+ − * buffer fragment.
+ − * The readOutFunc function modifies the contents of the size array
+ − * to return the driver the number of processed characters. Each
+ − * array entry is decremented by the number of bytes read in the
+ − * fragment.
+ − * If the UAF_ReadData is called while the RX buffer is empty, it
+ − * depends on the suspend parameter to suspend the call-back or to
+ − * leave without any operation. In the case of suspension, the
+ − * return value of UAF_ReadData is UAF_SUSPENDED. A delayed call-back
+ − * will be performed if:
+ − * - the RX buffer reachs the adjusted threshold (rxThreshold of
+ − * UAF_SetBuffer),
+ − * - the state of a V.24 input line has changed,
+ − * - a break is detected,
+ − * - an escape sequence is detected.
+ − * If no suspension is necessary the function returns the number of
+ − * processed bytes.
+ − *
+ − * Arguments: In : suspend : mode of suspension in case of RX buffer empty.
+ − * readOutFunc: Callback function.
+ − * cldFromIrq: The driver sets this parameter to 1
+ − * if the callback function is called
+ − * from an interrupt service routine.
+ − * reInstall : The call-back function sets this
+ − * parameter to rm_reInstall if the
+ − * driver must call again the callback
+ − * function when the RX threshold level
+ − * is reached. Else it will be set to
+ − * rm_noInstall. Before to call the
+ − * readOutFunc function this parameter
+ − * is set to rm_notDefined.
+ − * nsource : Informed the callback function about
+ − * the number of fragments which are
+ − * ready to copy from the circular RX
+ − * buffer.
+ − * source : Array which contains the addresses
+ − * of the fragments.
+ − * size : Array which contains the sizes of
+ − * each fragments.
+ − * state : The state parameter is the status
+ − * of the V.24 lines and the break /
+ − * escape detection. The state
+ − * parameter is described in the
+ − * specification of UAF_GetLineState.
+ − * Out: none
+ − *
+ − * Returns : >= 0 : Succesful operation. Amount of processed bytes.
+ − * FD_SUSPENDED : The callback is suspended until the buffer or
+ − * state condition changed.
+ − * FD_NOT_READY : The function is called while the callback is
+ − * activated and still not terminated.
+ − * FD_INTERNAL_ERR : Internal problems with the hardware.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_ReadData (T_fd_UartId uartNo,
+ − T_suspendMode suspend,
+ − void (readOutFunc (SYS_BOOL cldFromIrq,
+ − T_reInstMode *reInstall,
+ − SYS_UWORD8 nsource,
+ − SYS_UWORD8 *source[],
+ − SYS_UWORD16 size[],
+ − SYS_UWORD32 state)))
+ − {
+ − T_FDRET result;
+ − t_uart *uart;
+ − SYS_UWORD16 bytes_read;
+ − SYS_UWORD16 bytes_in_rx_buffer;
+ −
+ − /*
+ − * There is no case where FD_INTERNAL_ERR may be returned.
+ − */
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − if (uart->rd_call_setup == rm_notDefined)
+ − result = FD_NOT_READY;
+ −
+ − else if (get_bytes_in_rx_buffer (uart) || uart->esc_seq_received) {
+ −
+ − uart->readOutFunc = readOutFunc;
+ − update_reading_callback (uart, 0); /* 0: call from application. */
+ −
+ − bytes_read = uart->rd_size_before_call[0] -
+ − uart->rd_size_after_call[0] +
+ − uart->rd_size_before_call[1] -
+ − uart->rd_size_after_call[1];
+ −
+ − uart->rx_out += bytes_read;
+ −
+ − if (uart->rx_out >= &(uart->rx_buffer[0]) + uart->buffer_size + 1)
+ − uart->rx_out = uart->rx_out - uart->buffer_size - 1;
+ −
+ − /*
+ − * Check if the low watermark is reached to enable the receiver.
+ − */
+ −
+ − if ((uart->flow_control_mode != fc_none) &&
+ − (get_bytes_in_rx_buffer (uart) <= RX_LOW_WATERMARK (
+ − uart->buffer_size))) {
+ −
+ − if ((!uart->rx_stopped_by_application) &&
+ − uart->rx_stopped_by_driver)
+ − start_receiver (uart);
+ −
+ − uart->rx_stopped_by_driver = 0;
+ − }
+ −
+ − uart->esc_seq_received = 0;
+ − result = (T_FDRET) bytes_read;
+ −
+ − } else if (suspend == sm_suspend) {
+ −
+ − uart->readOutFunc = readOutFunc;
+ − uart->reading_suspended = 1;
+ − result = FD_SUSPENDED;
+ −
+ − } else {
+ −
+ − /*
+ − * The previous callback function is deinstalled.
+ − */
+ −
+ − uart->rd_call_setup = rm_noInstall;
+ − uart->reading_suspended = 0;
+ − result = 0; /* 0 byte read. */
+ − }
+ −
+ − return (result);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_WriteData
+ − *
+ − * Purpose : To write characters into the TX buffer the address of a function
+ − * is passed. If free space is available in the buffer, the driver
+ − * calls this function and passes the destination address and the
+ − * amount of space. Because the RX buffer is circular, the callback
+ − * function may be called with more than one address of buffer
+ − * fragment.
+ − * The writeInFunc function modifies the contents of the size array
+ − * to return the driver the number of processed bytes. Each array
+ − * entry is decremented by the number of bytes written in this
+ − * fragment.
+ − * If the UAF_WriteData function is called while the TX buffer is
+ − * full, it depends on the suspend parameter to suspend the
+ − * call-back or to leave this function without any operation. In the
+ − * case of suspension the returned value of the UAF_WriteData is
+ − * UAF_SUSPENDED. A delayed call-back will be performed if the TX
+ − * buffer reaches the adjusted threshold (txThreshold of
+ − * UAF_SetBuffer). If no suspension is necessary the function returns
+ − * the number of processed bytes.
+ − *
+ − * Arguments: In : suspend : mode of suspension in case of TX buffer empty.
+ − * writeInFunc: Callback function.
+ − * cldFromIrq: The driver sets this parameter to 1
+ − * if the call-back function is called
+ − * from an interrupt service routine.
+ − * reInstall : The callback function sets this
+ − * parameter to rm_reInstall if the
+ − * driver must call again the callback
+ − * function when the TX threshold level
+ − * is reached. Else it will be set to
+ − * rm_noInstall. Before to call the
+ − * readOutFunc function this parameter
+ − * is set to rm_notDefined.
+ − * nsource : Informed the callback function about
+ − * the number of fragments which are
+ − * available in the TX buffer.
+ − * dest : Array which contains the addresses
+ − * of the fragments.
+ − * size : Array which contains the sizes of
+ − * each fragments.
+ − * Out: none
+ − *
+ − * Returns : >= 0 : Succesful operation. Amount of processed bytes.
+ − * FD_SUSPENDED : The callback is suspended until the buffer
+ − * condition changed.
+ − * FD_NOT_READY : The function is called while the callback is
+ − * activated and still not terminated.
+ − * FD_INTERNAL_ERR : Internal problems with the hardware.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_WriteData (T_fd_UartId uartNo,
+ − T_suspendMode suspend,
+ − void (writeInFunc (SYS_BOOL cldFromIrq,
+ − T_reInstMode *reInstall,
+ − SYS_UWORD8 ndest,
+ − SYS_UWORD8 *dest[],
+ − SYS_UWORD16 size[])))
+ − {
+ − T_FDRET result;
+ − t_uart *uart;
+ − SYS_UWORD16 bytes_written;
+ −
+ − /*
+ − * There is no case where FD_INTERNAL_ERR may be returned.
+ − */
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − if (uart->wr_call_setup == rm_notDefined)
+ − result = FD_NOT_READY;
+ −
+ − else if ((!DRIVER_DISABLED (uart)) &&
+ − (get_bytes_in_tx_buffer (uart) < uart->buffer_size)) {
+ −
+ − #if (BOARD == 31)
+ − /*while ((*((volatile SYS_UWORD16 *) ARMIO_IN) & 0x0100) == 0x0000)
+ − {
+ − *((volatile SYS_UWORD16 *) ARMIO_OUT) &= ~(0x0040);
+ − }*/
+ − if ((*((volatile SYS_UWORD16 *) ARMIO_IN) & 0x0100) == 0x0000)
+ − {
+ − *((volatile SYS_UWORD16 *) ARMIO_OUT) &= ~(0x0040);
+ − NU_Sleep(4); // 1.84 ms
+ − }
+ − *((volatile SYS_UWORD16 *) ARMIO_OUT) |= 0x0040;
+ −
+ − #endif
+ − uart->writeInFunc = writeInFunc;
+ − update_writing_callback (uart, 0); /* 0: call from application. */
+ −
+ − bytes_written = uart->wr_size_before_call[0] -
+ − uart->wr_size_after_call[0] +
+ − uart->wr_size_before_call[1] -
+ − uart->wr_size_after_call[1];
+ −
+ − uart->tx_in += bytes_written;
+ −
+ − if (uart->tx_in >= &(uart->tx_buffer[0]) + uart->buffer_size + 1)
+ − uart->tx_in = uart->tx_in - uart->buffer_size - 1;
+ −
+ − /*
+ − * If:
+ − * - there is no break to send,
+ − * - the flow control is not activated,
+ − * unmask the TX empty interrupt to be able to send characters.
+ − */
+ −
+ − if (!uart->break_to_send &&
+ − !uart->tx_stopped_by_driver)
+ − {
+ − /*
+ − * Disable sleep mode then unmask Tx interrupt.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) | ETBEI);
+ − }
+ −
+ − result = (T_FDRET) bytes_written;
+ −
+ − } else if (suspend == sm_suspend) {
+ −
+ − uart->writeInFunc = writeInFunc;
+ − uart->writing_suspended = 1;
+ − result = FD_SUSPENDED;
+ −
+ − } else {
+ −
+ − /*
+ − * The previous callback function is deinstalled.
+ − */
+ −
+ − uart->wr_call_setup = rm_noInstall;
+ − uart->writing_suspended = 0;
+ − result = 0;
+ − }
+ −
+ − return (result);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_StopRec
+ − *
+ − * Purpose : If a flow control mode is set, this function tells the terminal
+ − * equipment that no more data can be received.
+ − * XON/XOFF: XOFF is sent.
+ − * DTR/DSR : DTR is desactivated.
+ − * RTS/CTS : RTS is deactivated.
+ − *
+ − * Arguments: In : none
+ − * Out: none
+ − *
+ − * Returns : FD_OK : Successful operation.
+ − * FD_INTERNAL_ERR : Internal problem with the hardware.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_StopRec (T_fd_UartId uartNo)
+ − {
+ − t_uart *uart;
+ −
+ − /*
+ − * There is no case where FD_INTERNAL_ERR may be returned.
+ − */
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − if (uart->flow_control_mode != fc_none)
+ − stop_receiver (uart);
+ −
+ − uart->rx_stopped_by_application = 1;
+ −
+ − return (FD_OK);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_StartRec
+ − *
+ − * Purpose : If a flow control mode is set, this function tells the terminal
+ − * equipment that the receiver is again able to receive more data.
+ − * If the buffer has already reached the high water mark the driver
+ − * sends the signal only if the buffer drains to a low water mark.
+ − * XON/XOFF: XON is sent.
+ − * DTR/DSR : DTR is activated.
+ − * RTS/CTS : RTS is activated.
+ − *
+ − * Arguments: In : none
+ − * Out: none
+ − *
+ − * Returns : FD_OK : Successful operation.
+ − * FD_INTERNAL_ERR : Internal problem with the hardware.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_StartRec (T_fd_UartId uartNo)
+ − {
+ − t_uart *uart;
+ −
+ − /*
+ − * There is no case where FD_INTERNAL_ERR may be returned.
+ − */
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − if ((uart->flow_control_mode != fc_none) && (!uart->rx_stopped_by_driver))
+ − start_receiver (uart);
+ −
+ − uart->rx_stopped_by_application = 0;
+ −
+ − return (FD_OK);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_GetLineState
+ − *
+ − * Purpose : Returns the state of the V.24 lines, the flow control state and
+ − * the resukt of the break/escape detection process as a bit field.
+ − *
+ − * Arguments: In : none
+ − * Out: state : State of the V.24 lines, the flow control state and
+ − * the result of the break/escape sequence detection
+ − * process as a bit field.
+ − *
+ − * Returns : FD_OK : Successful operation.
+ − * FD_NOT_READY : The function is called while the callback of
+ − * the readOutFunc function is activated and still
+ − * not terminated.
+ − * FD_INTERNAL_ERR : Internal problem with the hardware.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_GetLineState (T_fd_UartId uartNo, SYS_UWORD32 *state)
+ − {
+ − T_FDRET result;
+ − t_uart *uart;
+ −
+ − /*
+ − * There is no case where FD_INTERNAL_ERR may be returned.
+ − * Signals not supported are reported as 0.
+ − */
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − if (uart->rd_call_setup == rm_notDefined)
+ − result = FD_NOT_READY;
+ −
+ − else {
+ −
+ − /*
+ − * The field state_2 is used when state_1 is set to 0 to avoid to
+ − * lose events detected in the RX interrupt handler.
+ − * Fields BRK and BRKLEN are set when a break is detected.
+ − * The field ESC is set when an escape sequence is detected.
+ − */
+ −
+ − *state = uart->state_2;
+ − uart->state_2 = 0;
+ − uart->state = &(uart->state_2);
+ −
+ − *state |= uart->state_1;
+ − uart->state_1 = 0;
+ − uart->state = &(uart->state_1);
+ −
+ − *state |= ((((SYS_UWORD32) uart->cts_level) << RTS) |
+ −
+ − (((SYS_UWORD32) (uart->tx_stopped_by_application |
+ − uart->tx_stopped_by_driver)) << TXSTP) |
+ −
+ − (((SYS_UWORD32) (uart->rx_stopped_by_application |
+ − uart->rx_stopped_by_driver)) << RXSTP) |
+ −
+ − (((SYS_UWORD32) (uart->buffer_size -
+ − get_bytes_in_rx_buffer (uart))) << RXBLEV));
+ −
+ − /*
+ − * Fields SA, SB and X are set according to the flow control:
+ − *
+ − * None RTS/CTS XON/XOFF
+ − * SA 0 (ns) 0 (ns) 0 (ns)
+ − * SB RTS 0 RTS
+ − * X 0 RTS XON:0 XOFF:1 (transmitter)
+ − *
+ − * ns: signal not supported.
+ − * DTR/DSR flow control is not supported.
+ − */
+ −
+ − if (uart->flow_control_mode != fc_rts)
+ − *state |= (((SYS_UWORD32) uart->cts_level) << SB);
+ −
+ − if (uart->flow_control_mode == fc_rts)
+ − *state |= (((SYS_UWORD32) uart->cts_level) << X);
+ −
+ − else if ((uart->flow_control_mode == fc_xoff) &&
+ − (uart->tx_stopped_by_application ||
+ − uart->tx_stopped_by_driver))
+ − *state |= (1 << X);
+ −
+ − result = FD_OK;
+ − }
+ −
+ − return (result);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_SetLineState
+ − *
+ − * Purpose : Sets the states of the V.24 status lines according to the bit
+ − * field of the parameter state.
+ − *
+ − * Arguments: In : state : Bit field. Only the signals which are marked with
+ − * the 'set' access can be used to change the state of
+ − * the signal.
+ − * mask : Bit field with the same structure as state. Each bit
+ − * in state corresponds to a bit in mask. Settabled
+ − * bits marked by a 1 are manipulated by the driver.
+ − * Out: none
+ − *
+ − * Returns : FD_OK : Successful operation.
+ − * FD_INTERNAL_ERR : Internal problem with the hardware.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_SetLineState (T_fd_UartId uartNo,
+ − SYS_UWORD32 state,
+ − SYS_UWORD32 mask)
+ − {
+ − t_uart *uart;
+ − UNSIGNED break_length;
+ −
+ − uart = &(uart_parameters[uartNo]);
+ −
+ − /*
+ − * There is no case where FD_INTERNAL_ERR may be returned.
+ − * DTR is not supported. The SA field is ignored.
+ − */
+ −
+ − if ((mask & (1 << SA)) || (mask & (1 << DCD)))
+ − return (FD_NOT_SUPPORTED); /* Return used to simplify the code */
+ −
+ − /*
+ − * Check if a break has to be sent.
+ − */
+ −
+ − uart->break_length = (UNSIGNED) ((state >> BRKLEN) & 0xFF);
+ −
+ − if (state & (1 << BRK) && (mask & (1 << BRK))) {
+ −
+ − if (uart->break_length > FIFO_SIZE)
+ − return (FD_NOT_SUPPORTED); /* Return used to simplify the code */
+ −
+ − else {
+ −
+ − uart->time_without_character =
+ − compute_break_time (uart->baudrate, uart->bits_per_char, 3);
+ −
+ − uart->break_to_send = 1;
+ −
+ − /*
+ − * If the TX FIFO is empty the break is send from this function
+ − * else the interrupt handler will send the break.
+ − */
+ −
+ − if (READ_UART_REGISTER (uart, LSR) & TEMT)
+ − send_break(uart);
+ − }
+ − }
+ −
+ − /*
+ − * Disable sleep mode.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
+ −
+ − /*
+ − * The CTS field is ignored if the RTS/CTS flow control is selected.
+ − */
+ −
+ − if (mask & (1 << CTS)) {
+ −
+ − if (uart->flow_control_mode != fc_rts) {
+ −
+ − /*
+ − * As the RTS/CTS flow control is not selected, the X bit does not
+ − * control CTS. CTS needs only to be activated or deactivated
+ − * according to the value of the CTS field.
+ − */
+ −
+ − if (state & (1 << CTS))
+ − WRITE_UART_REGISTER (
+ − uart, MCR, READ_UART_REGISTER (uart, MCR) | MRTS);
+ −
+ − else
+ − WRITE_UART_REGISTER (
+ − uart, MCR, READ_UART_REGISTER (uart, MCR) & ~MRTS);
+ −
+ − } else if (!(mask & (1 << X))) {
+ −
+ − /*
+ − * The RTS/CTS flow control is selected but the X bit in the mask
+ − * is null. Then the CTS bit controls CTS and the receiver must be
+ − * stopped or started according to the state of the CTS bit.
+ − * The receiver is started only if it was not stopped by the driver
+ − * and if it was stopped by the application.
+ − */
+ −
+ − if (state & (1 << CTS)) {
+ −
+ − if (!uart->rx_stopped_by_application) {
+ −
+ − if (!uart->rx_stopped_by_driver)
+ − stop_receiver (uart);
+ −
+ − uart->rx_stopped_by_application = 1;
+ − }
+ −
+ − } else {
+ −
+ − if ((!uart->rx_stopped_by_driver) &&
+ − uart->rx_stopped_by_application)
+ − start_receiver (uart);
+ −
+ − uart->rx_stopped_by_application = 0;
+ − }
+ − }
+ − }
+ −
+ − /*
+ − * The DCD field is ignored if the SB bit of the mask is set.
+ − */
+ −
+ − if (!(mask & (1 << SB)) && (mask & (1 << DCD))) {
+ −
+ − if (state & (1 << DCD))
+ − WRITE_UART_REGISTER (
+ − uart, MCR, READ_UART_REGISTER (uart, MCR) | MDTR);
+ −
+ − else
+ − WRITE_UART_REGISTER (
+ − uart, MCR, READ_UART_REGISTER (uart, MCR) & ~MDTR);
+ − }
+ −
+ − /*
+ − * Signals are set according to fields SA, SB and X states and flow
+ − * control:
+ − *
+ − * None RTS/CTS XON/XOFF
+ − * SA 0 (ns) 0 (ns) 0 (ns)
+ − * SB DCD DCD DCD
+ − * X ignore CTS XON:0 XOFF:1 (receiver)
+ − *
+ − * ns: signal not supported.
+ − * DTR/DSR flow control is not supported.
+ − */
+ −
+ − if (mask & (1 << SB)) {
+ −
+ − if (state & (1 << SB))
+ − WRITE_UART_REGISTER (
+ − uart, MCR, READ_UART_REGISTER (uart, MCR) | MDTR);
+ −
+ − else
+ − WRITE_UART_REGISTER (
+ − uart, MCR, READ_UART_REGISTER (uart, MCR) & ~MDTR);
+ − }
+ −
+ −
+ − if ((mask & (1 << X)) &&
+ − (uart->flow_control_mode != fc_none)) {
+ −
+ − if (state & (1 << X)) {
+ −
+ − if (!uart->rx_stopped_by_application) {
+ −
+ − if (!uart->rx_stopped_by_driver)
+ − stop_receiver (uart);
+ −
+ − uart->rx_stopped_by_application = 1;
+ − }
+ −
+ − } else {
+ −
+ − /*
+ − * The receiver is started only if it is not stopped by the driver
+ − * and if it is stopped by the application.
+ − */
+ −
+ − if ((!uart->rx_stopped_by_driver) &&
+ − uart->rx_stopped_by_application)
+ − start_receiver (uart);
+ −
+ − uart->rx_stopped_by_application = 0;
+ − }
+ − }
+ −
+ − /*
+ − * Re-enable sleep mode.
+ − */
+ −
+ − WRITE_UART_REGISTER (
+ − uart, IER, READ_UART_REGISTER (uart, IER) | IER_SLEEP);
+ −
+ − return (FD_OK);
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_InterruptHandler
+ − *
+ − * Purpose : Interrupt handler.
+ − *
+ − * Arguments: In : uart_id : origin of interrupt
+ − * interrupt_status: source of interrupt
+ − * Out: none
+ − *
+ − * Returns : none
+ − *
+ − ******************************************************************************/
+ −
+ − void
+ − UAF_InterruptHandler (T_fd_UartId uart_id,
+ − SYS_UWORD8 interrupt_status)
+ − {
+ −
+ − t_uart *uart;
+ −
+ − /*
+ − * uart_id is not used.
+ − */
+ −
+ − uart = &(uart_parameters[uart_id]);
+ −
+ − uart->current_time = NU_Retrieve_Clock ();
+ −
+ − /*
+ − * Causes of interrupt:
+ − * - trigger level reached,
+ − * - character time-out indication,
+ − * - transmitter holding register empty,
+ − * - modem status.
+ − */
+ −
+ − switch (interrupt_status) {
+ −
+ − case RX_DATA:
+ −
+ − read_rx_fifo (uart);
+ − break;
+ −
+ − case TX_EMPTY:
+ −
+ − fill_tx_fifo (uart);
+ − break;
+ −
+ − case MODEM_STATUS:
+ −
+ − check_v24_input_lines (uart);
+ − break;
+ − }
+ − }
+ −
+ − /*******************************************************************************
+ − *
+ − * UAF_CheckXEmpty
+ − *
+ − * Purpose : Checks the empty condition of the Transmitter.
+ − *
+ − * Arguments: In : none
+ − * Out: none
+ − *
+ − * Returns : FD_OK : Empty condition OK.
+ − * FD_NOT_READY : Empty condition not OK.
+ − * FD_INTERNAL_ERR : Internal problem with the hardware.
+ − *
+ − ******************************************************************************/
+ −
+ − T_FDRET
+ − UAF_CheckXEmpty (T_fd_UartId uartNo)
+ − {
+ − T_FDRET result;
+ − t_uart *uart;
+ − SYS_UWORD8 status;
+ −
+ − /*
+ − * There is no case where FD_INTERNAL_ERR may be returned.
+ − */
+ −
+ − result = FD_OK;
+ −
+ − uart = &(uart_parameters[uartNo]);
+ − status = READ_UART_REGISTER (uart, LSR);
+ −
+ − /*
+ − * Checks if:
+ − * - the TX SW Buffer is empty,
+ − * - the TX HW FIFO is empty (THRE),
+ − * - the Transmitter Shift Register is empty (TEMT).
+ − */
+ −
+ − if (!(TX_BUFFER_EMPTY (uart)) ||
+ − !(status & THRE) ||
+ − !(status & TEMT))
+ −
+ − result = FD_NOT_READY;
+ −
+ − return (result);
+ − }
+ −