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.

[参考译文] SK-AM62A-LP:如何支持 DMA 中的大端字节序

Guru**** 2463330 points
Other Parts Discussed in Thread: SK-AM62A-LP

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1464455/sk-am62a-lp-how-to-support-big-endian-in-dma

器件型号:SK-AM62A-LP

工具与软件:

您好、ti 专家:

我们使用 SK-AM62A-LP 平台和 SDK 09.02。

我们使用 GPMC 接口连接到 OLED (I-80模式) 模块。 并使用 DMA 将数据从帧缓冲区复制到 OLED 格式。

DMA 可以工作、OLED 可以显示照片、但照片颜色会反转、红色更改为蓝色。 原因是:OLED 的格式是大端,而 DMA 在小端字节序上是 wokes, DMA 的地址从低地址增加到高地址。 那么、如何解决该问题呢?

我参考了补丁文件 338.udma-dev-to-mem-1019.diff、并 为 drivers\dma\ti\k3-udma.c 打补丁

AM62A3:GPMC 器件寄存器至存储器传输的 Linux DMA 标识符-处理器论坛-处理器- TI E2E 支持论坛

DTS 和代码如下:

&gpmc0 {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&gpmc0_pins_default>;
	assigned-clock-parents = <&k3_clks 80 2>;	/*1mclk=10ns*/
	assigned-clock-rates = <33333333>; /*33333333  ,30 ns*/
	ranges = <1 0 0x00 0x50000000 0x01000000>; /* CS1 space. size = 128MiB*/

	oled@1,0 {
		compatible = "atmel,unication-oled-module";
		reg = <1 0 0x00000004>;
		reg-names = "data";

		oled_rs = <22>;  /* pin index for LCD_RS */
		madctl = <0x00>;	//bit3:0-rgb, 1-bgr. bit6:1-mirror-x
		oled_type = <0x00>;//1: rm96092, 0: FT2308
		rotate_degree = <270>;  //clockwide, vaild for 0,90,180,270
		atmel,oled-has-dma;
		atmel,oled-bank-width = <8>; /* 8bit */
		dmas = <&main_bcdma 1 0 0>;
		dma-names = "tx";

		oled_reset-gpios = <&main_gpio0 38 GPIO_ACTIVE_HIGH>;
		oled_panel_pw_ctl-gpios = <&main_gpio0 14 GPIO_ACTIVE_HIGH>;
		interrupt-parent = <&main_gpio0>;
		interrupts = <36 IRQ_TYPE_EDGE_FALLING>; //Tearing Effect(TE) singal


	//assigned-clock-parents = <&k3_clks 80 2>;	/*1mclk=10ns*/
	//assigned-clock-rates = <33333333>; /*33333333  ,30 ns*/
		// can read 3208 ID ,can display R G B

		// mclk=30 ns
		
		/* CONFIG1*/
		bank-width = <1>;
		/*gpmc,sync-read;*/
		/*gpmc,sync-write;*/
		/*gpmc,clk-activation-ns = <0>;*/
		gpmc,mux-add-data = <0>;

		/* CONFIG2*/
		/*gpmc,sync-clk-ps = <0>;*/
		gpmc,cs-on-ns = <30>;
		gpmc,cs-rd-off-ns = <900>;
		gpmc,cs-wr-off-ns = <228>;

		/* CONFIG3*/
		/*gpmc,adv-on-ns = <35>;*/
		/*gpmc,adv-rd-off-ns = <9>;*/
		/*gpmc,adv-wr-off-ns = <9>;*/
		
		/* CONFIG4*/
		gpmc,we-on-ns = <53>;
		gpmc,we-off-ns = <129>;
		gpmc,oe-on-ns = <53>;
		gpmc,oe-off-ns = <454>;
		
		/* CONFIG5*/
		gpmc,access-ns = <454>;
		gpmc,rd-cycle-ns = <930>;
		gpmc,wr-cycle-ns = <227>;
		gpmc,wr-access-ns = <129>;


	};
	
};

static inline int set_dma_config(struct oledfb_dev *oled_dev)
{
    int ret;
    struct dma_slave_config slave_config;

    oled_dev->dma_chan = dma_request_slave_channel(oled_dev->dev, "tx");
    if(!oled_dev->dma_chan) {
        dev_err(oled_dev->dev, "%s Failed to request DMA channel\n", __FUNCTION__);
        return -EINVAL;
    }
    dev_info(oled_dev->dev, "oled using %s for DMA transfer\n", dma_chan_name(oled_dev->dma_chan));

    memset(&slave_config, 0, sizeof(slave_config));

	slave_config.direction = DMA_MEM_TO_DEV;
	slave_config.dst_addr_width = 1;
	slave_config.dst_maxburst = 1;
	slave_config.dst_addr = (dma_addr_t)oled_dev->oled_data_phy_addr;

    ret = dmaengine_slave_config(oled_dev->dma_chan, &slave_config);
    if(ret) {
        dev_err(oled_dev->dev, "error in dma configuration\n");
        goto err;
    }
    return 0;
err:
    dma_release_channel(oled_dev->dma_chan);
    oled_dev->dma_chan = NULL;
    return ret;
    
}

static inline int prepare_dma_transfer(struct oledfb_dev *oled_dev)
{
    struct scatterlist *sgl = &oled_dev->sgl[0];
    struct dma_async_tx_descriptor *desc;
    struct dma_chan *chan = oled_dev->dma_chan;
    dma_addr_t p;

    if (!oled_dev->dma_chan) {
        if (set_dma_config(oled_dev) < 0) {
            dev_err(oled_dev->dev, "%s: set_dma_config fail\n", __FUNCTION__);
            return -1;
        }
    }

    /*
      The maximun transaction units is 0xFFFF length. 
      We have logo data 448*368*2= 329728bytes to be send, need at least 6 scatters
      transactions. 0xFFFF(65535)*4 + 33794*2 =329728bytes.
    */

    /* Since ARM's memory is little-endian, while the driver IC needs to be feed 
     * in big-endian, hence the walk around is setup DMA transfering 
     * from buffer memory's tail to head, with address decreasing */

    sg_init_table(sgl, 6);

	p = oled_dev->rotated_framebuf_phy_start;
    sg_dma_address(&sgl[0]) = p;
    sg_dma_len(&sgl[0]) = 0xFFFF;

    p = p + 0xFFFF;
    sg_dma_address(&sgl[1]) = p;
    sg_dma_len(&sgl[1]) = 0xFFFF;

    p = p + 0xFFFF;
    sg_dma_address(&sgl[2]) = p;
    sg_dma_len(&sgl[2]) = 0xFFFF;

    p = p + 0xFFFF;
    sg_dma_address(&sgl[3]) = p;
    sg_dma_len(&sgl[3]) = 0xFFFF;

    p = p + 0xFFFF;
    sg_dma_address(&sgl[4]) = p;
    sg_dma_len(&sgl[4]) = 33794;

    p = p + 33794;
    sg_dma_address(&sgl[5]) = p;
	sg_dma_len(&sgl[5]) = 33794;

    desc = dmaengine_prep_slave_sg(chan, sgl, 6,
                DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT|DMA_CTRL_ACK);

	if(desc == NULL) {
		dev_err(oled_dev->dev, "get dma desc fail.\n");
		return -1;
	}

    oled_dev->desc_tx = desc;
    desc->callback = dma_complete_callback_function;
    desc->callback_param = oled_dev;

	dma_cookie_t cookie_tx;

    /* Start DMA transmition, send RGB data */
    cookie_tx = dmaengine_submit(oled_dev->desc_tx);
	
    txchan->device->device_issue_pending(txchan);

    return 0;
}


static int update_oled_contents_by_dma(struct oledfb_dev *oled_dev)
{
    int ret;
	dev_info(oled_dev->dev, "update_oled_contents_by_dma ENTER.\n");

	if(oled_dev->desc_tx) {
		dev_info(oled_dev->dev, "The old screen update request has not been executed yet!\n");
		return 0;
	}

    ret = prepare_dma_transfer(oled_dev);
    if (ret < 0) {
        dev_err(oled_dev->dev, "%s: prepare_dma_transfer fail: %d\n", __FUNCTION__, ret);
        return ret;
    }

    if(oled_dev->oled_id == OLED_ID_FT2308)
    {
        /* Tearing Effect Line OFF */
        oled_ft2308_cmd(oled_dev, 0x34);
        /* Memory Write */
        oled_ft2308_cmd(oled_dev, 0x2C);
    }
    else
    {
        /* Tearing Effect Line OFF */
        oled_rm69092_cmd(oled_dev, 0x3400);
        /* Memory Write */
        oled_rm69092_cmd(oled_dev, 0x2C00);
    }
    struct dma_chan *txchan = oled_dev->dma_chan;
	dma_cookie_t cookie_tx;

    /* Start DMA transmition, send RGB data */
    cookie_tx = dmaengine_submit(oled_dev->desc_tx);
	
    txchan->device->device_issue_pending(txchan);
	dev_info(oled_dev->dev, "update_oled_contents_by_dma END. cookie_tx=%d\n", cookie_tx);

    return 0;
}


/* Issue pending requests and wait for callback notification */
static void dma_complete_callback_function(void *dma_async_param)
{
    struct oledfb_dev *oled_dev = (struct oledfb_dev *)dma_async_param;
    struct dma_chan *txchan = oled_dev->dma_chan;

    async_tx_ack(oled_dev->desc_tx);
    oled_dev->desc_tx = NULL;

    oled_dev->refresh_complete = 1;
}





                

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

    Eric、您好!

    我怀疑问题出在 DMA 中、而是 AM62Ax 与 OLED 模块之间的字节序不匹配。 我怀疑问题仍然存在,即使你不使用 DMA ,但使用 memcpy ()将数据移动到 GPMC。

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

    也许你是对的。 我会尝试它。

    我从 Intel sama5d3平台移植 oled dirver、该平台通过修改 dma 驱动程序来解决此问题、您能给我一些关于 dma drvier k3-udma.c 的帮助吗?我无法进一步了解 dma 如何工作。 例如、1。 增加或减少 DMA 地址、  2. icnt0、1、2、3、如何设置它。  您是否有这样的 dma pdf 文件? 谢谢。

    sama5d3平台按照以下方式进行修复:

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

     我使用 memcpy ,通过  确认是可以的。

    首先使用 memcpy、但 plack video 时运行缓慢、因此我需要使用 DMA 模式。

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

    Eric、

    很高兴看到您在另一个 e2e 线程上找到了补丁"338.udma-dev-to-mem-1019.diff"、它几乎适用于您的用例。

    除了 TRM 中的信息、我们没有任何其他公共 DMA 文档。

    1. 增加或减少 DMA 地址、  2. icnt0、1、2、3、如何设置它。

    TRM 第11.1.3.3.2.1节"线性寻址"演示了如何在 DMA 传输中使用 icnt0/1/2/3。 表11-38"转接请求字段"显示了所有字段的信息。

    sama5d3平台似乎使用非标准的"DMA_MEM_DEC_TO_DEV"转移来为您解决该问题。 但是、您能否解释一下理想的解决方案? DMA 在传输每个元素后支持大端字节序或地址递减?  能否解释一下存储器中的数据方案?

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

    感谢您的答复。

    此方法是可以的:传输每个元素后地址递减。 sama5d3 平台使用该方法。  

    我想 设置 从缓冲存储器尾部到存储器头的 DMA 传输、但要减小地址。  

     一个像素的 OLED 尺寸为448*368, rgb16。 因此 我们有448*368*2=329728字节要发送。

    内存中的数据方案如下所示:

    1.要发送的数据:

    const unsigned char gImage_logome[329728] = {
    0X18,0X54,0X18,0X54,0X18,0X54,0X18,0X54,0X18,0X54,0X18,0X54,0X18,0X54,0X18,0X54,
    0X18,0X54,0X18,0X54,0X18,0X54,0X18,0X54,0X18,0X54,0X18,0X54,0X18,0X54,0X18,0X54,
    0X18,0X54,0X18,0X54,0X18,0X54,0X18,0X54,0X18,0X54,0X18,0X54,0X18,0X54,0X18,0X54,
    ..........
    ..........
    0X8F,0X5B,0X4E,0X53,0XCC,0X42,0XED,0X42,0X2E,0X4B,0X0D,0X4B,0X2D,0X4B,0X4E,0X53,
    0X4E,0X53,0X2E,0X4B,0XF1,0X63,0X72,0X74,0X31,0X6C,0X93,0X7C,0XD0,0X63,0X4E,0X53,
    };
    

    2.我想发送如下: gImage_logome[329728], gImage_logome[329727] , gImage_logome[329726] .. gImage_logome[0]

    这种模式可以解决此问题。

        sg_init_table(sgl, 6);
    
        /* start to send from tail to head.
        *  p = &gImage_logome[329728] 
        */
    	p = oled_dev->rotated_framebuf_phy_start +SCREEN_SIZE -1;
        sg_dma_address(&sgl[0]) = p;
        sg_dma_len(&sgl[0]) = 0xFFFF;
    
        p = p - 0xFFFF;
        sg_dma_address(&sgl[1]) = p;
        sg_dma_len(&sgl[1]) = 0xFFFF;
    
        p = p - 0xFFFF;
        sg_dma_address(&sgl[2]) = p;
        sg_dma_len(&sgl[2]) = 0xFFFF;
    
        p = p - 0xFFFF;
        sg_dma_address(&sgl[3]) = p;
        sg_dma_len(&sgl[3]) = 0xFFFF;
    
        p = p - 0xFFFF;
        sg_dma_address(&sgl[4]) = p;
        sg_dma_len(&sgl[4]) = 0xFFFF;
    
        p = p - 0xFFFF;
        sg_dma_address(&sgl[5]) = p;
        sg_dma_len(&sgl[5]) = 2063;
    
        desc = dmaengine_prep_slave_sg(chan, sgl, 6,
                    DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT|DMA_CTRL_ACK);
    

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

    抱歉出错、从  gImage_logome[329727]开始、而不是 gImage_logome[329728]

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

    Eric、您好!

    仅对于原型设计、请尝试以下内核 DMA 补丁、以查看它是否可以正确地从 MEM 传输到 GPMC。

    diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
    index 208f4c120eab..1255b12f5654 100644
    --- a/drivers/dma/ti/k3-udma.c
    +++ b/drivers/dma/ti/k3-udma.c
    @@ -3133,16 +3133,16 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
                            tr_req[tr_idx].icnt1 = tr_cnt1;
                            tr_req[tr_idx].icnt2 = tr0_cnt2;
                            tr_req[tr_idx].icnt3 = tr0_cnt3;
    -                       tr_req[tr_idx].dim1 = tr_cnt0;
    -                       tr_req[tr_idx].dim2 = trigger_size;
    -                       tr_req[tr_idx].dim3 = trigger_size * tr0_cnt2;
    +                       tr_req[tr_idx].dim1 = (-1) * tr_cnt0;
    +                       tr_req[tr_idx].dim2 = (-1) * trigger_size;
    +                       tr_req[tr_idx].dim3 = (-1) * trigger_size * tr0_cnt2;
     
                            tr_req[tr_idx].daddr = dev_addr;
                            tr_req[tr_idx].dicnt0 = tr_cnt0;
                            tr_req[tr_idx].dicnt1 = tr_cnt1;
                            tr_req[tr_idx].dicnt2 = tr0_cnt2;
                            tr_req[tr_idx].dicnt3 = tr0_cnt3;
    -                       tr_req[tr_idx].ddim1 = (-1) * tr_cnt0;
    +                       tr_req[tr_idx].ddim1 = 0;
                    }
     
                    tr_idx++;
    @@ -3179,15 +3179,15 @@ udma_prep_slave_sg_triggered_tr(struct udma_chan *uc, struct scatterlist *sgl,
                                    tr_req[tr_idx].icnt1 = tr_cnt1;
                                    tr_req[tr_idx].icnt2 = tr1_cnt2;
                                    tr_req[tr_idx].icnt3 = 1;
    -                               tr_req[tr_idx].dim1 = tr_cnt0;
    -                               tr_req[tr_idx].dim2 = trigger_size;
    +                               tr_req[tr_idx].dim1 = (-1) * tr_cnt0;
    +                               tr_req[tr_idx].dim2 = (-1) * trigger_size;
     
                                    tr_req[tr_idx].daddr = dev_addr;
                                    tr_req[tr_idx].dicnt0 = tr_cnt0;
                                    tr_req[tr_idx].dicnt1 = tr_cnt1;
                                    tr_req[tr_idx].dicnt2 = tr1_cnt2;
                                    tr_req[tr_idx].dicnt3 = 1;
    -                               tr_req[tr_idx].ddim1 = (-1) * tr_cnt0;
    +                               tr_req[tr_idx].ddim1 = 0;
                            }
                            tr_idx++;
                    }

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

    谢谢、我来尝试一下。

    然后再给你出声。

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

    谢谢、Bin。 你给我很多帮助。

    它工作得非常完美。

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

    Eric、您好!

    太棒了! 感谢您的更新。

    您能解释一下如何生成需要 DMA 递减传输的数据(gImage_logome)吗? 正如我之前所说的、内核 DMAEngine 不支持"DMA_MEM_DEC_TO_DEV"等类型的函数、但如果您有一个有效的用例、我们可能必须扩展 DMAEngine 以支持此类递减传输。

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

    1.如何生成数据(gImage_logome) ?

    -->它是 logo.bmp、大小为448*368、rgb16 (2字节)、一个像素、 我使用 Img2Lcd.exe、 Img2Lcd.exe 可以生成 gImage_logome 阵列的徽标、它只是用于测试 OLED。

    2、为什么我需要按规定的方式进行 DMA 传输?

    CPU 内存中的数据像这样、第一个像素值为0x5418 (16位)、低8位为0x18、高8位为0x54。 通常、它会先发送0x18、然后再发送0x54。

    但以 OLED 格式表示的数据是大端字节序、低8位和高8位是反转的。 而 OLED 总线宽度为8位。 因此、它需要先接收数据0x54、然后再接收数据0x18、  

    当我用 DMA 来发送数据尾部到头递减时、它会像这样发送数据:0x53、0x4e、0x63、0xd0、...... 、0x54、0x18。 它与 OLED 数据格式相匹配。

    const unsigned char gImage_logome[329728]={
    0X18、0X54、0X18、0X54、0X54、0X18、0X54、0X54、0X54、0X54、0X18、0X54、0X54、
    0X18、0X54、0X18、0X54、0X54、0X18、0X54、0X54、0X54、0X54、0X18、0X54、0X54、
    0X18、0X54、0X18、0X54、0X54、0X18、0X54、0X54、0X54、0X54、0X18、0X54、0X54、
    …………
    …………
    0x8F、0X5B、0X4E、0X540XCC、0X420XED、0X420X2E、0X4B、0x0D、0X4B、0x2D、0X4B、0X4E、0X53、
    0X4E、0X35、0X2E、0X4B、0XF1 1、0X630、0X74、0X31、0X93、0X7C、0XD1、0X630、0X63、X4E、0X53、
    };

    3.我有个问题,我 用 DMA 在 OLED 上播放视频(Jellyfish_448x368_h265.mp4),这是不流畅的。 但 memcpy 的通量。 我不确定原因是否是 DMA?

    root@am62axx-evm:/opt/edgeai-gst-apps# gst-launch-1.0 filesrc location=Jellyfish_448x368_h265.mp4 ! qtdemux name=demux demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! fbdevsink
    Setting pipeline to PAUSED ...
    Pipeline is PREROLLING ...
    Redistribute latency...
    Redistribute latency...
    Pipeline is PREROLLED ...0 %)
    Setting pipeline to PLAYING ...
    Redistribute latency...
    New clock: GstSystemClock
    WARNING: from element /GstPipeline:pipeline0/GstFBDEVSink:fbdevsink0: A lot of buffers are being dropped.
    Additional debug info:
    ../gstreamer-1.20.7/libs/gst/base/gstbasesink.c(3143): gst_base_sink_is_too_late (): /GstPipeline:pipeline0/GstFBDEVSink:fbdevsink0:
    There may be a timestamping problem, or this computer is too slow.
    WARNING: from element /GstPipeline:pipeline0/GstFBDEVSink:fbdevsink0: A lot of buffers are being dropped.
    Additional debug info:
    ../gstreamer-1.20.7/libs/gst/base/gstbasesink.c(3143): gst_base_sink_is_too_late (): /GstPipeline:pipeline0/GstFBDEVSink:fbdevsink0:
    There may be a timestamping problem, or this computer is too slow.
    WARNING: from element /GstPipeline:pipeline0/GstFBDEVSink:fbdevsink0: A lot of buffers are being dropped.
    Additional debug info:
    ../gstreamer-1.20.7/libs/gst/base/gstbasesink.c(3143): gst_base_sink_is_too_late (): /GstPipeline:pipeline0/GstFBDEVSink:fbdevsink0:
    There may be a timestamping problem, or this computer is too slow.
    WARNING: from element /GstPipeline:pipeline0/GstFBDEVSink:fbdevsink0: A lot of buffers are being dropped.
    Additional debug info:
    ../gstreamer-1.20.7/libs/gst/base/gstbasesink.c(3143): gst_base_sink_is_too_late (): /GstPipeline:pipeline0/GstFBDEVSink:fbdevsink0:
    There may be a timestamping problem, or this computer is too slow.
    Got EOS from element "pipeline0".
    Execution ended after 0:00:12.192273104
    Setting pipeline to NULL ...
    Freeing pipeline ...
    root@am62axx-evm:/opt/edgeai-gst-apps# 

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

    memcpy 的缺陷是 CPU 使用率很高、60%~80%。

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

    Eric、您好!

    当我使用 DMA 以递减方式向尾部发送数据时、它将发送如下数据:0x53、0x4e、0x63、0xd0、...... 、0x54、0x18。 它与 OLED 数据格式匹配。[/QUOT]

    您是否是指缓冲区中的最后两个字节(0x53、0x4e)用于显示面板上的第一个像素(左上角)、缓冲区中的前两个字节(0x54、0x18)用于最后一个像素(右下角)?

    如果是、在播放视频时、如何将视频帧数据转换为该方案? 据我所知、内存中的视频帧数据的顺序相反-缓冲区的开头是第一个像素、而缓冲区的结尾是最后一个像素。

    3. 我有一个问题、我 使用 DMA 在 OLED 上播放视频(Jellyfish_448x368_h265.mp4)、这不是流畅的。 [报价]

    则必须分析/调试问题以了解根本原因。

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

    1.不用担心左上角和 右下角,OLED 驱动器 IC 可以使角度变差。 我关心的只是大端字节序、首先发送高8位。 它与 OLED 革兰的姆杜埃匹配。

    2、视频是相框中的照片。 当输入到 OLED 图时、视频串行将变为一帧一帧。  

    3.我想、我会测试 DMA 移动数据时有多少次。  

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

    这不是旋转、而是对角线翻转。 很高兴听到 OLED IC 能够处理这种变换!

    您可能需要首先测量 DMA 传输一个帧所需的时间,从调用 dmaengine_submit()到调用 DMA 完成回调函数。

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

    DMA 从  dmaengine_submit()到 DMA 完成需要80ms、 memcpy 需要85~100ms。 这无法解释上面的视频。  

    我不知道这个。 而 DMA 耗时80ms、令人惊讶的是、它几乎等于 memcpy。  

    我就是这样测试的。

    static int update_oled_contents_by_dma(struct oledfb_dev *oled_dev)
    {
        int ret;
    
    	if(oled_dev->desc_tx) {
    		dev_info(oled_dev->dev, "The old screen update request has not been executed yet!\n");
    		return 0;
    	}
    
        ret = prepare_dma_transfer(oled_dev);
        if (ret < 0) {
            dev_err(oled_dev->dev, "%s: prepare_dma_transfer fail: %d\n", __FUNCTION__, ret);
            return ret;
        }
    
    
        if(oled_dev->oled_id == OLED_ID_FT2308)
        {
            /* Tearing Effect Line OFF */
     //       oled_ft2308_cmd(oled_dev, 0x34);
            /* Memory Write */
            oled_ft2308_cmd(oled_dev, 0x2C);
        }
        else
        {
            /* Tearing Effect Line OFF */
    //        oled_rm69092_cmd(oled_dev, 0x3400);
            /* Memory Write */
            oled_rm69092_cmd(oled_dev, 0x2C00);
        }
        struct dma_chan *txchan = oled_dev->dma_chan;
    	dma_cookie_t cookie_tx;
    	dev_info(oled_dev->dev,"update_oled_contents dma ENTER.222\n");
    #ifdef DBG_GPO_TIMING
    	gpiod_set_value(oled_dev->dbg_gpo_timing, 1);
    #endif
    
        /* Start DMA transmition, send RGB data */
        cookie_tx = dmaengine_submit(oled_dev->desc_tx);
        txchan->device->device_issue_pending(txchan);
    
        return 0;
    }
    
    
    /* Issue pending requests and wait for callback notification */
    static void dma_complete_callback_function(void *dma_async_param)
    {
        struct oledfb_dev *oled_dev = (struct oledfb_dev *)dma_async_param;
        struct dma_chan *txchan = oled_dev->dma_chan;
    
    #ifdef DBG_GPO_TIMING
    	gpiod_set_value(oled_dev->dbg_gpo_timing, 0);
    #endif
    	dev_info(oled_dev->dev, "%s(%d): ENTER2b.\n",__func__, __LINE__);
    
        async_tx_ack(oled_dev->desc_tx);
        oled_dev->desc_tx = NULL;
    
        oled_dev->refresh_complete = 1;
    }
    
    //k3-am62a-oled.dtsi
    //add dbg_gpo_timing gpio
    
    		dbg_gpo_timing-gpios = <&main_gpio1 10 GPIO_ACTIVE_HIGH>;
    
    
    

    memcpy 测试代码。

    static int update_oled_contents(struct oledfb_dev *oled_dev)
    {
        int i;
        char *pcontent = oled_dev->rotated_framebuf;
    	dev_info(oled_dev->dev,"update_oled_contents ENTER.\n");
    
        oled_prepare_to_write_pixel(oled_dev);
    #ifdef DBG_GPO_TIMING
    	gpiod_set_value(oled_dev->dbg_gpo_timing, 1);
    #endif
    
        /* RGB contents are written to OLED from tail to head */
        for(i=(OLED_MAX_X_PIXELS * OLED_MAX_Y_PIXELS * 2); i>0; i=i-2) {	//tail to head
            oled_ft2308_write(oled_dev, *(pcontent+i+1)); // upper one
            oled_ft2308_write(oled_dev, *(pcontent+i));    // lower one
        }
    #ifdef DBG_GPO_TIMING
    	gpiod_set_value(oled_dev->dbg_gpo_timing, 0);
    #endif
    
        oled_dev->refresh_complete = 1;
    
        return 0;
    }
    

    DMA 测试时间。

    memcpy 测试时间

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [报价 userid="637618" url="~/support/processors-group/processors/f/processors-forum/1464455/sk-am62a-lp-how-to-support-big-endian-in-dma/5628062 #5628062"]

    DMA 从  dmaengine_submit()到 DMA 完成需要80ms、 memcpy 需要85~100ms。 这无法解释上面的视频。  

    我不知道这个。 而 DMA 耗时80ms、令人惊讶的是、它几乎等于 memcpy。  

    [报价]

    由于时间非常相似(且 CPU 负载在 memcpy ()中未满),我认为瓶颈很可能是 GPMC 接口,它只在33MHz 处运行,每次访问接收一个字节。

    329728字节/80ms = 4.1MB/秒

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

    你是对的、我同意你对 DMA 事业的看法。

    1.我在播放视频时测试 CPU 使用情况,使用此命令。

    gst-launch-1.0 filesrc location=Jellyfish_448x368_h265.mp4 ! qtdemux name=demux demux.video_0 ! queue ! h265parse ! v4l2h265dec capture-io-mode=dmabuf ! videoconvert ! videoscale ! fbdevsink
    

    测试结果如下:

    memcpy 模式、 gst-launch-1.0 CPU uage 为80%、 VPU_IRQ_thread 为2%。 它是 流畅的。

    DMA 模式、 GST-LAUNCH-1.0为40%、 VPU_IRQ_THREAD 为35%。 它不是 流畅的。

    2.播放视频,使用此命令:

    gst-launch-1.0 filesrc location=Jellyfish_448x368_h265.mp4 ! qtdemux name=demux demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! kmssink driver-name=tidss -v
    

    测试结果如下:

    GST-LAUNCH-1.0 CPU 耗电量为4.6%、 VPU_IRQ_THREAD 为2.3%。 它是 流畅的。

    我的问题是:视频由硬解码器播放。 为什么输出到 fbsink 时 CPU 使用率如此高?  

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

    Eric、您好!

    我正在与我们的多媒体专家联系以获取评论。

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

    Eric、您好!

    是的、解码器应进行硬件加速。 但在你的管道中,我确实看到你正在使用软件插件像 videconvert、videoscale 这将增加 CPU 的使用率。 是否可以使用以下命令运行该文件:

    gst-launch-1.0 -v filesrc location= .mp4! 真的很棒! h264parse! v4l2h264dec! fpsdisplaysink video-sink="kmssink driver-name=tidss sync=false"并查看其是否运行正常

    希望您也可以附加您的文件。

    此致、

    Suren

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

    e2e.ti.com/.../Jellyfish_5F00_448x368_5F00_h265.mp4

    宾, Suren、谢谢。

    我将尝试您的命令。 这是我的视频文件。

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

    e2e.ti.com/.../Jellyfish_5F00_448x368_5F00_h265.zip

    视频文件 zip

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    当以下两个命令用于在 HDMI 大屏幕上播放时、CPU 使用率不高、约在10%至28%之间。

    1. gst-launch-1.0 -v filesrc location=Jellyfish_448x368_h265.mp4 ! 真的很棒! h265parse! v4l2h265dec! fpsdisplaysink video-sink="kmssink driver-name=tidss sync=false"
    2. gst-launch-1.0 filesrc location=Jellyfish_448x368_h265.mp4 ! qtdemux name=Demux Demux.video_0! 队列! 诱饵! 视频转换! videoscale! kmssink driver-name=tidss -v

    我主要关心的是 fbdevsink 的回放。 当回放输出被定向到 fbdevsink 时、CPU 使用率极高。 但是、如果您提到的 videoconvert 元素没有被使用、则 v4l2h265dec 似乎无法直接输出到 fbdevsink。 例如、使用如下所示的命令:
    gst-launch-1.0 filesrc location=Jellyfish_448x368_h265.mp4 ! qtdemux name=demux demux.video_0 ! queue ! h265parse ! v4l2h265dec ! videoconvert ! fbdevsink
    是否有任何命令可以在不使用您提到的 SW 插件的情况下输出到 fbdevsink? 谢谢你。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    Eric、您好!

    感谢您共享该文件。

    我使用10.1 SDK 发布的软件在我的 AM62A 板上运行以下 gstreamer 命令。

    gst-launch-1.0 -v filesrc location=Jellyfish_448x368_h265.mp4 ! qtdemux ! h265parse ! v4l2h265dec capture-io-mode=dmabuf ! kmssink driver-name=tidss sync=false plane_id=31
    
    观察到 kmsink 时的 htop 为1.3%- 2%。

    此外、在我们的 SoC 上、我们还支持 kmssink 和 waylandsink。 当前不支持 Fbdevsink。 此外、我假设 fbdevsink 会使用 CPU、这就是您可能会看到巨大 CPU 负载的原因。 此外,为了使用 SW 插件 videocale,转换所需的格式, videoscale 将花费大量的 CPU 利用率。

    此致、

    Suren

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

    您好、Suren

    我已经将 OLED 连接到 GPMC 接口。 它支持 fbdevsink。 在启动时、界面应用程序已显示在上面。

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

    Eric、您好!

    我曾尝试在 AM62A 上使用 fbdevsink 运行相同的流水线、但需要 videoconvert (需要支付 CPU 成本的 SW 插件)才能让 fbdevsink 支持 BGRx 格式。

    gst-launch-1.0 -v filesrc location=Jellyfish_448x368_h265.mp4 ! 真的很棒! h265parse! v4l2h265dec capture-io-mode=dmabuf!  视频转换! fbdevsink device=/dev/fb1  

    我确实看到 CPU 利用率为~60-70%  

    此致、

    Suren

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

    您好、 Suren

    谢谢。

    是的、回答正确。  

    我还刚刚对其进行了测试。 它必须使用  videoconvert ,我使用 gst-checke-1.0 fbdevsink , gst-checke-1.0 v4l2h265dec ,检查 src 和接收能力。

      

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

    Eric、您好!

    您是否已在 fbdevsink 上联系到社区? AFAIK、其已弃用以及使用 kmssink/waylandsink 的建议。

    此外、fbdevsink 接收电容器显示支持 RGB、但在使用 ticolorconvert 时、它无法接受 RGB 输入、只期望输入为 BGRx 格式。

    此致、

    Suren

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

    您好、 Suren

    我还在度假、所以我没有看到您的回复。 当我有新的进步时、我会再次与您沟通。 谢谢你。