Understand the principle and application of S3C2440 touch screen driver

Publisher:灵感之翼Latest update time:2023-01-12 Source: elecfansKeywords:S3C2440 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

1. Development environment

Host: VMWare--Fedora 9

Development board: Mini2440--64MB Nand, Kernel:2.6.30.4

Compiler: arm-linux-gcc-4.3.2


2. Prerequisite knowledge

1. Linux input subsystem (Input Subsystem):

In Linux, the input subsystem is composed of the input subsystem device driver layer, the input subsystem core layer (Input Core), and the input subsystem event processing layer (Event Handler). The device driver layer provides read and write access to each hardware register and converts the underlying hardware's response to user input access into standard input events, which are then submitted to the event processing layer through the core layer; while the core layer provides the device driver layer for the lower layer The programming interface provides the programming interface of the event processing layer; the event processing layer provides our user space applications with a unified access to the device interface and event processing submitted by the driver layer. So this makes the driver part of our input device no longer care about the operation of the device file, but the operation of each hardware register and the submitted input events. Let’s use graphics to describe the relationship between these three!

In addition, I found another picture to illustrate the structure of the Linux input subsystem, which may be more vivid and easier to understand. as follows:


2. Implementation principle of input subsystem device driver layer:

In Linux, the Input device is described by the input_dev structure, which is defined in input.h. The device driver only needs to be implemented by following the steps below.
①. Set in the driver module loading function which events of the input subsystem are supported by the Input device;
②. Register the Input device into the input subsystem;
③. When an input operation occurs on the Input device (for example: the keyboard is pressed/raised) , when the touch screen is touched/lifted/moved, when the mouse is moved/clicked/raised, etc.), submit the events that occurred and the corresponding key values/coordinates and other states.

The event types of input devices in Linux are (only some commonly used ones are listed here, please see linux/input.h for more):

EV_SYN 0x00 Synchronization event
EV_KEY 0x01 Key event
EV_REL 0x02 Relative coordinates (such as mouse movement, reporting the offset relative to the last position)
EV_ABS 0x03 Absolute coordinates (such as touch screens and joysticks, reporting absolute coordinate positions)
EV_MSC 0x04 Other
EV_LED 0x11 LED
EV_SND 0x12 Sound
EV_REP 0x14 Repeat
EV_FF 0x15 Force feedback


Functions used to submit the more commonly used event types to the input subsystem are:

void input_report_key(struct input_dev *dev, unsigned int code, int value); //Function to submit key events
void input_report_rel(struct input_dev *dev, unsigned int code, int value); //Function to submit relative coordinate events
void input_report_abs( struct input_dev *dev, unsigned int code, int value); //Function to submit absolute coordinate events


Note that after submitting an input device event, you must use the following method to synchronize the event so that it informs the input system that the device driver has issued a complete report:

void input_sync(struct input_dev *dev)


3. Implementation steps of touch screen driver

1. Hardware schematic analysis:

The internal touch screen interface and ADC interface of the S3c2440 chip are integrated together. For the hardware structure schematic diagram, please see: The diagram in the ADC driver example development explanation on S3C2440. Channel 7 (XP or AIN7) is used as the X coordinate input of the touch screen interface. Channel 5 (YP or AIN5) as the Y coordinate input of the touch screen interface. In "Explanation of ADC driver development example on S3C2440", the analog signal of AD conversion is generated by a potentiometer on the development board and input through channel 1 (AIN0), and the analog signal here is generated by touching the touch screen The two analog signals of X coordinate and Y coordinate are input through channel 7 and channel 5 respectively. The touch screen interface provided by S3c2440 has 4 processing modes, namely: normal conversion mode, separate X/Y position conversion mode, automatic X/Y position conversion mode and waiting for interrupt mode. For the requirements for working in each mode, please See the data sheet description for details. This driver example will adopt automatic X/Y position conversion mode and waiting for interrupt mode.

Note: In each step, in order to make the code logic more organized and easy to understand, the order of the code is not considered. For example, functions must be defined first and then called. If you want to compile this code, please adjust the order of the code strictly according to the specifications of C language.

2. Create the touch screen driver my2440_ts.c. First implement the loading and unloading part. In the driver loading part, the main things we do are: enable the clock required by the ADC, map the IO port, initialize the register, apply for interrupt, initialize the input device, Register the input device with the input subsystem. code show as below:

#include
#include
#include #include
#include
#include
#include
#include
#include

/*Used to save the ADC clock obtained from the platform clock list*/
staTIc struct clk *adc_clk;

/*Define a memory address used to save the virtual mapping*/
staTIc void __iomem *adc_base;

/*Define an input Device to represent our touch screen device*/
staTIc struct input_dev *ts_dev;

/*Device name*/
#define DEVICE_NAME "my2440_TouchScreen"

/*Define a WAIT4INT macro, which will operate the ADC touch screen control register
S3C2410_ADCTSC_YM_SEN. These macros are defined in In regs-adc.h*/
#define WAIT4INT(x) (((x)<<8) | S3C2410_ADCTSC_YM_SEN | S3C2410_ADCTSC_YP_SEN |
                    S3C2410_ADCTSC_XP_SEN | S3C2410_ADCTSC_XY_PST(3))

staTIc int __init ts_init( void)
{
    int ret;

    /*From platform Obtain the clock of the ADC in the clock queue. Why do we need to obtain this clock here? Because the conversion frequency of the ADC is related to the clock.
    Some clocks of the system are defined in arch/arm/plat-s3c24xx/s3c2410-clock.c*/
    adc_clk = clk_get(NULL, "adc");
    if(!adc_clk)
    {
        /*Error handling*/
        printk(KERN_ERR "falied to find adc clock sourcen");
        return -ENOENT;
    }

    /*After the clock is obtained, it must be enabled before it can be used. clk_enable is defined in arch/arm/plat-s3c/clock.c*/
    clk_enable(adc_clk);

    /* Map the IO space occupied by the ADC's IO port to the virtual address of the memory. ioremap is defined in io.h.
     Note: The IO space must be mapped before it can be used. In the future, the operation of the virtual address is the operation of the IO space.
     S3C2410_PA_ADC is the base address of the ADC controller, which is defined in mach-s3c2410/include/mach/map.h. 0x20 is virtual Address length */
    adc_base = ioremap(S3C2410_PA_ADC, 0x20);
    if(adc_base == NULL)
    {
        /*Error handling*/
        printk(KERN_ERR "failed to remap register blockn");
        ret = -EINVAL;
        goto err_noclk;
    }

    / *Initialize the ADC control register and ADC touch screen control register*/
    adc_initialize();

    /*Apply for ADC interrupt and trigger after AD conversion is completed. The shared interrupt IRQF_SHARED is used here because the interrupt number is also used in the ADC driver.
    The last parameter 1 is a value given randomly, because if the value is not set to NULL, the interrupt application will be unsuccessful*/
    ret = request_irq( IRQ_ADC, adc_irq, IRQF_SHARED | IRQF_SAMPLE_RANDOM, DEVICE_NAME, 1);
    if(ret)
    {
        printk(KERN_ERR "IRQ%d error %dn", IRQ_ADC, ret);
        ret = -EINVAL;
        goto err_nomap;
    }

    /*Apply for touch screen interrupt, Triggered when the touch screen is pressed or the pen is lifted*/
    ret = request_irq(IRQ_TC, tc_irq, IRQF_SAMPLE_RANDOM, DEVICE_NAME, 1);
    if(ret)
    {
        printk(KERN_ERR "IRQ%d error %dn", IRQ_TC, ret);
        ret = -EINVAL;
        goto err_noirq;
    }

    /*Apply space for the input device, input_allocate_device is defined in input.h*/
    ts_dev = input_allocate_device();

    /*The input device is initialized below, that is, the value is set for the member of the input device structure input_dev.
    The evbit field is used to describe supported events. It supports synchronization events, key events, and absolute coordinate events.
    The BIT macro actually performs bit operations on 1 and is defined in linux/bitops.h */
    ts_dev->evbit[0] = BIT (EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);
    
    /*The keybit field is used to describe the type of key, and many are defined in input.h. The BTN_TOUCH type is used here to represent clicks on the touch screen*/
    ts_dev->keybit[BITS_TO_LONGS(BTN_TOUCH)] = BIT(BTN_TOUCH);

    /*For touch screens, the absolute coordinate system is used. Here set the minimum and maximum values ​​of the X and Y coordinates in the coordinate system (0-1023 range)
    ABS_X and ABS_Y represent the X coordinate and Y coordinate, and ABS_PRESSURE represents whether the touch screen is pressed or lifted */
    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);

    /*The following are settings for touch screen input devices Identity information is written directly here.
    This information can be viewed in /proc/bus/input/devices after the driver is mounted*/
    ts_dev->name = DEVICE_NAME; /*Device name*/
    ts_dev->id.bustype = BUS_RS232; /*Bus type*/    
    ts_dev->id.vendor = 0xDEAD; /*Dealer ID number*/
    ts_dev->id.product = 0xBEEF; /*Product ID number*/
    ts_dev->id.version = 0x0101; /*Version ID number*/

    / *Okay, everything is ready, now register the ts_dev touch screen device into the input subsystem*/
    input_register_device(ts_dev);

    return 0;

/*The following is error jump processing*/
err_noclk:
    clk_disable(adc_clk);
    clk_put( adc_clk);

err_nomap:
    iounmap(adc_base);

err_noirq:
    free_irq(IRQ_ADC, 1);

    return ret;
}

/*Initialize the ADC control register and ADC touch screen control register*/
static void adc_initialize(void)
{
    /*The calculation result is (binary ): 111111111000000, and according to the data sheet,
    it is known that the AD conversion prescaler value is set to 255, and the AD conversion prescaler enable is valid*/
    writel(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(0xFF), adc_base + S3C2410_ADCCON);

    /* Set the ADC start delay register. The delay value is 0xffff*/
    writel(0xffff, adc_base + S3C2410_ADCDLY);

    /*WAIT4INT macro calculation result is (binary): 11010011. According to the data sheet, we know that
    this is the ADC touch screen The control register is set to wait for interrupt mode*/
    writel(WAIT4INT(0), adc_base + S3C2410_ADCTSC);
}

static void __exit ts_exit(void)
{
    /*Mask and release interrupts*/
    disable_irq(IRQ_ADC);
    disable_irq(IRQ_TC);
    free_irq( IRQ_ADC, 1);
    free_irq(IRQ_TC, 1);

    /*Release virtual address mapping space*/
    iounmap(adc_base);

    /*Mask and destroy clock*/
    if(adc_clk)
    {
        clk_disable(adc_clk);
        clk_put(adc_clk);
        adc_clk = NULL;
    }

    /*Unregister the touch screen device from the input subsystem*/
    input_unregister_device(ts_dev);
}

module_init(ts_init);
module_exit(ts_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Huang Gang");
MODULE_DESCRIPTION( "My2440 Touch Screen Driver");

[1] [2]
Keywords:S3C2440 Reference address:Understand the principle and application of S3C2440 touch screen driver

Previous article:Set-top box media player based on TQ2440 development board
Next article:ARM register analysis and exception handling methods

Recommended ReadingLatest update time:2024-11-23 15:32

STM32F103 uses analog I2C to drive ADS1115
ADS1115 is driven by simulating I2C: (Part of the code was borrowed from several on the Internet, and configured according to the pins, but none of them worked. I spent a day adjusting it today and finally adjusted it in the evening) Note: This part of the code only needs part of the program of ADS1115 (some used arra
[Microcontroller]
Several isolated LED drive power supply solutions
In the context of global energy shortage and increasing environmental protection requirements, countries around the world are vigorously developing green energy-saving lighting. LED lighting, as a revolutionary energy-saving lighting technology, is developing rapidly. However, the requirements for LED dri
[Power Management]
Several isolated LED drive power supply solutions
51 MCU drives ds1302 program (12864 LCD display)
This is the main interface This is the main menu interface This is the sub-interface for setting time This is the setting date Setting the Backlight This is the status icon that appears on the main interface after the key tone and alarm are set.  
[Microcontroller]
51 MCU drives ds1302 program (12864 LCD display)
In-depth discussion of key technologies for electric drive system development
The asymmetry of the parallel-axis electric drive axle geometry significantly increases the angle between the torque shaft and the motor shaft (B1). The torque shaft suspension arrangement is no longer suitable for electric drive axles. Assembly; The motor's low speed, high torque and fast response c
[Embedded]
In-depth discussion of key technologies for electric drive system development
JZ2440 driver compilation, installation and testing
1. Compile the Linux kernel Documents needed: a. Kernel file (e.g. linux-2.6.22.6.tar.bz2) b. Corresponding patch file (for example, linux-2.6.22.6_jz2440.patch) $ tar xjf linux-2.6.22.6.tar.bz2//Unzip the kernel file $ cd linux-2.6.22.6 $ patch -p1 ../linux-2.6.22.6_jz2440.patch //Apply patch $ mv ../4.3-inch LCD_
[Microcontroller]
Implementation of touch screen driver in Linux (1) - based on s3c6410 processor
These articles are mainly about touch screen drivers in Linux, based on the s3c6410 processor. This article is mainly about the implementation of touch screen devices as platform devices, as well as the source code analysis of the corresponding probe function and remove function. 1. Loading and unloading functions o
[Microcontroller]
Implementation of touch screen driver in Linux (1) - based on s3c6410 processor
Design of hysteresis control circuit based on buck-type LED constant current drive [Figure]
This paper designs a hysteresis control circuit for a buck-type LED constant current driver chip. The chip adopts a high-side current detection scheme and uses a hysteresis current control method to perform hysteresis control on the drive current, thereby obtaining a constant average drive current. The design adopts a
[Power Management]
Design of hysteresis control circuit based on buck-type LED constant current drive [Figure]
ON Semiconductor's line driver for smart meter PLC communication applications
Smart meters play a key role in the emerging smart grid applications. Designers need to choose a suitable communication method for the communication between smart meters and data concentrators. Power line carrier (PLC) technology uses power lines as data transmission media and existing power distribution networks
[Power Management]
ON Semiconductor's line driver for smart meter PLC communication applications
Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

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