This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] AM62x:具有 DMA 支持的 Linux UART 驱动程序

Guru**** 2538860 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1303959/am62x-linux-uart-driver-with-dma-support

您好!

 我的项目使用以下 TI 芯片组。

SoC:   AM62X SR1.0 GP
Model: Texas Instruments K3 AM625 SoC

我已修改器件树以将数据包 DMA (PKTDMA)用于 UART。

&main_uart0 {
pinctrl-names = "default";
pinctrl-0 = <&main_uart0_pins_default>;
dmas = <&main_pktdma 0x4400 0>, <&main_pktdma 0xc400 0>;
dma-names = "rx", "tx";
};

根据 CONFIG_SERIAL_8250_DMA 的定义、RX DMA 函数在8250_omap.c 文件中是"OMAP_8250_Rx_DMA ()"、而在8250_dma.c 文件中不是"serial8250_Rx_dma ()"函数。

3.2.12. UART–Processor SDK AM62x 文档

通过使用 printk、我了解到 RX DMA 仅在 FIFO 有数据时进行设置、而是通过 UART IRQ 完成。

static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir,
				     unsigned char status)
{
	/*
	 * Queue a new transfer if FIFO has data.
	 */
	if ((status & (UART_LSR_DR | UART_LSR_BI)) &&
	    (up->ier & UART_IER_RDI)) {
		omap_8250_rx_dma(up);
		serial_out(up, UART_OMAP_EFR2, UART_OMAP_EFR2_TIMEOUT_BEHAVE);
	} 

我想了解以下 DMA 操作是否可以在该 SOC 上进行。

针对 UART RX DMA 进行一次性设置、然后让 UART 内核发送 DMA 请求、以便每当 RX  FIFO 有数据而不需要 CPU 时启动 DMA 传输。

DMA 内核将继续前进到下一个缓冲区描述符、直到结束、 然后返回到循环模式下的第一个缓冲区描述符。

当然、DMA 内核需要能够在已传输多少数据时报告进度。

提出该要求的原因是、我们的测量数据将 以3.125Mbps 波特率从测量硬件连续流式传输。

产品需要满足每秒50,000次读数的要求。 因此、我们不希望系统每秒发生50,000个中断。

Rgds、

KC Wong

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Kiong:

    感谢您的提问。

    请预计在几个工作日内收到回复。

    谢谢。

    瓦伊布哈夫

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Kiong:

    请预计因节假日而延迟回复。

    感谢您的耐心等待。

    此致、

    瓦伊布哈夫

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    当前的8250_OMAP UART 驱动程序和 UDMA 驱动程序不支持 UART 接口的 DMA 循环模式。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    高支持、


    我花了一些时间来跟踪"drivers/tty/serial/8250/8250_omap.c"中的 Linux UART 驱动程序代码。

    这是我对它如何工作的理解。

    当 RX FIFO 有数据时,会生成中断,只有在 DMA 传输排队以移动 OMAP_8250_RX_DMA ()函数中的数据。 同时、RX FIFO 中断被禁用、而 RX DMA 被启用。

    https://elixir.bootlin.com/linux/v5.10.145/source/drivers/tty/serial/8250/8250_omap.c#L923

    当 RX 超时中断被生成时、OMAP_8250_Rx_dma_flush ()函数将必须暂停 DMA (如果它仍在进行中)。 然后在__dma_rx_do_complete()函数中将数据从 dma 缓冲区复制到 tty 缓冲区,当然,重新启用 RX FIFO 中断。

    https://elixir.bootlin.com/linux/v5.10.145/source/drivers/tty/serial/8250/8250_omap.c#L898
    https://elixir.bootlin.com/linux/v5.10.145/source/drivers/tty/serial/8250/8250_omap.c#L810


    该使用模式使用 RX FIFO 中断来启动 RX DMA 传输。 并使用 RX 超时中断将数据从 DMA 缓冲区传输到另一个中间缓冲区。

    问题是,我们可以 在 RX FIFO 有数据之前执行 OMAP_8250_RX_DMA ()函数中的 RX DMA 设置吗? 或者必须首先在 RX FIFO 中包含数据、那么就只能设置 RX DMA?

    这是因为根据我在其他处理器上使用 DMA 的经验、可以在 RX 数据实际可用之前设置 DMA。  

    Rgds、

    KC Wong

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    问题是我们可以像 OMAP_8250_RX_DMA  ()函数那样在 RX FIFO 有数据之前进行 RX DMA 设置吗?

    我认为这在技术上是可能的。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Bin Liu:

    我想解释一下我们为什么要尝试创建定制的串行 DMA 驱动程序。 希望您能有所帮助。

    我们的项目主要是迁移一个最初在 SPEAr320S 上运行的已使用10年的 WinCE 应用。

     

    SPEAR320S 使用具有3.125Mbps 波特率的 UART 与测量板通信。

     

    SPEAr320S 具有 PrimeCell UART (PL011)和 PrimeCell DMA 控制器(PL080)。

     

    PL080有一个应用目标地址寄存器、用于知道 DMA 接下来将写入的位置。 该目标地址寄存器的作用基本上类似于 DMA 写入指针。

     

    然后、设置循环缓冲区、以便应用程序和 DMA 都可以访问以进行 UART 接收。

     

    因此、应用只需以10ms 的间隔轮询该寄存器。 如果 DMA 写入指针与应用程序读取指针不同、应用程序将知道缓冲区中有新数据。

     

    这种定制串行 DMA 驱动程序将面向带有一组 IOCTL 命令的应用。 该自定义驱动程序的主要目的是使用 DMA 进行 UART 接收、从而避免标准文件 API 的开销。

     

    作为替代、定制驱动程序将通过 DMA 引擎从 API 直接使用 DMA 驱动程序。

    ioctl 命令

    ioctl_dmac_alloc_memory

    ioctl_dmac_free_memory

    ioctl_dmac_start_dma

    ioctl_dmac_wait_dma_complete

    ioctl_dmac_disable_dma

    ioctl_dmac_abort_dma

    ioctl_dmac_get_dma_status

    定制驱动程序由2个主要部分组成:-

    1. 存储器分配:
      (1) dma_alloc_相干()函数分配非缓存物理连续内存。
      (2) dma_free_sicon()
    2. 使用 DMA 引擎从 API 进行 DMA 操作控制:
      (1) dma_request_channel ()
      (2) dma_release_channel ()
      (3) dmaengine_prep_slave_sg ()/dmaengine_prep_dma_cyclic ()
      (4) dmaengine_submit()
      (5) dma_async_issue_pending()
      (6) dmaengine_tx_status ()

     

    第一部分很简单。 但是、由于 DMA 内核的差异、第二部分不那么直接。

    末尾附加的是 ST SPEAR320S 处理器的定制串行 DMA 驱动程序、它可以正常工作。 我们还让它在 NXP I 上运行。 MX6ULL 处理器。



    现在、我们将尝试为 TI AM62x 处理器执行相同的操作。  以下是有关  TI AM62x 处理器的该项工作的进度。


    (a)我已在器件树中为 DMAC 器件添加了一个新的器件节点。

    	dmac {
    		compatible = "dmac_driver";
    		status = "okay";
    		dmas = <&main_pktdma 0x4400 0>, <&main_pktdma 0xc400 0>;
    		dma-names = "rx", "tx";    
    	};


    (b)并成功请求使用以下代码访问 DMA 通道。

    static int dmac_open(struct inode *inode, struct file *file)
    {
        struct device *dev = dmac_misc_device.this_device;
        dma_cap_mask_t mask;
        
        struct dma_slave_config rx_conf = {
            .src_addr = (UART_BASE + UART_RX),
            .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
            .direction = DMA_DEV_TO_MEM,
            .src_maxburst = 1,
            .device_fc = false,
        };
    
        dmac_t *p_dmac = (dmac_t *) devm_kzalloc(dev, sizeof(dmac_t ), GFP_KERNEL);
        if (!p_dmac)
        {
            dev_err(p_dmac->dev, "Failed to allocate memory for dmac_t\n");
            return -1;
        }
    
        p_dmac->dev = dev;
    
        file->private_data = p_dmac;
    
        dma_cap_zero(mask);
        dma_cap_set(DMA_SLAVE | DMA_CYCLIC, mask);
    
        dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
    
        p_dmac->chan = dma_request_chan(p_dmac->dev, "rx");
        if (IS_ERR_OR_NULL(p_dmac->chan))
        {
            dev_err(p_dmac->dev, "Failed to request DMA channel\n");
            return -1;
        }
    
        dev_dbg(p_dmac->dev, "open %s\n", dma_chan_name(p_dmac->chan));
    
        dmaengine_slave_config(p_dmac->chan, &rx_conf);
    
        p_dmac->uart_base = ioremap(UART_BASE, 1024);
        if (!p_dmac->uart_base)
        {
            dev_err(p_dmac->dev, "Failed to ioremap\n");
            return -1;
        }
    
        return 0;
    }

    (C)这也显示在 dmaengine 摘要中。

    root@p550:~# cat /sys/kernel/debug/dmaengine/summary
    dma0 (485c0100.dma-controller): number of channels: 48
    
    dma1 (485c0000.dma-controller): number of channels: 35
     dma1chan0 | dmac:rx (DEV_TO_MEM, rchan0 [0x4400 -> 0x9000], rflow0, PDMA, Packet mode)
    root@p550:~#

    (D)现在我们尝试使用以下代码启动 RX DMA。 但是、它似乎不起作用。 这是我们现在的位置...希望,你可以帮助。

        case DMAC_START_DMA:
            {
                start_dma_arg_t k_arg;
    
                struct scatterlist sglist;
                struct dma_async_tx_descriptor *desc;
    
                unsigned int ier;
                unsigned int scr;
    
                if ( copy_from_user(&k_arg , (start_dma_arg_t *)arg, sizeof(k_arg)) )
                {
                    dev_err(p_dmac->dev, "Failed copy from user\n");
                    return -EFAULT;
                }
    
                dev_dbg(p_dmac->dev, "DMAC_START_DMA, size = %ld block_size = %ld physical = 0x%llx\n",
                        k_arg.i_size,
                        k_arg.i_block_size,
                        k_arg.i_physical_address);
    
                {
                    sg_init_table(&sglist, 1);
                    sg_set_page(&sglist, phys_to_page(k_arg.i_physical_address), k_arg.i_size, offset_in_page(k_arg.i_physical_address));
                    sg_dma_address(&sglist) = k_arg.i_physical_address;
                    sg_dma_len(&sglist) = k_arg.i_size;
    
                    desc = dmaengine_prep_slave_sg(p_dmac->chan,
                        &sglist,
                        1,
                        DMA_DEV_TO_MEM,
                        DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
                }
    
    
                if (!desc)
                {
                    dev_err(p_dmac->dev, "Failed to get a descriptor for transaction\n");
                    return -EBUSY;
                }
    
    
                desc->callback = dmac_rx_callback;
                desc->callback_param = p_dmac;
    
                p_dmac->cookie = dmaengine_submit(desc);
                if ( dma_submit_error(p_dmac->cookie) )
                {
                    dev_err(p_dmac->dev, "Failed to submit a descriptor for transaction\n");
                    return -EIO;
                }
                
                dma_async_issue_pending(p_dmac->chan);
    
                ier = readl(p_dmac->uart_base + (UART_IER << REG_SHIFT));
                scr = readl(p_dmac->uart_base + (UART_OMAP_SCR << REG_SHIFT));
    
    			/*
    			 * Disable RX interrupts to allow RX DMA completion
    			 * callback to run.
    			 */
                ier &= ~(UART_IER_RLSI | UART_IER_RDI);
                scr = OMAP_UART_SCR_RX_TRIG_GRANU1_MASK | OMAP_UART_SCR_TX_EMPTY |
                            OMAP_UART_SCR_TX_TRIG_GRANU1_MASK;
                scr |= OMAP_UART_SCR_DMAMODE_1 | OMAP_UART_SCR_DMAMODE_CTL;
    
                writel(ier, p_dmac->uart_base + (UART_IER << REG_SHIFT));
    
                /*
                 * The manual recommends not to enable the DMA mode selector in the SCR
                 * (instead of the FCR) register _and_ selecting the DMA mode as one
                 * register write because this may lead to malfunction.
                 */
                writel(scr & ~OMAP_UART_SCR_DMAMODE_MASK, p_dmac->uart_base + (UART_OMAP_SCR << REG_SHIFT));
                writel(scr, p_dmac->uart_base + (UART_OMAP_SCR << REG_SHIFT));
    
                // p_dmac->physical_chan = dmac_find_physical_chan(p_dmac, p_dmac->data.dma_request);
                if ( p_dmac->physical_chan != INVALID_DMA_CHAN ) p_dmac->running = true;
    
                k_arg.o_dma_chan = p_dmac->physical_chan;
                
                if ( copy_to_user((start_dma_arg_t *)arg, &k_arg, sizeof(k_arg)) )
                {
                    dev_err(p_dmac->dev, "Failed copy to user\n");
                    return -EFAULT;
                }
            }
            break;

    Rgds、

    KC Wong

    e2e.ti.com/.../dmac_5F00_driver.c

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 KC:

    感谢您的解释、现在我了解您正在开发 UART 的自定义驱动程序。 我们通常不提供自定义驱动程序开发支持、因此我看了您的代码、但没有读取每一行代码。 我的第一个问题是、您无法对您的应用使用标准 Linux UART 驱动程序、必须拥有此自定义驱动程序?

    但是,第二部分由于 DMA 内核的差异而不是那么简单。

    这不应该是这样的情况、因为内核 dmaEngine 框架的目的是提供统一的 API 并隐藏 DMA 内核的详细信息。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Bin Liu:

    是的、标准 Linux UART 驱动程序与该旧版应用程序的用例不匹配。

    此应用需要直接访问 DMA 缓冲区、以便可以采用如视频中所述的零拷贝缓冲区设计。


    https://www.youtube.com/watch?v=kRYtkvDbZSg&t=1479s

    https://www.youtube.com/watch?v=yJg-DkyH5CM&t=1029s

    Rgds、

    KC Wong

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 KC:

    了解了要求。

    让我们离线讨论细节。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 KC:

    请应用以下内核补丁并在非 DMA 模式下测试 UART 8250_OMAP 驱动程序、查看您是否仍在3Mbps 下丢失 RX 数据。

    此补丁基本上删除了"UART_RX_TIMEOUT_QUIRK"标志。

    diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
    index 2bc6b982238f..842f3c19192e 100644
    --- a/drivers/tty/serial/8250/8250_omap.c
    +++ b/drivers/tty/serial/8250/8250_omap.c
    @@ -1337,7 +1337,7 @@ static struct omap8250_dma_params am33xx_dma = {
     static struct omap8250_platdata am654_platdata = {
            .dma_params     = &am654_dma,
            .habit          = UART_HAS_EFR2 | UART_HAS_RHR_IT_DIS |
    -                         UART_RX_TIMEOUT_QUIRK | UART_HAS_NATIVE_RS485,
    +                         UART_HAS_NATIVE_RS485,
     };
     
     static struct omap8250_platdata am33xx_platdata = {

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Bin Liu:

    我在  非 DMA 模式下删除了"UART_RX_TIMEOUT_QUIRK"标志。

    这对我们的应用程序没有帮助。

    Rgds、

    KC Wong

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 KC:

    您能否解释一下它对您没有帮助? 非 DMA 模式下有什么症状? 请注意、我曾要求您使用8250_OMAP 驱动程序而不进行任何其它修改、例如向用户空间复制直接存储器。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Bin Liu:

    是的、这是 在没有任何其他修改的情况下进行的、仅是您在非 DMA 模式下给出的补丁。

    在没有任何自定义驱动程序的情况下、应用程序仅使用标准文件 API 从 UART 端口读取。

    SerialDma::StatusCode SerialDma::read(uint8_t const*& bBytes,
    									  uint32_t& iBytesRead,
    									  uint32_t iMaxBytesToRead)
    	{
    		static volatile uint8_t *pBuffer =  _pDmaMemory;
    		static volatile uint8_t *pBufferEnd = pBuffer + _sAllocInputParms.sizeInBytes;
    		static int fd = (int)_hSerial;
    		
    		bBytes = NULL;
    		iBytesRead = 0;
    		
    		fd_set fds;
    		FD_ZERO(&fds);
    		FD_SET(fd, &fds);
    		
    		int ms = getTimeout();
    		
    		struct timeval timeout;
    		timeout.tv_sec = ms / 1000;
    		timeout.tv_usec = (ms % 1000) * 1000;
    		
    		if (::select(fd + 1, &fds, NULL, NULL, (ms == INFINITE)?NULL:&timeout) > 0)
    		{
    			int n = ::read(fd, (void *)pBuffer, 4096);
    		
    			if (n > 0)
    			{
    				bBytes = (const uint8_t*)pBuffer;
    				iBytesRead = n;
    		
    				pBuffer = pBuffer + n;		
    				if (pBuffer > (pBufferEnd - 4096)) pBuffer =  _pDmaMemory;
    			}
    			
    			return ok;	
    		}
    		else
    		{
    			return ReadTimeout;
    		}
    	}

    在较高层次上、应用程序实施 HDLC 协议。 无论是否带有 "UART_RX_TIMEOUT_QUIRK"标志、应用程序仍会错过预期的 HDLC 数据包。

    高阶数据链路控制-维基百科,自由的百科全书

    Rgds、

    KC Wong

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 KC:

    [报价用户 id="230224" url="~/support/processors-group/processors/f/processors-forum/1303959/am62x-linux-uart-driver-with-dma-support/5000949 #5000949"] 、带或不带"UART_RX_TIMEOUT_QUIRK"标志[/报价]

    请应用补丁以删除此标志。 否则、可能会发生随机字节丢失。

    应用程序仍然缺少预期的 HDLC 数据包。

    我无法调试 HDLC 应用。 请进行调试、并告诉我在/dev/ttySx 读写中有哪些数据错误。

    也可以使用下面链接中提到的 UART 测试方法来测试 UART。

    https://dev.ti.com/tirex/explore/node?node=A__AaoTgeq5bZLef17lYvUnsw__AM62-ACADEMY__uiYMDcq__LATEST&placeholder=true

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Bin Liu:

    基于 另一个线程的类似思路、我修改了/drivers/tty/serial/8250/8250_port.c 以将 UART RX 数据定向到缓冲区设置中、由应用程序直接访问、而不是如下适用于非 DMA 模式的补丁所示的 TTY 缓冲区。

    diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
    index 9d60418e4adb..cf62bace525d 100644
    --- a/drivers/tty/serial/8250/8250_port.c
    +++ b/drivers/tty/serial/8250/8250_port.c
    @@ -37,6 +37,8 @@
     
     #include "8250.h"
     
    +#include "/home/keysight/sambashare/projects/torreys/dmms/Torreys/software/firmware/lkm/dmac_driver.c"
    +
     /* Nuvoton NPCM timeout register */
     #define UART_NPCM_TOR          7
     #define UART_NPCM_TOIE         BIT(7)  /* Timeout Interrupt Enable */
    @@ -1765,7 +1767,11 @@ void serial8250_read_char(struct uart_8250_port *up, unsigned char lsr)
     	if (uart_prepare_sysrq_char(port, ch))
     		return;
     
    -	uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
    +	if ( IRQ_NO != up->port.irq ||
    +		write_to_dmac_buffer(&ch, 1) < 0 )
    +	{
    +		uart_insert_char(port, lsr, UART_LSR_OE, ch, flag);
    +	}
     }
     EXPORT_SYMBOL_GPL(serial8250_read_char);
     
    

    通过 将 UART RX 数据重定向到应用程序缓冲区、 这使我们能够 对应用程序执行测试。  测试结果显示了  使用 和不使用 "UART_RX_TIMEOUT_QUIRK"标志构建的图像之间的差异。  

    通过删除 "UART_RX_TIMEOUT_QUIRK"标志、应用程序 可以 按照预期从测量板接收读数、否则我们会看到缺少读数。 感谢该贴片。 并确保在发布修复时及时通知我们。

    但是、我们看到测试中发生了超限情况。 我想这表明我们最终仍需要 DMA 模式才能工作。

    root@p550:~# cat /proc/tty/driver/serial
    serinfo:1.0 driver revision:
    0: uart:unknown port:00000000 irq:0
    1: uart:8250 mmio:0x02810000 irq:20 tx:80 rx:265 pe:90 RTS|DTR
    2: uart:8250 mmio:0x02860000 irq:21 tx:34965 rx:266 RTS|DTR|DSR
    3: uart:8250 mmio:0x02800000 irq:19 tx:0 rx:1464811229 brk:53845 oe:83 RTS|DTR|DSR
    4: uart:unknown port:00000000 irq:0
    5: uart:unknown port:00000000 irq:0
    6: uart:unknown port:00000000 irq:0
    7: uart:unknown port:00000000 irq:0
    8: uart:unknown port:00000000 irq:0
    9: uart:unknown port:00000000 irq:0
    root@p550:~#
    

     同时、我们将花一些时间来调试为什么使用 标准文件 API 从 UART 端口读取 数据会出现数据包丢失、而不会出现数据包丢失的情况、方法是将 UART RX 数据重定向到应用程序缓冲区。

    Rgds、

    KC Wong

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 KC:

    DMA 模式只能帮助卸载 CPU、不能解决 RX 溢出问题。

    如果发生溢出、基本上意味着 RX FIFO 读取速度不够快、需要进行硬件流控制。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Bin Liu:

    暂时、 我们 使用 CPU 通过中断接收 UART、至少它使我们能够继续进行一些应用测试。


    我相信 AM62x Cortex-A53内核足够强大、能够使用 CPU 进行 UART 中断接收。  但遗憾的是、 CPU 内核并不是专用于 只执行一个任务。

    可能存在较高优先级的中断正在运行、 或者中断被禁用以访问操作系统关键部分。 因此、使用 CPU 通过中断进行 UART 接收可能不可靠、如发生溢出时所示。

    这就是 UART 需要专用 DMA 来接收来自测量板的实时测量读流的原因。

    该应用最初在  SPEAR320S  WinCE 上运行、实际上不需要 硬件流控制、当然需要 DMA。 我们现在要将此应用程序移植到 AM62x Linux、并且我们需要 DMA 能够在不丢失任何字节的情况下工作。

    Rgds、

    KC Wong

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 KC:

    您是否在处理器 SDK 中使用 RT Linux 进行了测试?