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次分配的内存区,从而引起数据的错乱而使程序崩溃

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/silenceee/archive/2006/12/25/1460497.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值