📄 uart.c
字号:
* Select UART mode. */ WRITE_UART_REGISTER (uart, MDR1, UART_MODE); /* * Clear Interrupt and check that Rx FIFO is empty. */ dummy = READ_UART_REGISTER (uart, IIR); while (READ_UART_REGISTER (uart, LSR) & DR) dummy = READ_UART_REGISTER (uart, RHR);#if ((CHIPSET != 5) && (CHIPSET != 6)) /* * Enable sleep mode. */ WRITE_UART_REGISTER (uart, IER, IER_SLEEP);#endif}/******************************************************************************* * * UA_Init * * Purpose : Initializes the module and the UART. * * Arguments: In : uart_id : UART id. * baudrate: baud rate selected. * callback: user's function called characters are received. * Out: none * * Returns: none * * Warning: Parameters are not verified. * ******************************************************************************/voidUA_Init (T_tr_UartId uart_id, T_tr_Baudrate baudrate, void (callback_function (void))){ t_uart *uart; int index;#ifdef UART_RX_BUFFER_DUMP uart_rx_buffer_dump.rx_in = uart_rx_buffer_dump.rx_buffer;#endif for (index = 0; index < NUMBER_OF_TR_UART; index++) uart_parameter[index].base_address = base_address[index]; uart = &(uart_parameter[uart_id]); uart->rx_in = &(uart->rx_buffer[0]); uart->rx_out = &(uart->rx_buffer[0]); uart->callback_function = callback_function; uart->framing_error = 0; uart->parity_error = 0; uart->overrun_error = 0; uart->dle_detected = 0; uart->inframe = 0; uart->encapsulation_flag = 0; uart->frame_length = 0; /* * Mask all interrupts causes and disable sleep mode. */ WRITE_UART_REGISTER (uart, IER, 0x00); /* * Reset UART mode configuration. */ WRITE_UART_REGISTER (uart, MDR1, RESET_DEFAULT_STATE | 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); /* * 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);#if ((CHIPSET == 5) || (CHIPSET == 6)) /* * Unmask RX interrupt */ WRITE_UART_REGISTER (uart, IER, ERBI);#else /* * Unmask RX interrupt and allow sleep mode. */ WRITE_UART_REGISTER (uart, IER, ERBI | IER_SLEEP);#endif}/******************************************************************************* * * UA_ReadNChars * * Purpose : Reads N characters from the RX buffer. * * Arguments: In : uart_id : UART id. * buffer : buffer address where the characters are * copied. * chars_to_read: number of characters to read. * Out: none * * Returns : The number of characters read. * * Warning: Parameters are not verified. * ******************************************************************************/SYS_UWORD32UA_ReadNChars (T_tr_UartId uart_id, char *buffer, SYS_UWORD32 chars_to_read){ SYS_UWORD32 chars_in_rx_buffer; SYS_UWORD32 chars_to_copy; SYS_UWORD32 chars_written; char *rx_in; t_uart *uart; uart = &(uart_parameter[uart_id]); /* * A copy of the rx_in pointer is used because it may be updated by * the interrupt handler. * Get the number of bytes available in the RX buffer. */ rx_in = uart->rx_in; if (uart->rx_out <= rx_in) chars_in_rx_buffer = (SYS_UWORD32) (rx_in - uart->rx_out); else chars_in_rx_buffer = (SYS_UWORD32) (rx_in - uart->rx_out + BUFFER_SIZE + 1); /* * No more bytes than those received may be written in the output buffer. */ if (chars_in_rx_buffer >= chars_to_read) chars_to_copy = chars_to_read; else chars_to_copy = chars_in_rx_buffer; chars_written = chars_to_copy; /* * Write the received bytes in the output buffer. */ while (chars_to_copy) { *(buffer++) = *(uart->rx_out++); chars_to_copy--; if (uart->rx_out == &(uart->rx_buffer[0]) + BUFFER_SIZE + 1) uart->rx_out = &(uart->rx_buffer[0]); } return (chars_written);}/******************************************************************************* * * UA_ReadNBytes * * Purpose : Reads and destuff N bytes from the RX buffer. * * Arguments: In : uart_id : UART id. * buffer : buffer address where the bytes are copied. * chars_to_read: number of bytes to read. * Out: eof_detected : indicates if an EOF has been detected. Possible * values are: * - 0: EOF not detected, * - 1: EOF detected and no more bytes left, * - 2: EOF not detected and more bytes left. * Users must invoke this function one more * time in order to get those remaining * bytes, * - 3: EOF detected and more bytes left. Users * must invoke this function one more time * in order to get those remaining bytes. * * Returns : The number of bytes read. * * Warning: Parameters are not verified. * ******************************************************************************/SYS_UWORD32UA_ReadNBytes (T_tr_UartId uart_id, char *buffer_p, SYS_UWORD32 bytes_to_read, SYS_BOOL *eof_detected_p){ SYS_UWORD32 bytes_written; SYS_UWORD32 bytes_in_rx_buffer; SYS_UWORD32 bytes_to_process; t_uart *uart_p; char *rx_in_p; bytes_written = 0; uart_p = &(uart_parameter[uart_id]); /* * A copy of the rx_in pointer is used because it may be updated by * the interrupt handler. * Get the number of bytes available in the RX buffer. */ rx_in_p = uart_p->rx_in; if (uart_p->rx_out <= rx_in_p) bytes_in_rx_buffer = (SYS_UWORD32) (rx_in_p - uart_p->rx_out); else bytes_in_rx_buffer = (SYS_UWORD32) (rx_in_p - uart_p->rx_out + BUFFER_SIZE + 1); /* * No more bytes than those received may be processed and then written * in the output buffer. */ if (bytes_in_rx_buffer > bytes_to_read) { bytes_to_process = bytes_to_read; /* * More bytes left. Users must invoke this function one more time * in order to get those remaining bytes. */ *eof_detected_p = 2; } else { bytes_to_process = bytes_in_rx_buffer; /* * No more bytes left. */ *eof_detected_p = 0; } /* * Perform the byte destuffing and then write the "valid" received bytes in * the output buffer. */ while ((bytes_to_process) && !(*eof_detected_p & 0x01)) { switch (*(uart_p->rx_out)) { /* * Current byte is DLE. */ case DLE: if (!uart_p->dle_detected) { /* * No DLE previously detected => * Skip the current byte and set the flag. */ uart_p->dle_detected = 1; uart_p->rx_out++; } else { /* if (uart_p->dle_detected) */ if (uart_p->inframe) { /* * DLE previously detected AND currently inside of a frame => * Copy the current byte in the output buffer, reset the flag * and increase the frame length. */ uart_p->dle_detected = 0; uart_p->frame_length++; *(buffer_p++) = *(uart_p->rx_out++); bytes_written++; } else { /* if (!uart_p->inframe) */ /* * DLE previously detected AND currently outside of a frame => * Skip the current byte. */ uart_p->rx_out++; } } break; /* case DLE */ /* * Current byte is STX. */ case STX: if ((!uart_p->dle_detected) && (uart_p->inframe)) { /* * No DLE previously detected AND currently inside of a frame. */ if (uart_p->frame_length) { /* * Frame length is not zero (End of Frame) => * Skip the current byte and set the flags (EOF). */ uart_p->inframe = 0; uart_p->frame_length = 0; uart_p->rx_out++; /* * More bytes left. */ if ((*eof_detected_p == 0) && (bytes_to_process)) *eof_detected_p = 2; /* * EOF detected. */ (*eof_detected_p)++; } else { /* if (!uart_p->frame_length) */ /* * Frame length is zero (STX followed by another STX = * Synchro lost but start of a new frame) => * Skip the current byte and keep the flag set. */ uart_p->rx_out++; } } else if ((!uart_p->dle_detected) && (!uart_p->inframe)) { /* * No DLE previously detected AND currently outside of a * frame (Start of Frame) => * Skip the current byte and set the flag. */ uart_p->inframe = 1; uart_p->rx_out++; } else if ((uart_p->dle_detected) && (uart_p->inframe)) { /* * DLE previously detected AND currently inside of a frame => * Copy the current byte in the output buffer, reset the flag * and increase the frame length. */ uart_p->dle_detected = 0; uart_p->frame_length++; *(buffer_p++) = *(uart_p->rx_out++); bytes_written++; } else if ((uart_p->dle_detected) && (!uart_p->inframe)) { /* * DLE previously detected AND currently outside of a frame => * Skip the current byte and reset the flag. */ uart_p->dle_detected = 0; uart_p->rx_out++; } break; /* case STX */ /* * Current byte is neither DLE nor STX. */ default: if (uart_p->inframe) { /* * Currently inside of a frame => * Copy the current byte in the output buffer and increase * the frame length. */ uart_p->frame_length++; *(buffer_p++) = *(uart_p->rx_out++); bytes_written++; } else { /* if (!uart_p->inframe) */ /* * Currently outside of a frame => * Skip the current byte. */ uart_p->rx_out++; } break; /* default */ } if (uart_p->rx_out == &(uart_p->rx_buffer[0]) + BUFFER_SIZE + 1) uart_p->rx_out = &(uart_p->rx_buffer[0]); bytes_to_process--; } return (bytes_written);}/*******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -