200 lines
6.5 KiB
C
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); }
|