当前xboot似乎没有DMA的驱动,我想看看能否把SPI的读写以及memcpy用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]);
}
}
离线
请问显示的时候是不是已经用了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软拷贝的
离线
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
离线
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);
}
离线
好帖, 帮顶起来.
离线
v3s的好像不一样的,能不能找到v3s的?
离线
这个不错,顶起来
离线
当前xboot似乎没有DMA的驱动,我想看看能否把SPI的读写以及memcpy用DMA来加速
楼主有没有调出来SPI的DMA?
发现用XBoot的DMA约有40%的时间在空闲,想用DMA加速。XBoot里设置成50M SPI,波形看CLK确实是50M,但算上空闲的部分就只有29.xMHz了。
离线
@达克罗德 楼主,有没有调通SPI的DMA?(顺便问晕哥,回复帖子能不能强提醒某人?)
离线
既然不能收藏,做个标记先:F1C100s的DMA。
离线
好,正在写f1c100s的dvp摄像头驱动,需要用dma
离线
@达克罗德 楼主,有没有调通SPI的DMA?(顺便问晕哥,回复帖子能不能强提醒某人?)
没有继续研究了
离线
F1C100S上用DMA+SPI驱动tft屏 很有优势!
离线
赞赞赞
离线
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软拷贝的
dma_cache_sync这个函数只是简单的同步一下cache,保证数据的一致性而已
离线