关于ucGUI+ucOS在LPC2200上的移植

时间:2021-01-05 18:00:55
 

在嵌入式系统中通常用的图形用户界面有ucGUIminiGUIQT等。

ucGUI是嵌入式应用中的图形支持系统。.它设计用于为任何使用LCD图形显示的应用提供高效的独立于处理器及LCD控制器的图形用户接口,它适用单任务或是多任务系统环境, 并适用于任意LCD控制器和CPU下任何尺寸的真实显示或虚拟显示。

要将ucGUI移植到先关的液晶屏上我们首先要了解ucGUI的层次结构以及它各个层次之间的相互调用好相互协作关系。关于GUI的文件目录以及相关GUI层次结构本文不再叙述,详细的资料可以在网上找到。本文着重介绍如何在Smart ARM2200开发平台上移植带ucOS操作系统的ucGUI

注意:在添加操作系统和GUI的时候,开始的工程模板为操作系统的模板!

1、 进行高层配置

(1)GUI配置

ucGUI目录下的config文件夹中的GUIConf.h头文件,将GUI_OS配置成1,这样GUI才能支持多任务的操作系统。由于开发板没有触摸,所以将GUI_SUPPORT_TOUCH配置为0LCDConf.h中的文件改为如下:

#define LCD_XSIZE      (240)   /* X-resolution of LCD, Logical coor. */

#define LCD_YSIZE      (320)   /* Y-resolution of LCD, Logical coor. */

#define LCD_BITSPERPIXEL (16)

#define LCD_CONTROLLER -1

#define LCD_SWAP_RB     1

GUI提供了多种液晶控制器的驱动程序,开发板的控制器多对应的启动程序并没有出现在GUI(这里BS以下ZLG,给的配套教材和开发板上TFT型号不一样!)。宏定义LCD_CONTROLLER定义为-1表示驱动程序在GUI中并没有提供,而需要用户自己来编写。如果用户采用的控制器驱动程序是GUI提供的,那么就把这个宏定义改为驱动器的型号(注意:是驱动器的型号而不是LCD的型号)LCD_SWAP_RB定义为1GUI的颜色和屏的颜色能对应(以前就是因为这个问题颜色一直有错误)LCDConf.h中其他的代码可以不需要(个人认为其他的代码是GUI为它提供的驱动程序准备的)

(2)、系统配置

config.h文件中添加GUI中所有的头文件。如果不添加的话有些定义不能使用。

2、系统总线速率的更改

由于GUI在运行的过程中采用了16位数据传输,在传输速率上有一定的要求,因此我们需要在工程模板的Startup.s文件中更改总线速率。将原初始化外部总线控制器的代码(如下)

ResetInit

;Initial extenal bus controller.

;初始化外部总线控制器,根据目标板决定配置

        LDR     R0, =PINSEL2

    IF :DEF: EN_CRP

        LDR     R1, =0x0f814910

    ELSE

        LDR     R1, =0x0f814914

    ENDIF

        STR     R1, [R0]

 

        LDR     R0, =BCFG0

        LDR     R1, =0x1000ffef

        STR     R1, [R0]

 

        LDR     R0, =BCFG1

        LDR     R1, =0x1000ffef

        STR     R1, [R0]

 

;        LDR     R0, =BCFG2

;        LDR     R1, =0x2000ffef

;        STR     R1, [R0]

 

;        LDR     R0, =BCFG3

;        LDR     R1, =0x2000ffef

;        STR     R1, [R0]

       

        BL      InitStack               ;初始化堆栈 Initialize the stack

        BL      TargetResetInit         ;目标板基本初始化 Initialize the target board

                                        ;跳转到c语言入口 Jump to the entry point of C program

        B       __main

 

改为:

ResetInit

;Initial the extenal bus controller

;初始化外部总线控制器,根据目标板决定配置

 

        LDR     R0, =PINSEL2

    IF :DEF: EN_CRP

        LDR     R1, =0x0f814910

    ELSE

        LDR     R1, =0x0f814914

    ENDIF

        STR     R1, [R0]

 

        ; 定义总线速度控制字

BCFG_DEF    EQU              0x10000400

 

IDCY             EQU              (0x00<<0)

WST1            EQU              (0x01<<5)

WST2            EQU              (0x01<<11)

BCFG3_SET   EQU              (BCFG_DEF | IDCY | WST1 | WST2)

 

 

IDCYFS         EQU              (0x01<<0)

WST1FS        EQU              (0x03<<5)

WST2FS       EQU              (0x03<<11)

BCFG_FS       EQU            (BCFG_DEF | IDCYFS | WST1FS | WST2FS)

       

 

        LDR     R0, =BCFG0

        LDR     R1, =BCFG_FS

        STR     R1, [R0]

 

        LDR     R0, =BCFG1

        LDR     R1, =BCFG_FS

        STR     R1, [R0]

 

        LDR     R0, =BCFG2

        LDR     R1, =0x1000ffef

        STR     R1, [R0]

 

        LDR     R0, =BCFG3

        LDR     R1, =BCFG3_SET

        STR     R1, [R0]

       

        BL      InitStack               ;初始化堆栈 Initialize the stack

        BL      TargetResetInit         ;目标板基本初始化 Initialize the target board

                                        ;跳转到c语言入口 Jump to the entry point of C program

        B       __main

这样就完成了总线的更改。(程序具体的含义可参照配套教材)

3、驱动程序的移植

GUI的层次调用中,所有的API函数都是最后调用了针对屏的画点函数。因此在进行驱动程序的移植的过程中只需要编写针对次液晶屏的画点和初始化函数即可(个人任务,如何大家有不同意见可以提出来)。用户自己的驱动程序在gui文件夹下的LCDDriver下的LCDDummy.c文件。在这个文件中有2个函数分别为:void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex)unsigned int LCD_L0_GetPixelIndex(int x, int y),而在这2个函数中可以分别看到

/* Write into hardware ... Adapt to your system */

 {

    /* ... */

 }

/* Read from hardware ... Adapt to your system */

 {

    PixelIndex = 0;/* ... */

 }

这段注释的意思就是要求用户添加自己的驱动程序。在下面的LCD_L0_Init函数中将LCD_INIT_CONTROLLER()改为用户自己的LCD初始化函数。

开发板上的驱动程序在配套的光盘中提供了。我们需要使用的是其中的2个函数,一个画点函数和一个初始化函数。LCD_L0_SetPixelIndexLCD_L0_GetPixelIndex以及LCD_L0_Init函数需要修改的部分如下:

void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex)

{

 #if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y

    int xPhys = LOG2PHYS_X(x, y);

    int yPhys = LOG2PHYS_Y(x, y);

 #else

    #define xPhys x

    #define yPhys y

 #endif

 GUI_Point(x, y, PixelIndex);

}

 

unsigned int LCD_L0_GetPixelIndex(int x, int y) {

 LCD_PIXELINDEX PixelIndex;

 #if LCD_SWAP_XY | LCD_MIRROR_X| LCD_MIRROR_Y

    int xPhys = LOG2PHYS_X(x, y);

    int yPhys = LOG2PHYS_Y(x, y);

 #else

    #define xPhys x

    #define yPhys y

 #endif

 /* Read from hardware ... Adapt to your system */ 

 PixelIndex = 0;

 TftSetWrite(x,y);

 PixelIndex = TftRcvDat();

 return PixelIndex;

}

int LCD_L0_Init(void) {

 TftInit();

 return 0;

}

4、时间函数的修改

从网上下载的GUI源码文件中有个Sample文件夹,在它下面有个GUI_X文件夹,在这个文件夹下有3GUI_X*文件。分别为:GUI_X.cGUI_X_embOS.cGUI_X_ucOS.c3个文件分别对应无操作系统embOSucOS。我们采用的是ucOS,所以采用第三个文件使用。这个文件内容入下:

#include "uCOS_II.h"

#include "GUI.H"

#include "stdio.H"

 

int GUI_X_GetTime(void) {

 return OSTimeGet();

}

 

void GUI_X_Delay(int Period) {

 OSTimeDly(Period);

}

 

void GUI_X_ExecIdle(void) {

 OS_X_Delay(1);

}

 

static OS_EVENT * DispSem;

 

U32 GUI_X_GetTaskId(void) { return ((U32)(OSTCBCur->OSTCBPrio)); }

void GUI_X_InitOS(void)    { DispSem = OSSemCreate(1); }

void GUI_X_Unlock(void)    { OSSemPost(DispSem); }

void GUI_X_Lock(void) {

 INT8U err;

 OSSemPend(DispSem, 0, &err);

}

 

void GUI_X_Init(void) {}

 

改为:

#include "GUI.h"

#include "GUI_X.h"

#include "config.h"

 

int GUI_X_GetTime(void) {

 return OSTimeGet();

}

 

void GUI_X_Delay(int ms) {

 OSTimeDly(ms);

}

 

void GUI_X_Init(void) {}

void GUI_X_ExecIdle(void) {}

 

void GUI_X_Log(const char *s)      {}

void GUI_X_Warn(const char *s)     {}

void GUI_X_ErrorOut(const char *s) {}

 

OS_EVENT * DispSem;

 

U32 GUI_X_GetTaskId(void) { return ((U32)(OSTCBCur->OSTCBPrio)); }

void GUI_X_InitOS(void)    { DispSem = OSSemCreate(1); }

void GUI_X_Unlock(void)    { OSSemPost(DispSem); }

void GUI_X_Lock(void) {

 INT8U err;

 OSSemPend(DispSem, 0, &err);

}

如果出现编译错误,提示说函数没有被定义,那么只需要将函数定义一个就行,写个空函数就可以。

如果在编译过程中出现错误,那么按照错误信息进行修改即可。至此,移植+操作系统以初步可用。