就像在linux系统一样,eCos把lcd设备抽象为framebuf设备,并提供了framebuf抽象层,使得用户GUI程序不依赖于具体的frambuf设备,增加了用户GUI程序的独立性、可移植性,便于移植和使用第三方开发的GUI系统。

本章节主要介绍如何实现eCos中的LCD驱动,并展示了一个简单的测试用例。 

LCD硬件

image

如上图所示,stm32板使用FSMC来驱动LCD,16 bits数据总线,液晶屏大小:400X240,自带LCD控制器(型号为:SPFD5420A)和触摸屏(型号为:TSC2046)。

LCD驱动源码下载

【eCos组件】STM32板的eCos LCD驱动组件包

LCD驱动组成

LCD驱动主体由stm32fb.c源文件实现,整个LCD驱动主要由LCD初始化、LCD底层函数、framebuf实例、framebuf IO操作内联文件及其头文件自动生成文件等4部分组成。下面分别介绍。

LCD初始化

LCD的初始化位于stm32fb_init.cxx文件中,如下:

#include <pkgconf/devs_framebuf_stm32.h>
#include <cyg/io/framebuf.h>

extern "C" void _cyg_stm32_fb_instantiate(struct cyg_fb *);

class _stm32_fb_init {

  public:
    _stm32_fb_init(void)
    {
#ifdef CYGPKG_DEVS_FRAMEBUF_STM32_FB0
        _cyg_stm32_fb_instantiate(&cyg_stm32_fb0);
#endif
    }
};

static _stm32_fb_init _stm32_fb_init_object CYGBLD_ATTRIB_INIT_PRI(CYG_INIT_DEV_CHAR);

//-------------------------------------------------------------------------
// End of file

这里定义了一个非常简单的初始化类:_stm32_fb_init,它仅包含一个构造函数,主要启动LCD初始化的实体部分:_cyg_stm32_fb_instantiate()。

底下定义了这个类的静态对象_stm32_fb_init_object。后面有其属性:CYGBLD_ATTRIB_INIT_PRI。也就是说,eCos启动的时候,会执行这个类的构造函数,从而启动LCD的初始化。

_cyg_stm32_fb_instantiate()函数 这是LCD初始化实体部分,主要初始化FSMC的时序、FSMC所用IO的引脚配置、LCD寄存器的初始化等。 在前期调试的时候,由于没有对FSMC所用IO的引脚进行配置,导致LCD初始化失败,这点需要注意。如果初始化成功了,可以看到LCD会有反应的。LCD寄存器的初始化是直接拷贝安富莱开发板上带的例子。

LCD底层函数

LCD底层主要实现如LCD寄存器读写、LCD像素点读写、LCD坐标设定、LCD显示窗口设置等,对应stm32fb_lcd.inl源文件,它是一个内联文件。之所以用内联文件实现,这是因为不仅LCD驱动主体需要使用它,而且framebuf IO操作内联文件也需要使用这些LCD底层操作函数。

在LCD底层,定义了一个LCD结构体:

// Internal structure for the platform dependent operations
typedef struct cyg_stm32_lcd_t
{
    cyg_uint32   base;     /* base address, N/A */
    cyg_uint32   width;    /* width */
    cyg_uint32   height;   /* height */
    cyg_uint32   pwm_io;   /* IO controlling the LCD backlight */
} cyg_stm32_lcd_t;

// Declare the LCD 0 screen
externC cyg_stm32_lcd_t cyg_stm32_lcd_0;

#define CYG_PLF_FB_fb0_BASE        &cyg_stm32_lcd_0

cyg_stm32_lcd_0定义在stm32fb.c文件中,作为framebuf的私有数据。LCD初始化的时候会对这个变量进行初始化的。

注意宏:CYG_PLF_FB_fb0_BASE,它定义为cyg_stm32_lcd_0的地址。

framebuf实例:即 struct cyg_fb结构体对象

eCos中每个framebuf都对应着一个struct cyg_fb定义的对象,从另一方面说,LCD驱动的编写就是围绕这个结构体展开的,主要实现这个结构体中的相关成员函数。定义一个framebuf采用工具宏:CYG_FB_FRAMEBUFFER。

下面是本LCD驱动中framebuf的定义:

#define FB_STM32_MAKE_FN1(_fn_, _orientation_, _suffix_)  \
                    stm32_fb_ ## _fn_ ## _ ## _orientation_ ## _ ##_suffix_
#define FB_STM32_MAKE_FN( _fn_, _orientation_, _suffix_)  \
                    FB_STM32_MAKE_FN1(_fn_, _orientation_, _suffix_)

#define FB_STM32_COLOUR_FN1(_fn_, _suffix_)  cyg_fb_dev_ ## _fn_ ## _ ## _suffix_
#define FB_STM32_COLOUR_FN( _fn_, _suffix_)  FB_STM32_COLOUR_FN1(_fn_, _suffix_)

#ifdef CYGPKG_DEVS_FRAMEBUF_STM32_FB0

CYG_FB_FRAMEBUFFER(CYG_FB_fb0_STRUCT,
                    CYG_FB_fb0_DEPTH,
                    CYG_FB_fb0_FORMAT,
                    CYG_FB_fb0_WIDTH,
                    CYG_FB_fb0_HEIGHT,
                    CYG_FB_fb0_VIEWPORT_WIDTH,
                    CYG_FB_fb0_VIEWPORT_HEIGHT,
                    CYG_FB_fb0_BASE,
                    CYG_FB_fb0_STRIDE,
                    CYG_FB_fb0_FLAGS0,
                    CYG_FB_fb0_FLAGS1,
                    CYG_FB_fb0_FLAGS2,
                    CYG_FB_fb0_FLAGS3,
                    (CYG_ADDRWORD) 0,
                    (CYG_ADDRWORD) 0,
                    (CYG_ADDRWORD) 0,
                    (CYG_ADDRWORD) 0,
                    &stm32_fb_on,
                    &stm32_fb_off,
                    &stm32_fb_ioctl,
                    &cyg_fb_nop_synch,
                    &cyg_fb_nop_read_palette,
                    &cyg_fb_nop_write_palette,
      &FB_STM32_COLOUR_FN(make_colour, 16bpp_true_565),
      &FB_STM32_COLOUR_FN(break_colour, 16bpp_true_565),
      FB_STM32_MAKE_FN(write_pixel, CYG_FB_fb0_ORIENTATION, CYG_FB_fb0_DEPTH),
      FB_STM32_MAKE_FN(read_pixel,  CYG_FB_fb0_ORIENTATION, CYG_FB_fb0_DEPTH),
      FB_STM32_MAKE_FN(write_hline, CYG_FB_fb0_ORIENTATION, CYG_FB_fb0_DEPTH),
      FB_STM32_MAKE_FN(write_vline, CYG_FB_fb0_ORIENTATION, CYG_FB_fb0_DEPTH),
      FB_STM32_MAKE_FN(fill_block,  CYG_FB_fb0_ORIENTATION, CYG_FB_fb0_DEPTH),
      FB_STM32_MAKE_FN(write_block, CYG_FB_fb0_ORIENTATION, CYG_FB_fb0_DEPTH),
      FB_STM32_MAKE_FN(read_block,  CYG_FB_fb0_ORIENTATION, CYG_FB_fb0_DEPTH),
      FB_STM32_MAKE_FN(move_block,  CYG_FB_fb0_ORIENTATION, CYG_FB_fb0_DEPTH),
                    0, 0, 0, 0
    );
#endif
  • stm32_fb_on()函数:打开LCD设备,相当于open方法;
  • stm32_fb_off ()函数:关闭LCD设备,相当于close方法;
  • stm32_fb_ioctl() 函数:LCD设备的IO控制,相当于ioctl方法;

上面3个函数不难理解,可能需要关注的是上面代码中FB_STM32_MAKE_FN宏定义的部分。 实际上,这些是一些LCD基本操作的实现,比如画点、画横线、画竖线、填充块等操作,对应eCos的framebuf IO层接口,供应用程序调用。这些函数分为Landscape(宽屏)、Portrait(竖屏)2类。编译时会根据图形配置工具中LCD宽(width)、高(height)的设置自动编译链接相应类别的函数。如果你设置的是宽屏,则不会链接竖屏类别的函数。通过这种实现,提高了程序的适应性和移植性。

看下2个简单的LCD基本操作函数(分别对应画点和画横线函数):

// Landscape

void
stm32_fb_write_pixel_landscape_16(cyg_fb* fb,
                             cyg_ucount16 x, cyg_ucount16 y, cyg_fb_colour colour)
{
    stm32_fb_write_pixel_landscape_16_inl(fb->fb_base, fb->fb_stride, x, y, colour);
}

void
stm32_fb_write_hline_landscape_16(cyg_fb* fb,
                             cyg_ucount16 x, cyg_ucount16 y, cyg_ucount16 len, cyg_fb_colour colour)
{
    stm32_fb_write_hline_landscape_16_inl(fb->fb_base, fb->fb_stride, x, y, len, colour);
}

这些基本操作函数,实际上使用的是内联文件中定义的内联函数。由于篇幅限制,这部分内容详见下节 LCD驱动第4部分内容:framebuf IO操作内联文件及其头文件自动生成文件。

» 文章出处: reille博客—http://velep.com , 如果没有特别声明,文章均为reille博客原创作品
» 郑重声明: 原创作品未经允许不得转载,如需转载请联系reille#qq.com(#换成@)
分享到:

 Leave a Reply

(必须)

(我会替您保密的)(必须)

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.

   
© 2012 velep.com | reille blog | 管理| 粤ICP备15065318号-2| 谷歌地图| 百度地图| Suffusion theme|Sayontan Sinha

无觅相关文章插件,快速提升流量