📄 uartfax.c
字号:
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 /* No error */
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 (VOID)
{
SYS_UWORD16 bytes_free_in_rx_buffer;
SYS_UWORD16 wrap_around_counter;
SYS_UWORD16 bytes_in_rx_buffer;
SYS_UWORD16 bytes_read;
SYS_UWORD16 bytes_to_copy;
SYS_UWORD8 *current_byte;
SYS_UWORD8 xon_xoff_detected;
t_uart *uart;
/*
* Since new characters have been received, the sleep timer is reset then
* restarted preventing the system to enter deep-sleep for a new period of
* time.
*/
SER_restart_uart_sleep_timer ();
uart_sleep_timer_enabled = 1;
#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41) || (BOARD == 43) || (BOARD == 45))
uart->index_hisr = (uart->index_hisr + 1) & 0x01; /* 0 or 1 */
#endif
xon_xoff_detected = 0;
uart = &uart_parameters;
/*
* 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 (uart)) {
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) {
/*
* For SW Flow Control, need to further investigate the processing
* in order to improve the performance of the driver, and in order
* to avoid managing the wrap around of the circular buffer each
* time a character is copied.
*/
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;
#if ((CHIPSET != 5) && (CHIPSET != 6))
/*
* Disable sleep mode.
*/
WRITE_UART_REGISTER (
uart, IER, READ_UART_REGISTER (uart, IER) & ~IER_SLEEP);
#endif
/*
* Unmask Tx interrupt.
*/
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 { /* No Flow Control or HW Flow Control */
/*
* Figure out the most restricting condition.
*/
bytes_to_copy =
Min3 (bytes_free_in_rx_buffer, wrap_around_counter, bytes_read);
/*
* Copy characters into the circular Rx buffer.
*/
memcpy (uart->rx_in, current_byte, bytes_to_copy);
/*
* Update first the variables associated to blocking conditions:
* if (bytes_read = 0) OR
* (bytes_free_in_rx_buffer = 0) => No more characters to copy.
*/
bytes_free_in_rx_buffer -= bytes_to_copy;
bytes_read -= bytes_to_copy;
wrap_around_counter -= bytes_to_copy;
if (!wrap_around_counter)
uart->rx_in = &(uart->rx_buffer[0]);
else
uart->rx_in += bytes_to_copy;
/*
* Check if there are still some characters to copy.
*/
if (bytes_read && bytes_free_in_rx_buffer) {
/*
* Update the remaining variables and figure out again the
* most restricting condition. Since (bytes_read = 0) and
* (bytes_free_in_rx_buffer = 0) are blocking conditions, if
* we reach that point it means that the wrap around condition
* has just occurred and it is not needed to manage it again.
*/
current_byte += bytes_to_copy;
bytes_to_copy = Min (bytes_read, bytes_free_in_rx_buffer);
/*
* Copy characters into the circular Rx buffer and update
* current pointer.
*/
memcpy (uart->rx_in, current_byte, bytes_to_copy);
uart->rx_in += bytes_to_copy;
/*
* bytes_free_in_rx_buffer not updated since not used anymore.
*/
}
} /* end if (uart->flow_control_mode == fc_xoff) */
/*
* 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) ||
#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41) || (BOARD == 43) || (BOARD == 45))
uart->dtr_change_detected[uart->index_hisr] ||
#endif
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;
#if ((BOARD == 8) || (BOARD == 9) || (BOARD == 40) || (BOARD == 41) || (BOARD == 43) || (BOARD == 45))
uart->dtr_change_detected[uart->index_hisr] = 0;
#endif
}
}
}
}
/*******************************************************************************
*
* 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 (VOID)
{
t_uart *uart;
uart = &uart_parameters;
/*
* 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_susp
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -