Files
AC707N/SensorHub/apps/bsp/cpu/br35/uart.c
T
2025-12-03 11:12:34 +08:00

214 lines
5.5 KiB
C

#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".uart.bss")
#pragma data_seg(".uart.data")
#pragma const_seg(".uart.const")
#pragma code_seg(".uart.text")
#pragma str_literal_override(".uart.text")
#endif /* #ifdef SUPPORT_MS_EXTENSIONS */
#include "includes.h"
#include "uart.h"
#include "gpio.h"
#include "ipc_spin_lock.h"
//uart时钟选择:
//#define UART_CLK_SEL UART_CLK_SYS_CLK //由主系统gpcnt模块算出rc16m频率,rc16m频率跟pvdd有关,注意配置被覆盖。
#define UART_CLK_SEL UART_CLK_STD_12M //低功耗不能使用该时钟源
//uart波特率选择:
#define UART_TARGET_BAUD CONFIG_DEBUG_UART_BAUD
//#define UART_TARGET_BAUD 1000000L
//调试串口选择: P11_UART0/P11_UART1
#define DEBUG_UART_SELECT P11_UART0
//输入选择. 只有UART0有输入功能
#define DEBUG_UART_RX_ENABLE 0
#if DEBUG_UART_RX_ENABLE
#define DEBUG_UART_RX_IO IO_PORTB_05
#define DEBUG_UART_RX_OVERTIME 100 //ms
#endif /* #if DEBUG_UART_RX_ENABLE */
static u8 init = 0;
#define P11_UART_CLK_SEL(x) SFR(P11_CLOCK->CLK_CON2, 2, 2, x)
#define UART_ENTER_CRITICAL() irq_disable_core();//ipc_spin_lock(IPC_SPIN_LOCK_EVENT_UART)
#define UART_EXIT_CRITICAL() irq_enable_core(); //ipc_spin_unlock(IPC_SPIN_LOCK_EVENT_UART)
___interrupt
static void uart0_isr(void)
{
u8 rx = 0;
if (UART_RX_PENDING_IS(P11_UART0)) {
rx = UART_BUF_READ(P11_UART0);
UART_RX_PENDING_CLEAR(P11_UART0);
printf("RX pending, rx: 0x%x\n", rx);
}
if (UART_OT_PENDING_IS(P11_UART0)) {
rx = UART_BUF_READ(P11_UART0);
UART_OT_PENDING_CLEAR(P11_UART0);
printf("OT pending, rx: 0x%x\n", rx);
}
}
static u32 uart_src_clk_get(void)
{
u32 freq = 0;
if (UART_CLK_SEL == UART_CLK_STD_12M) {
SFR(P11_CLOCK->CLK_CON1, 15, 2, 1); //MSYS_BT24M --> P11_BT24M
SFR(P11_CLOCK->CLK_CON1, 17, 3, 1); //STD12M sel P11_BT24M input
SFR(P11_CLOCK->CLK_CON1, 20, 2, 0); // div0
SFR(P11_CLOCK->CLK_CON1, 22, 2, 1); // div1
freq = 12000000;
} else if (UART_CLK_SEL == UART_CLK_RC16M) {
freq = 16000000;//(u32)((u32)m2p_message[M2P_RCH_FEQ_H] << 8 | m2p_message[M2P_RCH_FEQ_L]) * 1000;
} else if (UART_CLK_SEL == UART_CLK_SYS_CLK) {
freq = 24000000;
}
return freq;
}
void uart_clk_sel(enum UART_CLK_TABLE clk)
{
u32 freq = 0;
if (clk == UART_CLK_STD_12M) {
freq = 12000000;
} else if (clk == UART_CLK_RC16M) {
freq = 16000000;
} else if (clk == UART_CLK_SYS_CLK) {
freq = 24000000;
}
P11_UART_CLK_SEL(clk);
u16 baud_reg = (freq / UART_TARGET_BAUD) / 4 - 1;
UART_BAUD_SET(DEBUG_UART_SELECT, baud_reg);
}
void debug_uart_init(u8 tx_port)
{
UART_CON0_CLEAR(DEBUG_UART_SELECT);
UART_CON1_CLEAR(DEBUG_UART_SELECT);
uart_clk_sel(UART_CLK_SEL);
//tx io inita
gpio_set_output_value(tx_port, 1);
gpio_set_direction(tx_port, 0);
if (DEBUG_UART_SELECT == P11_UART1) {
//gpio_set_fun_output_port(tx_port, P11_FO_UART1_TX, 1, 1);
} else if (DEBUG_UART_SELECT == P11_UART0) {
gpio_set_fun_output_port(tx_port, P11_FO_UART0_TX, 1, 1);
}
#if DEBUG_UART_RX_ENABLE
u32 ot_value = 0;
if (DEBUG_UART_SELECT == P11_UART0) {
//rx io init:
gpio_set_direction(DEBUG_UART_RX_IO, 1);
gpio_set_pull_up(DEBUG_UART_RX_IO, 1);
gpio_set_pull_down(DEBUG_UART_RX_IO, 0);
gpio_set_die(DEBUG_UART_RX_IO, 1);
//iomc:
gpio_set_fun_input_port(DEBUG_UART_RX_IO, PFI_UART0_RX);
//rx config:
UART_OT_PENDING_CLEAR(P11_UART0);
UART_RX_PENDING_CLEAR(P11_UART0);
ot_value = (uart_src_clk_get() * DEBUG_UART_RX_OVERTIME) / 1000;
UART_OTCNT_SET(P11_UART0, ot_value);
UART_OT_INT_ENABLE(P11_UART0);
UART_RX_INT_ENABLE(P11_UART0);
UART_RX_ENABLE(P11_UART0);
P11_CLOCK->WKUP_EN |= BIT(IRQ_UART0_IDX);
request_irq(IRQ_UART0_IDX, uart0_isr, 0);
}
#endif /* #if DEBUG_UART_RX_ENABLE */
UART_TX_ENABLE(DEBUG_UART_SELECT);
init = 1;
}
void uart_putbyte(char a)
{
u32 ot = 400;
while (!UART_TX_PENDING_IS(DEBUG_UART_SELECT)) {
if (ot-- == 0) {
break;
}
}
UART_TX_PENDING_CLEAR(DEBUG_UART_SELECT);
UART_BUF_WRITE(DEBUG_UART_SELECT, a);
}
__WEAK__
void putchar(char a)
{
if (init == 0) {
return;
}
if (a == '\r') {
return;
}
if (a == '\n') {
uart_putbyte('\r');
}
uart_putbyte(a);
}
__WEAK__
void putbyte(char a)
{
putchar(a);
}
#include "power_interface.h"
static P11_UART_TypeDef UART0_POWEROFF;
static u8 uart_enter_deepsleep(void)
{
UART0_POWEROFF.CON0 = DEBUG_UART_SELECT->CON0;
UART0_POWEROFF.CON1 = DEBUG_UART_SELECT->CON1;
UART0_POWEROFF.CON2 = DEBUG_UART_SELECT->CON2;
UART0_POWEROFF.BAUD = DEBUG_UART_SELECT->BAUD;
UART0_POWEROFF.OTCNT = DEBUG_UART_SELECT->OTCNT;
return 0;
}
static u8 uart_exit_deepsleep(void)
{
DEBUG_UART_SELECT->CON1 = UART0_POWEROFF.CON1;
DEBUG_UART_SELECT->BAUD = UART0_POWEROFF.BAUD;
DEBUG_UART_SELECT->OTCNT = UART0_POWEROFF.OTCNT;
DEBUG_UART_SELECT->CON2 = UART0_POWEROFF.CON2;
DEBUG_UART_SELECT->CON0 = UART0_POWEROFF.CON0;
DEBUG_UART_SELECT->CON0 |= (BIT(13) | BIT(12) | BIT(10));
return 0;
}
#if CONFIG_UART_DEBUG_ENABLE
DEEPSLEEP_TARGET_REGISTER(uart) = {
.name = "uart",
.enter = uart_enter_deepsleep,
.exit = uart_exit_deepsleep,
};
#endif
/*-----------------------------------------------------------*/