S3C2440 触摸屏驱动(针对Android版)

发布者:lambda21最新更新时间:2024-06-13 来源: elecfans关键字:S3C2440  触摸屏驱动  Android版 手机看文章 扫描二维码
随时随地手机看文章

和原来的触摸屏驱动区别不是很大,增加了report函数来将事件发送到应用层

驱动结构:

很简单的字符设备+平台设备驱动,总的结构来说,主要四个部分构成:

probe

remove

resume

suspend

工作机制则是注册设备,然后发生ts按下事件后产生ts中断以及adc中断,获得按下坐标。

没有读写函数,重点就是在两个中断处理函数上。

1,平台设备架构部分分析:

probe函数:

流程:ts基址的重映射->获得并启动时钟->ADCCON、ADCDLY、ADCTSC的初始化->初始化input设备完善ts结构体->建立ts_filter_chain->申请中断->注册input设备(2.6.27后为event0不再是ts0)。


static int __init s3c2410ts_probe(struct platform_device *pdev)
{
    int rc;
    struct s3c2410_ts_mach_info *info;
    struct input_dev *input_dev;
    int ret = 0;

    dev_info(&pdev->dev, 'Startingn');

    info = (struct s3c2410_ts_mach_info *)pdev->dev.platform_data;//获得平台设备数据


    if (!info)
    {
        dev_err(&pdev->dev, 'Hm... too bad: no platform data for tsn');
        return -EINVAL;
    }

#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
    printk(DEBUG_LVL 'Entering s3c2410ts_initn');
#endif

    adc_clock = clk_get(NULL, 'adc');
    if (!adc_clock) {
        dev_err(&pdev->dev, 'failed to get adc clock sourcen');
        return -ENOENT;
    }
    clk_enable(adc_clock);

#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
    printk(DEBUG_LVL 'got and enabled clockn');
#endif

    base_addr = ioremap(S3C2410_PA_ADC,0x20);//将PA_ADC寄存器重映射到内存上

    if (base_addr == NULL) {
        dev_err(&pdev->dev, 'Failed to remap register blockn');
        ret = -ENOMEM;
        goto bail0;
    }


    /* If we acutally are a S3C2410: Configure GPIOs */
    if (!strcmp(pdev->name, 's3c2410-ts'))
        s3c2410_ts_connect();//初始化相关gpio口


    if ((info->presc & 0xff) > 0)
        writel(S3C2410_ADCCON_PRSCEN |
         S3C2410_ADCCON_PRSCVL(info->presc&0xFF),
                         base_addr + S3C2410_ADCCON);
    else
        writel(0, base_addr+S3C2410_ADCCON);

    /* Initialise registers */
    if ((info->delay & 0xffff) > 0)
        writel(info->delay & 0xffff, base_addr + S3C2410_ADCDLY);

    writel(WAIT4INT(0), base_addr + S3C2410_ADCTSC);

    /* Initialise input stuff */
    memset(&ts, 0, sizeof(struct s3c2410ts));
    input_dev = input_allocate_device();

    if (!input_dev) {
        dev_err(&pdev->dev, 'Unable to allocate the input devicen');
        ret = -ENOMEM;
        goto bail1;
    }

//初始化input设备

    ts.dev = input_dev;
    ts.dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) |
             BIT_MASK(EV_ABS);
    ts.dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
    input_set_abs_params(ts.dev, ABS_X, 0, 0x3FF, 0, 0);
    input_set_abs_params(ts.dev, ABS_Y, 0, 0x3FF, 0, 0);
    input_set_abs_params(ts.dev, ABS_PRESSURE, 0, 1, 0, 0);

    ts.dev->name = s3c2410ts_name;
    ts.dev->id.bustype = BUS_RS232;
    ts.dev->id.vendor = 0xDEAD;
    ts.dev->id.product = 0xBEEF;
    ts.dev->id.version = S3C2410TSVERSION;
    ts.state = TS_STATE_STANDBY;//设置ts状态为就绪

    ts.event_fifo = kfifo_alloc(TS_EVENT_FIFO_SIZE, GFP_KERNEL, NULL);//为event队列申请内存空间

    if (IS_ERR(ts.event_fifo)) {
        ret = -EIO;
        goto bail2;
    }

    /* create the filter chain set up for the 2 coordinates we produce */
    ts.chain = ts_filter_chain_create(pdev, info->filter_config, 2);//针对Android的,建立filter_chain


    if (IS_ERR(ts.chain))
        goto bail2;

    ts_filter_chain_clear(ts.chain);

    /* Get irqs */
    if (request_irq(IRQ_ADC, stylus_action, IRQF_SAMPLE_RANDOM,
                         's3c2410_action', ts.dev)) {
        dev_err(&pdev->dev, 'Could not allocate ts IRQ_ADC !n');
        iounmap(base_addr);
        ret = -EIO;
        goto bail3;
    }
    if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM,
            's3c2410_action', ts.dev)) {
        dev_err(&pdev->dev, 'Could not allocate ts IRQ_TC !n');
        free_irq(IRQ_ADC, ts.dev);
        iounmap(base_addr);
        ret = -EIO;
        goto bail4;
    }

    dev_info(&pdev->dev, 'Successfully loadedn');

    /* All went ok, so register to the input system */
    rc = input_register_device(ts.dev);
    if (rc) {
        ret = -EIO;
        goto bail5;
    }

    return 0;

bail5:
    free_irq(IRQ_TC, ts.dev);
    free_irq(IRQ_ADC, ts.dev);
    clk_disable(adc_clock);
    iounmap(base_addr);
    disable_irq(IRQ_TC);
bail4:
    disable_irq(IRQ_ADC);
bail3:
    ts_filter_chain_destroy(ts.chain);
    kfifo_free(ts.event_fifo);
bail2:
    input_unregister_device(ts.dev);
bail1:
    iounmap(base_addr);
bail0:

    return ret;
}


remove:
就是probe的逆运算,

static int s3c2410ts_remove(struct platform_device *pdev)
{
    disable_irq(IRQ_ADC);
    disable_irq(IRQ_TC);
    free_irq(IRQ_TC,ts.dev);
    free_irq(IRQ_ADC,ts.dev);

    if (adc_clock) {
        clk_disable(adc_clock);
        clk_put(adc_clock);
        adc_clock = NULL;
    }

    input_unregister_device(ts.dev);
    iounmap(base_addr);

    ts_filter_chain_destroy(ts.chain);

    kfifo_free(ts.event_fifo);

    return 0;
}


resume与suspend函数可有可无,完成触摸屏的激活和挂起,

2,中断处理分析:

三种模式转换过程:等待down中断模式->x,y连续坐标转换模式->等待up中断模式->等待down中断模式->..
两个中断的发生:触摸屏按下,发生ts中断,开始ad转换,ad转换结束,发生adc中断。
              触摸屏抬起,发生ts中断。
ts中断处理函数:

//判断ts中断是up还是down

static irqreturn_t stylus_updown(int irq, void *dev_id)
{
    unsigned long data0;
    unsigned long data1;
    int event_type;

    data0 = readl(base_addr+S3C2410_ADCDAT0);
    data1 = readl(base_addr+S3C2410_ADCDAT1);

    ts.is_down = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) &&
                     (!(data1 & S3C2410_ADCDAT0_UPDOWN));

    event_type = ts.is_down ? 'D' : 'U';

    if (unlikely(__kfifo_put(ts.event_fifo, (unsigned char *)&event_type,
         sizeof(int)) != sizeof(int))) /* should not happen */
        printk(KERN_ERR __FILE__': stylus_updown lost event!n');

    if (ts.is_down)
        s3c2410_ts_start_adc_conversion();//down

    else
        writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);//up


    mod_timer(&event_send_timer, jiffies + 1);//延时


    return IRQ_HANDLED;
}

[1] [2]
关键字:S3C2440  触摸屏驱动  Android版 引用地址:S3C2440 触摸屏驱动(针对Android版)

上一篇:S3C2440 UDA1341声卡驱动分析(oos)
下一篇:S3C2440 rtc 平台设备驱动 卸载问题 oops

推荐阅读最新更新时间:2024-11-07 07:23

s3c2440串口使用
一、串口通信原理 UART:Universal Asynchronous Receiver/Transmitter(通用异步收发送器),用来传输串行数据,发送数据时,CPU将并行数据写入UART,UART按照一定格式在TxD线上串行发出;接收数据时,UART检测到RxD线上的信号,将串行收集放到缓冲区中,CPU即可读取UART获得的这些数据。 UART最精简的连线形式只有3根线,TXD用于发送,RXD用于接收,GND用于提供参考电平。UART之间以帧作为数据传输单位,帧由具有完整意义的若干位组成,它包含开始位、数据位、校验位和停止位。发送数据之前,互相通信的UART之间要约定好数据传输速率(波特率的倒数)、数据的传输格式(
[单片机]
<font color='red'>s3c2440</font>串口使用
S3C2440 初始化时钟
一、S3C2440 时钟 1、时钟树 从s3c2440的技术手册的时钟树可以了解到,它的时钟分四大块FCLK,HCLK,PCLK,UCLK。FCLK主要用于CPU的运行时钟,HCLK主要用于内存控制器,中断控制器等一些高速设备的时钟,PCLK主要用于GPIO控制器,I2C控制器等一些较低速设备的时钟,UCLK主要给USB控制器提供时钟的。时钟树如下图: 2、S3C2440支持的时钟速率 1、S3C2440的最高速率:FCLK最高支持400MHz,HCLK最高支持136MHz,PCLK最高支持68MHz。 2、在本实验将 FCLK设置为400MHz,HCLK设置为100MHz,PCLK设置为50MHz。 二、设
[单片机]
<font color='red'>S3C2440</font> 初始化时钟
s3c2440_LCD控制器设置及代码详解
1. LCD工作的硬件需求: 要使一块LCD正常的显示文字或图像,不仅需要LCD驱动器,而且还需要相应的LCD控制器。在通常情况下,生产厂商把LCD驱动器会以COF/COG的 形式与LCD玻璃基板制作在一起,而LCD控制器则是由外部的电路来实现,现在很多的MCU内部都集成了LCD控制器,如S3C2410/2440等。通 过LCD控制器就可以产生LCD驱动器所需要的控制信号来控制STN/TFT屏了。 2. S3C2440内部LCD控制器结构图: 我们根据数据手册来描述一下这个集成在S3C2440内部的LCD控制器: a:LCD控制器由REGBANK、LCDCDMA、TIMEGEN、VIDPRCS寄存器组成; b:REGBAN
[单片机]
s3c2440_LCD控制器设置及代码详解
S3C2440 DMA 驱动示例
将 DMA 抽象为一个字符设备,在初始化函数中调用 void *dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp) 函数来分配两段物理地址连续的空间,一段作为源空间,一段作为目的空间。 然后将物理地址进行 ioremap 供驱动使用,最后调用 register_chrdev 来注册这个字符设备。 DMA 的 regs: #define DMA0_BASE_ADDR 0x4B000000 #define DMA1_BASE_ADDR 0x4B000040 #define DMA2_
[单片机]
S3C2440 存储器控制器分析
首先说一下,S3C2440 存储器空间并不包括NAND FLASH ,NAND FLASH只是一个外设而已。 S3C2440存储器控制器的寻址范围是0~0x3fff ffff,共1G。这1G空间分为8个BANK,BANK0~BANK7。 在产品开发阶段,一般使用BANK0控制NOR FLASH,BANK6控制SDRAM;对于成品,则会去掉NOR FLASH,而将固件放在NAND FLASH上,SDRAM不变。 对于代码存储,如NOR FLASH,是没有必要访问到具体字节;而对于SDRAM,因为可能保存有字节变量,必须得支持访问到字节。这里就说一下,在32位总线宽度下,存储器控制器是如何访问SDR
[单片机]
变电所遥视监控系统研究
  1 引言   随着我国电网调度管理水平的不断提高, 许多地区电力通信网的建设取得了很大的进展,基本上实现了数字化通信。采用光纤、数字微波或无线扩频等通信方式,信道带宽和信道质量明显提高。而要全面直观地了解变电站的真实情况,远程视觉监控是必备的监控管理手段,它可在几十公里及更远之外的调度中心及时准确地掌握变电站的情况, 并对各种情况进行操作控制,做到真正的无人值守。   2 无人值班变电所运行现状   近年来, 随着电网规模的迅速扩大, 电力系统科技水平不断提高, 无人值守变电所的数量日益增加, 尤其随着变电所自动化程度的不断提高,非电气因素造成的事故比例越来越高。如何降低或避免这类事故的发生,已是实现无人值班变电所要解决
[单片机]
变电所遥视监控系统研究
s3c2440代码重定位和段的引入——学以致用,综合Makefile的锻炼
对于2440而言,nand启动,nand的前4k内容由硬件复制到sram。 nor flash,可以像内存一样读,但是不能像内存一样写,执行写操作需要特殊的操作。 程序中包含有需要写的全局或者静态变量,它们在bin文件中,写在nor flash上,直接修改这样的变量是无效的。 到底什么意思呢?还是看例子比较有说服力。 在学习C语言的过程中,我们或多或少知道一些东西,c/c++可执行文件需要预处理,编译,汇编,连接。 程序有text段,data段,bss段,rodata段等等,今天,就和它们来个亲密接触吧。 还是先说上面的问题吧,看例子: 在之前的程序代码基础上,启动代码增加自动识别是nand还是nor启
[单片机]
<font color='red'>s3c2440</font>代码重定位和段的引入——学以致用,综合Makefile的锻炼
MMU 和 MPU的区别
S3C2440里面带的是MMU,而现在流行的Cortex-M3/4 里面带的是MPU。 MMU vs MPU 内存是现代计算机最重要的组件之一。因此,它的内容不能被任何错误的应用所篡改。这个功能可以通过MMU(Memory Management Unit)或者MPU(Memory Protection Unit)来实现。尽管这个两个东西有同样的基本功能,但是它们之间还是存在一些不同。MMU被认为是比MPU更先进的设备。MMU能完成MPU的所有工作,并且它还具备MPU没有的一些高级特性。 MMU具备而MPU不具备的特性包括:缓存控制,总线仲裁,bank切换。这些特性是更复杂的计算机所需要的,以便信息处理流程更顺畅无误。通过使用
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved