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");
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
- Naxin Micro and Xinxian jointly launched the NS800RT series of real-time control MCUs
- How to learn embedded systems based on ARM platform
- Summary of jffs2_scan_eraseblock issues
- Application of SPCOMM Control in Serial Communication of Delphi7.0
- Using TComm component to realize serial communication in Delphi environment
- Bar chart code for embedded development practices
- Embedded Development Learning (10)
- Embedded Development Learning (8)
- Embedded Development Learning (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Intel promotes AI with multi-dimensional efforts in technology, application, and ecology
- ChinaJoy Qualcomm Snapdragon Theme Pavilion takes you to experience the new changes in digital entertainment in the 5G era
- Infineon's latest generation IGBT technology platform enables precise control of speed and position
- Two test methods for LED lighting life
- Don't Let Lightning Induced Surges Scare You
- Application of brushless motor controller ML4425/4426
- Easy identification of LED power supply quality
- World's first integrated photovoltaic solar system completed in Israel
- Sliding window mean filter for avr microcontroller AD conversion
- What does call mean in the detailed explanation of ABB robot programming instructions?
- STMicroelectronics discloses its 2027-2028 financial model and path to achieve its 2030 goals
- 2024 China Automotive Charging and Battery Swapping Ecosystem Conference held in Taiyuan
- State-owned enterprises team up to invest in solid-state battery giant
- The evolution of electronic and electrical architecture is accelerating
- The first! National Automotive Chip Quality Inspection Center established
- BYD releases self-developed automotive chip using 4nm process, with a running score of up to 1.15 million
- GEODNET launches GEO-PULSE, a car GPS navigation device
- Should Chinese car companies develop their own high-computing chips?
- Infineon and Siemens combine embedded automotive software platform with microcontrollers to provide the necessary functions for next-generation SDVs
- Continental launches invisible biometric sensor display to monitor passengers' vital signs
- The Problem with Fully Differential Op Amp Output Voltage Rails
- Take a break and have a laugh
- Radio disturbance characteristics test of switching power supply and uninterruptible power supply
- Bluetooth and WUSB work together to achieve perfect UWB connection
- EEWORLD University - Master the basic knowledge and artistic design of high-voltage gate driver design
- MSP430F149 uses JTAG and BSL to download configuration diagram
- Design of a regenerative braking control circuit
- Monitoring and automatic switching of the inverter control system circuit power supply
- What are the ideas for making lyrics display screen?
- Why does the waveform oscillate after amplification?