您的位置:首页 > 其它

Microwindows 及其 触摸屏驱动 在eCos MINI2440 上的实现

2011-04-01 23:04 489 查看

1. 修复MINI2440 QEMU的BUG

开始的我用ecos里面仅有的两个ARM下面的touch 驱动来做一个中断测试,

都快疯了,没有任何反应。
后来看到RT-Thread的例子可以正常运行,于是才想看看他们呢对MINI2440 QEMU的修改。

真的要感谢所有自由组织的无私奉献。

果然,MINI2440的QEMU采用的是S3C2410的TOUCH接口,里面关于PenDown和PenUP的寄存器位都木有。

代码已经上传到了emboslab git 库中qemu-mini2440的ecos-emboslab 分支,这里还是简要介绍一下。

--------------------------------- hw/s3c2410.c ---------------------------------

index
d1e4c92..bdf8a73 100644
@@ -1630,6 +1630,14 @@ static
void
s3c_adc_tick(void
*opaque)
qemu_mod_timer(s->tst, qemu_get_clock(vm_clock) +
(ticks_per_sec >> 5));
}
/*

这个是QEMU实现ARM中断方式的机制

可以这样理解:如果对QEMU的窗口做Penup的时候,触发一个专断给CPU。

*/

+ else

+ {

+ if
(((s->ts & 3) == 3) && (s->ts & (1<<8)) && (s->enable))

+ qemu_irq_raise(s->tcirq);

+

+
qemu_mod_timer(s->tst, qemu_get_clock(vm_clock) +

+ (ticks_per_sec >> 5));

+ }

}

static
void
s3c_adc_event(void
*opaque,
@@ -1689,7 +1697,7 @@ static
void
s3c_adc_write(void
*opaque, target_phys_addr_t addr,
break
;

case
S3C_ADCTSC:
- s->ts = value & 0xff;

+ s->ts = value & 0x1ff; /*增加了Pendown和Penup的控制位*/

break
;

case
S3C_ADCDLY:

2. 实现触摸屏驱动(尚有BUG)

目前官方的触屏驱动有两个,我们看下

ricky@ricky-laptop:ecos-emboslab$ cd
packages/devs/touch/arm/

ricky@ricky-laptop:arm$ ls

aaed2000 ipaq

如果让Microwindows支持Touch只要实现这样的一个标准的Touch驱动就可以了。

在Microwindows的部分调用这个标准的ecos字符形设备就可以了。

不过从代码看来,ecos并没有对Touch驱动有严格的API定义,所以在网上你能看到很多种实现方法。

既然Microwindows用了字符形的设备,那么我们也就按照这个架构实现一下吧。

我们先看一下ecos的字符形设备是什么样子的,具体的请看ecos的参考手册(如何生成最新的参考手册,我会在另一篇博客中讲述)

CHAR_DEVIO_TABLE(mini2440_ts_handlers,

NULL, // Unsupported write() function

ts_read,

ts_select,

ts_get_config,

ts_set_config);

CHAR_DEVTAB_ENTRY(mini2440_ts_device,

CYGDAT_DEVS_TOUCH_MINI2440_NAME, /*这个是字符形设备的描述符
,
在CDL文件中定义
"/dev/ts"
,和Linux的驱动文件很相似
*/

NULL, // Base device name

&mini2440_ts_handlers,

ts_init,

ts_lookup, /*重点看这个函数:当设备被open的时候这个callback函数会被调用*/

NULL); // Private data pointer

关于如何实现更好的touch架构,本人还在研究。

现在的方案是

在设备初始化的时候配置硬件资源和终端设置,

在设备被打开,也就是ts_lookup里面创建中断响应函数,把转化好的touch 数据放到队列中等待上层(Microwindows)

来读取。

看下初始化部分

static
bool

ts_init(struct
cyg_devtab_entry *tab)

{

cyg_uint32
_dummy;

HAL_WRITE_UINT32(ADCCON,S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(9));

HAL_WRITE_UINT32(ADCDLY,50000);

HAL_WRITE_UINT32(ADCTSC,WAIT4INT(0)); /*这里就是使能,PenDownUP终端*/

//HAL_WRITE_UINT32(INTMSK, BIT_ALLMSK);

HAL_READ_UINT32(SUBSRCPND, _dummy);

_dummy |= BIT_SUB_TC;

_dummy |= BIT_SUB_ADC;

HAL_WRITE_UINT32(SUBSRCPND, _dummy);

cyg_drv_interrupt_acknowledge(CYGNUM_HAL_INTERRUPT_ADC);

cyg_selinit(&ts_select_info);

/* install interrupt handler */

HAL_READ_UINT32(INTSUBMSK, _dummy);

_dummy &= ~BIT_SUB_ADC;

_dummy &= ~BIT_SUB_TC;

HAL_WRITE_UINT32(INTSUBMSK, _dummy);

HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_ADC);

return
true
;

}

/*设备打开函数,创建了AD
C中断的挂钩函数cyg_mini2440_ts_isr和cyg_mini2440_ts_dsr*/

if
(!_is_open) {

_is_open = true;

cyg_drv_interrupt_create(CYGNUM_HAL_INTERRUPT_ADC,

0,

(CYG_ADDRWORD)0,

cyg_mini2440_ts_isr,

cyg_mini2440_ts_dsr,

&ts_thread_handle,

&ts_thread_data);

cyg_drv_interrupt_attach(ts_thread_handle);

cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_ADC);

}

return
ENOERR;

}

罗嗦两句,ecos在创建的时候就参考了很多linux的风格,比如我们看到上面的isr和dsr很像Linux对中断处理的上半和下半。

具体的实现机理本人也在研究呢,目前位置我只是知道如何应用。

isr中希望用户能快速的响应终端,在isr结束的时候往往有下面的代码

cyg_drv_interrupt_acknowledge

(CYGNUM_HAL_INTERRUPT_ADC);

上面的这行主要是在函数返回前开启这个中断

return
CYG_ISR_HANDLED

| CYG_ISR_CALL_DSR

;

后面这个有两个含义,第一个是告诉系统这个中断我已经知道了,做了我应该做的事情。第二个含义就是红色的部分会在函数返回之后

出发这个终端的DSR处理程序。

那么这个touch驱动到底需要还是不需要DSR呢,本人下不了结论。

本人是做Linux的,知道Linux一般的input driver一般用到后半的多是处理report机制,

为了不把问题复杂化,我们现让硬件能动起来,欢迎其他人给我建议

2440的Touch中断处理暂时比较简单

if (res& (1 << 10))
/*ADC的采用的后要继续出发PenDownUP中断*/

{

//diag_printf("ADC Interrupt/n");

HAL_READ_UINT32(SUBSRCPND, reg);

reg |= BIT_SUB_ADC;

HAL_WRITE_UINT32(SUBSRCPND, reg);

x = read_ts_x();

y = read_ts_y();

lastX = x; lastY = y;

//diag_printf("X = %x, Y = %x/n", x, y);

HAL_WRITE_UINT32(ADCTSC,WAIT4INT(1));

}

if (res& (1 << 9)){
/*PenDownUp中断记录Touch的按下和抬起,同时出发ADC的采样*/

//diag_printf("TS Interrupt/n");

HAL_READ_UINT32(SUBSRCPND, reg);

reg |= BIT_SUB_TC;

HAL_WRITE_UINT32(SUBSRCPND, reg);

HAL_READ_UINT32(ADCDAT0, data0);

HAL_READ_UINT32(ADCDAT1, data1);

updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));

if(updown)

{

x = read_ts_x();

y = read_ts_y();

//diag_printf("X = %x, Y = %x/n", x, y);

//diag_printf("pen_down#######################################################################/n");

if ((x < X_THRESHOLD) || (y < Y_THRESHOLD)) {

// Ignore 'bad' samples

}

lastX = x; lastY = y;

HAL_WRITE_UINT32(ADCTSC, S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST);

HAL_READ_UINT32(ADCCON, reg);

reg |= S3C2410_ADCCON_ENABLE_START;

HAL_WRITE_UINT32(ADCCON, reg);

pen_down = true;

}

else

{

x = lastX;

y = lastY;

HAL_WRITE_UINT32(ADCTSC,WAIT4INT(0));

pen_down = false;

//diag_printf("pen_up#######################################################################/n");

}

}

/*把合理的数据处理后放入一个events数组中,等待上层来读取*/

if (num_events < MAX_EVENTS) {

num_events++;

ev = &_events[_event_put++];

if (_event_put == MAX_EVENTS) {

_event_put = 0;

}

ev->button_state = pen_down ? 0x04 : 0x00;

ev->xPos = x;

ev->yPos = y;

if (ts_select_active) {

ts_select_active = false;

cyg_selwakeup(&ts_select_info);

}

}

3. 修正eCos自带Microwindows的ecos_app错误

目前发现的一个问题是,ecos之前曾经采纳了一个牛的patch,他应用HAL_TABLE实现了基于Microwindows的APP定义方式。

很巧妙,那么什么是HAL_TABLE呢,我们可以理解为为了实现更好的表的管理的一种机制,可以把我们要存放的表通过宏

放到内存中的某个位置,大家可以在google上找一下,ecos在这个部分应用还是比较有特点的。

尤其是在二维表的处理上有很多特别的应用,redboot的一些命令就是例子

ecos_mw_app.h

typedef void fun(CYG_ADDRWORD);

typedef struct _mw_app_entry {

char *name;

fun *entry;

int prio;

fun *init;

cyg_handle_t t;

cyg_thread t_obj;

char stack[STACKSIZE];

} CYG_HAL_TABLE_TYPE _mw_app_entry_t;

#define _mw_app(_name_,_id_,_pri_,_init_) /

externC void _id_##_thread(CYG_ADDRWORD data); /

_mw_app_entry_t _mw_app_##_pri_##_##_id_ /

CYG_HAL_TABLE_QUALIFIED_ENTRY(_mw_apps,_pri_) = /

{ _name_, _id_##_thread, _pri_, _init_};

#define ECOS_MW_STARTUP_PRIORITY 11

#define ECOS_MW_NANOX_PRIORITY (ECOS_MW_STARTUP_PRIORITY+1)

#define ECOS_MW_KND_PRIORITY (ECOS_MW_STARTUP_PRIORITY+2)

#define ECOS_MW_NANOWM_PRIORITY (ECOS_MW_STARTUP_PRIORITY+4)

#define ECOS_MW_APP_PRIORITY (ECOS_MW_STARTUP_PRIORITY+5)

ecos_app.c

CYG_HAL_TABLE_BEGIN( __MW_APP_TAB__, _mw_apps );

CYG_HAL_TABLE_END( __MW_APP_TAB_END__, _mw_apps );

extern struct _mw_app_entry __MW_APP_TAB__[], __MW_APP_TAB_END__;

为什么提到这个呢,到目前位置我不能十分的确定是这个机制有问题还是QEMU本身对于内存管理的问题。

如果我在Microwindows访问我的设备文件,就是open我们之前创建的/dev/ts这个时候貌似用HAL_TABLE存放的UI线程信息就读不到了。

如果可以打message,可以看到不能创建我们要的Microwindows的一些线程,当然也就不能看到画面了。

比较简单的做法就是参考ecos之前的代码,或者干脆去看官方Microwindows的代码,用一个数组去存放线程信息。

struct
nx_thread _threads[] = {

{ "System startup", startup_thread, 11 },

{ "Nano-X server", nanox_thread, 12 },

{ "Nano-WM", nanowm_thread, 14 },

/*{ "Nano-KBD", nxkbd_thread, 13 },*/

#ifdef
USE_NXSCRIBBLE

{ "Scribble", nxscribble_thread, 20 },

#endif

#ifdef
USE_LANDMINE

{ "Landmine", landmine_thread, 19 },

#endif

#ifdef
USE_NTETRIS

{ "Nano-Tetris", ntetris_thread, 18 },

#
endif

#ifdef
USE_WORLD

{ "World Map", world_thread, 21 },

#endif

{ "demo", demo_thread, 22 },

};

接下来你就看到Microwindows了,进入下一个环节。

4. Show 图咯

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: