#include "board.h" #include "hard_hdma_int.h" #include "hpm_uart_drv.h" #include "hpm_dmamux_drv.h" #include "hpm_dma_drv.h" #include "hpm_gpio_drv.h" #include "hpm_clock_drv.h" #include "rkfifo.h" #include /* ========== 配置宏定义 ========== */ #ifndef UART_RX_FIFO_BUFFER_LEN #define UART_RX_FIFO_BUFFER_LEN 256 #endif #ifndef UART_TX_FIFO_BUFFER_LEN #define UART_TX_FIFO_BUFFER_LEN 256 #endif #ifndef UART_TX_DMA_BUFFER_LEN #define UART_TX_DMA_BUFFER_LEN 1024 #endif /* ========== 外部DMA完成标志声明 ========== */ extern bool uart1_tx_dma_done; extern bool uart2_tx_dma_done; extern bool uart3_tx_dma_done; extern bool uart4_tx_dma_done; extern bool uart5_tx_dma_done; extern bool uart6_tx_dma_done; /* ========== 结构体定义 ========== */ struct _uart_config { UART_Type *uart_base; /* UART基地址 */ uart_intr_enable_t uart_irq_mask; /* UART中断掩码 */ uint8_t uart_irq_num; /* 中断号 */ /* GPIO配置 */ uint8_t tx_port; /* TX端口: 0-9 (GPIOA-GPIOJ) */ uint8_t tx_pin; /* TX引脚 */ uint8_t rx_port; /* RX端口 */ uint8_t rx_pin; /* RX引脚 */ uint8_t tx_af; /* TX复用功能 */ uint8_t rx_af; /* RX复用功能 */ /* DMA配置 */ DMA_Type *dma_base; /* DMA控制器基地址 */ DMAMUX_Type *dma_mux_base; /* DMA MUX */ uint8_t dma_enable; /* DMA 使能 (修正拼写) */ uint8_t dma_channel; /* DMA通道 */ uint8_t dma_irq_num; /* DMA中断号 */ uint8_t dma_request; /* DMA请求源 */ /* 缓冲区 */ uint8_t *tx_fifo_buff; /* TX FIFO缓冲区 */ uint32_t tx_fifo_buff_size; /* TX FIFO大小 */ uint8_t *rx_fifo_buff; /* RX FIFO缓冲区 */ uint32_t rx_fifo_buff_size; /* RX FIFO大小 */ /* DMA缓冲区 */ uint8_t *dma_tx_buff; /* DMA发送缓冲区 */ uint32_t dma_tx_buff_size; /* DMA发送缓冲区大小 */ /* 内部使用 */ rkfifo_t tx_fifo; /* TX FIFO */ rkfifo_t rx_fifo; /* RX FIFO */ volatile uint8_t dma_busy; /* DMA发送忙标志 */ }; struct _uart_ops { int (*init)(struct _uart_config *config, uint32_t baudrate); uint32_t (*read)(struct _uart_config *config, void *data, uint32_t len); uint32_t (*write)(struct _uart_config *config, const void *data, uint32_t len); }; struct _uart_device { struct _uart_config *config; struct _uart_ops *ops; }; /* ========== 辅助函数:获取DMA完成标志指针 ========== */ static bool* _get_dma_done_flag(UART_Type *uart_base) { if (uart_base == HPM_UART1) { return &uart1_tx_dma_done; } else if (uart_base == HPM_UART2) { return &uart2_tx_dma_done; } else if (uart_base == HPM_UART3) { return &uart3_tx_dma_done; } else if (uart_base == HPM_UART4) { return &uart4_tx_dma_done; } else if (uart_base == HPM_UART5) { return &uart5_tx_dma_done; } else if (uart_base == HPM_UART6) { return &uart6_tx_dma_done; } return NULL; } /* ========== 时钟使能函数 ========== */ static void _uart_clock_enable(UART_Type *uart_base) { if (uart_base == HPM_UART0) { clock_set_source_divider(clock_uart0, clk_src_osc24m, 1); clock_add_to_group(clock_uart0, 0); } else if (uart_base == HPM_UART1) { clock_set_source_divider(clock_uart1, clk_src_osc24m, 1); clock_add_to_group(clock_uart1, 0); } else if (uart_base == HPM_UART2) { clock_set_source_divider(clock_uart2, clk_src_osc24m, 1); clock_add_to_group(clock_uart2, 0); } else if (uart_base == HPM_UART3) { clock_set_source_divider(clock_uart3, clk_src_osc24m, 1); clock_add_to_group(clock_uart3, 0); } else if (uart_base == HPM_UART4) { clock_set_source_divider(clock_uart4, clk_src_osc24m, 1); clock_add_to_group(clock_uart4, 0); } else if (uart_base == HPM_UART5) { clock_set_source_divider(clock_uart5, clk_src_osc24m, 1); clock_add_to_group(clock_uart5, 0); } else if (uart_base == HPM_UART6) { clock_set_source_divider(clock_uart6, clk_src_osc24m, 1); clock_add_to_group(clock_uart6, 0); } else if (uart_base == HPM_UART7) { clock_set_source_divider(clock_uart7, clk_src_osc24m, 1); clock_add_to_group(clock_uart7, 0); } } /* ========== DMA时钟使能 ========== */ static void _dma_clock_enable(DMA_Type *dma_base) { /* HDMA 时钟来源于系统总线时钟(AHB),已默认使能 */ (void)dma_base; } /* ========== GPIO配置 ========== */ static void _uart_gpio_config(UART_Type *uart_base) { if (uart_base == HPM_UART1) { HPM_IOC->PAD[IOC_PAD_PA02].FUNC_CTL = IOC_PA02_FUNC_CTL_UART1_TXD; HPM_IOC->PAD[IOC_PAD_PA01].FUNC_CTL = IOC_PA01_FUNC_CTL_UART1_RXD; } else if (uart_base == HPM_UART2) { HPM_IOC->PAD[IOC_PAD_PB21].FUNC_CTL = IOC_PB21_FUNC_CTL_UART2_RXD; HPM_IOC->PAD[IOC_PAD_PB22].FUNC_CTL = IOC_PB22_FUNC_CTL_UART2_TXD; } else if (uart_base == HPM_UART3) { HPM_IOC->PAD[IOC_PAD_PB24].FUNC_CTL = IOC_PB24_FUNC_CTL_UART3_RXD; HPM_IOC->PAD[IOC_PAD_PB25].FUNC_CTL = IOC_PB25_FUNC_CTL_UART3_TXD; } else if (uart_base == HPM_UART4) { HPM_IOC->PAD[IOC_PAD_PA09].FUNC_CTL = IOC_PA09_FUNC_CTL_UART4_RXD; HPM_IOC->PAD[IOC_PAD_PA04].FUNC_CTL = IOC_PA04_FUNC_CTL_UART4_TXD; } else if (uart_base == HPM_UART5) { HPM_IOC->PAD[IOC_PAD_PA08].FUNC_CTL = IOC_PA08_FUNC_CTL_UART5_TXD; HPM_IOC->PAD[IOC_PAD_PA07].FUNC_CTL = IOC_PA07_FUNC_CTL_UART5_RXD; } else if (uart_base == HPM_UART6) { HPM_IOC->PAD[IOC_PAD_PA05].FUNC_CTL = IOC_PA05_FUNC_CTL_UART6_RXD; HPM_IOC->PAD[IOC_PAD_PA06].FUNC_CTL = IOC_PA06_FUNC_CTL_UART6_TXD; } } /* ========== UART配置 ========== */ static int _uart_config(struct _uart_config *config, uint32_t baudrate) { uart_config_t uart_cfg; uint32_t uart_clock_freq = 0; /* 使能时钟 */ _uart_clock_enable(config->uart_base); /* 配置GPIO */ _uart_gpio_config(config->uart_base); /* 获取UART时钟频率 */ if (config->uart_base == HPM_UART0) { uart_clock_freq = clock_get_frequency(clock_uart0); } else if (config->uart_base == HPM_UART1) { uart_clock_freq = clock_get_frequency(clock_uart1); } else if (config->uart_base == HPM_UART2) { uart_clock_freq = clock_get_frequency(clock_uart2); } else if (config->uart_base == HPM_UART3) { uart_clock_freq = clock_get_frequency(clock_uart3); } else if (config->uart_base == HPM_UART4) { uart_clock_freq = clock_get_frequency(clock_uart4); } else if (config->uart_base == HPM_UART5) { uart_clock_freq = clock_get_frequency(clock_uart5); } else if (config->uart_base == HPM_UART6) { uart_clock_freq = clock_get_frequency(clock_uart6); } else if (config->uart_base == HPM_UART7) { uart_clock_freq = clock_get_frequency(clock_uart7); } /* 配置UART */ uart_default_config(config->uart_base, &uart_cfg); uart_cfg.baudrate = baudrate; uart_cfg.word_length = word_length_8_bits; uart_cfg.num_of_stop_bits = stop_bits_1; uart_cfg.parity = parity_none; uart_cfg.fifo_enable = true; uart_cfg.dma_enable = config->dma_enable ? true : false; uart_cfg.tx_fifo_level = uart_tx_fifo_trg_not_full; uart_cfg.rx_fifo_level = uart_rx_fifo_trg_gt_three_quarters; uart_cfg.src_freq_in_hz = uart_clock_freq; uart_init(config->uart_base, &uart_cfg); return 0; } /* ========== DMA配置 ========== */ static int _uart_dma_config(struct _uart_config *config) { dma_handshake_config_t handshake_config; if (config->dma_tx_buff == NULL) { return -1; } /* 使能DMA时钟 */ _dma_clock_enable(config->dma_base); /* 配置 DMAMUX */ dmamux_config(config->dma_mux_base, DMA_SOC_CHN_TO_DMAMUX_CHN(config->dma_base, config->dma_channel), config->dma_request, true); /* 配置 TX 握手参数 */ dma_default_handshake_config(config->dma_base, &handshake_config); handshake_config.ch_index = config->dma_channel; handshake_config.dst = (uint32_t)&config->uart_base->THR; handshake_config.dst_fixed = true; handshake_config.src = core_local_mem_to_sys_address(0, (uint32_t)config->dma_tx_buff); handshake_config.src_fixed = false; handshake_config.data_width = DMA_TRANSFER_WIDTH_BYTE; handshake_config.size_in_byte = config->dma_tx_buff_size; hpm_stat_t stat = dma_setup_handshake(config->dma_base, &handshake_config, false); if (stat != status_success) { printf("uart dma tx config error\r\n"); return -1; } return 0; } /* ========== NVIC中断配置 ========== */ static void _uart_nvic_config(struct _uart_config *config) { /* 使能UART中断 */ uart_enable_irq(config->uart_base, config->uart_irq_mask); intc_m_enable_irq_with_priority(config->uart_irq_num, 1); /* 使能DMA中断 */ if (config->dma_enable) { intc_m_enable_irq_with_priority(config->dma_irq_num, 1); } } /* ========== UART初始化 ========== */ int _uart_init(struct _uart_config *config, uint32_t baudrate) { /* 初始化FIFO */ rkfifo_init(&config->tx_fifo, config->tx_fifo_buff, config->tx_fifo_buff_size, 1); rkfifo_init(&config->rx_fifo, config->rx_fifo_buff, config->rx_fifo_buff_size, 1); /* 配置UART硬件 */ _uart_config(config, baudrate); /* 配置DMA */ if (config->dma_enable) { _uart_dma_config(config); } /* 配置中断 */ _uart_nvic_config(config); config->dma_busy = 0; return 0; } /** * @brief 获取串口发送是否忙碌 */ bool usart_tx_isbusy(struct _uart_config *config) { bool *dma_done_flag = _get_dma_done_flag(config->uart_base); if (dma_done_flag) { return !(*dma_done_flag); } return false; } void open_usart_dma_tx(struct _uart_config *config, uint32_t len) { dma_handshake_config_t handshake_config; bool *dma_done_flag = _get_dma_done_flag(config->uart_base); /* 等待上次发送完成 */ uint32_t timeout = 1000000; while (usart_tx_isbusy(config) && timeout--) { __asm("nop"); } if (timeout == 0) { /* 超时处理,复位DMA */ dma_abort_channel(config->dma_base, config->dma_channel); if (dma_done_flag) { *dma_done_flag = true; } } /* 清除DMA完成标志 */ if (dma_done_flag) { *dma_done_flag = false; } /* 重新配置 TX 传输大小 */ dma_default_handshake_config(config->dma_base, &handshake_config); handshake_config.ch_index = config->dma_channel; handshake_config.dst = (uint32_t)&config->uart_base->THR; handshake_config.dst_fixed = true; handshake_config.src = core_local_mem_to_sys_address(0, (uint32_t)config->dma_tx_buff); handshake_config.src_fixed = false; handshake_config.data_width = DMA_TRANSFER_WIDTH_BYTE; handshake_config.size_in_byte = len; dma_setup_handshake(config->dma_base, &handshake_config, true); } /* ========== UART发送数据(DMA方式) ========== */ static uint32_t uart_tx_data(struct _uart_config *config, const void *data, uint32_t len) { uint32_t ret = 0; if (len == 0) return 0; /* 将数据压入TX FIFO */ ret = rkfifo_in(&config->tx_fifo, data, len); if (config->dma_tx_buff != NULL && config->dma_enable) { /* DMA方式发送 */ if (!config->dma_busy) { /* DMA空闲,立即发送 */ uint32_t count = rkfifo_out(&config->tx_fifo, config->dma_tx_buff, config->dma_tx_buff_size); if (count > 0) { open_usart_dma_tx(config, count); config->dma_busy = 1; } } } return ret; } /* ========== UART接收数据(从fifo往外读) ========== */ static uint32_t uart_rx_data(struct _uart_config *config, void *data, uint32_t len) { return rkfifo_out(&config->rx_fifo, data, len); } /* ========== UART中断处理函数 ========== */ void uart_isr_callback(struct _uart_config *config) { uint8_t count = 0; rkfifo_t *rxfifo = &config->rx_fifo; uint8_t irq_id = uart_get_irq_id(config->uart_base); if (irq_id == uart_intr_id_rx_data_avail) { while (uart_check_status(config->uart_base, uart_stat_data_ready)) { uint8_t byte = uart_read_byte(config->uart_base); rkfifo_in(rxfifo, &byte, 1); count++; /* 确保RX FIFO不会溢出 */ if (count > 12) { break; } } } if (irq_id == uart_intr_id_rx_timeout) { /* 接收超时,读取剩余数据 */ while (uart_check_status(config->uart_base, uart_stat_data_ready)) { uint8_t byte = uart_read_byte(config->uart_base); rkfifo_in(rxfifo, &byte, 1); } } } /* ========== DMA发送完成中断处理 ========== */ void uart_tx_dma_isr_callback(struct _uart_config *config) { bool *dma_done_flag = _get_dma_done_flag(config->uart_base); /* 设置DMA完成标志 */ if (dma_done_flag) { *dma_done_flag = true; } config->dma_busy = 0; rkfifo_t *tx_fifo = &config->tx_fifo; uint8_t *dma_buff = config->dma_tx_buff; uint32_t dma_buff_size = config->dma_tx_buff_size; uint32_t count = rkfifo_out(tx_fifo, dma_buff, dma_buff_size); if (count > 0) { open_usart_dma_tx(config, count); config->dma_busy = 1; } } /* ========== UART1 配置 ========== */ #ifdef DRV_USING_UART1 static uint8_t u1_rx_fifo_buff[UART_RX_FIFO_BUFFER_LEN]; static uint8_t u1_tx_fifo_buff[UART_TX_FIFO_BUFFER_LEN]; static uint8_t u1_dma_tx_buff[UART_TX_DMA_BUFFER_LEN]; struct _uart_config _u1_config = { .uart_base = HPM_UART1, /* 修正:应该是UART1 */ .uart_irq_mask = uart_intr_rx_rdy | uart_intr_rx_timeout, /* 添加中断掩码 */ .uart_irq_num = IRQn_UART1, /* 修正:IRQn_UART1 */ /* DMA配置 */ .dma_base = HPM_DMA0, .dma_mux_base = HPM_DMAMUX0, .dma_enable = 1, /* 修正拼写 */ .dma_channel = 0, .dma_irq_num = IRQn_DMA0_CH0, .dma_request = DMA_REQUEST_UART1_TX, /* 修正:UART1_TX */ /* FIFO缓冲区 */ .tx_fifo_buff = u1_tx_fifo_buff, .tx_fifo_buff_size = sizeof(u1_tx_fifo_buff), .rx_fifo_buff = u1_rx_fifo_buff, .rx_fifo_buff_size = sizeof(u1_rx_fifo_buff), /* DMA缓冲区 */ .dma_tx_buff = u1_dma_tx_buff, .dma_tx_buff_size = sizeof(u1_dma_tx_buff), }; static uint32_t u1_write_data(const void *data, uint32_t len) { return uart_tx_data(&_u1_config, data, len); } static uint32_t u1_read_data(void *data, uint32_t len) { return uart_rx_data(&_u1_config, data, len); } static int u1_init(uint32_t baudrate) { return _uart_init(&_u1_config, baudrate); } static struct _uart_ops _u1_ops = { .init = u1_init, .read = u1_read_data, .write = u1_write_data, }; static struct _uart_device uart1 = { .config = &_u1_config, .ops = &_u1_ops, }; /* UART1中断处理函数 */ void uart1_irq_handler(void) { uart_isr_callback(&_u1_config); } /* DMA0通道0中断处理函数 */ void dma0_ch0_irq_handler(void) { uart_tx_dma_isr_callback(&_u1_config); } #endif /* DRV_USING_UART1 */ /* ========== UART查找函数 ========== */ struct _uart_device *uart_find(const char *name) { struct _uart_device *uart = NULL; if (strncmp(name, "uart1", 5) == 0) { #ifdef DRV_USING_UART1 uart = &uart1; #endif } else if (strncmp(name, "uart2", 5) == 0) { #ifdef DRV_USING_UART2 uart = &uart2; #endif } else if (strncmp(name, "uart3", 5) == 0) { #ifdef DRV_USING_UART3 uart = &uart3; #endif } else if (strncmp(name, "uart4", 5) == 0) { #ifdef DRV_USING_UART4 uart = &uart4; #endif } else if (strncmp(name, "uart5", 5) == 0) { #ifdef DRV_USING_UART5 uart = &uart5; #endif } else if (strncmp(name, "uart6", 5) == 0) { #ifdef DRV_USING_UART6 uart = &uart6; #endif } return uart; }