tq2440 linux下图形编程 framebuffer,framebuffer驱动qemu仿真调试--Apple的学习笔记

一,前言

之前ubuntu18.04配置网桥支持qemu模拟开发板挂载NFS启动LCD--Apple的学习笔记

已经完成了qemu仿真LCD,并且实现了framebuffer的应用。于是想调试下源码,原因是光看代码可能会理解错误。但是vexpress a9开发板看了下设备树后发现他用的不是LCDC的framebuffer而是用了drm框架。

但是复习了下DRM框架后,发现其实framebuffer都是注册的,那么就可以当做fbdev用了。然后分析代码的话还是选简单的s3c2410fb.c来分析,看了代码后,发现和我之前分析fbtft使用framebuffer子系统类似,可以参考Linux驱动OLED屏st7735s(framebuffer学习)--Apple的学习笔记。为了能实际调试我在直接下载了一个被二次开发过的qemu,能支持mini2440仿真。

二,s3c2410fb.c关键代码分析(内核版本5.4.61)

1.设置寄存器为LCDC设置总线时序margin timer及刷新频率,LCD内存起始地址

s3c2410fb_set_par ->s3c2410fb_activate_var --->s3c2410fb_calculate_tft_lcd_regs和s3c2410fb_set_lcdaddr

2.probe函数会挂上具体芯片的操作函数

fbinfo->fbops = &s3c2410fb_ops;

static struct fb_ops s3c2410fb_ops = {

.owner = THIS_MODULE,

.fb_check_var = s3c2410fb_check_var,

.fb_set_par = s3c2410fb_set_par,

.fb_blank = s3c2410fb_blank,

.fb_setcolreg = s3c2410fb_setcolreg,

.fb_fillrect = cfb_fillrect,

.fb_copyarea = cfb_copyarea,

.fb_imageblit = cfb_imageblit,

};

`

2.probe函数中填充fbinfo后注册register_framebuffer,然后用户空间就可以操作文件系统了。

ret = register_framebuffer(fbinfo);

```c

static const struct file_operations fb_fops = {

.owner = THIS_MODULE,

.read = fb_read,

.write = fb_write,

.unlocked_ioctl = fb_ioctl,

#ifdef CONFIG_COMPAT

.compat_ioctl = fb_compat_ioctl,

#endif

.mmap = fb_mmap,

.open = fb_open,

.release = fb_release,

#if defined(HAVE_ARCH_FB_UNMAPPED_AREA) || \

(defined(CONFIG_FB_PROVIDE_GET_FB_UNMAPPED_AREA) && \

!defined(CONFIG_MMU))

.get_unmapped_area = get_fb_unmapped_area,

#endif

#ifdef CONFIG_FB_DEFERRED_IO

.fsync = fb_deferred_io_fsync,

#endif

.llseek = default_llseek,

};

3.fb_mmap在s3c2410.c中没有调用。PAGE_ALIGN和vm_iomap_memory为关键函数,一个是alian一个是将虚拟地址转到物理地址,具体的page MMU相关函数内容我不展开,将来做专题分析。

static int fb_mmap(struct file *file, struct vm_area_struct * vma)

{

int fbidx = iminor(file->f_path.dentry->d_inode);

struct fb_info *info = registered_fb[fbidx];

struct fb_ops *fb = info->fbops;

unsigned long off;

unsigned long start;

u32 len;

if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))

return -EINVAL;

off = vma->vm_pgoff << PAGE_SHIFT;

if (!fb)

return -ENODEV;

mutex_lock(&info->mm_lock);

//没有注册mmap所以没进入

if (fb->fb_mmap) {

printk("mmap-1\n");

int res;

res = fb->fb_mmap(info, vma);

mutex_unlock(&info->mm_lock);

return res;

}

// 走如下路径

/* frame buffer memory */

start = info->fix.smem_start;

len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);

printk("mmap-start=0x%x,len=%d\n",start,len);

if (off >= len) {

printk("mmap-off=0x%x\n",off);

/* memory mapped io */

off -= len;

if (info->var.accel_flags) {

mutex_unlock(&info->mm_lock);

return -EINVAL;

}

start = info->fix.mmio_start;

len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);

}

mutex_unlock(&info->mm_lock);

start &= PAGE_MASK;

if ((vma->vm_end - vma->vm_start + off) > len)

return -EINVAL;

off += start;

vma->vm_pgoff = off >> PAGE_SHIFT;

/* This is an IO map - tell maydump to skip this VMA */

vma->vm_flags |= VM_IO | VM_RESERVED;

fb_pgprotect(file, vma, off);

printk("mmap-2\n");

if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,

vma->vm_end - vma->vm_start, vma->vm_page_prot))

return -EAGAIN;

return 0;

}

三,调试

之前我记得fbtft还使用了通用的mmap,并且开启了defio。s3c2410bf.c中没有使用自己的mmap,我添加调试信息来验证,打印输出的结果也如此,实际仿真与理解一致。见下图左下角log。

b441d4c739f0

image.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值