S5PV210开发系列四_uCGUI的移植
S5PV210开发系列四
uCGUI的移植
象棋小子 1048272975
GUI(图形用户界面)极大地方便了非专业用户的使用,用户无需记忆大量的命令,取而代之的是能够通过窗体、菜单、按键等方式进行操作。
在某些场合,设计一款人机界面丰富友好的嵌入式产品能赢得很多其它的用户。笔者此处就S5PV210基于uCGUI图形用户界面的使用作一个简单的介绍。
1. uCGUI移植概述
1.1. S5PV210 Bootloader
笔者的S5PV210的Bootloader设置最高的CPU主频1GHZ,MMU进行1:1内存空间线性映射,并开启L1 I/D Cache、L2 Cache、硬件分支预測功能,使CPU能达到最大的吞吐量性能。初始化内存,可以识别sd/mmc启动和Nand flash启动,自己主动载入应用代码到RAM位置。统一的中断管理架构、重定向底层IO操作。支持代码直接下载内存执行以及Nandflash下载。可以更加专注于应用的开发。
1.2. uCGUI源代码
笔者以uCGUI 3.98这个版本号移植作为解说。这个版本号的uCGUI是开放源代码的最高版本号。之后版本号仅仅提供库文件,不再开源。关于uCGUI概述、使用、移植等具体内容,能够直接阅读uCGUI用户手冊。
1.3. uCGUI接口实现
uCGUI依据其使用的功能,必须先实现其对应的功能接口。对于uCGUI,显示以及时基计时这两部分是必须的。因此必须实现其接口。
显示即是实现对应的屏驱动。时基计时即是实现1ms/tick的定时计数,uCGUI用来实现时间计时。
此处还使用uCGUI触摸屏功能,因此也应实现对应的触摸屏驱动。
2. 接口移植驱动
2.1. 屏驱动
屏驱动主要提供设置某一坐标像素颜色接口Display_SetPixel 和从某一坐标读出像素颜色接口Display_GetPixel给uCGUI就可以。S5PV210具有RGB接口。因此屏驱动也主要是RGB接口的初始化。依据详细的屏,设置其水平分辩率、垂直分辩率、像素时钟、缓存位置等就可以。RGB控制器是通过DMA的方式把显存帧传输数据到外部接口。因此CPU对显存数据的更改均应写回显存所在的物理主存。不然会有Cache数据一致性的问题。
Bootloader对于Cache提供了相应的四种内存分配策略:
cached, write-back。写回模式,CPU的每次读写假设Cache命中则仅仅读写Cache,不读写主存。这样的模式不用过多地读写缓慢的主存,因此CPU具有最高的性能,默认的内存分配方式。
cached, write-through。写通模式。CPU每次读假设Cache命中则仅仅读Cache。不读主存。每次写即使Cache命中更新Cache外。还会随后写入主存,减少了系统的写速度,在Bootloader中的内存域为” .mem_cnb”。
non-cached, buffered,不可Cached,写缓存开启。CPU每次读写均不会Cache命中。CPU写数据时写入缓存后马上继续运行,缓存随后更新到主存。
未用Cache功能,CPU读写性能相对低下。在Bootloader中的内存域为” .mem_ncb”。
non-cached, non-buffered,不可Cached。未开启写缓存。
CPU每次读写均从主存读写。因为主存的缓慢。这样的模式读写性能低下。在Bootloader中的内存域为” .mem_ncnb”。
对于RGB显存,除了写回模式外,其他模式写均会更新主存,不存在显示的一致性问题。为了达到最高的CPU性能,RGB显存应分配在写通模式内存区。
//16 bit(565)
uint16_tDisplayBuffer[HSize*VSize] @ ".mem_cnb"; // cached, write through
同一时候。对于数据DMA,为保证数据一致性总是,可用最简单的方式,DMA区域内存分配到non-cached, non-buffered域,尽管牺牲性能,但没有Cache一致性问题。
uint32_tDMA_Buffer[xxx] @ ".mem_ncnb";
2.2. 触摸屏驱动
触摸屏驱动主要提供有触摸时返回触摸点X位置接口TP_GetPoint1_X和返回触摸点Y位置接口TP_GetPoint1_Y给uCGUI就可以。
笔者使用的是电容屏,一般电容屏均是使用I2C接口。因此必须先实现I2C驱动。电容屏一般支持多点触摸。但uCGUI仅仅支持单点触摸。因此电容屏中断输出配置成查询方式,通过查询中断线的电平状态来确定有无触摸事件。
int32_tTP_GetPoint1_X(void)
{
uint8_t Point1_X[2];
if (!(GPH0DAT_REG & FT5206_INT)) { // 触屏按下时。INT拉低
// 获得12位X轴坐标
TP_ReadRegs(FT5206_TOUCH1_XH, Point1_X,2);
if (!(GPH0DAT_REG & FT5206_INT)) {
//获得AD时应保持按下。不然AD值可能不准确。应丢弃
return((((int32_t)(Point1_X[0]&0xf)) << 8) | Point1_X[1]);
}
}
return -1; //返回无效值,表未按下或释放了
}
int32_tTP_GetPoint1_Y(void)
{
uint8_t Point1_Y[2];
if (!(GPH0DAT_REG & FT5206_INT)) { // 触屏按下时,INT拉低
// 获得12位Y轴坐标
TP_ReadRegs(FT5206_TOUCH1_YH, Point1_Y,2);
if (!(GPH0DAT_REG & FT5206_INT)) {
//获得AD时应保持按下,不然AD值可能不准确。应丢弃
return((((int32_t)(Point1_Y[0]&0xf)) << 8) | Point1_Y[1]);
}
}
return -1; //返回无效值,表未按下或释放了
}
int32_tTP_WriteRegs(uint8_t WriteAddr, uint8_t *pData,uint8_t Len)
{
uint8_t Packet[64];
uint8_t i;
if (Len >= sizeof(Packet)) {
return -1;
}
Packet[0] = WriteAddr;
for (i=0; i<Len; i++) {
Packet[i+1] = pData[i];
}
return I2C_WriteBytes(FT5206_ADDR, Packet,Len+1);
}
int32_tTP_ReadRegs(uint8_t ReadAddr, uint8_t *pData, uint8_t Len)
{
int32_t Ret;
// 写需读取的内部寄存器地址
Ret = I2C_WriteBytes(FT5206_ADDR,&ReadAddr, 1);
if (Ret == 0) {
return I2C_ReadBytes(FT5206_ADDR, pData,Len);
}
return Ret;
}
2.3. 定时器驱动
uCGUI通过OS_TimeMS来作为时基,因此须要一个定时器实现1ms/tick更新OS_TimeMS这个时基计数器。
此处採用S5PV210的Timer4。初始化并注冊对应的中断后。在当中断回调函数更新OS_TimeMS。同一时候处理uCGUI约100HZ频率查询触摸屏输入任务。
uint8_tTP_Period;
staticvoid Timer4_Callback(void)
{
extern volatile int OS_TimeMS;
OS_TimeMS++; // 1ms计数,在GUI_X.c中定义,用来uCGUI延时计数
#ifGUI_SUPPORT_TOUCH
TP_Period++;
if (TP_Period >= 10) { // 每隔10ms检查触摸屏输入
TP_Period = 0;
IRQ_DisableInt(INT_TIMER4); // 禁止同一中断重入
IRQ_Enable(); // 在定时器中断处理中同意I2C嵌套中断
GUI_TOUCH_Exec(); // 保证100HZ的触摸屏输入检查
IRQ_EnableInt(INT_TIMER4);
}
#endif
}
3. uCGUI改动
3.1. GUIConfig文件夹
进入GUIConfig文件夹,打开GUIConf.h对GUI进行整体的配置。因为内存充足。能够设置较大的动态内存以及支持内存设备。此处并不支持操作系统以及鼠标。改动后的内容例如以下:
#ifndef GUICONF_H
#define GUICONF_H
#define GUI_OS (0) /* 不支持多任务 */
#defineGUI_SUPPORT_TOUCH (1) /* Support a touch screen (req. win-manager)*/
#define GUI_SUPPORT_MOUSE (0) /* 不支持鼠标 */
#defineGUI_SUPPORT_UNICODE (1) /* Support mixed ASCII/UNICODE strings */
#defineGUI_DEFAULT_FONT &GUI_Font6x8
#defineGUI_ALLOC_SIZE (4*1024*1024) /* 动态内存4M*/
/*********************************************************************
*
* Configuration of available packages
*/
#defineGUI_WINSUPPORT 1 /* Window manager package available */
#defineGUI_SUPPORT_MEMDEV 1 /* Memory devices available */
#defineGUI_SUPPORT_AA 1 /* Anti aliasing available */
#endif /* Avoidmultiple inclusion */
打开LCDConf.h对LCD进行配置。笔者使用的是16位(R:5-G:6-B:5)色深800*480的RGB屏,清空LCDConf.h中的全部内容,由于这是其他LCD屏的配置,与所用屏全然不一致。改动后的内容例如以下:
#ifndef LCDCONF_H
#define LCDCONF_H
/*********************************************************************
* Generalconfiguration of LCD
**********************************************************************
*/
#define LCD_XSIZE (800) /* 屏X水平像素点 */
#define LCD_YSIZE (480) /* 屏Y水平像素点 */
#define LCD_BITSPERPIXEL (16) /* 16位色深*/
#define LCD_CONTROLLER (-1) /* 宏开关,使用LCDDriver下的模板 */
#define LCD_FIXEDPALETTE (565) /* R:5-G:6-B:5 */
#define LCD_SWAP_RB (1) /*RB颜色调换 */
#define LCD_SWAP_XY (0) /* 屏x,y方向不调换 */
#define LCD_INIT_CONTROLLER() Display_Init()/* 屏驱动初始化接口 */
#endif /* LCDCONF_H */
打开GUITouchConf.h对触摸屏进行配置,笔者使用的是电容屏,驱动IC已处理好返回的触摸坐标值与屏像素坐标一一相应,也能够在移植后进行校准。
#ifndefGUITOUCH_CONF_H
#defineGUITOUCH_CONF_H
#define GUI_TOUCH_AD_LEFT 0 /* 触摸屏能返回最左边的值 */
#defineGUI_TOUCH_AD_RIGHT 800 /* 触摸屏能返回最右边的值 */
#defineGUI_TOUCH_AD_TOP 0 /* 触摸屏能返回最上面的值 */
#defineGUI_TOUCH_AD_BOTTOM 480 /* 触摸屏能返回最以下的值 */
#defineGUI_TOUCH_SWAP_XY 0 /* 触摸屏x,y方向不调换 */
#defineGUI_TOUCH_MIRROR_X 0 /* 触摸屏x方向不镜像调换*/
#defineGUI_TOUCH_MIRROR_Y 0 /* 触摸屏y方向不镜像调换*/
#endif /*GUITOUCH_CONF_H */
3.2. LCDDriver文件夹
进入GUI->LCDDriver文件夹,需改动uCGUI关于实际LCD的底层接口调用。
因为我们在LCDConf.h里配置LCD_CONTROLLER为-1,这个宏开关会选择LCDTemplate.c这个模板文件进行编译,其他的接口文件不会被编译。LCDTemplate.c里面已经有相关的模板代码,仅仅需增加LCD_L0_SetPixelIndex()和LCD_L0_GetPixelIndex()的实现就可以,LCD_L0_SetPixelIndex设置LCD某一坐标的像素值,LCD_L0_GetPixelIndex从LCD某一坐标读出像素值,分别相应RGB屏驱动底层函数Display_SetPixel
()和Display_GetPixel()。增加这两个底层函数就可以。
LCD_L0_SetPixelIndex()改动后代码例如以下:
void LCD_L0_SetPixelIndex(int x, int y, int PixelIndex) {
GUI_USE_PARA(x);
GUI_USE_PARA(y);
GUI_USE_PARA(PixelIndex);
/* Convert logical into physicalcoordinates (Dep. on LCDConf.h) */
#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
/* Write into hardware ... Adapt toyour system */
{
Display_SetPixel(x, y, (unsignedshort)PixelIndex);
}
}
LCD_L0_GetPixelIndex()改动后的代码例如以下:
unsigned int LCD_L0_GetPixelIndex(int x, int y) {
LCD_PIXELINDEX PixelIndex;
GUI_USE_PARA(x);
GUI_USE_PARA(y);
/* Convert logical into physicalcoordinates (Dep. on LCDConf.h) */
#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 toyour system */
{
PixelIndex= (LCD_PIXELINDEX)(Display_GetPixel(x, y));
}
return PixelIndex;
}
3.3. GUI_X文件夹
GUI启动前,除了LCD可能还有其他需初始化的硬件设备,比如uCGUI要用到LCD以及触摸屏,那么在GUI使用前就应先初始化这些设备,这部分在GUI_X_Init()函数中处理。在GUI_X_Init()函数中实现例如以下:
void GUI_X_Init(void)
{
#if GUI_SUPPORT_TOUCH
TP_Init();// 使用uCGUI时先初始化触摸屏
#endif
}
GUI_X_Touch.c为uCGUI触摸屏訪问接口,仅仅要实现GUI_TOUCH_X_MeasureX()和GUI_TOUCH_X_MeasureY()就可以。这两个函数分别与电容屏驱动获得第一个触摸点x,y位置的底层函数TP_GetPoint1_X()与TP_GetPoint1_Y()相应。
int GUI_TOUCH_X_MeasureX(void) {
return TP_GetPoint1_X();
}
int GUI_TOUCH_X_MeasureY(void) {
return TP_GetPoint1_Y();
}
4. uCGUI Demo应用
应用程序中调用对应的uCGUI的例程Demo,其效果例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHVhbmcyMDA4MzIwMDA1Ng==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHVhbmcyMDA4MzIwMDA1Ng==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
5. 附录
S5PV210_uCGUI.rar,uCGUI在IAR下的移植project,包含S5PV210 Bootloader、uCGUI源代码、以及对应的RGB、TP、I2C、Timer驱动。
S5PV210开发系列四_uCGUI的移植的更多相关文章
- 转:arcgis api for js入门开发系列四地图查询
原文地址:arcgis api for js入门开发系列四地图查询 arcgis for js的地图查询方式,一般来说,总共有三种查询方式:FindTask.IdentifyTask.QueryTas ...
- S5PV210开发系列三_简易Bootloader的实现
S5PV210开发系列三 简易Bootloader的实现 象棋小子 1048272975 Bootloader是嵌入式系统上电后第一段运行的代码.对于功能简单的处理器,可能并没有Bo ...
- 【Qt编程】基于Qt的词典开发系列<四>--无边框窗口的缩放与拖动
在现在,绝大多数软件都向着简洁,时尚发展.就拿有道的单词本和我做的单词本来说,绝大多数用户肯定喜欢我所做的单词本(就单单界面,关于颜色搭配和布局问题,大家就不要在意了). 有道的单词本: 我所做的单词 ...
- BizTalk 开发系列(四十一) BizTalk 2010 BAM 安装手记
使用64位系统可以支持更大的内存,现在服务器基本上都使用64位系统.微软从Windows Server 2008 R2开始服务器版的操作系统也只支持64位了,不过对于像BizTalk这种“繁杂的东西” ...
- 微信小程序开发系列四:微信小程序之控制器的初始化逻辑
微信小程序开发系列教程 微信小程序开发系列一:微信小程序的申请和开发环境的搭建 微信小程序开发系列二:微信小程序的视图设计 微信小程序开发系列三:微信小程序的调试方法 这个教程的前两篇文章,介绍了如何 ...
- leaflet-webpack 入门开发系列四图层控件样式优化篇(附源码下载)
前言 leaflet-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 w ...
- BizTalk 开发系列(四十二) 为BizTalk应用程序打包不同的环境Binding
我们在使用微软或者其他公司提供的BizTalk应用程序MSI包的时候经常会有一个目标环境的选择选项.该选项可以在不同的环境下使用不同的绑定(BizTalk应用程序配置)感觉很高级. 其实这个非常的简单 ...
- BizTalk 开发系列(四十) BizTalk WCF-SQL Adapter读取SQL Service Broker消息
SQL Service Broker 是在SQL Server 2005中新增的功能.Service Broker 为 SQL Server 提供队列和可靠的消息传递,可以可用来建立以异步消息为基础的 ...
- BizTalk开发系列(四) 深入Map测试
在BizTalk的开发过程中XML消息间的映射是一个很重要的内容.如果只是一般的从源节点的值复制到目标节点的话,BizTalk项目提供的 MAP测试和验证就已经可以满足需求了.但是很多时候需要在映射的 ...
随机推荐
- ECshop 二次开发模板教程4
今天我们学习一下如何在首页调取某个分类的商品:注意了,这里的修改有一些麻烦了哦:首先你需要下载一套新的模板,比如blueksy 上传到模板目录 /themes/ 也就是 /themes/bluesky ...
- HDU5790 Prefix 字典树+主席树
分析:这个题和spoj的d_query是一个题,那个是求一段区间里有多少个不同的数字,这里是统计有多少个不同的前缀 用字典树进行判重,(和查询不同的数字一样)对于每个不同的前缀,只保留它最后一次出现的 ...
- OpenGL超级宝典第5版&&glProvokingVertex
翻译:https://www.opengl.org/sdk/docs/man3/xhtml/glProvokingVertex.xml 方法原型:void glProvokingVertex(GLen ...
- ios游戏开发--cocos2d学习(2)
在第一节中简单介绍了2d项目模板HelloWorld的基础代码,并做了一点小小的改变,像触摸接收.旋转.移动和颜色转变序列CCSequence的使用等等,2d本身封装好了很多方便使用的动作,只需要调用 ...
- Canvas入门(3):图像处理和绘制文字
来源:http://www.ido321.com/997.html 一.图像处理(非特别说明,所有结果均来自最新版Google) 在HTML 5中,不仅可以使用Canvas API绘制图形,也可以用于 ...
- bzoj 1576 [Usaco2009 Jan]安全路经Travel(树链剖分,线段树)
[题意] 给定一个无向图,找到1-i所有的次短路经,要求与最短路径的最后一条边不重叠. [思路] 首先用dijkstra算法构造以1为根的最短路树. 将一条无向边看作两条有向边,考察一条不在最短路树上 ...
- Mahout应用(一)
Mahout应用(一) Mahout 是应用于hadoop上的数据挖掘工具(废话不多说) 这里先简单介绍一下mahout的一般使用方法. 拿kmeans为列子 Mahout中的kmeans所需要的输入 ...
- virt viewer Usbredir USB重定向
编译virt viewer之前执行的configure命令,是没有使能usb-redir相关的功能,virt viewer是否支持usbredir是完全依赖于spice-gtk的. virt view ...
- Lua学习笔记(四):表和数组
表 在Lua中,表(table)是十分重要的一种数据结构,实际上Lua对于复杂数据类型也仅提供了表给我们,我们通过表可以实现我们需要的大部分重要的数据结构,比如数组. table类型实现了关联数组,关 ...
- SQL Delta实用案例介绍 (对应软件)
http://blog.csdn.net/hongdi/article/details/5363209