Files
2026-06-06 16:49:48 +08:00

200 lines
6.5 KiB
C

/*!
* \file xc6xxx_hal_uart.c
*
* \brief Target xc6xxx hal uart implementation
*
* \copyright Revised BSD License, see section \ref LICENSE.
*
* \code
*
* _ __ _ ________ _
* | |/ /(_)___ / ____/ /_ (_)___
* | // / __ \/ / / __ \/ / __ \
* / |/ / / / / /___/ / / / / /_/ /
* /_/|_/_/_/ /_/\____/_/ /_/_/ .___/
* /_/
* (C) 2022-2025 XinChip
*
* \endcode
*
* \author ( XinChip ) Alex-J
*
* \author ( XinChip )
*/
/*-----------------------------------------------------------------------------------
INCLUDE HEADE FILES
------------------------------------------------------------------------------------*/
#include "xc_drv_uart.h"
/*------------------------------------------------------------------------------------
Macros
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Local Variables
-------------------------------------------------------------------------------------*/
uint8_t __attribute__((aligned(4))) uart_txdmabuff[UART_BUFF_LEN];
uint8_t __attribute__((aligned(4))) uart_rxdmabuff[UART_BUFF_LEN];
UART_Block_t uart_ctl_block;
bool buffer_complet_flag = 0;
/*------------------------------------------------------------------------------------
Func Prototype
-------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------
Functions
-------------------------------------------------------------------------------------*/
void xc_uart_init(uint8_t reg_idx, UART_InitCfg_t *uart_cfg)
{
uint32_t val;
uint32_t uart_clk = 0x00;
uint32_t div, mul, clk_ctl, adj_div, m0_fclk_div;
m0_fclk_div = cpr_m0_fclk_ctl__m0_fclk_div__getf();
uart_clk = xc_clock_hfclk_in_get() * (m0_fclk_div + 1);
mul = (uart_cfg->BaudRate >> 20) & 0xFFFF;
div = (uart_cfg->BaudRate >> 4) & 0xFFFF;
adj_div = uart_clk / 1000000;
clk_ctl = (mul << 16) | (div * adj_div / 32);
if (reg_idx == UART0_IDX) {
cpr_rstctl_subrst_sw__uart0_rstn__setf(RSTCTL_ENABLE);
cpr_rstctl_subrst_sw__uart0_rstn__setf(RSTCTL_DISABLE);
val = cpr_lp_ctl_get();
val &= ~(UART0_CLK_OFF_PROTECT_EN_BIT);
cpr_lp_ctl_set(val);
cpr_ctlapbclken_grctl__uart0_pclk_en__setf(ENABLE);
cpr_uart0_clk_grctl__uart0_clk_gr__setf(8);
cpr_uart0_clk_grctl__uart0_clk_gr_upd__setf(ENABLE);
cpr_uart0_clk_ctl_set(clk_ctl);
}
if (reg_idx == UART1_IDX) {
cpr_rstctl_subrst_sw__uart1_rstn__setf(RSTCTL_ENABLE);
cpr_rstctl_subrst_sw__uart1_rstn__setf(RSTCTL_DISABLE);
val = cpr_lp_ctl_get();
val &= ~(UART1_CLK_OFF_PROTECT_EN_BIT);
cpr_lp_ctl_set(val);
cpr_ctlapbclken_grctl__uart1_pclk_en__setf(ENABLE);
cpr_uart1_clk_grctl__uart1_clk_gr__setf(8);
cpr_uart1_clk_grctl__uart1_clk_gr_upd__setf(ENABLE);
cpr_uart1_clk_ctl_set(clk_ctl);
}
if (reg_idx == UART2_IDX) {
cpr_rstctl_subrst_sw__uart2_rstn__setf(RSTCTL_ENABLE);
cpr_rstctl_subrst_sw__uart2_rstn__setf(RSTCTL_DISABLE);
cpr_uart2_clk_grctl__uart2_pclk_en__setf(ENABLE);
cpr_uart2_clk_grctl__uart2_clk_gr__setf(8);
cpr_uart2_clk_grctl__uart2_clk_gr_upd__setf(ENABLE);
cpr_uart2_clk_ctl_set(clk_ctl);
}
uart_tcr__dlab__setf(reg_idx, UART_TCR_DLAB_DLLH_ENABLE);
uart_dll__dll__setf(reg_idx, (uart_cfg->BaudRate & 0xF));
uart_ier_set(reg_idx, 0);
uart_tcr__dlab__setf(reg_idx, UART_TCR_DLAB_DLLH_DISABLE);
while (uart_usr_get(reg_idx) == 1) {
};
uart_tcr__eps__setf(reg_idx, uart_cfg->Parity);
uart_tcr__stop__setf(reg_idx, uart_cfg->StopBits);
uart_tcr__cls__setf(reg_idx, uart_cfg->WordLength);
uart_mcr__afce__setf(reg_idx, uart_cfg->HardwareFlowControl);
uart_fcr_pack(reg_idx, UART_FCR_RCVR_TRIGGER_FIFO_2_1, UART_FCR_TX_EMPTY_TRIGGER_FIFO_2_1,
UART_FCR_XMIT_FIFO_RESET_CLEAR, UART_FCR_RCVR_FIFO_RESET_CLEAR, UART_FCR_FIFO_ENABLE_ENABLE);
}
void xc_uart_enable_rx_it(uint8_t reg_idx) { uart_ier__erdai__setf(reg_idx, UART_IER_ERDAI_ENABLE); }
void xc_uart_disable_rx_it(uint8_t reg_idx) { uart_ier__erdai__setf(reg_idx, UART_IER_ERDAI_DISABLE); }
void xc_uart_send_byte(uint8_t reg_idx, uint8_t byte)
{
while (1) {
if (uart_tsr__thre__getf(reg_idx) & UART_TSR_THRE_VALID) {
break;
}
}
uart_thr__thr__setf(reg_idx, byte);
}
void xc_uart_send_data(uint8_t reg_idx, uint8_t *data, uint16_t len)
{
for (int i = 0; i < len; i++) {
xc_uart_send_byte(reg_idx, data[i]);
}
}
void xc_uart_ctl_block_reset(void)
{
memset(&uart_ctl_block, 0, sizeof(uart_ctl_block));
uart_ctl_block.uart_receive_cb = NULL;
}
void xc_uart_register_receive_cb(uart_handler_callback uart_cb) { uart_ctl_block.uart_receive_cb = uart_cb; }
__WEAK void uart_user_handler(uint8_t reg_idx)
{
uint8_t rx_val;
uint32_t IIR, TSR;
IIR = uart_iir__iid__getf(reg_idx);
TSR = uart_tsr_get(reg_idx);
if (((IIR & IID_MASK) == UART_IIR_IID_BUSY)) {
uart_usr_get(reg_idx);
}
if (((IIR & IID_MASK) == UART_IIR_IID_ETSI)) {
DEBUG("line=%d, error handle \n", __LINE__);
}
if (((IIR & IID_MASK) == UART_IIR_IID_ERDAI)) {
TSR = uart_tsr_get(reg_idx);
while ((TSR & UART_TSR_DR_VALID) == UART_TSR_DR_VALID) {
rx_val = uart_rbr__rbr__getf(reg_idx);
TSR = uart_tsr_get(reg_idx);
if (uart_ctl_block.uart_receive_cb != NULL) {
uart_ctl_block.uart_receive_cb(&rx_val, 1);
}
}
}
if ((IIR & IID_MASK) == UART_IIR_IID_TO) {
TSR = uart_tsr_get(reg_idx);
while ((TSR & UART_TSR_DR_VALID) == UART_TSR_DR_VALID) {
rx_val = uart_rbr__rbr__getf(reg_idx);
TSR = uart_tsr_get(reg_idx);
if (uart_ctl_block.uart_receive_cb != NULL) {
uart_ctl_block.uart_receive_cb(&rx_val, 1);
}
}
}
}
void UART0_Handler(void) { uart_user_handler(UART0_IDX); }
void UART1_Handler(void) { uart_user_handler(UART1_IDX); }
void UART2_Handler(void) { uart_user_handler(UART2_IDX); }