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

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 图咯

Microwindows 及其 触摸屏驱动 在eCos MINI2440 上的实现_第1张图片

你可能感兴趣的:(thread,linux,struct,table,终端,events)