免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2340 | 回复: 5
打印 上一主题 下一主题

请教一个比较困惑的问题,各位大侠指教一下 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-01-22 17:10 |只看该作者 |倒序浏览
1.硬件平台:AT91SAM9263,操作系统:Linux2.6.27,TFT LCD 480*272(触摸屏)
2.问题描述:由于项目的特点,需要编写一个驱动程序,根据应用层传下来的数据,进行描点动作,(就是根据数据,在LCD上显示对应的像素)。
为了实现这个功能,我的做法是,编写一个字符设备驱动,在模块初始化时,获取内核映射好的分配给LCD的内存空间(framebuffer的内存空间)。然后根据应用层传下来的数据进行描点,描点的方法就是往这段内存空间添数据。。
现在遇到很困惑的问题是:这个驱动程序都很正确描点,但是在一个屏幕上的图形只要多一些,就会明显感觉到一个屏幕的显示会很慢,会明显感觉到CPU在画线。。
但是,在uboot下,显示一个彩色图片,都感觉比较快。。。
这是为什么啊???有做过这方面工作的大侠指点一下。。有什么方法可以使得刷屏的速度快一些??

部分代码如下:





static struct file_operations Fops_lcd =
{       
    .owner        =        THIS_MODULE,
    .open        =        lcd_device_open,
    .release=        lcd_device_release,
    .read        =        lcd_device_read,
    .write        =        lcd_device_write,
    .ioctl        =        NULL,
};

static struct fb_fix_screeninfo fix;
static struct fb_var_screeninfo var;
static int bytes_per_pixel;

static struct fb_info *atmel_fb=NULL; /*所要操作的LCD控制器对应的FB设备结构体*/
static unsigned char *line_addr;


static void lcdport_write(unsigned int addr, char data)
{   
        unsigned int x,y;
        int kk,bits;

        bits = data;
               


#if LINE_SCAN_MODE == 1
        for(kk=0;kk<8;kk++,bits <<=1)
        {
                if(bits & 0x80)
                        pixel(x+kk,y,COLOR_INDEX);
        }
#elif LINE_SCAN_MODE == 2
        for(kk=0;kk<8;kk++,bits <<=1)
        {
                if(bits & 0x80)
                        pixel(x+8-kk,y,COLOR_INDEX);
        }
       
#elif LINE_SCAN_MODE == 3
        for(kk=0;kk<8;kk++,bits <<=1)
        {
                if(bits & 0x80)
                        pixel(x,y+kk,COLOR_INDEX);
        }

#elif LINE_SCAN_MODE == 4
        for(kk=0;kk<8;kk++,bits <<=1)
        {
                if(bits & 0x80)
                        pixel(x,y+8-kk,COLOR_INDEX);
        }
#endif

}


static inline void __setpixel (union multiptr loc, unsigned xormode, unsigned color)
{
        switch(bytes_per_pixel) {
        case 1:
        default:
                if (xormode)  //transparent
                        *loc.p8 ^= color;
                else
                        *loc.p8 = color;
                break;
        case 2:
                if (xormode)
                        *loc.p16 ^= color;
                else
                        *loc.p16 = color;
                break;
        case 3:
                if (xormode)
                        *loc.p32 ^= color;
                else
                        *loc.p32 = color;
                break;
        case 4:
                if (xormode)
                        *loc.p32 ^= color;
                else
                        *loc.p32 = color;
                break;
        }
}

static void pixel (int x, int y, unsigned colidx)
{
        unsigned xormode;
        union multiptr loc;

        if ((x < 0) || ((__u32)x >= var.xres_virtual) ||
            (y < 0) || ((__u32)y >= var.yres_virtual))
                return;

        xormode = colidx & XORMODE;
        colidx &= ~XORMODE;

        loc.p8 = line_addr + y*fix.line_length + x * bytes_per_pixel;
        //__setpixel (loc, xormode, colormap [colidx]);
        __setpixel (loc, xormode, 255);
}

static int __init lcd_device_init (void)
{
        int ret;       
        int i;
        char *fbp;

        /* Register the character device */
        if ((ret = register_chrdev(DEVICE_MAJOR, DEVICE_NAME, &Fops_lcd)) < 0)
        {       
                printk ("LCD Device failed with %d\n", ret);
                return (ret);
        }
       
        /*PRINT_TRACE(Debug)("%s the major is %d.\n",lcd_device_driver_ver,DEVICE_MAJOR);*/       
        for(i = 0;i < num_registered_fb; i++)
        {
                /*printk("*******%s******\n",registered_fb->monspecs.manufacturer);*/
                if(memcmp(registered_fb->monspecs.manufacturer,"HIT",4)==0)
                {
                        atmel_fb = registered_fb;
                        break;
                }
        }
        if(atmel_fb==NULL)
                        goto no_lcd;

        fix = atmel_fb->fix;
        var = atmel_fb->var;
        bytes_per_pixel        = var.bits_per_pixel / 8;
        line_addr = atmel_fb->screen_base;       



        printk("LCD Paramres=%d,yres=%d,bytes_per_pixel=%d\n",var.xres,var.yres,bytes_per_pixel);
        printk("******screen_base:0x%X\n",atmel_fb->screen_base);
        printk("******screen_size:0x%X\n",atmel_fb->screen_size);
        printk("******smem_start:0x%X\n",fix.smem_start);
        printk("******smem_len:0x%X\n",fix.smem_len);
        /*printk("*******%s******\n",atmel_fb->monspecs.manufacturer);*/
        printk("LCD driver:Find specified LCD device!\n";
        return 0;

no_lcd:
        printk("LCD driver:Not find specified LCD device!\n";
        return (0);
}

module_init (lcd_device_init);

论坛徽章:
0
2 [报告]
发表于 2010-01-23 10:34 |只看该作者
自己顶一下。。
各位有什么想法,请指教一下。。

论坛徽章:
0
3 [报告]
发表于 2010-01-23 12:42 |只看该作者
static void lcdport_write(unsigned int addr, char data)
{   
        unsigned int x,y;
        int kk,bits;

        bits = data;
               


#if LINE_SCAN_MODE == 1
        for(kk=0;kk<8;kk++,bits <<=1)
        {
                if(bits & 0x80)
                        pixel(x+kk,y,COLOR_INDEX);
        }
#elif LINE_SCAN_MODE == 2
        for(kk=0;kk<8;kk++,bits <<=1)
        {
                if(bits & 0x80)
                        pixel(x+8-kk,y,COLOR_INDEX);
        }
        
#elif LINE_SCAN_MODE == 3
        for(kk=0;kk<8;kk++,bits <<=1)
        {
                if(bits & 0x80)
                        pixel(x,y+kk,COLOR_INDEX);
        }

#elif LINE_SCAN_MODE == 4
        for(kk=0;kk<8;kk++,bits <<=1)
        {
                if(bits & 0x80)
                        pixel(x,y+8-kk,COLOR_INDEX);
        }
#endif

}

我想知道这个函数里的局部变量x和y初始为什么没有赋值?函数参数addr为什么没有使用?

论坛徽章:
0
4 [报告]
发表于 2010-01-25 08:24 |只看该作者
漏了。。
static void lcdport_write(unsigned int addr, char data)
{   
        unsigned int x,y;
        int kk,bits;

        bits = data;
               
        y = addr / 40;
        x = (addr%40)×8

        //printk("+++addr=%d,x=%d,y=%d,data=%d\n",addr,x,y,data);

#if LINE_SCAN_MODE == 1
        for(kk=0;kk<8;kk++,bits <<=1)
        {
                if(bits & 0x80)
                        pixel(x+kk,y,COLOR_INDEX);
        }
#elif LINE_SCAN_MODE == 2
        for(kk=0;kk<8;kk++,bits <<=1)
        {
                if(bits & 0x80)
                        pixel(x+8-kk,y,COLOR_INDEX);
        }
       
#elif LINE_SCAN_MODE == 3
        for(kk=0;kk<8;kk++,bits <<=1)
        {
                if(bits & 0x80)
                        pixel(x,y+kk,COLOR_INDEX);
        }

#elif LINE_SCAN_MODE == 4
        for(kk=0;kk<8;kk++,bits <<=1)
        {
                if(bits & 0x80)
                        pixel(x,y+8-kk,COLOR_INDEX);
        }
#endif
        LCDFrambuffer[addr] = data;

}

版上的各位有什么想法,建议啊。。

论坛徽章:
0
5 [报告]
发表于 2010-01-25 09:52 |只看该作者
google上搜一下pixclock
估计与硬件寄存器设置有关系

论坛徽章:
0
6 [报告]
发表于 2010-01-25 11:01 |只看该作者
原帖由 readkernel 于 2010-1-25 09:52 发表
google上搜一下pixclock
估计与硬件寄存器设置有关系

谢谢回复,刚才问了一个朋友,说是DMA操作太频率了,每次写1bit的数据,有可能DMA就要操作一次,所以导致速度会比较慢。。。
想试一下disable DMA一下,写完一个字节数据,再enble DMA。。有没有哪位大侠知道要使用哪个函数
添加代码如下:
static void lcdport_write(unsigned int addr, char data)
{   
        unsigned int x,y;
        int kk,bits;

        bits = data;
               
        y = addr / 40;
        x = (addr%40)*8;

        //printk("+++addr=%d,x=%d,y=%d,data=%d\n",addr,x,y,data);
        //添加DISABLE DMA函数
#if LINE_SCAN_MODE == 1
        for(kk=0;kk<8;kk++,bits <<=1)
        {
                if(bits & 0x80)
                        pixel(x+kk,y,COLOR_INDEX);
        }
#elif LINE_SCAN_MODE == 2
        for(kk=0;kk<8;kk++,bits <<=1)
        {
                if(bits & 0x80)
                        pixel(x+8-kk,y,COLOR_INDEX);
        }
       
#elif LINE_SCAN_MODE == 3
        for(kk=0;kk<8;kk++,bits <<=1)
        {
                if(bits & 0x80)
                        pixel(x,y+kk,COLOR_INDEX);
        }

#elif LINE_SCAN_MODE == 4
        for(kk=0;kk<8;kk++,bits <<=1)
        {
                if(bits & 0x80)
                        pixel(x,y+8-kk,COLOR_INDEX);
        }
#endif
        //添加enable DMA 函数

}
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP