Windows CE S3C2440A显示驱动编码分析

在Windows CE下显示驱动是一个比较复杂的驱动,不仅仅设计到硬件的操作,还有上层驱动的GDI接口支持,有时候还需要支持DirectDraw等绘图接口。如果所有的编码工作都重新做一遍的话,难度还是挺大的,庆幸的是微软已经把大部分的接口都提供好了,DDI中包含的20个接口函数(以函数指针的方式表示),需要我们实现的也仅仅只有GPEEnableDriver。闲话不多说,我们先来看看S3C2440A_LCD_REG结构体吧,如下所示;

typedef struct {

    UINT32 LCDCON1;             // 0x00

    UINT32 LCDCON2;             // 0x04

    UINT32 LCDCON3;             // 0x08

    UINT32 LCDCON4;             // 0x0C

    UINT32 LCDCON5;             // 0x10

    UINT32 LCDSADDR1;           // 0x14

    UINT32 LCDSADDR2;           // 0x18

    UINT32 LCDSADDR3;           // 0x1C

    UINT32 REDLUT;              // 0x20

    UINT32 GREENLUT;            // 0x24

    UINT32 BLUELUT;             // 0x28

    UINT32 PAD[8];              // 0x2C - 0x48

    UINT32 DITHMODE;            // 0x4C

    UINT32 TPAL;                // 0x50

    UINT32 LCDINTPND;           // 0x54

    UINT32 LCDSRCPND;           // 0x58

    UINT32 LCDINTMSK;           // 0x5C  

    UINT32 TCONSEL;             // 0x60

} S3C2440A_LCD_REG, *PS3C2440A_LCD_REG;

其中这里面的成员分别对应着LCD控制器中的相关的寄存器,一旦映射成功就可以对这些寄存器进行直接性质的操作了。先来看看Eboot是如何对其进行初始化操作的,如下代码;

static void InitDisplay(void)

{

     volatile S3C2440A_IOPORT_REG *s2440IOP = (S3C2440A_IOPORT_REG *)OALPAtoVA(S3C2440A_BASE_REG_PA_IOPORT, FALSE);

     volatile S3C2440A_LCD_REG    *s2440LCD = (S3C2440A_LCD_REG *)OALPAtoVA(S3C2440A_BASE_REG_PA_LCD, FALSE);

     // Set up the LCD controller registers to display a power-on bitmap image.

     s2440IOP->GPCUP     = 0xFFFFFFFF;

     s2440IOP->GPCCON    = 0xAAAAAAAA;

     s2440IOP->GPDUP     = 0xFFFFFFFF;

     s2440IOP->GPDCON    = 0xAAAAAAAA;

     s2440IOP->GPGCON &= ~(3 << 8);                     // Set LCD_PWREN as output

     s2440IOP->GPGCON |=  (1 << 8);

     s2440IOP->GPGDAT |=  (1 << 4);                     // LCD3V3 ON

     //clkval_calc = (WORD)((float)(S3C2440A_HCLK)/(2.0*5000000)+0.5)-1;

     s2440LCD->LCDCON1   =  (CLKVAL_TFT   <<  8) |/* VCLK = HCLK /((CLKVAL + 1) * 2) -> About7Mhz  */

(LCD_MVAL_USED     <<  7) |     /* 0 : Each Frame              */

(3                 <<  5) |     /* TFT LCD Pannel               */

(12                <<  1) |     /* 16bpp Mode                 */

(0                 <<  0) ;     /* Disable LCD Output          */

     s2440LCD->LCDCON2   =  (LCD_VBPD << 24) |      /* VBPD          :   1                     */

                   (LCD_LINEVAL_TFT   << 14) |      /* Vertical Size : 320 - 1                 */

                   (LCD_VFPD          <<  6) |      /* VFPD          :   2                     */

                   (LCD_VSPW          <<  0) ;      /* VSPW          :   1                     */

     s2440LCD->LCDCON3   =  (LCD_HBPD << 19) |      /* HBPD          :   6                     */

                   (LCD_HOZVAL_TFT    <<  8) |      /* HOZVAL_TFT    : 240 - 1                 */

                   (LCD_HFPD              <<  0) ; /* HFPD          :   2                     */

     s2440LCD->LCDCON4   =  (LCD_MVAL <<  8) |      /* MVAL          :  13                     */

                   (LCD_HSPW              <<  0) ;      /* HSPW     :   4                      */

     s2440LCD->LCDCON5   =  (0            << 12) |      /* BPP24BL  : LSB valid                */

                   (1                     << 11) |      /* FRM565 MODE   : 5:6:5 Format           */

                   (0                     << 10) |      /* INVVCLK   : VCLK Falling Edge         */

                   (1                          <<  9) | /* INVVLINE:Inverted Polarity           */

                   (1                          <<  8) | /* INVVFRAME : Inverted Polarity        */

                   (0                          <<  7) | /* INVVD     : Normal                  */

                   (0                          <<  6) | /* INVVDEN   : Normal                   */

                   (0                          <<  5) | /* INVPWREN   : Normal                  */

                   (0                          <<  4) | /* INVENDLINE  : Normal               */

                   (1                          <<  3) | /* PWREN     : Disable PWREN            */

                   (0                          <<  2) | /* ENLEND: Disable LEND signal         */

                   (0                          <<  1) | /* BSWP     : Swap Disable            */

                   (1                          <<  0) ; /* HWSWP   : Swap Enable              */

     s2440LCD->LCDSADDR1 = ((IMAGE_FRAMEBUFFER_DMA_BASE_eboot >> 22)     << 21) |

                          ((M5D(IMAGE_FRAMEBUFFER_DMA_BASE_eboot >> 1)) <<  0);

     s2440LCD->LCDSADDR2 = M5D((IMAGE_FRAMEBUFFER_DMA_BASE_eboot + (LCD_XSIZE_TFT * LCD_YSIZE_TFT * 2)) >> 1);

     s2440LCD->LCDSADDR3 = (((LCD_XSIZE_TFT - LCD_XSIZE_TFT) / 1) << 11) | (LCD_XSIZE_TFT / 1);       

     //s2440LCD->TCONSEL   |= 0x3;

     s2440LCD->TCONSEL   &= (~7);

     //s2440LCD->TCONSEL   |= (0x1<<4);

     s2440LCD->TPAL      = 0x0;       

     s2440LCD->LCDCON1  |= 1;

     // Display a bitmap image on the LCD...

     //memcpy((void *)IMAGE_FRAMEBUFFER_UA_BASE, ScreenBitmap, LCD_ARRAY_SIZE_TFT_16BIT);

     memset((void *)IMAGE_FRAMEBUFFER_UA_BASE_eboot, 0xef, LCD_ARRAY_SIZE_TFT_16BIT);

}

上面的代码已经注释的很清楚,其中IMAGE_FRAMEBUFFER_UA_BASE_eboot指向的是显示屏幕的内存区域,其中主要可以装载RGB256 4MB的图片数据;OALPAtoVA函数的作用是将物理地址转化为虚拟地址,物理地址和虚拟地址的映射表可以在oemaddrtab_cfg.inc文件中可以看到,对应的数组为g_oalAddressTable二维数组。

然而驱动模式下的内存映射API和Eboot完全不同,正如前几节中介绍,驱动的内存映射方式常采用VirtualAlloc、VirtualCopy等函数,如下代码;

v_s2440CLKPWR = (volatile S3C2440A_CLKPWR_REG *)VirtualAlloc(0, sizeof(S3C2440A_CLKPWR_REG), MEM_RESERVE, PAGE_NOACCESS);

VirtualCopy((PVOID)v_s2440CLKPWR, (PVOID)(S3C2440A_BASE_REG_PA_CLOCK_POWER>>8), sizeof(S3C2440A_CLKPWR_REG), PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL ))

vm_pIOPreg = (volatile S3C2440A_IOPORT_REG *)VirtualAlloc(0, sizeof(S3C2440A_IOPORT_REG), MEM_RESERVE, PAGE_NOACCESS);

VirtualCopy((PVOID)vm_pIOPreg, (PVOID)(S3C2440A_BASE_REG_PA_IOPORT >> 8), sizeof(S3C2440A_IOPORT_REG), PAGE_PHYSICAL | PAGE_READWRITE | PAGE_NOCACHE))

CursorOn操作

   显示的操作对于上层应用来说,通过微软的封装GDI接口可以实现各种各样的图形绘制,包括简单的线、点、矩形等操作,然而对于系统来说就比较简单了,其中只需要实现最基本的点操作,线操作即可,当然需要复杂的操作还可以扩展。如下介绍CursorOn的操作,这个函数主要实现对鼠标类型的各个操作绘制,相反的还有CursorOff函数操作,如下代码;

if (!m_CursorForcedOff && !m_CursorDisabled && !m_CursorVisible)

     {

         RECTL cursorRectSave = m_CursorRect;

         int   iRotate;

         RotateRectl(&m_CursorRect);

         for (y = m_CursorRect.top; y < m_CursorRect.bottom; y++){

              if (y < 0){

                   continue;

              }

              if (y >= m_nScreenHeightSave){

                   break;

              }

              ptrLine = &ptrScreen[y * m_pPrimarySurface->Stride()];

              cbsLine = &m_CursorBackingStore[(y - m_CursorRect.top) * (m_CursorSize.x * (m_colorDepth >> 3))];

              for (x = m_CursorRect.left; x < m_CursorRect.right; x++){

                   if (x < 0){

                       continue;

                   }

                   if (x >= m_nScreenWidthSave){

                       break;

                   }

                   // x' = x - m_CursorRect.left; y' = y - m_CursorRect.top;

                   // Width = m_CursorSize.x;   Height = m_CursorSize.y;

                   switch (m_iRotate){

                       case DMDO_0:

                            iRotate = (y - m_CursorRect.top)*m_CursorSize.x + x - m_CursorRect.left;

                            break;

                       case DMDO_90:

iRotate = (x - m_CursorRect.left)*m_CursorSize.x + m_CursorSize.y - 1 - (y - m_CursorRect.top);  

                            break;

                       case DMDO_180:

iRotate = (m_CursorSize.y - 1 - (y - m_CursorRect.top))*m_CursorSize.x + m_CursorSize.x - 1 - (x - m_CursorRect.left);

                            break;

                       case DMDO_270:

iRotate = (m_CursorSize.x -1 - (x - m_CursorRect.left))*m_CursorSize.x + y - m_CursorRect.top;

                            break;

                       default:

iRotate = (y - m_CursorRect.top)*m_CursorSize.x + x - m_CursorRect.left;

                            break;

                   }

cbsLine[(x - m_CursorRect.left) * (m_colorDepth >> 3)] = ptrLine[x * (m_colorDepth >> 3)];

                   ptrLine[x * (m_colorDepth >> 3)] &= m_CursorAndShape[iRotate];

                   ptrLine[x * (m_colorDepth >> 3)] ^= m_CursorXorShape[iRotate];

                   if (m_colorDepth > 8)

                   {

cbsLine[(x - m_CursorRect.left) * (m_colorDepth >> 3) + 1] = ptrLine[x * (m_colorDepth >> 3) + 1];

                       ptrLine[x * (m_colorDepth >> 3) + 1] &= m_CursorAndShape[iRotate];

                       ptrLine[x * (m_colorDepth >> 3) + 1] ^= m_CursorXorShape[iRotate];

                       if (m_colorDepth > 16)

                       {

cbsLine[(x - m_CursorRect.left) * (m_colorDepth >> 3) + 2] = ptrLine[x * (m_colorDepth >> 3) + 2];

                            ptrLine[x * (m_colorDepth >> 3) + 2] &= m_CursorAndShape[iRotate];

                            ptrLine[x * (m_colorDepth >> 3) + 2] ^= m_CursorXorShape[iRotate];

                       }

                   }

              }

         }

         m_CursorRect = cursorRectSave;

         m_CursorVisible = TRUE;

     }

    其他还有如电源操作(需要初始化话屏幕,其原理有点像Windows XP的驱动开发模式),绘制各种图形操作等,显示的编码与硬件操作的这块不是很难,只需要继承DDGPE,实现相应的虚拟函数即可,可以说这也是C++高妙之处。随后几节将介绍DDGPE的实现;   

时间: 2024-11-29 04:56:53

Windows CE S3C2440A显示驱动编码分析的相关文章

Windows CE S3C440A LED驱动编码分析

      基于TQ2440硬件平台,该平台处理器S3C2440A,在这个平台当中存在四个LED,用于测试,显示其他硬件运行情况等.LED驱动是一个典型的I/O驱动,简单但健全,是学习Windows CE嵌入式平台的典型例子.首先我们来看看这个平台这这部分电路图吧!           这四个LED分别加了1K偶的电阻,另一端接3.3V电压,接下来看看核心板的接口.       从这里可以看住,这四个LED分别由GPB5.GPB6.GPB7和GPB8控制,都处于B组GPIO口.接下来介绍具体的编

Windows CE S3C2440A开机启动滚动条编码分析

    和Windows XP一样,Windows CE任然可以绘制美妙的进度条,其实这个操作过程主要是对屏幕缓存进行操作.在S3C2440 CPU BSP代码中已经给出了这段缓冲的地址即IMAGE_FRAMEBUFFER_UA_BASE_eboot,这段缓冲支持的视频编码格式是RGB16,默认颜色为白色,在这个过程当中,并不像EVC一样提供了很多GDI绘图的函数,如绘制线条.矩形等,所有的操作都是从点开始的,由点绘制成线,由线绘制成矩形.可以发现,整个缓冲可以定义为一个二唯数据,每一个元素就是

Windows CE6.0 S3C2440A IIC驱动编码解析

S3C2440A RISC微处理器可以支持多主设备IIC总线串行接口.专用串行总线(SDA)和串行时钟线(SCL)承载总线主机设备和连接IIC总线的外围设备之间的信息.SDA和SCL线都是双向的.本章采用TQ2440开发板进行分析,我们先来看看其硬件电路图: 从这里可以看的出 TQ2440 采用的是AT24C02A IIC器件,其中I2CSCL和I2CSDA分别表示时钟线和数据线.接下来看看IIC寄存器的相关结构体: typedef struct _I2C_CONTEXT {     DWORD

Mac安装Windows会因显示驱动升级黑屏?

尽管Mac与Windows兼容已经很多年了,但有些该出现的问题还是要出现的. Mac 使用双系统并不是什么新鲜事儿.实际上,如果 Mac 不能安装 Windows 系统,其用户基数势必会受到影响.也许当初乔布斯也是看中了这一点,所以 Mac 才可以通过 Bootcamp 工具安装 Windows 系统,并保持至今.虽然这些年过得还算平稳,但 Mac 安装 Windows 时仍难免会不时出现一些小问题. 比如我们最近遇到的这个.威锋网通过论坛以及其它社交平台了解到,近段时间有不少用户反映,他们的

Windows CE S3C2440A下按键驱动程序编码分析

    这些程序基于TQ2440平台,主要是实现键盘按键的运作,方便起见,只实现了上下左右四个按键.该部分硬件结构图如下:          从硬件图可以看出,按键连接EINT1.EINT2.EINT4和EINT0四个中断引脚.在WindowsCE中,我们只需要处理好这四个中断即可,如下详细介绍:     从这幅图中可以看出,EINT0~4的是由GPF0~4控制的,因此在驱动之前需要先配置这四个GPIO口,使其下降延触发,如下代码: v_pIOPregs->GPFCON  &= ~(0x3

Windows CE嵌入式导航系统研究(内核相关)

1.1 嵌入式车载导航系统的软件设计流程 嵌入式车载系统软件主要包括系统内核.驱动程序.应用程序三部分.设计的过程当中,我们采用瀑布模型进行设计,首先制定Windows CE5.0系统内核,再次编写相关设备驱动,最后编写或移植应用程序. 制定内核时,我们采用SunSaung2440 BSP(板级支持包)进行制定,同时提交组建保证系统支持网络通讯.文件系统.CAB包安装.汉语支持等功能.不仅如此,为方便系统应用程序开发,内核制定之后,我们发布相应的SDK. 图 5.1 软件设计流程 1.2 Win

基于S3C2410的Windows CE 5.0 BSP移植

基于S3C2410的Windows CE 5.0 BSP移植 摘要  嵌入式开发中一个重要的环节是板级支持包(BSP)的开发,实际开发过程更倾向于移植BSP而不是重新开发BSP.本文先介绍了samsung公司的S3C2410微处理器和嵌入式操作系统Windows CE 5.0 特性,分析BSP结构,在此基础上,通过bootloader, OAL, 触摸屏驱动的移植来具体探讨BSP移植过程.   1 引言 在当今后PC时代,嵌入式系统应用得越来越广泛,嵌入式产品充斥着许多领域,日常生活的手机,MP

Windows CE环境下无线网卡的自动安装

摘要:讨论了Windows CE环境下无线网卡的安装,并提出了一种在系统断电重启时自动安装无线网卡的解决方案.对Windows CE的系统定制.应用程序的开发及系统封装进行了介绍. 关键词:嵌入式系统 Windows CE 无线网卡 设备驱动 Windows CE是为多种嵌入式系统和产品而设计的紧凑.高效.可升级的操作系统,并特别为有限的硬件资源设计了多线程.多任务和完全优先的操作系统环境.在无线通信领域有很大的应用前景. 本文重点讨论了Windows CE环境下无线网卡的安装,并提出了一种在系

[转]“我再也不用Windows CE或者嵌入式Windows XP了”

  "我再也不用Windows CE或者嵌入式Windows XP了" 原文:http://www.windowsembedded.com.cn/about_windows_embedded_1.asp 编者注: 指出常见的开发者为何使用嵌入式Windows的原因 摘录自Mike Hall的blog, 列举了他经常听到"我再也不用Windows CE或者嵌入式Windows XP了",奇怪吗?那么为何我将不会再使用Windows CE或者嵌入式Windows XP呢