WhyCan Forum(哇酷开发者社区)

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn

您尚未登录。

#1 2018-08-14 12:33:04

达克罗德
会员
注册时间: 2018-04-10
累计积分: 957

谁有V3S或者F1C100s的DMA例程?

当前xboot似乎没有DMA的驱动,我想看看能否把SPI的读写以及memcpy用DMA来加速

离线

#2 2018-08-14 13:39:07

晕哥
管理员
注册时间: 2017-09-06
累计积分: 9,190

Re: 谁有V3S或者F1C100s的DMA例程?

离线

#3 2018-08-14 13:48:32

达克罗德
会员
注册时间: 2018-04-10
累计积分: 957

Re: 谁有V3S或者F1C100s的DMA例程?

非常感谢,你找资源可真快呀!

离线

#4 2018-08-14 13:55:43

晕哥
管理员
注册时间: 2017-09-06
累计积分: 9,190

Re: 谁有V3S或者F1C100s的DMA例程?

因为刚好在搞这个 f1c100s 官方bsp, 用官方的 sys_config.fex(全志发明的设备树)套路, 发现屏幕驱动有问题。
顺手就传上来了.

离线

#5 2018-08-19 22:10:41

mianhua
会员
注册时间: 2018-08-19
累计积分: 6

Re: 谁有V3S或者F1C100s的DMA例程?

请问显示的时候是不是已经用了DMA?
void fb_present(struct framebuffer_t * fb, struct render_t * render)
{
    struct fb_f1c100s_pdata_t * pdat = (struct fb_f1c100s_pdata_t *)fb->priv;

    if(render && render->pixels)
    {
        pdat->index = (pdat->index + 1) & 0x1;
        memcpy(pdat->vram[pdat->index], render->pixels, render->pixlen);
        dma_cache_sync(pdat->vram[pdat->index], render->pixlen, DMA_TO_DEVICE);
        f1c100s_debe_set_address(pdat, pdat->vram[pdat->index]);
    }
}

离线

#6 2018-08-19 22:23:59

达克罗德
会员
注册时间: 2018-04-10
累计积分: 957

Re: 谁有V3S或者F1C100s的DMA例程?

mianhua 说:

请问显示的时候是不是已经用了DMA?
void fb_present(struct framebuffer_t * fb, struct render_t * render)
{
    struct fb_f1c100s_pdata_t * pdat = (struct fb_f1c100s_pdata_t *)fb->priv;

    if(render && render->pixels)
    {
        pdat->index = (pdat->index + 1) & 0x1;
        memcpy(pdat->vram[pdat->index], render->pixels, render->pixlen);
        dma_cache_sync(pdat->vram[pdat->index], render->pixlen, DMA_TO_DEVICE);
        f1c100s_debe_set_address(pdat, pdat->vram[pdat->index]);
    }
}

这里dma_cache_sync我没有看到dma具体实现,感觉还是靠memcpy软拷贝的

离线

#7 2018-08-26 23:21:17

达克罗德
会员
注册时间: 2018-04-10
累计积分: 957

Re: 谁有V3S或者F1C100s的DMA例程?

void sys_dma_init()
{
	/* Enable gate for DMA clock, and perform softreset */
	write32(F1C100S_CCU_BASE + CCU_BUS_CLK_GATE0, read32(F1C100S_CCU_BASE + CCU_BUS_CLK_GATE0) | (0x1 << 6));
	write32(F1C100S_CCU_BASE + CCU_BUS_SOFT_RST0, read32(F1C100S_CCU_BASE + CCU_BUS_SOFT_RST0) & ~(0x1 << 6));
	for(int i = 0; i < 10; i++)
		continue;
	write32(F1C100S_CCU_BASE + CCU_BUS_SOFT_RST0, read32(F1C100S_CCU_BASE + CCU_BUS_SOFT_RST0) | (0x1 << 6));
}

void sys_dma_wait_end(int ch)
{
	u32_t cfg_reg = 0x80000000;
	/* when the dma end, it clear this bit automatically */
	while ((cfg_reg & 0x80000000) ) {
		cfg_reg = read32(NDMA_CHANNEL_REG_BASE(ch) +
						NDMA_CFG_REG);
	}
}

void sys_dma_dram_copy(int dma_ch, void * dest, void *src, size_t len)
{
	virtual_addr_t addr = NDMA_CHANNEL_REG_BASE(dma_ch);
	u32_t val = 0;
	u32_t bytes_cnt;

	while(len)
	{
		if(len >= SZ_128K)
		{
			bytes_cnt = SZ_128K;
		}
		else
		{
			bytes_cnt = len;
		}
		len -= bytes_cnt;

		/* Set source address */
		write32(addr + NDMA_SRC_ADR_REG, (u32_t)src);

		/* Set dst address */
		write32(addr + NDMA_DST_ADR_REG, (u32_t)dest);

		/* Set byte number */
		write32(addr + NDMA_BYTE_CNT_REG, bytes_cnt);

		/* Set config and start */
		val = (1 << 31) | (2 << 24) | (1 << 23) | (0x11 << 16) | (2 << 8) | (1 << 7) | (0x11 << 0);
		// val = NDMA_SDRAM2SDRAM_CFG;
		write32(addr + NDMA_CFG_REG, val);

		/* Wait end */
		sys_dma_wait_end(dma_ch);
		src += bytes_cnt;
		dest += bytes_cnt;
	}
}

今天写了个最简单的SDRAM to SDRAM的DMA copy函数,已经调试通过。
注意src需要是用dma_alloc_coherent函数得到的空间才行,估计是cache同步的问题,否则数据有异常。

把这个函数用在framebuffer的拷贝上,替代memcpy,结果发现速度还不如memcpy。估计F1C100S的DMA时钟很慢?另外一个主要原因是DMA一次传输竟然只支持128KB字节,所以不得不CPU polling在这里然后等结束后继续下一个128KB传输,DMA的并行处理机制完全没被充分利用起来。等我有时间了,做个用中断中管理DMA的,才能充分发挥DMA的优势。

下面是带头文件的源程序:
f1c100s-dma.zip

离线

#8 2018-08-27 07:38:58

晕哥
管理员
注册时间: 2017-09-06
累计积分: 9,190

Re: 谁有V3S或者F1C100s的DMA例程?

这个实在太好了,
晚点移植到MDK也分享上来。

离线

#9 2018-09-03 11:34:24

达克罗德
会员
注册时间: 2018-04-10
累计积分: 957

Re: 谁有V3S或者F1C100s的DMA例程?

dedicated DMA支持16M字节传输,所以可以简化代码

static void sys_ddma_wait_end(int ch)
{
	u32_t cfg_reg = 0x80000000;
	/* when the dma end, it clear this bit automatically */
	while ((cfg_reg & 0x80000000) ) {
		cfg_reg = read32(DDMA_CHANNEL_REG_BASE(ch) +
						DDMA_CFG_REG);
	}
}

void sys_ddma_dram_copy(int dma_ch, void * dest, void *src, size_t bytes_cnt)
{
	virtual_addr_t base = DDMA_CHANNEL_REG_BASE(dma_ch);
	u32_t val = 0;

	if (bytes_cnt > SZ_16M)
	{
		bytes_cnt = SZ_16M;
	}

	/* Set source address */
	write32(base + DDMA_SRC_ADR_REG, (u32_t)src);

	/* Set dst address */
	write32(base + DDMA_DST_ADR_REG, (u32_t)dest);

	/* Set byte number */
	write32(base + DDMA_BYTE_CNT_REG, bytes_cnt);

	/* Set config and start */
	val = (1 << 31) | (2 << 24) | (1 << 23) | (0x1 << 16) | (2 << 8) | (1 << 7) | (0x1 << 0);
	// val = NDMA_SDRAM2SDRAM_CFG;
	write32(base + DDMA_CFG_REG, val);

	/* Wait end */
	sys_ddma_wait_end(dma_ch);
}

离线

#10 2019-10-30 19:57:05

ffplay
会员
注册时间: 2019-08-31
累计积分: 92

Re: 谁有V3S或者F1C100s的DMA例程?

好帖, 帮顶起来.

离线

#11 2020-01-15 18:43:17

wangzhg1
会员
注册时间: 2019-08-24
累计积分: 25

Re: 谁有V3S或者F1C100s的DMA例程?

v3s的好像不一样的,能不能找到v3s的?

离线

#12 2020-01-30 11:17:05

linhuaou
会员
注册时间: 2019-08-09
累计积分: 35

Re: 谁有V3S或者F1C100s的DMA例程?

这个不错,顶起来

离线

#13 2020-04-17 17:27:47

Quotation
会员
注册时间: 2018-10-04
累计积分: 238

Re: 谁有V3S或者F1C100s的DMA例程?

达克罗德 说:

当前xboot似乎没有DMA的驱动,我想看看能否把SPI的读写以及memcpy用DMA来加速

楼主有没有调出来SPI的DMA?
发现用XBoot的DMA约有40%的时间在空闲,想用DMA加速。XBoot里设置成50M SPI,波形看CLK确实是50M,但算上空闲的部分就只有29.xMHz了。

离线

#14 2020-04-20 22:56:12

Quotation
会员
注册时间: 2018-10-04
累计积分: 238

Re: 谁有V3S或者F1C100s的DMA例程?

@达克罗德 楼主,有没有调通SPI的DMA?(顺便问晕哥,回复帖子能不能强提醒某人?)

离线

#15 2020-04-24 17:11:05

armstrong
会员
注册时间: 2019-04-10
累计积分: 125

Re: 谁有V3S或者F1C100s的DMA例程?

既然不能收藏,做个标记先:F1C100s的DMA。

离线

#16 2020-04-30 14:36:52

梁大帅真的帅
会员
注册时间: 2020-04-15
累计积分: 2

Re: 谁有V3S或者F1C100s的DMA例程?

好,正在写f1c100s的dvp摄像头驱动,需要用dma

离线

#17 2020-04-30 15:46:21

达克罗德
会员
注册时间: 2018-04-10
累计积分: 957

Re: 谁有V3S或者F1C100s的DMA例程?

Quotation 说:

@达克罗德 楼主,有没有调通SPI的DMA?(顺便问晕哥,回复帖子能不能强提醒某人?)

没有继续研究了

离线

#18 2020-05-24 23:19:43

hongdong
会员
注册时间: 2019-05-20
累计积分: 2

Re: 谁有V3S或者F1C100s的DMA例程?

F1C100S上用DMA+SPI驱动tft屏 很有优势!

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB