linux adc is a hybrid device driver; in linux2.6.30.4, the system already comes with the ADC universal driver file "arch/arm/plat-s3c24xx/adc.c", which is based on the platform driver It is written according to the architecture of the device model, and contains some relatively general and stable codes.
The operating environment of this tutorial: linux2.6.30.4 system, Dell G3 computer.
What kind of device is linux adc?
linux mixed device driver adc driver
In linux2.6.30.4, the system has been automatically It comes with the ADC universal driver file ---arch/arm/plat-s3c24xx/adc.c, which is written based on the architecture of the platform driver device model. It contains some relatively common and stable codes, but linux2.6.30.4 The version of the ADC universal driver file is not complete, and there is no reading function. Later, I took a look at the ADC general file of the Linux 3.8 version - arch/arm/plat-samsung/adc.c which is relatively complete.
But this section is not to analyze this file, but to write the ADC driver in another architecture. Because the ADC driver is relatively simple, it is not used. The platform driver device model is written for the architecture, this time we use a misc device driver.
Q: What is a misc device driver?
Answer: miscdevice shares a major device number MISC_MAJOR (10), but the minor device numbers are different. All miscdevice devices form a linked list. When accessing the device, the kernel searches for the corresponding miscdevice device based on the device number, and then calls the file operation interface registered in its file_operations structure to operate.
struct miscdevice { int minor; //次设备号,如果设置为MISC_DYNAMIC_MINOR则系统自动分配 const char *name; //设备名 const struct file_operations *fops; //操作函数 struct list_head list; struct device *parent; struct device *this_device; };dev_init entry function analysis:
static int __init dev_init(void) { int ret; base_addr=ioremap(S3C2410_PA_ADC,0x20); if (base_addr == NULL) { printk(KERN_ERR "failed to remap register block\n"); return -ENOMEM; } adc_clock = clk_get(NULL, "adc"); if (!adc_clock) { printk(KERN_ERR "failed to get adc clock source\n"); return -ENOENT; } clk_enable(adc_clock); ADCTSC = 0; ret = request_irq(IRQ_ADC, adcdone_int_handler, IRQF_SHARED, DEVICE_NAME, &adcdev); if (ret) { iounmap(base_addr); return ret; } ret = misc_register(&misc); printk (DEVICE_NAME" initialized\n"); return ret; }The first is to map the ADC register address and convert it into a virtual address. Then get the ADC clock and enable the ADC clock, then apply for the ADC interrupt, the interrupt handler function is
adcdone_int_handler, and the flags is IRQF_SHARED, which is a shared interrupt, because the touch screen also needs to apply for the ADC interrupt, and finally register a hybrid equipment.
When the application opens ("/dev/adc",...), the open function in the driver will be called, so let's take a look See what the open function does?
static int tq2440_adc_open(struct inode *inode, struct file *filp) { /* 初始化等待队列头 */ init_waitqueue_head(&(adcdev.wait)); /* 开发板上ADC的通道2连接着一个电位器 */ adcdev.channel=2; //设置ADC的通道 adcdev.prescale=0xff; DPRINTK( "ADC opened\n"); return 0; }It’s very simple, first initialize a waiting queue head, because since there is an application for ADC interrupt in the entry function, you must use waiting Queue, then set the ADC channel, because the ADC input channel of TQ2440 is 2 by default, set the prescaler value to 0xff.
When the application reads, the read function in the driver will be called. So let’s take a look at what the read function does?
static ssize_t tq2440_adc_read(struct file *filp, char *buffer, size_t count, loff_t *ppos) { char str[20]; int value; size_t len; /* 尝试获得ADC_LOCK信号量,如果能够立刻获得,它就获得信号量并返回0 * 否则,返回非零,它不会导致调用者睡眠,可以在中断上下文使用 */ if (down_trylock(&ADC_LOCK) == 0) { /* 表示A/D转换器资源可用 */ ADC_enable = 1; /* 使能预分频,选择ADC通道,最后启动ADC转换*/ START_ADC_AIN(adcdev.channel, adcdev.prescale); /* 等待事件,当ev_adc = 0时,进程被阻塞,直到ev_adc>0 */ wait_event_interruptible(adcdev.wait, ev_adc); ev_adc = 0; DPRINTK("AIN[%d] = 0x%04x, %d\n", adcdev.channel, adc_data, ((ADCCON & 0x80) ? 1:0)); /* 将在ADC中断处理函数读取的ADC转换结果赋值给value */ value = adc_data; sprintf(str,"%5d", adc_data); copy_to_user(buffer, (char *)&adc_data, sizeof(adc_data)); ADC_enable = 0; up(&ADC_LOCK); } else { /* 如果A/D转换器资源不可用,将value赋值为-1 */ value = -1; } /* 将ADC转换结果输出到str数组里,以便传给应用空间 */ len = sprintf(str, "%d\n", value); if (count >= len) { /* 从str数组里拷贝len字节的数据到buffer,即将ADC转换数据传给应用空间 */ int r = copy_to_user(buffer, str, len); return r ? r : len; } else { return -EINVAL; } }The tq2440_adc_read function first tries to obtain the ADC_LOCK semaphore, because the touch screen driver also uses ADC resources, and the two compete with each other. After ADC resources, enable prescaler, select ADC channel, and finally start ADC conversion, then call the wait_event_interruptible function to wait until ev_adc>0 process will continue to run, running down will adc_data data is read out, the copy_to_user function is called to transfer the ADC data to the application space, and finally the ADC_LOCK semaphore is released.
Q: When is ev_adc>0? Default ev_adc = 0
Answer: In the adcdone_int_handler interrupt processing function, after the data is read out, ev_adc is set to 1.
ADC interrupt handler function adcdone_int_handler
##
/* ADC中断处理函数 */ static irqreturn_t adcdone_int_handler(int irq, void *dev_id) { /* A/D转换器资源可用 */ if (ADC_enable) { /* 读ADC转换结果数据 */ adc_data = ADCDAT0 & 0x3ff; /* 唤醒标志位,作为wait_event_interruptible的唤醒条件 */ ev_adc = 1; wake_up_interruptible(&adcdev.wait); } return IRQ_HANDLED; }When the AD conversion is completed, the ADC interrupt will be triggered and adcdone_int_handler will be entered. This function will read the AD conversion data into adc_data, then set the wake-up flag ev_adc to 1, and finally call the wake_up_interruptible function to wake up adcdev.wait and wait. queue.
Summarize the workflow of ADC:
1. In the open function, set the analog input channel and set the prescaler value
2. In the read function, AD conversion is started and the process sleeps
三、adc_irq函数里,AD转换结束后触发ADC中断,在ADC中断处理函数将数据读出,唤醒进程
四、read函数里,进程被唤醒后,将adc转换数据传给应用程序
ADC驱动参考源码:
/************************************* NAME:EmbedSky_adc.c COPYRIGHT:www.embedsky.net *************************************/ #includeADC应用测试参考源码:#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "tq2440_adc.h" #undef DEBUG //#define DEBUG #ifdef DEBUG #define DPRINTK(x...) {printk(KERN_DEBUG "EmbedSky_adc: " x);} #else #define DPRINTK(x...) (void)(0) #endif #define DEVICE_NAME "adc" /* 设备节点: /dev/adc */ static void __iomem *base_addr; typedef struct { wait_queue_head_t wait; /* 定义等待队列头 */ int channel; int prescale; }ADC_DEV; DECLARE_MUTEX(ADC_LOCK); /* 定义并初始化信号量,并初始化为1 */ static int ADC_enable = 0; /* A/D转换器资是否可用标志位 */ static ADC_DEV adcdev; /* 用于表示ADC设备 */ static volatile int ev_adc = 0; /* 作为wait_event_interruptible的唤醒条件 */ static int adc_data; static struct clk *adc_clock; #define ADCCON (*(volatile unsigned long *)(base_addr + S3C2410_ADCCON)) //ADC control #define ADCTSC (*(volatile unsigned long *)(base_addr + S3C2410_ADCTSC)) //ADC touch screen control #define ADCDLY (*(volatile unsigned long *)(base_addr + S3C2410_ADCDLY)) //ADC start or Interval Delay #define ADCDAT0 (*(volatile unsigned long *)(base_addr + S3C2410_ADCDAT0)) //ADC conversion data 0 #define ADCDAT1 (*(volatile unsigned long *)(base_addr + S3C2410_ADCDAT1)) //ADC conversion data 1 #define ADCUPDN (*(volatile unsigned long *)(base_addr + 0x14)) //Stylus Up/Down interrupt status #define PRESCALE_DIS (0 0 */ wait_event_interruptible(adcdev.wait, ev_adc); ev_adc = 0; DPRINTK("AIN[%d] = 0x%04x, %d\n", adcdev.channel, adc_data, ((ADCCON & 0x80) ? 1:0)); /* 将在ADC中断处理函数读取的ADC转换结果赋值给value */ value = adc_data; sprintf(str,"%5d", adc_data); copy_to_user(buffer, (char *)&adc_data, sizeof(adc_data)); ADC_enable = 0; up(&ADC_LOCK); } else { /* 如果A/D转换器资源不可用,将value赋值为-1 */ value = -1; } /* 将ADC转换结果输出到str数组里,以便传给应用空间 */ len = sprintf(str, "%d\n", value); if (count >= len) { /* 从str数组里拷贝len字节的数据到buffer,即将ADC转换数据传给应用空间 */ int r = copy_to_user(buffer, str, len); return r ? r : len; } else { return -EINVAL; } } static int tq2440_adc_open(struct inode *inode, struct file *filp) { /* 初始化等待队列头 */ init_waitqueue_head(&(adcdev.wait)); /* 开发板上ADC的通道2连接着一个电位器 */ adcdev.channel=2; //设置ADC的通道 adcdev.prescale=0xff; DPRINTK( "ADC opened\n"); return 0; } static int tq2440_adc_release(struct inode *inode, struct file *filp) { DPRINTK( "ADC closed\n"); return 0; } static struct file_operations dev_fops = { owner: THIS_MODULE, open: tq2440_adc_open, read: tq2440_adc_read, release: tq2440_adc_release, }; static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &dev_fops, }; static int __init dev_init(void) { int ret; base_addr=ioremap(S3C2410_PA_ADC,0x20); if (base_addr == NULL) { printk(KERN_ERR "failed to remap register block\n"); return -ENOMEM; } adc_clock = clk_get(NULL, "adc"); if (!adc_clock) { printk(KERN_ERR "failed to get adc clock source\n"); return -ENOENT; } clk_enable(adc_clock); ADCTSC = 0; ret = request_irq(IRQ_ADC, adcdone_int_handler, IRQF_SHARED, DEVICE_NAME, &adcdev); if (ret) { iounmap(base_addr); return ret; } ret = misc_register(&misc); printk (DEVICE_NAME" initialized\n"); return ret; } static void __exit dev_exit(void) { free_irq(IRQ_ADC, &adcdev); iounmap(base_addr); if (adc_clock) { clk_disable(adc_clock); clk_put(adc_clock); adc_clock = NULL; } misc_deregister(&misc); } EXPORT_SYMBOL(ADC_LOCK); module_init(dev_init); module_exit(dev_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("www.embedsky.net"); MODULE_DESCRIPTION("ADC Drivers for EmbedSky SKY2440/TQ2440 Board and support touch");
/************************************* NAME:EmbedSky_adc.c COPYRIGHT:www.embedsky.net *************************************/ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys> #include <sys> #include <sys> #include <fcntl.h> #include <linux> #include <errno.h> #include <string.h> int main(void) { int fd ; char temp = 1; fd = open("/dev/adc", 0); if (fd 0) { buffer[len] = '\0'; int value; sscanf(buffer, "%d", &value); printf("ADC Value: %d\n", value); } else { perror("read ADC device !"); exit(1); } sleep(1); } adcstop: close(fd); }</string.h></errno.h></linux></fcntl.h></sys></sys></sys></stdlib.h></unistd.h></stdio.h>测试结果:
[WJ2440]# ./adc_test ADC Value: 693 ADC Value: 695 ADC Value: 694 ADC Value: 695 ADC Value: 702 ADC Value: 740 ADC Value: 768 ADC Value: 775 ADC Value: 820 ADC Value: 844 ADC Value: 887 ADC Value: 937 ADC Value: 978 ADC Value: 1000 ADC Value: 1023 ADC Value: 1023 ADC Value: 1023
相关推荐:《Linux视频教程》
The above is the detailed content of What device is linux adc. For more information, please follow other related articles on the PHP Chinese website!

The key steps in Linux system management and maintenance include: 1) Master the basic knowledge, such as file system structure and user management; 2) Carry out system monitoring and resource management, use top, htop and other tools; 3) Use system logs to troubleshoot, use journalctl and other tools; 4) Write automated scripts and task scheduling, use cron tools; 5) implement security management and protection, configure firewalls through iptables; 6) Carry out performance optimization and best practices, adjust kernel parameters and develop good habits.

Linux maintenance mode is entered by adding init=/bin/bash or single parameters at startup. 1. Enter maintenance mode: Edit the GRUB menu and add startup parameters. 2. Remount the file system to read and write mode: mount-oremount,rw/. 3. Repair the file system: Use the fsck command, such as fsck/dev/sda1. 4. Back up the data and operate with caution to avoid data loss.

This article discusses how to improve Hadoop data processing efficiency on Debian systems. Optimization strategies cover hardware upgrades, operating system parameter adjustments, Hadoop configuration modifications, and the use of efficient algorithms and tools. 1. Hardware resource strengthening ensures that all nodes have consistent hardware configurations, especially paying attention to CPU, memory and network equipment performance. Choosing high-performance hardware components is essential to improve overall processing speed. 2. Operating system tunes file descriptors and network connections: Modify the /etc/security/limits.conf file to increase the upper limit of file descriptors and network connections allowed to be opened at the same time by the system. JVM parameter adjustment: Adjust in hadoop-env.sh file

This guide will guide you to learn how to use Syslog in Debian systems. Syslog is a key service in Linux systems for logging system and application log messages. It helps administrators monitor and analyze system activity to quickly identify and resolve problems. 1. Basic knowledge of Syslog The core functions of Syslog include: centrally collecting and managing log messages; supporting multiple log output formats and target locations (such as files or networks); providing real-time log viewing and filtering functions. 2. Install and configure Syslog (using Rsyslog) The Debian system uses Rsyslog by default. You can install it with the following command: sudoaptupdatesud

When choosing a Hadoop version suitable for Debian system, the following key factors need to be considered: 1. Stability and long-term support: For users who pursue stability and security, it is recommended to choose a Debian stable version, such as Debian11 (Bullseye). This version has been fully tested and has a support cycle of up to five years, which can ensure the stable operation of the system. 2. Package update speed: If you need to use the latest Hadoop features and features, you can consider Debian's unstable version (Sid). However, it should be noted that unstable versions may have compatibility issues and stability risks. 3. Community support and resources: Debian has huge community support, which can provide rich documentation and

This article describes how to use TigerVNC to share files on Debian systems. You need to install the TigerVNC server first and then configure it. 1. Install the TigerVNC server and open the terminal. Update the software package list: sudoaptupdate to install TigerVNC server: sudoaptinstalltigervnc-standalone-servertigervnc-common 2. Configure TigerVNC server to set VNC server password: vncpasswd Start VNC server: vncserver:1-localhostno

Configuring a Debian mail server's firewall is an important step in ensuring server security. The following are several commonly used firewall configuration methods, including the use of iptables and firewalld. Use iptables to configure firewall to install iptables (if not already installed): sudoapt-getupdatesudoapt-getinstalliptablesView current iptables rules: sudoiptables-L configuration

The steps to install an SSL certificate on the Debian mail server are as follows: 1. Install the OpenSSL toolkit First, make sure that the OpenSSL toolkit is already installed on your system. If not installed, you can use the following command to install: sudoapt-getupdatesudoapt-getinstallopenssl2. Generate private key and certificate request Next, use OpenSSL to generate a 2048-bit RSA private key and a certificate request (CSR): openss


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Zend Studio 13.0.1
Powerful PHP integrated development environment

PhpStorm Mac version
The latest (2018.2.1) professional PHP integrated development tool

WebStorm Mac version
Useful JavaScript development tools

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

VSCode Windows 64-bit Download
A free and powerful IDE editor launched by Microsoft