S3C44B0X中关于frameBuffer的问题

  S3C44B0X中关于frameBuffer的问题

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

.

.

#if (LCD_TYPE==MLCD_240_320)

#define SCR_XSIZE     (480) 

#define SCR_YSIZE     (640)

.

.

.

#define ARRAY_SIZE_G16        (SCR_XSIZE/2*SCR_YSIZE)

.

.

unsigned int (*frameBuffer16)[SCR_XSIZE/8];

.

.

void Lcd_Init(int depth)

{       

    switch(depth)

    {case 16:

       if((U32)frameBuffer16==0)

       {

           //The total frame memory should be inside 4MB.

           //For example, if total memory is 8MB, the frame memory

           //should be in 0xc000000~0xc3fffff or c400000~c7fffff.

           //But, the following code doesn't meet this condition(4MB)

           //if the code size & location is changed..

           frameBuffer16=(unsigned int (*)[SCR_XSIZE/8])malloc(ARRAY_SIZE_G16);

        .

        .

        .

 

       }

我的S3C44B0X开发板外接的是240X320的STN  16级灰度LCD,在初步学习了相关的LCD显示的程序后,通过改动开发板配套的程序也实现了在LCD上显示自己照片的功能,对LCD的驱动显示过程有了一个大体的了解,但是在学习程序的细节上有很多的疑惑,主要是某些涉及指针的变量,函数,以及某些运算过程。以上的一段程序(将必要的语句集合到一起以便研究)就让我迷惑了很久,在网上搜索了相关的资料,发现一些论坛上对于这个问题的讨论也不少,但都没有太详细的解答,参考了各种资料和大家的讨论后,我自己琢磨了一下,问题终于有点眉目了,我想把我的一点心得写出来和大家分享,有什么不对的地方,欢迎大家一起讨论!

    **首先要弄清楚LCD是如何显示的,16灰度的LCD是每4位(也就是半个字节)代表一个象素,那么对于256色的LCD来说就是8位(恰好是一个字节的数据宽度)对应一个象素,而S3C44B0X是通过写显示缓冲区来实现在LCD屏上显示图象的,也就是显示缓冲区映射的是LCD屏幕上的每一点!明白这一点很关键,接下来看一下相关的程序**

 

一下程序中相关的参量的意义:

 

#if (LCD_TYPE==MLCD_240_320) 

  //这里是LCD的类型,我板上的是24X320的16级灰度屏

#define SCR_XSIZE     (480)

#define SCR_YSIZE     (640)

 //这实际是定义的虚拟屏幕的宽度(X)和高度(Y),就是说用                                240X320的屏可以局部显示480X640的图象,当然也可以定义的更大                                一些来显示更大的图象

#define ARRAY_SIZE_G16         (SCR_XSIZE/2*SCR_YSIZE)

 //这里将ARRAY_SIZE_G16的大小定义为SCR_XSIZE/2*SCR_YSIZE,也就是480*640/2,为什么要/2呢?我的理解是,以后涉及到以ARRAY_SIZE_G16为大小的参量时肯定是以字节为单位存储的!参照之前说的LCD的显示规则,要想在16级灰度屏上完整显示大小为480X640的图象,至少要有480X640 BYTE的显示缓冲才能对应480X640个点,而字节的数据宽度是8位,因此只需要480X640/2个字节型的数据就可以了。

unsigned int (*frameBuffer16)[SCR_XSIZE/8];

//在这里定义了显示缓冲区,它的大小是SCR_XSIZE/8,也就是480/8,在这里frameBuffer16是一个指针,它指向的是包含SCR_XSIZE/8个unsigned int类型的(在DEF.H中该类型为32位,即U32)元素的数组;这时,SCR_XSIZE/8的意义就显而易见了,因为数组的元素是32位的unsigned int类型的,只需要有SCR_XSIZE/8个元素即可以实现输出480个象素的目的!当然480个象素只是480X640图象大小的1/640,也就是屏幕上的一行,——是一行的显示缓冲区;要对应480X640大小的图象,至少需要480X640大小显示缓冲区,所以我们接着往下看,

void Lcd_Init(int depth)

//来到真正LCD初始化的地方,在这里要着重理解的是其中分配内存的一句,其他的很容易理解,就略去了。

if((U32)frameBuffer16==0)

//这一句是在检查是否已经为显示缓冲分配过内存了?(我的猜测,不知道省掉这一句会有什么区别?)

frameBuffer16=(unsigned int (*)[SCR_XSIZE/8])malloc(ARRAY_SIZE_G16);

//由于刚才已经定义了一个指针frameBuffer16,而且知道要显示480X640的图象至少需有480X640/2字节大小的显示缓冲,理解这一句已经不象开始那样一头雾水了,通过malloc(ARRAY_SIZE_G16)在内存中分出一块大小为ARRAY_SIZE_G16字节,也就是刚好可以满足480X640显示需要的内存区做为显示缓存,也许有人要问了,刚才不是定义过frameBuffer16了吗?为什么现在又定义一次?第1次定义了frameBuffer16这个指针,是指向数组类型的指针,而第2次是将frameBuffer16指向一个实际的内存区域,也就是通过malloc(ARRAY_SIZE_G16)分配的,注意ARRAY_SIZE_G16的大小是480X640/2个字节,(unsigned int (*)[SCR_XSIZE/8])是强制类转换;我理解这里在(*)后加一个[SCR_XSIZE/8]的用意,其实只是把malloc(ARRAY_SIZE_G16)分配的内存分成大小为SCR_XSIZE/8的块(并没有实际的意义,为了便于理解可以这么考虑),也就是说frameBuffer16每进行一次‘+1’的操作,实际上是地址增加[SCR_XSIZE/8]个字,指针frameBuffer16仍然是32位的,这样的话就共有(ARRAY_SIZE_G16/8(换算成U32类型的))/(SCR_XSIZE/8)=(480X640/8)/(480/8)=640块,这说明什么呢?要是换个理解方式,用2维数组的概念来理解的话,也就是说frameBuffer16指向的是一块[640][480/8]的2维空间。

有了以上的理解,可以看一个最基本的象素输出函数:

void _PutPixelG16(U32 x,U32 y,U8 c)

{

    if(x<SCR_XSIZE && y<SCR_YSIZE)

        frameBuffer16[(y)][(x)/8]=( frameBuffer16[(y)][x/8] & ~(0xc0000000>>((x)%8)*4) )

            | ( (c)<<((8-1-((x)%8))*4) );

}

 

为了更方便形象地对应屏幕上指定位置(X,Y)的点,可以看到_PutPixelG16这个函数即是通过frameBuffer16[(y)][(x)/8],以2维数组的形式来写显示缓冲区的。

 

有了这些理解,对于其它图形函数的理解应该会更轻松了!

不知道以上我说的有没有什么不对的地方,我也是刚刚学S3C44B0X,没有什么经验可谈,就把我自己的理解和大家分享吧!

 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

补充:

在lcdlib.c可以找到关于MALLOC()的定义,可以看出MALLOC分配的内存的大小以字节来计算,

char Image$$RW$$Limit[];

 

void *mallocPt=Image$$RW$$Limit;

.

.

.

void * malloc(unsigned nbyte)

/*Very simple; Use malloc() & free() like Stack*/

{

    void *returnPt=mallocPt;

    mallocPt= (int *)mallocPt+nbyte/4+((nbyte%4)>0); //to align 4byte

    if( (int)mallocPt > HEAPEND )

    {

       mallocPt=returnPt;

       return NULL;

    }

    return returnPt;

}

当程序中第1次使用MALLOC   时,RETURNPT指向的初始位置就是Image$$RW$$Limit[]的起始位置,由mallocPt= (int *)mallocPt+nbyte/4+((nbyte%4)>0)来计算出分配NBYTE后的指针的位置,接下来判断所分配的内存大小是否超过了堆(HEAP)的界限,如果没有超过界限,将可以使用从Image$$RW$$Limit到mallocPt之间的内存块,由于mallocPt是一个全局变量,所以在第1次分配内存后,它的值将是(int *)mallocPt+nbyte/4+((nbyte%4)>0),在下一次使用MALLOC的时候将从这个位置开始分配。但这样来分配内存似乎存在一个很严重的问题,特别是在多次使用MALLOC的时候,由于没有有效的边界检测,误操作很可能导致指针从第1次MALLOC分配的内存区进入第2次分配的内存区,从而引起数据的错乱而使程序崩溃

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值