| 我们在使用UART1的接收,实时要求高的通信,不能漏收数据,这里介绍开启DMA方式接收的示例。 1)以simple示例,在main.c文件中添加 //用于测试DMA mem2time的宏定义 #define DMA_DECLARE_LLIP(name, n) static dma_llip_t name[n]   /// Declare link list item #define CCR_BLOCK_NUM     4                 // the ccr block num #define DATA_COUNTS 19                  //用于统计buf_32bits_aligned中待搬移数据的个数 #define TIM         HS_TIM0             //选则定时器 #define CHANNEL     TIM_PWM_CHANNEL_0   //选择通道 /*********************************************************************  * LOCAL VARIABLES  */ //用于测试DMA mem2time的局部变量 /*********************************************************************  * GLOBAL VARIABLES  */ HS_DMA_CH_Type *dma_ch; uint8_t Uar_recv_Dma_Buffer[BUF_SIZE]; dma_block_t block[1]; /*********************************************************  *  *  DMA UART  * **********************************************************/ void print_buf(void *buf, int length, char *title) {     if (title)         log_debug("%s:\r\n", title);     // use length == 0 as string flag.     if (length == 0)         log_debug("%s\r\n", (char *)buf);     else {         for (int i = 0; i < length; i++)             log_debug("%02x%s", ((uint8_t *)buf)[i], (i%16 != 15) ? " " : "\r\n");     }     //log_debug("\r\n"); } static void dma_print_block(dma_block_t *block) {     for (dma_block_t *p = block; p; p = (dma_block_t *)p->LLPointer)         log_debug("\nblock: addr = 0x%08x, Ctrl = 0x%08x, \nSrcAddr = 0x%08x, DstAddr = 0x%08x, LLPointer = 0x%08x\r\n",                   p, p->Ctrl, p->SrcAddr, p->DstAddr, p->LLPointer); } /**  * DMA callback function of type @p dma_callback_t.  */ static void dma_cb(dma_status_t status, uint32_t cur_src_addr, uint32_t cur_dst_addr, uint32_t xfer_size) {     log_debug("\r\n");     if (status == DMA_STATUS_BLOCK_OK)     {         log_debug("DMA block transfer succeed, block info: ");     }     else if (status == DMA_STATUS_ABORT)     {         log_debug("DMA block transfer aborted, current info: ");     }     else     {         log_debug("DMA block transfer error, current info: ");     }     log_debug("status = 0x%08x, src_addr = 0x%08x, dst_addr = 0x%08x, xfer_size = %d\r\n",               status, cur_src_addr, cur_dst_addr, xfer_size);     //fflush(stdout);     //log_debug_array(Uar_recv_Dma_Buffer, sizeof(Uar_recv_Dma_Buffer)); //full print     //print_buf(Uar_recv_Dma_Buffer, 0, "Uar_recv_Dma_Buffer"); } dma_dev_t dma_mem = {     .id         = MEM_DMA_ID,     .addr       = Uar_recv_Dma_Buffer,     .addr_ctrl  = DMA_ADDR_CTRL_INC,     .bus_width  = DMA_SLAVE_BUSWIDTH_8BITS,     .burst_size = DMA_BURST_LEN_1UNITS, }; dma_dev_t dma_uart = {     .id         = UART1_RX_DMA_ID,     .addr       = (void *) &HS_UART1->RBR,     .addr_ctrl  = DMA_ADDR_CTRL_FIX,     .bus_width  = DMA_SLAVE_BUSWIDTH_8BITS,     .burst_size = DMA_BURST_LEN_1UNITS, }; dma_block_config_t block_config = {     .src                 = &dma_uart,     .dst                 = &dma_mem,     //.block_size_in_bytes = 64,     .block_size_in_bytes = BUF_SIZE,     .priority            = 0,     .flow_controller     = DMA_FLOW_CONTROLLER_USE_NONE,     .intr_en             = false, }; static void cmd_dma_uart_to_mem(void) {     pinmux_config(5, PINMUX_UART1_SDA_O_CFG);     pinmux_config(6, PINMUX_UART1_SDA_I_CFG);     uart_open(HS_UART1, 115200, UART_FLOW_CTRL_DISABLED, NULL);     //(void)argc; #if 0     if (strcmp(argv[0], "1") != 0)     {         log_debug("Only uart 1 is supported by DMA.\r\n");         return;     } #endif     dma_init();     // Allocate and init buffers     for (int i = 0; i < BUF_SIZE; i++)     {         Uar_recv_Dma_Buffer[i] = 0xFF;     }     log_debug_array(Uar_recv_Dma_Buffer, sizeof(Uar_recv_Dma_Buffer));     log_debug("\r\n uart1 to mem multiple block transfer test:\r\n");     log_debug("\r\n Transfer: uart1 => Uar_recv_Dma_Buffer.\r\n");     // Build blocks //    dma_block_t block[1];     #if 0     /* dma_build_block_ex(&block[0], &dma_uart, &dma_mem, 1, 0, DMA_FLOW_CONTROLLER_USE_NONE, false); */     /* dma_build_block_ex(&block[1], &dma_uart, &dma_mem, 3, 0, DMA_FLOW_CONTROLLER_USE_NONE, false); */     /* dma_build_block_ex(&block[2], &dma_uart, &dma_mem, 5, 0, DMA_FLOW_CONTROLLER_USE_NONE, false); */     #endif     dma_build_block(&block[0], &block_config);     #if 0     //block_config.block_size_in_bytes = 64;     // dma_build_block(&block[1], &block_config);     // dma_mem.addr = Uar_recv_Dma_Buffer;     // block_config.block_size_in_bytes = 5;     // dma_build_block(&block[2], &block_config);     // dma_append_block(block, block + 1);     //dma_append_block(block+1, block+2);     #endif     //dma_print_block(block);     // Init DMA and start transfer.     log_debug("\n1");     //dma_init();     log_debug("\n2");     /**      * 1. DMA Software Ackknowledge must be executed before start using UART1 DMA after manual UART1 transfers,      * because UART1 has no DMA enable/disable control, and its DMA interface is always enabled from the start.      * So any transfer before connecting to DMA module will make the dma_tx/rx_req asserted and keeping, and a      * dma_tx/rx_ack is required to deassert the corresponding req signal before using DMA.      * 2. uart.dma_tx_req will always be asserted when the tx fifo is empty, so it can't and there's no need to be cleared.      * 3. Do not use HS_UART->FCR.bit1 to clear the UART.dma_rx_req signal, cause it reset whole control portion of rx fifo.      */     HS_UART1->DMASA = 1; //    HS_DMA_CH_Type *dma_ch;         dma_ch = dma_start_transfer(NULL, block, dma_cb);     //HS_DMA_CH_Type *dma_ch = dma_start_transfer(NULL, block, NULL);     log_debug("\n3");     if (dma_ch == NULL)     {         log_debug("DMA uart1-to-mem transfer fails.\r\n");         return;     }     log_debug("\n4");     #if 1     dma_wait_stop(dma_ch);   //     log_debug("\n5");     //dma_release(dma_ch);      //     // Check result by manual     log_debug("\n6\n");     //print_buf(Uar_recv_Dma_Buffer, 512, "Uar_recv_Dma_Buffer");         log_debug_array_ex("dma have stop:",Uar_recv_Dma_Buffer, sizeof(Uar_recv_Dma_Buffer));     log_debug("DMA uart1-to-mem transfer sucess.\r\n");     #endif } 2)定时器函数中调用,反复接收 static void simple_timer_handler(co_timer_t *timer, void *param) { //    wdt_keepalive(); //    pmu_dump(printf);     // muti dma rec start         for (int i = 0; i < BUF_SIZE; i++)     {         Uar_recv_Dma_Buffer[i] = 0xFF;     }         dma_init();     HS_UART1->DMASA = 1;     dma_ch = dma_start_transfer(NULL, block, dma_cb);     log_debug("\n-3");     if (dma_ch == NULL)     {         log_debug("DMA uart1-to-mem transfer fails.\r\n");         return;     }     log_debug("\n-4");       dma_wait_stop(dma_ch);   //              log_debug_array_ex("dma have stop:",Uar_recv_Dma_Buffer, sizeof(Uar_recv_Dma_Buffer));   } 3)main函数中调用 cmd_dma_uart_to_mem();//init dma uart 4)dma_nds.c修改如下: void dma_wait_stop(HS_DMA_CH_Type *ch) {     uint32_t ch_index = DMA_CH2INDEX(ch);     uint32_t ch_mask = 1u << ch_index; //    while(ch->Ctrl.Enable || ch->TranSize || ch->LLPointer);     uint32_t wait_time = 3500000;//5000000;     while (ch->Ctrl.Enable || ch->TranSize || ch->LLPointer)     {         wait_time--;         if(wait_time ==0)           break;       };       HS_DMAC->IntStatus.TC    = ch_mask;     HS_DMAC->IntStatus.Abort = ch_mask;     HS_DMAC->IntStatus.Error = ch_mask;     pmu_lowpower_allow(pmu_lp_dma_ch(ch_index)); } 5)打印如下: 
 | 

 
                            
                        