LCD驱动程序架构和分析
来源:互联网 发布:手机淘宝抠图 编辑:程序博客网 时间:2024/06/14 05:16
一、LCD驱动程序架构
1.裸机驱动代码分析
①LCD初始化:控制器初始化,端口初始化,指明帧缓冲
②LCD图形显示:将图形数据写入帧缓冲
2.帧缓冲体验
帧缓冲:内存中的一段区域,通过对内存的修改。LCD控制器从内存中获取数据,自动的控制LCD的显示。
将图片显示到lcd。
3.帧缓冲架构
/dev/fb0就是帧缓冲,字符设备
fbmem_init():
fb_ops:
fb_write:
info结构:
主要是fb_var_screeninfo、fb_fix_screeninfo、fb_ops三个结构体:
struct fb_var_screeninfo:主要记录用户可以修改的控制器的参数。
fb_fix_screeninfo:主要记录用户不可以修改的控制器的参数
fb_ops:底层硬件操作的函数指针
http://www.cnblogs.com/lishixian/articles/2999923.html
二、LCD驱动程序分析
s3c2410fb_init:
s3c2410fb_driver:
s3c24xxfb_probe:
s3c2410fb_map_vedio_memory:
分析到这里发现并没有设置帧缓冲的地址:
于是可以通过搜索帧地址来辨别,在哪个函数中实现。
s3c2410fb_set_lcdaddr:
但是如何知道调用顺序呢,可以在函数中调用dump_stack():
1.裸机驱动代码分析
①LCD初始化:控制器初始化,端口初始化,指明帧缓冲
②LCD图形显示:将图形数据写入帧缓冲
- void lcd_init()
- {
- lcd_port_init(); //初始化gpdcon和gpccon初始化
- lcd_control_init(); //时序初始化和帧缓冲初始化
- //打开LCD电源
- GPGCON |= 0b11<<8;
- LCDCON5 |= (1<<3);
- LCDCON1 |= 1;
- }
帧缓冲:内存中的一段区域,通过对内存的修改。LCD控制器从内存中获取数据,自动的控制LCD的显示。
- # cat tq2440.bin > /dev/fb0
3.帧缓冲架构
/dev/fb0就是帧缓冲,字符设备
fbmem_init():
- static int __init
- fbmem_init(void)
- {
- proc_create("fb", 0, NULL, &fb_proc_fops);
- if (register_chrdev(FB_MAJOR,"fb",&fb_fops)) //注册设备文件,注册帧缓冲,fp_fops是操作函数集
- printk("unable to get major %d for fb devs\n", FB_MAJOR);
- fb_class = class_create(THIS_MODULE, "graphics");
- if (IS_ERR(fb_class)) {
- printk(KERN_WARNING "Unable to create fb class; errno = %ld\n", PTR_ERR(fb_class));
- fb_class = NULL;
- }
- return 0;
- }
- 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,
- #ifdef HAVE_ARCH_FB_UNMAPPED_AREA
- .get_unmapped_area = get_fb_unmapped_area,
- #endif
- #ifdef CONFIG_FB_DEFERRED_IO
- .fsync = fb_deferred_io_fsync,
- #endif
- };
- static ssize_t
- fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
- {
- unsigned long p = *ppos;
- struct inode *inode = file->f_path.dentry->d_inode;
- int fbidx = iminor(inode);
- struct fb_info *info = registered_fb[fbidx];
- u32 *buffer, *src;
- u32 __iomem *dst;
- int c, i, cnt = 0, err = 0;
- unsigned long total_size;
- if (!info || !info->screen_base)
- return -ENODEV;
- if (info->state != FBINFO_STATE_RUNNING)
- return -EPERM;
- if (info->fbops->fb_write)
- return info->fbops->fb_write(info, buf, count, ppos);
-
- total_size = info->screen_size;
- if (total_size == 0)
- total_size = info->fix.smem_len;
- if (p > total_size)
- return -EFBIG;
- if (count > total_size) {
- err = -EFBIG;
- count = total_size;
- }
- if (count + p > total_size) {
- .........各种info
- }
info结构:
- struct fb_info {
- int node;
- int flags;
- struct mutex lock; //控制io操作锁
- struct fb_var_screeninfo var;/*LCD可变参数*/
- struct fb_fix_screeninfo fix;/*LCD固定参数*/
- struct fb_monspecs monspecs; /*LCD显示器标准*/
- struct work_struct queue; /*帧缓冲事件队列*/
- struct fb_pixmap pixmap; /*图像硬件mapper*/
- struct fb_pixmap sprite; /*光标硬件mapper*/
- struct fb_cmap cmap; /*当前的颜色表*/
- struct fb_videomode *mode; /*当前的显示模式*/
-
- #ifdef CONFIG_FB_BACKLIGHT
- struct backlight_device *bl_dev;/*对应的背光设备*/
- struct mutex bl_curve_mutex;
- u8 bl_curve[FB_BACKLIGHT_LEVELS];/*背光调整*/
- #endif
- #ifdef CONFIG_FB_DEFERRED_IO
- struct delayed_work deferred_work;
- struct fb_deferred_io *fbdefio;
- #endif
-
- struct fb_ops *fbops; /*对底层硬件操作的函数指针*/
- struct device *device;
- struct device *dev; /*fb设备*/
- int class_flag;
- #ifdef CONFIG_FB_TILEBLITTING
- struct fb_tile_ops *tileops; /*图块Blitting*/
- #endif
- char __iomem *screen_base; /*虚拟基地址*/
- unsigned long screen_size; /*LCD IO映射的虚拟内存大小*/
- void *pseudo_palette; /*伪16色颜色表*/
- #define FBINFO_STATE_RUNNING 0
- #define FBINFO_STATE_SUSPENDED 1
- u32 state; /*LCD的挂起或恢复状态*/
- void *fbcon_par;
- void *par;
- };
struct fb_var_screeninfo:主要记录用户可以修改的控制器的参数。
- struct fb_var_screeninfo {
- __u32 xres; /* visible resolution */
- __u32 yres;
- __u32 xres_virtual; /* virtual resolution */
- __u32 yres_virtual;
- __u32 xoffset; /* offset from virtual to visible */
- __u32 yoffset; /* resolution */
- __u32 bits_per_pixel; /* guess what */每个像素的位数即BPP
- __u32 grayscale; /* != 0 Graylevels instead of colors */
- struct fb_bitfield red; /* bitfield in fb mem if true color, */
- struct fb_bitfield green; /* else only length is significant */
- struct fb_bitfield blue;
- struct fb_bitfield transp; /* transparency */
- __u32 nonstd; /* != 0 Non standard pixel format */
- __u32 activate; /* see FB_ACTIVATE_* */
- __u32 height; /* height of picture in mm */
- __u32 width; /* width of picture in mm */
- __u32 accel_flags; /* (OBSOLETE) see fb_info.flags */
- /* Timing: All values in pixclocks, except pixclock (of course) */
- __u32 pixclock; /* pixel clock in ps (pico seconds) */
- __u32 left_margin; /* time from sync to picture */
- __u32 right_margin; /* time from picture to sync */
- __u32 upper_margin; /* time from sync to picture */
- __u32 lower_margin;
- __u32 hsync_len; /* length of horizontal sync */
- __u32 vsync_len; /* length of vertical sync */
- __u32 sync; /* see FB_SYNC_* */
- __u32 vmode; /* see FB_VMODE_* */
- __u32 rotate; /* angle we rotate counter clockwise */
- __u32 reserved[5]; /* Reserved for future compatibility */
- };
- struct fb_fix_screeninfo {
- char id[16]; /* identification string eg "TT Builtin" */
- unsigned long smem_start; /* Start of frame buffer mem */
- /* (physical address) */
- __u32 smem_len; /* Length of frame buffer mem */
- __u32 type; /* see FB_TYPE_* */
- __u32 type_aux; /* Interleave for interleaved Planes */
- __u32 visual; /* see FB_VISUAL_* */
- __u16 xpanstep; /* zero if no hardware panning */
- __u16 ypanstep; /* zero if no hardware panning */
- __u16 ywrapstep; /* zero if no hardware ywrap */
- __u32 line_length; /* length of a line in bytes */
- unsigned long mmio_start; /* Start of Memory Mapped I/O */
- /* (physical address) */
- __u32 mmio_len; /* Length of Memory Mapped I/O */
- __u32 accel; /* Indicate to driver which */
- /* specific chip/card we have */
- __u16 reserved[3]; /* Reserved for future compatibility */
- };
- struct fb_ops {
- /* open/release and usage marking */
- struct module *owner;
- int (*fb_open)(struct fb_info *info, int user);
- int (*fb_release)(struct fb_info *info, int user);
- /* For framebuffers with strange non linear layouts or that do not
- * work with normal memory mapped access
- */
- ssize_t (*fb_read)(struct fb_info *info, char __user *buf,
- size_t count, loff_t *ppos);
- ssize_t (*fb_write)(struct fb_info *info, const char __user *buf,
- size_t count, loff_t *ppos);
- /* checks var and eventually tweaks it to something supported,
- * DO NOT MODIFY PAR */
- int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
- /* set the video mode according to info->var */
- int (*fb_set_par)(struct fb_info *info);
- /* set color register */
- int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp, struct fb_info *info);
- /* set color registers in batch */
- int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
- /* blank display */
- int (*fb_blank)(int blank, struct fb_info *info);
- /* pan display */
- int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
- /* Draws a rectangle */
- void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
- /* Copy data from area to another */
- void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
- /* Draws a image to the display */
- void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
- /* Draws cursor */
- int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
- /* Rotates the display */
- void (*fb_rotate)(struct fb_info *info, int angle);
- /* wait for blit idle, optional */
- int (*fb_sync)(struct fb_info *info);
- /* perform fb specific ioctl (optional) */
- int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
- unsigned long arg);
- /* Handle 32bit compat ioctl (optional) */
- int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,
- unsigned long arg);
- /* perform fb specific mmap */
- int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
- /* save current hardware state */
- void (*fb_save_state)(struct fb_info *info);
- /* restore saved state */
- void (*fb_restore_state)(struct fb_info *info);
- /* get capability given var */
- void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,
- struct fb_var_screeninfo *var);
- };
二、LCD驱动程序分析
s3c2410fb_init:
- int __init s3c2410fb_init(void)
- {
- int ret = platform_driver_register(&s3c2410fb_driver); //注册平台驱动设备
- if (ret == 0)
- ret = platform_driver_register(&s3c2412fb_driver);;
- return ret;
- }
- static struct platform_driver s3c2410fb_driver = {
- .probe = s3c2410fb_probe, //probe函数,里面调用了s3c24xxfb_probe
- .remove = s3c2410fb_remove,
- .suspend = s3c2410fb_suspend,
- .resume = s3c2410fb_resume,
- .driver = {
- .name = "s3c2410-lcd",
- .owner = THIS_MODULE,
- },
- };
- static int __init s3c24xxfb_probe(struct platform_device *pdev,
- enum s3c_drv_type drv_type)
- {
- struct s3c2410fb_info *info;
- struct s3c2410fb_display *display;
- struct fb_info *fbinfo;
- struct s3c2410fb_mach_info *mach_info;
- struct resource *res;
- int ret;
- int irq;
- int i;
- int size;
- u32 lcdcon1;
- mach_info = pdev->dev.platform_data;
- if (mach_info == NULL) {
- dev_err(&pdev->dev,
- "no platform data for lcd, cannot attach\n");
- return -EINVAL;
- }
- if (mach_info->default_display >= mach_info->num_displays) {
- dev_err(&pdev->dev, "default is %d but only %d displays\n",
- mach_info->default_display, mach_info->num_displays);
- return -EINVAL;
- }
- display = mach_info->displays + mach_info->default_display;
- irq = platform_get_irq(pdev, 0); //获取中断号
- if (irq < 0) {
- dev_err(&pdev->dev, "no irq for device\n");
- return -ENOENT;
- }
- fbinfo = framebuffer_alloc(sizeof(struct s3c2410fb_info), &pdev->dev); //分配fb_info结构
- if (!fbinfo)
- return -ENOMEM;
- platform_set_drvdata(pdev, fbinfo);
- info = fbinfo->par;
- info->dev = &pdev->dev;
- info->drv_type = drv_type;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0); //获取寄存器地址
- if (res == NULL) {
- dev_err(&pdev->dev, "failed to get memory registers\n");
- ret = -ENXIO;
- goto dealloc_fb;
- }
- size = (res->end - res->start) + 1;
- info->mem = request_mem_region(res->start, size, pdev->name);
- if (info->mem == NULL) {
- dev_err(&pdev->dev, "failed to get memory region\n");
- ret = -ENOENT;
- goto dealloc_fb;
- }
- info->io = ioremap(res->start, size); //转化成虚拟地址
- if (info->io == NULL) {
- dev_err(&pdev->dev, "ioremap() of registers failed\n");
- ret = -ENXIO;
- goto release_mem;
- }
- info->irq_base = info->io + ((drv_type == DRV_S3C2412) ? S3C2412_LCDINTBASE : S3C2410_LCDINTBASE);
- dprintk("devinit\n");
- strcpy(fbinfo->fix.id, driver_name);
- /* Stop the video */ //初始化fbinfo结构
- lcdcon1 = readl(info->io + S3C2410_LCDCON1);
- writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1);
- fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
- fbinfo->fix.type_aux = 0;
- fbinfo->fix.xpanstep = 0;
- fbinfo->fix.ypanstep = 0;
- fbinfo->fix.ywrapstep = 0;
- fbinfo->fix.accel = FB_ACCEL_NONE;
- fbinfo->var.nonstd = 0;
- fbinfo->var.activate = FB_ACTIVATE_NOW;
- fbinfo->var.accel_flags = 0;
- fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
- fbinfo->fbops = &s3c2410fb_ops;
- fbinfo->flags = FBINFO_FLAG_DEFAULT;
- fbinfo->pseudo_palette = &info->pseudo_pal;
- for (i = 0; i < 256; i++)
- info->palette_buffer[i] = PALETTE_BUFF_CLEAR;
- ret = request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info); //注册中断函数
- if (ret) {
- dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret);
- ret = -EBUSY;
- goto release_regs;
- }
- info->clk = clk_get(NULL, "lcd");
- if (!info->clk || IS_ERR(info->clk)) {
- printk(KERN_ERR "failed to get lcd clock source\n");
- ret = -ENOENT;
- goto release_irq;
- }
- clk_enable(info->clk);
- dprintk("got and enabled clock\n");
- msleep(1);
- /* find maximum required memory size for display */
- for (i = 0; i < mach_info->num_displays; i++) {
- unsigned long smem_len = mach_info->displays[i].xres;
- smem_len *= mach_info->displays[i].yres;
- smem_len *= mach_info->displays[i].bpp;
- smem_len >>= 3;
- if (fbinfo->fix.smem_len < smem_len)
- fbinfo->fix.smem_len = smem_len;
- }
- /* Initialize video memory */
- ret = s3c2410fb_map_video_memory(fbinfo); //为帧缓冲分配内存空间。同时使用了dma
- if (ret) {
- printk(KERN_ERR "Failed to allocate video RAM: %d\n", ret);
- ret = -ENOMEM;
- goto release_clock;
- }
- dprintk("got video memory\n");
- fbinfo->var.xres = display->xres;
- fbinfo->var.yres = display->yres;
- fbinfo->var.bits_per_pixel = display->bpp;
- s3c2410fb_init_registers(fbinfo); //GPIO初始化
- s3c2410fb_check_var(&fbinfo->var, fbinfo); //设置fb_var_screeninfo
- ret = register_framebuffer(fbinfo); //注册帧缓冲-register_framebuffer
- if (ret < 0) {
- printk(KERN_ERR "Failed to register framebuffer device: %d\n",
- ret);
- goto free_video_memory;
- }
- /* create device files */
- ret = device_create_file(&pdev->dev, &dev_attr_debug);
- if (ret) {
- printk(KERN_ERR "failed to add debug attribute\n");
- }
- printk(KERN_INFO "fb%d: %s frame buffer device\n",
- fbinfo->node, fbinfo->fix.id);
- return 0;
- free_video_memory:
- s3c2410fb_unmap_video_memory(fbinfo);
- release_clock:
- clk_disable(info->clk);
- clk_put(info->clk);
- release_irq:
- free_irq(irq, info);
- release_regs:
- iounmap(info->io);
- release_mem:
- release_resource(info->mem);
- kfree(info->mem);
- dealloc_fb:
- platform_set_drvdata(pdev, NULL);
- framebuffer_release(fbinfo);
- return ret;
- }
- static int __init s3c2410fb_map_video_memory(struct fb_info *info)
- {
- struct s3c2410fb_info *fbi = info->par;
- dma_addr_t map_dma;
- unsigned map_size = PAGE_ALIGN(info->fix.smem_len);
- dprintk("map_video_memory(fbi=%p) map_size %u\n", fbi, map_size);
- info->screen_base = dma_alloc_writecombine(fbi->dev, map_size,
- &map_dma, GFP_KERNEL); //为帧缓冲分配内存空间。同时使用了dma
- if (info->screen_base) {
- /* prevent initial garbage on screen */
- dprintk("map_video_memory: clear %p:%08x\n",
- info->screen_base, map_size);
- memset(info->screen_base, 0x00, map_size);
- info->fix.smem_start = map_dma;
- dprintk("map_video_memory: dma=%08lx cpu=%p size=%08x\n",
- info->fix.smem_start, info->screen_base, map_size);
- }
- return info->screen_base ? 0 : -ENOMEM;
- }
分析到这里发现并没有设置帧缓冲的地址:
于是可以通过搜索帧地址来辨别,在哪个函数中实现。
s3c2410fb_set_lcdaddr:
- static void s3c2410fb_set_lcdaddr(struct fb_info *info)
- {
- unsigned long saddr1, saddr2, saddr3;
- struct s3c2410fb_info *fbi = info->par;
- void __iomem *regs = fbi->io;
- saddr1 = info->fix.smem_start >> 1;
- saddr2 = info->fix.smem_start;
- saddr2 += info->fix.line_length * info->var.yres;
- saddr2 >>= 1;
- saddr3 = S3C2410_OFFSIZE(0) |
- S3C2410_PAGEWIDTH((info->fix.line_length / 2) & 0x3ff);
- dprintk("LCDSADDR1 = 0x%08lx\n", saddr1);
- dprintk("LCDSADDR2 = 0x%08lx\n", saddr2);
- dprintk("LCDSADDR3 = 0x%08lx\n", saddr3);
- writel(saddr1, regs + S3C2410_LCDSADDR1); //这里设置了帧缓冲的地址
- writel(saddr2, regs + S3C2410_LCDSADDR2);
- writel(saddr3, regs + S3C2410_LCDSADDR3);
- }
- Backtrace:
- [<c0049048>] (dump_backtrace+0x0/0x10c) from [<c0373fac>] (dump_stack+0x18/0x1c)
- r7:232f3302 r6:5bd42233 r5:00000000 r4:3a352944
- [<c0373f94>] (dump_stack+0x0/0x1c) from [<c01718c8>] (s3c2410fb_set_par+0x150/0x78c)
- [<c0171778>] (s3c2410fb_set_par+0x0/0x78c) from [<c016a578>] (fbcon_init+0x42c/0x4b8)
- [<c016a14c>] (fbcon_init+0x0/0x4b8) from [<c0185800>] (visual_init+0xb8/0x100)
- [<c0185748>] (visual_init+0x0/0x100) from [<c018a65c>] (take_over_console+0x1f4/0x3d8)
- r7:00000000 r6:c03a6c90 r5:c05a75a0 r4:00000019
- [<c018a468>] (take_over_console+0x0/0x3d8) from [<c0167050>] (fbcon_takeover+0x7c/0xd4)
- [<c0166fd4>] (fbcon_takeover+0x0/0xd4) from [<c016b1b0>] (fbcon_event_notify+0x768/0x7b0)
- r5:ffffffff r4:00000000
- [<c016aa48>] (fbcon_event_notify+0x0/0x7b0) from [<c0070784>] (notifier_call_chain+0x54/0x94)
- [<c0070730>] (notifier_call_chain+0x0/0x94) from [<c0070d08>] (__blocking_notifier_call_chain+0x54/0x6c)
- r9:c04b5008 r8:00000005 r7:ffffffff r6:c381dd98 r5:c04c5470
- r4:c04c547c
- [<c0070cb4>] (__blocking_notifier_call_chain+0x0/0x6c) from [<c0070d40>] (blocking_notifier_call_chain+0x20/0x28)
- r8:c3842a04 r7:00000000 r6:c0513120 r5:c3842800 r4:c381dd60
- [<c0070d20>] (blocking_notifier_call_chain+0x0/0x28) from [<c015fc48>] (fb_notifier_call_chain+0x1c/0x24)
- [<c015fc2c>] (fb_notifier_call_chain+0x0/0x24) from [<c0160cf0>] (register_framebuffer+0x154/0x1fc)
- [<c0160b9c>] (register_framebuffer+0x0/0x1fc) from [<c0014bbc>] (s3c24xxfb_probe+0x4c4/0x6fc)
- [<c00146f8>] (s3c24xxfb_probe+0x0/0x6fc) from [<c0014e20>] (s3c2410fb_probe+0x14/0x18)
- [<c0014e0c>] (s3c2410fb_probe+0x0/0x18) from [<c019369c>] (platform_drv_probe+0x20/0x24)
- [<c019367c>] (platform_drv_probe+0x0/0x24) from [<c0192694>] (driver_probe_device+0x8c/0x1a0)
- [<c0192608>] (driver_probe_device+0x0/0x1a0) from [<c019283c>] (__driver_attach+0x94/0x98)
- [<c01927a8>] (__driver_attach+0x0/0x98) from [<c0191f38>] (bus_for_each_dev+0x6c/0x98)
- r7:c01927a8 r6:c04c56b8 r5:c381de98 r4:00000000
- [<c0191ecc>] (bus_for_each_dev+0x0/0x98) from [<c0192514>] (driver_attach+0x20/0x28)
- r7:c04c56b8 r6:00000000 r5:c04c56b8 r4:c001fc68
- [<c01924f4>] (driver_attach+0x0/0x28) from [<c0191764>] (bus_add_driver+0xa4/0x244)
- [<c01916c0>] (bus_add_driver+0x0/0x244) from [<c0192b00>] (driver_register+0x74/0x15c)
- [<c0192a8c>] (driver_register+0x0/0x15c) from [<c0193a80>] (platform_driver_register+0x6c/0x88)
- r7:c381c000 r6:00000000 r5:c001fa50 r4:c001fc68
- [<c0193a14>] (platform_driver_register+0x0/0x88) from [<c0014e38>] (s3c2410fb_init+0x14/0x30)
- [<c0014e24>] (s3c2410fb_init+0x0/0x30) from [<c0044284>] (do_one_initcall+0x3c/0x1bc)
- [<c0044248>] (do_one_initcall+0x0/0x1bc) from [<c0008438>] (kernel_init+0x88/0xf4)
- [<c00083b0>] (kernel_init+0x0/0xf4) from [<c005a2e8>] (do_exit+0x0/0x620)
0
上一篇:触摸屏驱动分析和编程
下一篇:块设备驱动系统架构和简单设计
相关热门文章
- SHTML是什么_SSI有什么用...
- 查看linux中某个端口(port)...
- 卡尔曼滤波的原理说明...
- shell中字符串操作
- 关于java中的“错误:找不到或...
给主人留下些什么吧!~~
评论热议
阅读全文
0 0
- LCD驱动程序架构和分析
- LCD驱动程序分析
- LCD驱动程序层次分析
- s3c2410 linux LCD驱动程序分析
- 显存fb和LCD驱动程序
- 6410之LCD驱动程序(层次分析)
- 6410之LCD驱动程序(层次分析)
- LCD 驱动程序
- Lcd驱动程序
- lcd驱动程序
- LCD驱动程序
- Linux系统LCD驱动架构分析
- Linux系统LCD驱动架构分析
- Linux系统LCD驱动架构分析
- LCD驱动程序分析---基于framebuffer
- LCD驱动程序——框架分析(一)
- LCD驱动程序——框架分析(一)
- LCD驱动程序——框架分析(一)
- DM9000网卡驱动深度分析
- DM9000驱动网卡编程
- 输入子系统模型解析和原理分析
- drawerlayout侧滑
- 触摸屏驱动分析和编程
- LCD驱动程序架构和分析
- 块设备驱动系统架构和简单设计
- MTD系统架构和yaffs2使用、Nandflash驱动设计
- I2C学习
- 蓝牙搜索
- I2C用户态驱动设计
- SpringBoot的热部署
- I2C自编设备驱动设计
- crontab执行shell脚本和直接运行的结果不一样
原创粉丝点击
热门IT博客
热门问题
老师的惩罚
人脸识别
我在镇武司摸鱼那些年
重生之率土为王
我在大康的咸鱼生活
盘龙之生命进化
天生仙种
凡人之先天五行
春回大明朝
姑娘不必设防,我是瞎子
聚划算吧
聚划算电脑版
聚划算报名费用
君乐宝每日活菌价格
如何参加聚划算团购
聚划算如何团购
巨金怪
巨金怪配招
巨金怪性格
巨蛛怪
金属怪几级进化成巨金怪
巨化股份
巨化股吧
巨化集团
巨化
巨化股份股吧
600160巨化股份
巨化股份股票
600160巨化股份股吧
杭州巨化宾馆
巨化股份不涨原因
巨化股份重组
巨化股份股票代码
巨化股份股票行情
巨化股份定向增发
巨化股份年报
浙江巨化集团
宝巨要崛起作品
归来的宗师宝巨要崛起
归来的宗师 宝巨要崛起
都市之宇宙大神壕 崛起的宝巨
玉嘴含情吹巨萧目录
黄容玉嘴含情吹巨杨过
巨型大白熊犬图片
巨型雪纳瑞犬
阿拉斯加图片巨型
巨型阿拉斯加犬图片
阿拉斯加犬图片巨型
巨型阿拉斯加犬多少钱一只
巨型贵宾犬图片价格
黑色巨型贵宾犬价格