/* * Copyright (c) 2022-2024 HPMicro * * SPDX-License-Identifier: BSD-3-Clause * * Change Logs: * Date Author Notes * 2022-03-08 HPMicro First version * 2022-07-28 HPMicro Fix compiling warning if RT_SERIAL_USING_DMA was not defined * 2022-08-08 HPMicro Integrate DMA Manager and support dynamic DMA resource assignment' * 2023-03-07 HPMicro Fix the issue that the data_width was not initialized before setup dma handshake * 2024-06-10 HPMicro Fix memory leakage issue * */ #include #include #include "board.h" #include "drv_uart_v2.h" #include "hpm_uart_drv.h" #include "hpm_sysctl_drv.h" #include "hpm_l1c_drv.h" #include "hpm_dma_mgr.h" #include "hpm_soc.h" #ifdef RT_USING_SERIAL_V2 #ifdef RT_SERIAL_USING_DMA #define BOARD_UART_DMAMUX HPM_DMAMUX #define UART_DMA_TRIGGER_LEVEL (1U) typedef struct dma_channel { struct rt_serial_device *serial; dma_resource_t resource; void (*tranfer_done)(struct rt_serial_device *serial); void (*tranfer_abort)(struct rt_serial_device *serial); void (*tranfer_error)(struct rt_serial_device *serial); void *ringbuf_ptr; } hpm_dma_channel_handle_t; //static struct dma_channel dma_channels[DMA_SOC_CHANNEL_NUM]; static int hpm_uart_dma_config(struct rt_serial_device *serial, void *arg); static void hpm_uart_receive_dma_next(struct rt_serial_device *serial); #endif #define UART_ROOT_CLK_FREQ BOARD_APP_UART_SRC_FREQ struct hpm_uart { UART_Type *uart_base; uint32_t irq_num; struct rt_serial_device *serial; char *device_name; #ifdef RT_SERIAL_USING_DMA uint32_t tx_dma_mux; uint32_t rx_dma_mux; uint32_t dma_flags; hpm_dma_channel_handle_t tx_chn_ctx; hpm_dma_channel_handle_t rx_chn_ctx; bool tx_resource_allocated; bool rx_resource_allocated; #if defined(HPM_IP_FEATURE_UART_RX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_RX_IDLE_DETECT == 1) && defined(RT_SERIAL_USING_DMA) ATTR_ALIGN(HPM_L1C_CACHELINE_SIZE) uint8_t rx_idle_tmp_buffer[1024]; #endif #endif }; extern void init_uart_pins(UART_Type *ptr); static void hpm_uart_isr(struct rt_serial_device *serial); static rt_err_t hpm_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg); static rt_err_t hpm_uart_control(struct rt_serial_device *serial, int cmd, void *arg); static int hpm_uart_putc(struct rt_serial_device *serial, char ch); static int hpm_uart_getc(struct rt_serial_device *serial); #ifdef RT_SERIAL_USING_DMA int hpm_uart_dma_register_channel(struct rt_serial_device *serial, bool is_tx, void (*done)(struct rt_serial_device *serial), void (*abort)(struct rt_serial_device *serial), void (*error)(struct rt_serial_device *serial)) { struct hpm_uart *uart = (struct hpm_uart *)serial->parent.user_data; if (is_tx) { uart->tx_chn_ctx.serial = serial; uart->tx_chn_ctx.tranfer_done = done; uart->tx_chn_ctx.tranfer_abort = abort; uart->tx_chn_ctx.tranfer_error = error; } else { uart->rx_chn_ctx.serial = serial; uart->rx_chn_ctx.tranfer_done = done; uart->rx_chn_ctx.tranfer_abort = abort; uart->rx_chn_ctx.tranfer_error = error; } return RT_EOK; } #endif /* RT_SERIAL_USING_DMA */ #if defined(BSP_USING_UART0) struct rt_serial_device serial0; void uart0_isr(void) { hpm_uart_isr(&serial0); } SDK_DECLARE_EXT_ISR_M(IRQn_UART0,uart0_isr) #endif #if defined(BSP_USING_UART1) struct rt_serial_device serial1; void uart1_isr(void) { hpm_uart_isr(&serial1); } SDK_DECLARE_EXT_ISR_M(IRQn_UART1,uart1_isr) #endif #if defined(BSP_USING_UART2) struct rt_serial_device serial2; void uart2_isr(void) { hpm_uart_isr(&serial2); } SDK_DECLARE_EXT_ISR_M(IRQn_UART2,uart2_isr) #endif #if defined(BSP_USING_UART3) struct rt_serial_device serial3; void uart3_isr(void) { hpm_uart_isr(&serial3); } SDK_DECLARE_EXT_ISR_M(IRQn_UART3,uart3_isr) #endif #if defined(BSP_USING_UART4) struct rt_serial_device serial4; void uart4_isr(void) { hpm_uart_isr(&serial4); } SDK_DECLARE_EXT_ISR_M(IRQn_UART4,uart4_isr) #endif #if defined(BSP_USING_UART5) struct rt_serial_device serial5; void uart5_isr(void) { hpm_uart_isr(&serial5); } SDK_DECLARE_EXT_ISR_M(IRQn_UART5,uart5_isr) #endif #if defined(BSP_USING_UART6) struct rt_serial_device serial6; void uart6_isr(void) { hpm_uart_isr(&serial6); } SDK_DECLARE_EXT_ISR_M(IRQn_UART6,uart6_isr) #endif #if defined(BSP_USING_UART7) struct rt_serial_device serial7; void uart7_isr(void) { hpm_uart_isr(&serial7); } SDK_DECLARE_EXT_ISR_M(IRQn_UART7,uart7_isr) #endif #if defined(BSP_USING_UART8) struct rt_serial_device serial8; void uart8_isr(void) { hpm_uart_isr(&serial8); } SDK_DECLARE_EXT_ISR_M(IRQn_UART8,uart8_isr) #endif #if defined(BSP_USING_UART9) struct rt_serial_device serial9; void uart9_isr(void) { hpm_uart_isr(&serial9); } SDK_DECLARE_EXT_ISR_M(IRQn_UART9,uart9_isr) #endif #if defined(BSP_USING_UART10) struct rt_serial_device serial10; void uart10_isr(void) { hpm_uart_isr(&serial10); } SDK_DECLARE_EXT_ISR_M(IRQn_UART10,uart10_isr) #endif #if defined(BSP_USING_UART11) struct rt_serial_device serial11; void uart11_isr(void) { hpm_uart_isr(&serial11); } SDK_DECLARE_EXT_ISR_M(IRQn_UART11,uart11_isr) #endif #if defined(BSP_USING_UART12) struct rt_serial_device serial12; void uart12_isr(void) { hpm_uart_isr(&serial12); } SDK_DECLARE_EXT_ISR_M(IRQn_UART12,uart12_isr) #endif #if defined(BSP_USING_UART13) struct rt_serial_device serial13; void uart13_isr(void) { hpm_uart_isr(&serial13); } SDK_DECLARE_EXT_ISR_M(IRQn_UART13,uart13_isr) #endif #if defined(BSP_USING_UART14) struct rt_serial_device serial14; void uart14_isr(void) { hpm_uart_isr(&serial14); } SDK_DECLARE_EXT_ISR_M(IRQn_UART14,uart14_isr) #endif #if defined(BSP_USING_UART15) struct rt_serial_device serial15; void uart15_isr(void) { hpm_uart_isr(&serial15); } SDK_DECLARE_EXT_ISR_M(IRQn_UART15,uart15_isr) #endif static struct hpm_uart uarts[] = { #if defined(BSP_USING_UART0) { HPM_UART0, IRQn_UART0, &serial0, "uart0", #ifdef RT_SERIAL_USING_DMA HPM_DMA_SRC_UART0_TX, HPM_DMA_SRC_UART0_RX, 0, #endif }, #endif #if defined(BSP_USING_UART1) { HPM_UART1, IRQn_UART1, &serial1, "uart1", #ifdef RT_SERIAL_USING_DMA HPM_DMA_SRC_UART1_TX, HPM_DMA_SRC_UART1_RX, 0, #endif }, #endif #if defined(BSP_USING_UART2) { HPM_UART2, IRQn_UART2, &serial2, "uart2", #ifdef RT_SERIAL_USING_DMA HPM_DMA_SRC_UART2_TX, HPM_DMA_SRC_UART2_RX, 0, #endif }, #endif #if defined(BSP_USING_UART3) { HPM_UART3, IRQn_UART3, &serial3, "uart3", #ifdef RT_SERIAL_USING_DMA HPM_DMA_SRC_UART3_TX, HPM_DMA_SRC_UART3_RX, 0, #endif }, #endif #if defined(BSP_USING_UART4) { HPM_UART4, IRQn_UART4, &serial4, "uart4", #ifdef RT_SERIAL_USING_DMA HPM_DMA_SRC_UART4_TX, HPM_DMA_SRC_UART4_RX, 0, #endif }, #endif #if defined(BSP_USING_UART5) { HPM_UART5, IRQn_UART5, &serial5, "uart5", #ifdef RT_SERIAL_USING_DMA HPM_DMA_SRC_UART5_TX, HPM_DMA_SRC_UART5_RX, 0, #endif }, #endif #if defined(BSP_USING_UART6) { HPM_UART6, IRQn_UART6, &serial6, "uart6", #ifdef RT_SERIAL_USING_DMA HPM_DMA_SRC_UART6_TX, HPM_DMA_SRC_UART6_RX, 0, #endif }, #endif #if defined(BSP_USING_UART7) { HPM_UART7, IRQn_UART7, &serial7, "uart7", #ifdef RT_SERIAL_USING_DMA HPM_DMA_SRC_UART7_TX, HPM_DMA_SRC_UART7_RX, 0, #endif }, #endif #if defined(BSP_USING_UART8) { HPM_UART8, IRQn_UART8, &serial8, "uart8", #ifdef RT_SERIAL_USING_DMA HPM_DMA_SRC_UART8_TX, HPM_DMA_SRC_UART8_RX, 0, #endif }, #endif #if defined(BSP_USING_UART9) { HPM_UART9, IRQn_UART9, &serial9, "uart9", #ifdef RT_SERIAL_USING_DMA HPM_DMA_SRC_UART9_TX, HPM_DMA_SRC_UART9_RX, 0, #endif }, #endif #if defined(BSP_USING_UART10) { HPM_UART10, IRQn_UART10, &serial10, "uart10", #ifdef RT_SERIAL_USING_DMA HPM_DMA_SRC_UART10_TX, HPM_DMA_SRC_UART10_RX, 0, #endif }, #endif #if defined(BSP_USING_UART11) { HPM_UART11, IRQn_UART11, &serial11, "uart11", #ifdef RT_SERIAL_USING_DMA HPM_DMA_SRC_UART11_TX, HPM_DMA_SRC_UART11_RX, 0, #endif }, #endif #if defined(BSP_USING_UART12) { HPM_UART12, IRQn_UART12, &serial12, "uart12", #ifdef RT_SERIAL_USING_DMA HPM_DMA_SRC_UART12_TX, HPM_DMA_SRC_UART12_RX, 0, #endif }, #endif #if defined(BSP_USING_UART13) { HPM_UART13, IRQn_UART13, &serial13, "uart13", #ifdef RT_SERIAL_USING_DMA HPM_DMA_SRC_UART13_TX, HPM_DMA_SRC_UART13_RX, 0, #endif }, #endif #if defined(BSP_USING_UART14) { HPM_UART14, IRQn_UART14, &serial14, "uart14", #ifdef RT_SERIAL_USING_DMA HPM_DMA_SRC_UART14_TX, HPM_DMA_SRC_UART14_RX, 0, #endif }, #endif #if defined(BSP_USING_UART15) { HPM_UART15, IRQn_UART15, &serial15, "uart15", #ifdef RT_SERIAL_USING_DMA HPM_DMA_SRC_UART15_TX, HPM_DMA_SRC_UART15_RX, 0, #endif }, #endif }; enum { #if defined(BSP_USING_UART0) HPM_UART0_INDEX, #endif #if defined(BSP_USING_UART1) HPM_UART1_INDEX, #endif #if defined(BSP_USING_UART2) HPM_UART2_INDEX, #endif #if defined(BSP_USING_UART3) HPM_UART3_INDEX, #endif #if defined(BSP_USING_UART4) HPM_UART4_INDEX, #endif #if defined(BSP_USING_UART5) HPM_UART5_INDEX, #endif #if defined(BSP_USING_UART6) HPM_UART6_INDEX, #endif #if defined(BSP_USING_UART7) HPM_UART7_INDEX, #endif #if defined(BSP_USING_UART8) HPM_UART8_INDEX, #endif #if defined(BSP_USING_UART9) HPM_UART9_INDEX, #endif #if defined(BSP_USING_UART10) HPM_UART10_INDEX, #endif #if defined(BSP_USING_UART11) HPM_UART11_INDEX, #endif #if defined(BSP_USING_UART12) HPM_UART12_INDEX, #endif #if defined(BSP_USING_UART13) HPM_UART13_INDEX, #endif #if defined(BSP_USING_UART14) HPM_UART14_INDEX, #endif #if defined(BSP_USING_UART15) HPM_UART15_INDEX, #endif }; #if defined(RT_SERIAL_USING_DMA) static void uart_dma_tc_callback(DMA_Type *base, uint32_t channel, void *user_data) { hpm_dma_channel_handle_t *dma_handle = (hpm_dma_channel_handle_t*)user_data; if ((dma_handle->resource.base != base) || (dma_handle->resource.channel != channel)) { return; } dma_handle->tranfer_done(dma_handle->serial); } static void uart_dma_abort_callback(DMA_Type *base, uint32_t channel, void *user_data) { hpm_dma_channel_handle_t *dma_handle = (hpm_dma_channel_handle_t*)user_data; if ((dma_handle->resource.base != base) || (dma_handle->resource.channel != channel)) { return; } dma_handle->tranfer_abort(dma_handle->serial); } static void uart_dma_error_callback(DMA_Type *base, uint32_t channel, void *user_data) { hpm_dma_channel_handle_t *dma_handle = (hpm_dma_channel_handle_t*)user_data; if ((dma_handle->resource.base != base) || (dma_handle->resource.channel != channel)) { return; } dma_handle->tranfer_error(dma_handle->serial); } static void uart_tx_done(struct rt_serial_device *serial) { rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DMADONE); } static void uart_rx_done(struct rt_serial_device *serial) { struct rt_serial_rx_fifo *rx_fifo; rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; #if defined(HPM_IP_FEATURE_UART_RX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_RX_IDLE_DETECT == 1) && defined(RT_SERIAL_USING_DMA) uint32_t uart_recv_data_count = 0; struct hpm_uart *uart = (struct hpm_uart *)serial->parent.user_data; uint32_t rx_idle_tmp_buffer_size = sizeof(uart->rx_idle_tmp_buffer); uart_recv_data_count = rx_idle_tmp_buffer_size - dma_get_remaining_transfer_size(uart->rx_chn_ctx.resource.base, uart->rx_chn_ctx.resource.channel); if (l1c_dc_is_enabled()) { uint32_t aligned_start = HPM_L1C_CACHELINE_ALIGN_DOWN((uint32_t)uart->rx_idle_tmp_buffer); uint32_t aligned_end = HPM_L1C_CACHELINE_ALIGN_UP((uint32_t)uart->rx_idle_tmp_buffer + rx_idle_tmp_buffer_size); uint32_t aligned_size = aligned_end - aligned_start; l1c_dc_invalidate(aligned_start, aligned_size); } /* if open uart again after closing uart, an idle interrupt may be triggered, but uart initialization is not performed at this time, and the program exits if the rxfifo is empty. */ if (rx_fifo == RT_NULL) { return; } rt_ringbuffer_put(&(rx_fifo->rb), uart->rx_idle_tmp_buffer, uart_recv_data_count); rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE); #else if (l1c_dc_is_enabled()) { uint32_t aligned_start = HPM_L1C_CACHELINE_ALIGN_DOWN((uint32_t)rx_fifo->rb.buffer_ptr); uint32_t aligned_end = HPM_L1C_CACHELINE_ALIGN_UP((uint32_t)rx_fifo->rb.buffer_ptr + serial->config.rx_bufsz); uint32_t aligned_size = aligned_end - aligned_start; l1c_dc_invalidate(aligned_start, aligned_size); } rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE | (serial->config.rx_bufsz << 8)); #endif /* prepare for next read */ hpm_uart_receive_dma_next(serial); } #endif /* RT_SERIAL_USING_DMA */ /** * @brief UART common interrupt process. This * * @param serial Serial device */ static void hpm_uart_isr(struct rt_serial_device *serial) { struct hpm_uart *uart; rt_uint32_t stat, enabled_irq; rt_uint8_t irq_id; rt_uint8_t count = 0; rt_uint8_t put_char = 0; RT_ASSERT(serial != RT_NULL); uart = (struct hpm_uart *)serial->parent.user_data; RT_ASSERT(uart != RT_NULL); struct rt_serial_rx_fifo *rx_fifo; rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; stat = uart_get_status(uart->uart_base); irq_id = uart_get_irq_id(uart->uart_base); if (irq_id == uart_intr_id_rx_data_avail) { while (uart_check_status(uart->uart_base, uart_stat_data_ready)) { count++; put_char = uart_read_byte(uart->uart_base); rt_ringbuffer_putchar(&(rx_fifo->rb), put_char); /*in order to ensure rx fifo there are remaining bytes*/ if (count > 12) { break; } } } if (irq_id == uart_intr_id_rx_timeout) { while ((uart_check_status(uart->uart_base, uart_stat_data_ready)) || (uart_check_status(uart->uart_base, uart_stat_overrun_error))) { put_char= uart_read_byte(uart->uart_base); rt_ringbuffer_putchar(&(rx_fifo->rb), put_char); } rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); } if ((irq_id & uart_intr_tx_slot_avail) && (stat & uart_stat_tx_slot_avail)) { /* UART in mode Transmitter */ struct rt_serial_tx_fifo *tx_fifo; tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx; RT_ASSERT(tx_fifo != RT_NULL); rt_uint8_t put_char = 0; uint32_t fifo_size = 0, ringbuffer_data_len = 0, tx_size = 0; uart_disable_irq(uart->uart_base, uart_intr_tx_slot_avail); fifo_size = uart_get_fifo_size(uart->uart_base); ringbuffer_data_len = rt_ringbuffer_data_len(&tx_fifo->rb); if (ringbuffer_data_len <= 0) { rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DONE); } else { tx_size = (ringbuffer_data_len > fifo_size) ? fifo_size : ringbuffer_data_len; for (uint32_t i = 0; i < tx_size; i++) { rt_ringbuffer_getchar(&tx_fifo->rb, &put_char); uart_write_byte(uart->uart_base, put_char); } uart_enable_irq(uart->uart_base, uart_intr_tx_slot_avail); } } #if defined(HPM_IP_FEATURE_UART_RX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_RX_IDLE_DETECT == 1) && defined(RT_SERIAL_USING_DMA) if (uart_is_rxline_idle(uart->uart_base)) { uart_rx_done(serial); uart_clear_rxline_idle_flag(uart->uart_base); uart_flush(uart->uart_base); } #endif } static rt_err_t hpm_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg) { RT_ASSERT(serial != RT_NULL); RT_ASSERT(cfg != RT_NULL); uart_config_t uart_config; struct hpm_uart *uart = (struct hpm_uart *)serial->parent.user_data; init_uart_pins(uart->uart_base); uart_default_config(uart->uart_base, &uart_config); uart_config.src_freq_in_hz = board_init_uart_clock(uart->uart_base); uart_config.baudrate = cfg->baud_rate; uart_config.num_of_stop_bits = cfg->stop_bits; uart_config.parity = cfg->parity; uart_config.rx_fifo_level = uart_rx_fifo_trg_gt_three_quarters; #ifdef RT_SERIAL_USING_DMA if (uart->dma_flags & (RT_DEVICE_FLAG_DMA_TX | RT_DEVICE_FLAG_DMA_RX)) { uart_config.fifo_enable = true; uart_config.dma_enable = true; if (uart->dma_flags & RT_DEVICE_FLAG_DMA_TX) { uart_config.tx_fifo_level = uart_tx_fifo_trg_not_full; } if (uart->dma_flags & RT_DEVICE_FLAG_DMA_RX) { uart_config.rx_fifo_level = uart_rx_fifo_trg_not_empty; } #if defined(HPM_IP_FEATURE_UART_RX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_RX_IDLE_DETECT == 1) uart_config.rxidle_config.detect_enable = true; uart_config.rxidle_config.detect_irq_enable = true; uart_config.rxidle_config.idle_cond = uart_rxline_idle_cond_rxline_logic_one; uart_config.rxidle_config.threshold = 16U; /* 10bit */ #endif } #endif uart_config.word_length = cfg->data_bits - DATA_BITS_5; hpm_stat_t status = uart_init(uart->uart_base, &uart_config); return (status != status_success) ? -RT_ERROR : RT_EOK; } #ifdef RT_SERIAL_USING_DMA hpm_stat_t hpm_uart_dma_rx_init(struct hpm_uart *uart_ctx) { hpm_stat_t status = status_fail; if (!uart_ctx->rx_resource_allocated) { status = dma_mgr_request_resource(&uart_ctx->rx_chn_ctx.resource); if (status == status_success) { uart_ctx->dma_flags |= RT_DEVICE_FLAG_DMA_RX; uart_ctx->rx_resource_allocated = true; dma_mgr_install_chn_tc_callback(&uart_ctx->rx_chn_ctx.resource, uart_dma_tc_callback, &uart_ctx->rx_chn_ctx); dma_mgr_install_chn_abort_callback(&uart_ctx->rx_chn_ctx.resource, uart_dma_abort_callback, &uart_ctx->rx_chn_ctx); dma_mgr_install_chn_error_callback(&uart_ctx->rx_chn_ctx.resource, uart_dma_error_callback, &uart_ctx->rx_chn_ctx); } } return status; } hpm_stat_t hpm_uart_dma_tx_init(struct hpm_uart *uart_ctx) { hpm_stat_t status = status_fail; if (!uart_ctx->tx_resource_allocated) { status = dma_mgr_request_resource(&uart_ctx->tx_chn_ctx.resource); if (status == status_success) { uart_ctx->dma_flags |= RT_DEVICE_FLAG_DMA_TX; uart_ctx->tx_resource_allocated = true; dma_mgr_install_chn_tc_callback(&uart_ctx->tx_chn_ctx.resource, uart_dma_tc_callback, &uart_ctx->tx_chn_ctx); dma_mgr_install_chn_abort_callback(&uart_ctx->tx_chn_ctx.resource, uart_dma_abort_callback, &uart_ctx->tx_chn_ctx); dma_mgr_install_chn_error_callback(&uart_ctx->tx_chn_ctx.resource, uart_dma_error_callback, &uart_ctx->tx_chn_ctx); } } return status; } static int hpm_uart_dma_config(struct rt_serial_device *serial, void *arg) { rt_ubase_t ctrl_arg = (rt_ubase_t) arg; struct hpm_uart *uart = (struct hpm_uart *)serial->parent.user_data; struct rt_serial_rx_fifo *rx_fifo; dma_mgr_chn_conf_t chg_config; dma_mgr_get_default_chn_config(&chg_config); if (ctrl_arg == RT_DEVICE_FLAG_DMA_RX) { rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; chg_config.dst_addr_ctrl = DMA_MGR_ADDRESS_CONTROL_INCREMENT; chg_config.dst_mode = DMA_MGR_HANDSHAKE_MODE_NORMAL; chg_config.dst_width = DMA_TRANSFER_WIDTH_BYTE; chg_config.en_dmamux = true; chg_config.dmamux_src = uart->rx_dma_mux; chg_config.src_addr = (uint32_t)&(uart->uart_base->RBR); chg_config.src_addr_ctrl = DMA_MGR_ADDRESS_CONTROL_FIXED; chg_config.src_mode = DMA_HANDSHAKE_MODE_HANDSHAKE; chg_config.src_width = DMA_TRANSFER_WIDTH_BYTE; #if defined(HPM_IP_FEATURE_UART_RX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_RX_IDLE_DETECT == 1) chg_config.dst_addr = (uint32_t)uart->rx_idle_tmp_buffer; chg_config.size_in_byte = sizeof(uart->rx_idle_tmp_buffer); #else chg_config.dst_addr = (uint32_t)rx_fifo->rb.buffer_ptr; chg_config.size_in_byte = serial->config.rx_bufsz; #endif if (status_success != dma_mgr_setup_channel(&uart->rx_chn_ctx.resource, &chg_config)) { return -RT_ERROR; } dma_mgr_enable_channel(&uart->rx_chn_ctx.resource); dma_mgr_enable_chn_irq(&uart->rx_chn_ctx.resource, DMA_MGR_INTERRUPT_MASK_TC); dma_mgr_enable_dma_irq_with_priority(&uart->rx_chn_ctx.resource, 1); #if !defined(HPM_IP_FEATURE_UART_RX_IDLE_DETECT) || (HPM_IP_FEATURE_UART_RX_IDLE_DETECT == 0) hpm_uart_dma_register_channel(serial, false, uart_rx_done, RT_NULL, RT_NULL); #else intc_m_enable_irq_with_priority(uart->irq_num, 1); #endif } else if (ctrl_arg == RT_DEVICE_FLAG_DMA_TX) { chg_config.src_addr_ctrl = DMA_MGR_ADDRESS_CONTROL_INCREMENT; chg_config.src_mode = DMA_MGR_HANDSHAKE_MODE_NORMAL; chg_config.src_width = DMA_TRANSFER_WIDTH_BYTE; chg_config.dst_addr = (uint32_t)&uart->uart_base->THR; chg_config.dst_addr_ctrl = DMA_MGR_ADDRESS_CONTROL_FIXED; chg_config.dst_mode = DMA_MGR_HANDSHAKE_MODE_HANDSHAKE; chg_config.dst_width = DMA_TRANSFER_WIDTH_BYTE; chg_config.en_dmamux = true; chg_config.dmamux_src = uart->tx_dma_mux; if (status_success != dma_mgr_setup_channel(&uart->tx_chn_ctx.resource, &chg_config)) { return -RT_ERROR; } dma_mgr_enable_chn_irq(&uart->tx_chn_ctx.resource, DMA_MGR_INTERRUPT_MASK_TC); dma_mgr_enable_dma_irq_with_priority(&uart->tx_chn_ctx.resource, 1); } return RT_EOK; } static void hpm_uart_receive_dma_next(struct rt_serial_device *serial) { uint32_t buf_addr; uint32_t buf_size; struct hpm_uart *uart = (struct hpm_uart *)serial->parent.user_data; struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; #if defined(HPM_IP_FEATURE_UART_RX_IDLE_DETECT) && (HPM_IP_FEATURE_UART_RX_IDLE_DETECT == 1) buf_addr = (uint32_t)uart->rx_idle_tmp_buffer; buf_size = sizeof(uart->rx_idle_tmp_buffer); #else buf_addr = (uint32_t)rx_fifo->rb.buffer_ptr; buf_size = serial->config.rx_bufsz; #endif dma_mgr_set_chn_dst_addr(&uart->rx_chn_ctx.resource, buf_addr); dma_mgr_set_chn_transize(&uart->rx_chn_ctx.resource, buf_size); dma_mgr_enable_channel(&uart->rx_chn_ctx.resource); } static void hpm_uart_transmit_dma(struct rt_serial_device *serial, uint8_t *src, uint32_t size) { struct hpm_uart *uart = (struct hpm_uart *)serial->parent.user_data; dma_mgr_set_chn_src_addr(&uart->tx_chn_ctx.resource, (uint32_t)src); dma_mgr_set_chn_transize(&uart->tx_chn_ctx.resource, size); dma_mgr_enable_channel(&uart->tx_chn_ctx.resource); } #endif /* RT_SERIAL_USING_DMA */ static rt_err_t hpm_uart_control(struct rt_serial_device *serial, int cmd, void *arg) { RT_ASSERT(serial != RT_NULL); rt_ubase_t ctrl_arg = (rt_ubase_t) arg; uint8_t *tmp_buffer = NULL; struct rt_serial_rx_fifo *rx_fifo = (struct rt_serial_rx_fifo*)serial->serial_rx; struct rt_serial_tx_fifo *tx_fifo = (struct rt_serial_tx_fifo*)serial->serial_tx; struct hpm_uart *uart = (struct hpm_uart *)serial->parent.user_data; if(ctrl_arg & (RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_RX_NON_BLOCKING)) { #ifdef RT_SERIAL_USING_DMA if (uart->dma_flags & RT_DEVICE_FLAG_DMA_RX) { ctrl_arg = RT_DEVICE_FLAG_DMA_RX; } else #endif { ctrl_arg = RT_DEVICE_FLAG_INT_RX; } } else if(ctrl_arg & (RT_DEVICE_FLAG_TX_BLOCKING | RT_DEVICE_FLAG_TX_NON_BLOCKING)) { #ifdef RT_SERIAL_USING_DMA if (uart->dma_flags & RT_DEVICE_FLAG_DMA_TX) { ctrl_arg = RT_DEVICE_FLAG_DMA_TX; } else #endif { ctrl_arg = RT_DEVICE_FLAG_INT_TX; } } switch (cmd) { case RT_DEVICE_CTRL_CLR_INT: if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) { /* disable rx irq */ uart_disable_irq(uart->uart_base, uart_intr_rx_data_avail_or_timeout); intc_m_disable_irq(uart->irq_num); } else if (ctrl_arg == RT_DEVICE_FLAG_INT_TX) { /* disable tx irq */ uart_disable_irq(uart->uart_base, uart_intr_tx_slot_avail); intc_m_disable_irq(uart->irq_num); } #ifdef RT_SERIAL_USING_DMA else if (ctrl_arg == RT_DEVICE_FLAG_DMA_TX) { dma_mgr_disable_chn_irq(&uart->tx_chn_ctx.resource, DMA_INTERRUPT_MASK_ALL); dma_abort_channel(uart->tx_chn_ctx.resource.base, uart->tx_chn_ctx.resource.channel); if (uart->tx_chn_ctx.ringbuf_ptr != RT_NULL) { rt_free(uart->tx_chn_ctx.ringbuf_ptr); uart->tx_chn_ctx.ringbuf_ptr = RT_NULL; } } else if (ctrl_arg == RT_DEVICE_FLAG_DMA_RX) { dma_mgr_disable_chn_irq(&uart->rx_chn_ctx.resource, DMA_INTERRUPT_MASK_ALL); dma_abort_channel(uart->rx_chn_ctx.resource.base, uart->rx_chn_ctx.resource.channel); if (uart->rx_chn_ctx.ringbuf_ptr != RT_NULL) { rt_free(uart->rx_chn_ctx.ringbuf_ptr); uart->rx_chn_ctx.ringbuf_ptr = RT_NULL; } } #endif break; case RT_DEVICE_CTRL_SET_INT: if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) { /* enable rx irq */ uart_enable_irq(uart->uart_base, uart_intr_rx_data_avail_or_timeout); intc_m_enable_irq_with_priority(uart->irq_num, 2); } else if (ctrl_arg == RT_DEVICE_FLAG_INT_TX) { /* enable tx irq */ uart_enable_irq(uart->uart_base, uart_intr_tx_slot_avail); intc_m_enable_irq_with_priority(uart->irq_num, 1); } break; case RT_DEVICE_CTRL_CONFIG: #ifdef RT_SERIAL_USING_DMA if ((ctrl_arg == RT_DEVICE_FLAG_DMA_RX) || (ctrl_arg == RT_DEVICE_FLAG_INT_RX)) { if ((rx_fifo) && (((rt_uint32_t)rx_fifo->rb.buffer_ptr % HPM_L1C_CACHELINE_SIZE) || (rx_fifo->rb.buffer_size % HPM_L1C_CACHELINE_SIZE))) { rt_free(rx_fifo); rx_fifo = RT_NULL; rx_fifo = (struct rt_serial_rx_fifo *) rt_malloc(sizeof(struct rt_serial_rx_fifo)); RT_ASSERT(rx_fifo != RT_NULL); tmp_buffer = rt_malloc(serial->config.rx_bufsz + HPM_L1C_CACHELINE_SIZE); RT_ASSERT(tmp_buffer != RT_NULL); if (uart->rx_chn_ctx.ringbuf_ptr != RT_NULL) { rt_free(uart->rx_chn_ctx.ringbuf_ptr); } uart->rx_chn_ctx.ringbuf_ptr = (void *)tmp_buffer; tmp_buffer += (HPM_L1C_CACHELINE_SIZE - ((rt_ubase_t) tmp_buffer % HPM_L1C_CACHELINE_SIZE)); rt_ringbuffer_init(&rx_fifo->rb, tmp_buffer, serial->config.rx_bufsz); rt_ringbuffer_reset(&rx_fifo->rb); serial->serial_rx = rx_fifo; } } if ((ctrl_arg == RT_DEVICE_FLAG_DMA_TX) || (ctrl_arg == RT_DEVICE_FLAG_INT_TX)) { if ((tx_fifo) && (((rt_uint32_t)tx_fifo->rb.buffer_ptr % HPM_L1C_CACHELINE_SIZE) || (tx_fifo->rb.buffer_size % HPM_L1C_CACHELINE_SIZE))) { rt_free(tx_fifo); tx_fifo = RT_NULL; tx_fifo = (struct rt_serial_tx_fifo *) rt_malloc(sizeof(struct rt_serial_tx_fifo)); RT_ASSERT(tx_fifo != RT_NULL); tmp_buffer = rt_malloc(serial->config.tx_bufsz + HPM_L1C_CACHELINE_SIZE); RT_ASSERT(tmp_buffer != RT_NULL); if (uart->tx_chn_ctx.ringbuf_ptr != RT_NULL) { rt_free(uart->tx_chn_ctx.ringbuf_ptr); } uart->tx_chn_ctx.ringbuf_ptr = (void *)tmp_buffer; tmp_buffer += (HPM_L1C_CACHELINE_SIZE - ((rt_ubase_t) tmp_buffer % HPM_L1C_CACHELINE_SIZE)); rt_ringbuffer_init(&tx_fifo->rb, tmp_buffer, serial->config.tx_bufsz); rt_ringbuffer_reset(&tx_fifo->rb); tx_fifo->activated = RT_FALSE; tx_fifo->put_size = 0; serial->serial_tx = tx_fifo; } } if (ctrl_arg & (RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX)) { hpm_uart_dma_config(serial, (void *)ctrl_arg); } else #endif { hpm_uart_control(serial, RT_DEVICE_CTRL_SET_INT, (void *)ctrl_arg); } break; case RT_DEVICE_CHECK_OPTMODE: #ifdef RT_SERIAL_USING_DMA if ((ctrl_arg & RT_DEVICE_FLAG_DMA_TX)) { return RT_SERIAL_TX_BLOCKING_NO_BUFFER; } else #endif { return RT_SERIAL_TX_BLOCKING_BUFFER; } } return RT_EOK; } static int hpm_uart_putc(struct rt_serial_device *serial, char ch) { struct hpm_uart *uart = (struct hpm_uart *)serial->parent.user_data; uart_send_byte(uart->uart_base, ch); uart_flush(uart->uart_base); return ch; } static int hpm_uart_getc(struct rt_serial_device *serial) { int result = -1; struct hpm_uart *uart = (struct hpm_uart *)serial->parent.user_data; if (uart_check_status(uart->uart_base, uart_stat_data_ready)) { uart_receive_byte(uart->uart_base, (uint8_t*)&result); } return result; } static rt_ssize_t hpm_uart_transmit(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size, rt_uint32_t tx_flag) { RT_ASSERT(serial != RT_NULL); RT_ASSERT(buf != RT_NULL); RT_ASSERT(size); uint32_t fifo_size = 0, tx_size = 0; uint32_t ringbuffer_data_len = 0; struct hpm_uart *uart = (struct hpm_uart *)serial->parent.user_data; struct rt_serial_tx_fifo *tx_fifo; tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx; uint8_t ch = 0; RT_ASSERT(tx_fifo != RT_NULL); #ifdef RT_SERIAL_USING_DMA if (uart->dma_flags & RT_DEVICE_FLAG_DMA_TX) { hpm_uart_dma_register_channel(serial, true, uart_tx_done, RT_NULL, RT_NULL); intc_m_enable_irq(uart->tx_chn_ctx.resource.irq_num); if (l1c_dc_is_enabled()) { uint32_t aligned_start = HPM_L1C_CACHELINE_ALIGN_DOWN((uint32_t)buf); uint32_t aligned_end = HPM_L1C_CACHELINE_ALIGN_UP((uint32_t)buf + size); uint32_t aligned_size = aligned_end - aligned_start; l1c_dc_flush(aligned_start, aligned_size); } hpm_uart_transmit_dma(serial, buf, size); return size; } else { #else { #endif if (size > 0) { if (uart_check_status(uart->uart_base, uart_stat_tx_slot_avail)) { uart_disable_irq(uart->uart_base, uart_intr_tx_slot_avail); fifo_size = uart_get_fifo_size(uart->uart_base); ringbuffer_data_len = rt_ringbuffer_data_len(&tx_fifo->rb); tx_size = (ringbuffer_data_len > fifo_size) ? fifo_size : ringbuffer_data_len; for (uint32_t i = 0; i < tx_size; i++) { rt_ringbuffer_getchar(&tx_fifo->rb, &ch); uart_write_byte(uart->uart_base, ch); } uart_enable_irq(uart->uart_base, uart_intr_tx_slot_avail); } } } return size; } static const struct rt_uart_ops hpm_uart_ops = { hpm_uart_configure, hpm_uart_control, hpm_uart_putc, hpm_uart_getc, hpm_uart_transmit, }; static int hpm_uart_config(void) { struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; hpm_stat_t status = status_success; #ifdef BSP_USING_UART0 uarts[HPM_UART0_INDEX].serial->config = config; uarts[HPM_UART0_INDEX].serial->config.rx_bufsz = BSP_UART0_RX_BUFSIZE; uarts[HPM_UART0_INDEX].serial->config.tx_bufsz = BSP_UART0_TX_BUFSIZE; #ifdef RT_SERIAL_USING_DMA uarts[HPM_UART0_INDEX].dma_flags = 0; #ifdef BSP_UART0_RX_USING_DMA status = hpm_uart_dma_rx_init(&uarts[HPM_UART0_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART0_RX_USING_DMA #ifdef BSP_UART0_TX_USING_DMA status = hpm_uart_dma_tx_init(&uarts[HPM_UART0_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART0_TX_USING_DMA #endif // RT_SERIAL_USING_DMA #endif //BSP_USING_UART0 #ifdef BSP_USING_UART1 uarts[HPM_UART1_INDEX].serial->config = config; uarts[HPM_UART1_INDEX].serial->config.rx_bufsz = BSP_UART1_RX_BUFSIZE; uarts[HPM_UART1_INDEX].serial->config.tx_bufsz = BSP_UART1_TX_BUFSIZE; #ifdef RT_SERIAL_USING_DMA uarts[HPM_UART1_INDEX].dma_flags = 0; #ifdef BSP_UART1_RX_USING_DMA status = hpm_uart_dma_rx_init(&uarts[HPM_UART1_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART1_RX_USING_DMA #ifdef BSP_UART1_TX_USING_DMA status = hpm_uart_dma_tx_init(&uarts[HPM_UART1_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART1_TX_USING_DMA #endif // RT_SERIAL_USING_DMA #endif //BSP_USING_UART1 #ifdef BSP_USING_UART2 uarts[HPM_UART2_INDEX].serial->config = config; uarts[HPM_UART2_INDEX].serial->config.rx_bufsz = BSP_UART2_RX_BUFSIZE; uarts[HPM_UART2_INDEX].serial->config.tx_bufsz = BSP_UART2_TX_BUFSIZE; #ifdef RT_SERIAL_USING_DMA uarts[HPM_UART2_INDEX].dma_flags = 0; #ifdef BSP_UART2_RX_USING_DMA status = hpm_uart_dma_rx_init(&uarts[HPM_UART2_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART2_RX_USING_DMA #ifdef BSP_UART2_TX_USING_DMA status = hpm_uart_dma_tx_init(&uarts[HPM_UART2_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART2_TX_USING_DMA #endif // RT_SERIAL_USING_DMA #endif //BSP_USING_UART2 #ifdef BSP_USING_UART3 uarts[HPM_UART3_INDEX].serial->config = config; uarts[HPM_UART3_INDEX].serial->config.rx_bufsz = BSP_UART3_RX_BUFSIZE; uarts[HPM_UART3_INDEX].serial->config.tx_bufsz = BSP_UART3_TX_BUFSIZE; #ifdef RT_SERIAL_USING_DMA uarts[HPM_UART3_INDEX].dma_flags = 0; #ifdef BSP_UART3_RX_USING_DMA status = hpm_uart_dma_rx_init(&uarts[HPM_UART3_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART3_RX_USING_DMA #ifdef BSP_UART3_TX_USING_DMA status = hpm_uart_dma_tx_init(&uarts[HPM_UART3_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART3_TX_USING_DMA #endif // RT_SERIAL_USING_DMA #endif //BSP_USING_UART3 #ifdef BSP_USING_UART4 uarts[HPM_UART4_INDEX].serial->config = config; uarts[HPM_UART4_INDEX].serial->config.rx_bufsz = BSP_UART4_RX_BUFSIZE; uarts[HPM_UART4_INDEX].serial->config.tx_bufsz = BSP_UART4_TX_BUFSIZE; #ifdef RT_SERIAL_USING_DMA uarts[HPM_UART4_INDEX].dma_flags = 0; #ifdef BSP_UART4_RX_USING_DMA status = hpm_uart_dma_rx_init(&uarts[HPM_UART4_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART4_RX_USING_DMA #ifdef BSP_UART4_TX_USING_DMA status = hpm_uart_dma_tx_init(&uarts[HPM_UART4_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART4_TX_USING_DMA #endif // RT_SERIAL_USING_DMA #endif //BSP_USING_UART4 #ifdef BSP_USING_UART5 uarts[HPM_UART5_INDEX].serial->config = config; uarts[HPM_UART5_INDEX].serial->config.rx_bufsz = BSP_UART5_RX_BUFSIZE; uarts[HPM_UART5_INDEX].serial->config.tx_bufsz = BSP_UART5_TX_BUFSIZE; #ifdef RT_SERIAL_USING_DMA uarts[HPM_UART5_INDEX].dma_flags = 0; #ifdef BSP_UART5_RX_USING_DMA status = hpm_uart_dma_rx_init(&uarts[HPM_UART5_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART5_RX_USING_DMA #ifdef BSP_UART5_TX_USING_DMA status = hpm_uart_dma_tx_init(&uarts[HPM_UART5_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART5_TX_USING_DMA #endif // RT_SERIAL_USING_DMA #endif //BSP_USING_UART5 #ifdef BSP_USING_UART6 uarts[HPM_UART6_INDEX].serial->config = config; uarts[HPM_UART6_INDEX].serial->config.rx_bufsz = BSP_UART6_RX_BUFSIZE; uarts[HPM_UART6_INDEX].serial->config.tx_bufsz = BSP_UART6_TX_BUFSIZE; #ifdef RT_SERIAL_USING_DMA uarts[HPM_UART6_INDEX].dma_flags = 0; #ifdef BSP_UART6_RX_USING_DMA status = hpm_uart_dma_rx_init(&uarts[HPM_UART6_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART6_RX_USING_DMA #ifdef BSP_UART6_TX_USING_DMA status = hpm_uart_dma_tx_init(&uarts[HPM_UART6_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART6_TX_USING_DMA #endif // RT_SERIAL_USING_DMA #endif //BSP_USING_UART6 #ifdef BSP_USING_UART7 uarts[HPM_UART7_INDEX].serial->config = config; uarts[HPM_UART7_INDEX].serial->config.rx_bufsz = BSP_UART7_RX_BUFSIZE; uarts[HPM_UART7_INDEX].serial->config.tx_bufsz = BSP_UART7_TX_BUFSIZE; #ifdef RT_SERIAL_USING_DMA uarts[HPM_UART7_INDEX].dma_flags = 0; #ifdef BSP_UART7_RX_USING_DMA status = hpm_uart_dma_rx_init(&uarts[HPM_UART7_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART7_RX_USING_DMA #ifdef BSP_UART7_TX_USING_DMA status = hpm_uart_dma_tx_init(&uarts[HPM_UART7_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART7_TX_USING_DMA #endif // RT_SERIAL_USING_DMA #endif //BSP_USING_UART7 #ifdef BSP_USING_UART8 uarts[HPM_UART8_INDEX].serial->config = config; uarts[HPM_UART8_INDEX].serial->config.rx_bufsz = BSP_UART8_RX_BUFSIZE; uarts[HPM_UART8_INDEX].serial->config.tx_bufsz = BSP_UART8_TX_BUFSIZE; #ifdef RT_SERIAL_USING_DMA uarts[HPM_UART8_INDEX].dma_flags = 0; #ifdef BSP_UART8_RX_USING_DMA status = hpm_uart_dma_rx_init(&uarts[HPM_UART8_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART8_RX_USING_DMA #ifdef BSP_UART8_TX_USING_DMA status = hpm_uart_dma_tx_init(&uarts[HPM_UART8_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART8_TX_USING_DMA #endif // RT_SERIAL_USING_DMA #endif //BSP_USING_UART8 #ifdef BSP_USING_UART9 uarts[HPM_UART9_INDEX].serial->config = config; uarts[HPM_UART9_INDEX].serial->config.rx_bufsz = BSP_UART9_RX_BUFSIZE; uarts[HPM_UART9_INDEX].serial->config.tx_bufsz = BSP_UART9_TX_BUFSIZE; #ifdef RT_SERIAL_USING_DMA uarts[HPM_UART9_INDEX].dma_flags = 0; #ifdef BSP_UART9_RX_USING_DMA status = hpm_uart_dma_rx_init(&uarts[HPM_UART9_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART9_RX_USING_DMA #ifdef BSP_UART9_TX_USING_DMA status = hpm_uart_dma_tx_init(&uarts[HPM_UART9_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART9_TX_USING_DMA #endif // RT_SERIAL_USING_DMA #endif //BSP_USING_UART9 #ifdef BSP_USING_UART10 uarts[HPM_UART10_INDEX].serial->config = config; uarts[HPM_UART10_INDEX].serial->config.rx_bufsz = BSP_UART10_RX_BUFSIZE; uarts[HPM_UART10_INDEX].serial->config.tx_bufsz = BSP_UART10_TX_BUFSIZE; #ifdef RT_SERIAL_USING_DMA uarts[HPM_UART10_INDEX].dma_flags = 0; #ifdef BSP_UART10_RX_USING_DMA status = hpm_uart_dma_rx_init(&uarts[HPM_UART10_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART10_RX_USING_DMA #ifdef BSP_UART10_TX_USING_DMA status = hpm_uart_dma_tx_init(&uarts[HPM_UART10_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART10_TX_USING_DMA #endif // RT_SERIAL_USING_DMA #endif //BSP_USING_UART10 #ifdef BSP_USING_UART11 uarts[HPM_UART11_INDEX].serial->config = config; uarts[HPM_UART11_INDEX].serial->config.rx_bufsz = BSP_UART11_RX_BUFSIZE; uarts[HPM_UART11_INDEX].serial->config.tx_bufsz = BSP_UART11_TX_BUFSIZE; #ifdef RT_SERIAL_USING_DMA uarts[HPM_UART11_INDEX].dma_flags = 0; #ifdef BSP_UART11_RX_USING_DMA status = hpm_uart_dma_rx_init(&uarts[HPM_UART11_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART11_RX_USING_DMA #ifdef BSP_UART11_TX_USING_DMA status = hpm_uart_dma_tx_init(&uarts[HPM_UART11_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART11_TX_USING_DMA #endif // RT_SERIAL_USING_DMA #endif //BSP_USING_UART11 #ifdef BSP_USING_UART12 uarts[HPM_UART12_INDEX].serial->config = config; uarts[HPM_UART12_INDEX].serial->config.rx_bufsz = BSP_UART12_RX_BUFSIZE; uarts[HPM_UART12_INDEX].serial->config.tx_bufsz = BSP_UART12_TX_BUFSIZE; #ifdef RT_SERIAL_USING_DMA uarts[HPM_UART12_INDEX].dma_flags = 0; #ifdef BSP_UART12_RX_USING_DMA status = hpm_uart_dma_rx_init(&uarts[HPM_UART12_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART12_RX_USING_DMA #ifdef BSP_UART12_TX_USING_DMA status = hpm_uart_dma_tx_init(&uarts[HPM_UART12_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART12_TX_USING_DMA #endif // RT_SERIAL_USING_DMA #endif //BSP_USING_UART12 #ifdef BSP_USING_UART13 uarts[HPM_UART13_INDEX].serial->config = config; uarts[HPM_UART13_INDEX].serial->config.rx_bufsz = BSP_UART13_RX_BUFSIZE; uarts[HPM_UART13_INDEX].serial->config.tx_bufsz = BSP_UART13_TX_BUFSIZE; #ifdef RT_SERIAL_USING_DMA uarts[HPM_UART13_INDEX].dma_flags = 0; #ifdef BSP_UART13_RX_USING_DMA status = hpm_uart_dma_rx_init(&uarts[HPM_UART13_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART13_RX_USING_DMA #ifdef BSP_UART13_TX_USING_DMA status = hpm_uart_dma_tx_init(&uarts[HPM_UART13_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART13_TX_USING_DMA #endif // RT_SERIAL_USING_DMA #endif //BSP_USING_UART13 #ifdef BSP_USING_UART14 uarts[HPM_UART14_INDEX].serial->config = config; uarts[HPM_UART14_INDEX].serial->config.rx_bufsz = BSP_UART14_RX_BUFSIZE; uarts[HPM_UART14_INDEX].serial->config.tx_bufsz = BSP_UART14_TX_BUFSIZE; #ifdef RT_SERIAL_USING_DMA uarts[HPM_UART14_INDEX].dma_flags = 0; #ifdef BSP_UART14_RX_USING_DMA status = hpm_uart_dma_rx_init(&uarts[HPM_UART14_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART14_RX_USING_DMA #ifdef BSP_UART14_TX_USING_DMA status = hpm_uart_dma_tx_init(&uarts[HPM_UART14_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART14_TX_USING_DMA #endif // RT_SERIAL_USING_DMA #endif //BSP_USING_UART14 #ifdef BSP_USING_UART15 uarts[HPM_UART15_INDEX].serial->config = config; uarts[HPM_UART15_INDEX].serial->config.rx_bufsz = BSP_UART15_RX_BUFSIZE; uarts[HPM_UART15_INDEX].serial->config.tx_bufsz = BSP_UART15_TX_BUFSIZE; #ifdef RT_SERIAL_USING_DMA uarts[HPM_UART15_INDEX].dma_flags = 0; #ifdef BSP_UART15_RX_USING_DMA status = hpm_uart_dma_rx_init(&uarts[HPM_UART15_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART15_RX_USING_DMA #ifdef BSP_UART15_TX_USING_DMA status = hpm_uart_dma_tx_init(&uarts[HPM_UART15_INDEX]); if (status != status_success) { return -RT_ERROR; } #endif //BSP_UART15_TX_USING_DMA #endif // RT_SERIAL_USING_DMA #endif //BSP_USING_UART15 return RT_EOK; } int rt_hw_uart_init(void) { /* Added bypass logic here since the rt_hw_uart_init function will be initialized twice, the 2nd initialization should be bypassed */ static bool initialized; rt_err_t err = RT_EOK; if (initialized) { return err; } else { initialized = true; } if (RT_EOK != hpm_uart_config()) { return -RT_ERROR; } for (uint32_t i = 0; i < sizeof(uarts) / sizeof(uarts[0]); i++) { uarts[i].serial->ops = &hpm_uart_ops; /* register UART device */ err = rt_hw_serial_register(uarts[i].serial, uarts[i].device_name, RT_DEVICE_FLAG_RDWR, (void*)&uarts[i]); } return err; } INIT_BOARD_EXPORT(rt_hw_uart_init); #endif /* RT_USING_SERIAL */