Linux-2.6.32 ported to add ADC driver on mini2440 development board

Publisher:RainbowPromiseLatest update time:2024-06-18 Source: elecfansKeywords:linux  mini2440 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Add ADC driver

Editor: Since the kernel does not support the ADC driver of S3C2440, the ADC driver is added here. The friendly manual introduces this in quite detail, so just follow the manual. The code inside also has detailed comments. The ADC driver belongs to the character type device, and is implemented here as a miscellaneous device.

1. About the ADC and touch screen interface of S3C2440
The Linux-2.6.32.2 kernel does not provide an ADC driver that supports S3C2440, so we designed one ourselves. This driver is relatively simple and belongs to a character device. It is located in the drivers/char directory. The driver file name is: mini2440_adc.c. In the S3C2440 chip, the AD input and touch screen interface use a common A/D converter, see Chapter 16 of the 2440 chip manual, as shown in the figure.


2 Add ADC driver in the kernel
If the ADC driver and the touch screen driver want to coexist, the problem of sharing the "A/D converter" resources must be solved. Therefore, a global "ADC_LOCK" semaphore is declared in the ADC driver. The content and annotations of the ADC driver are as follows:

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

#include
#include
#include
#include #include

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

#include
#include
; Self-defined header files, because the native kernel does not include

#include "s3c24xx-adc.h"
#undef DEBUG
//#define DEBUG
#ifdef DEBUG
#define DPRINTK(x...) {printk(__FUNCTION__"(%d): ",__LINE__);printk(##x);}
#else
#define DPRINTK(x...) (void)(0)
#endif
;Define the ADC conversion device name, which will appear in /dev/adc
#define DEVICE_NAME "adc"
static void __iomem *base_addr;
;Define ADC device structure
typedef struct {
wait_queue_head_t wait;
int channel;
int prescale;
}ADC_DEV;

;Declare a global semaphore to share the A/D converter with the touch screen driver
DECLARE_MUTEX(ADC_LOCK);
;Status variable for whether the ADC driver owns the A/D converter resource
static int OwnADC = 0;
static ADC_DEV adcdev;
static volatile int ev_adc = 0;
static int adc_data;
static struct clk *adc_clock;
;Define ADC related registers
#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 << 14)
#define PRESCALE_EN (1 << 14)
#define PRSCVL(x) ((x) << 6)
#define ADC_INPUT(x) ((x) << 3)
#define ADC_START (1 << 0)
#define ADC_ENDCVT (1 << 15)
; Define the “turn on AD input” macro. It is not made into a function because it is relatively simple.
#define START_ADC_AIN(ch, prescale)
do{
ADCCON = PRESCALE_EN | PRSCVL(prescale) | ADC_INPUT((ch)) ;
ADCCON |= ADC_START;
}while(0)
;ADC interrupt handler function
static irqreturn_t adcdone_int_handler(int irq, void *dev_id)

{
;If the ADC driver owns the "A/D converter" resource, read the conversion result from the ADC registerif
(OwnADC) {
adc_data = ADCDAT0 & 0x3ff;
ev_adc = 1;
wake_up_interruptible(&adcdev.wait);
}
return IRQ_HANDLED;
}
;ADC read function, generally corresponds to the device read function (read) of the user layer/application
layerstatic ssize_t s3c2410_adc_read(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{
char str[20];
int value;
size_t len;
;Judge whether the "A/D converter" resource is availableif
(down_trylock(&ADC_LOCK) == 0) {
OwnADC = 1; //Mark the "A/D converter" resource status as availableSTART_ADC_AIN
(adcdev.channel, adcdev.prescale); //Start conversion
wait_event_interruptible(adcdev.wait, ev_adc); //Wait for conversion result through terminal
ev_adc = 0;
DPRINTK("AIN[%d] = 0x%04x, %dn", adcdev.channel, adc_data, ADCCON & 0x80 ? 1:0);
;Assign the conversion result to value so as to pass it to the user layer/application layer
value = adc_data;
;Release "A/D converter" resources
OwnADC = 0;
up(&ADC_LOCK);
} else {
;There is no "A/D converter" resource, assign it to "-1"
value = -1;
}

len = sprintf(str, "%dn", value);
if (count >= len) {
;Pass the conversion result to the user layer/application layer
int r = copy_to_user(buffer, str, len);
return r ? r : len;
} else {
return -EINVAL;
}
}
;The function of opening the ADC device generally corresponds to the open of the user mode program
static int s3c2410_adc_open(struct inode *inode, struct file *filp)
{
;Initialize the interrupt queue
init_waitqueue_head(&(adcdev.wait));
;The default channel is "0"
adcdev.channel=0;
adcdev.prescale=0xff;
DPRINTK( "adc openedn");
return 0;
}
static int s3c2410_adc_release(struct inode *inode, struct file *filp)
{
DPRINTK( "adc closedn");
return 0;
}
static struct file_operations dev_fops = {
owner: THIS_MODULE,
open: s3c2410_adc_open,
read: s3c2410_adc_read,
release: s3c2410_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 blockn");
return -ENOMEM;
}
adc_clock = clk_get(NULL, "adc");
if (!adc_clock) {
printk(KERN_ERR "failed to get adc clock sourcen");
return -ENOENT;
}
clk_enable(adc_clock);
/* normal ADC */
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"tinitializedn");
return ret;
}

static void __exit dev_exit(void)
{
;Release interrupt
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 semaphore "ADC_LOCK" for touch screen driver to use
EXPORT_SYMBOL(ADC_LOCK);
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("FriendlyARM Inc.");


The above driver also includes a simple header file "s3c24xx-adc.h", which is also in the drivers/char directory. The content is:
#ifndef _S3C2410_ADC_H_
#define _S3C2410_ADC_H_
#define ADC_WRITE(ch, prescale) ((ch)<<16|(prescale))
#define ADC_WRITE_GETCH(data) (((data)>>16)&0x7)
#define ADC_WRITE_GETPRE(data) ((data)&0xff)
#endif /* _S3C2410_ADC_H_ */

The above driver also includes a simple header file "s3c24xx-adc.h", which is also in the drivers/char directory. The content is:
#ifndef _S3C2410_ADC_H_
#define _S3C2410_ADC_H_
#define ADC_WRITE(ch, prescale) ((ch)<<16|(prescale))
#define ADC_WRITE_GETCH(data) (((data)>>16)&0x7)
#define ADC_WRITE_GETPRE(data) ((data)&0xff)
#endif /* _S3C2410_ADC_H_ */

Then open the drivers/char/Makefile file and add the ADC driver target module at about line 114:
obj-$(CONFIG_JS_RTC) += js-rtc.o
js-rtc-y = rtc.o
obj-$(CONFIG_MINI2440_ADC) += mini2440_adc.o

# Files generated that shall be removed upon make clean
clean-files := consolemap_deftbl.c defkeymap.c
and then open the drivers/char/Kconfig file and add the ADC driver configuration option:
config DEVKMEM
bool "/dev/kmem virtual device support"
default y
help
Say Y here if you want to support the /dev/kmem device. The
/dev/kmem device is rarely used, but can be used for certain
kind of kernel debugging operations.
When in doubt, say "N".
config MINI2440_ADC
bool "ADC driver for FriendlyARM Mini2440 development boards"
depends on MACH_MINI2440
default y if MACH_MINI2440
help
this is ADC driver for FriendlyARM Mini2440 development boards
Notes: the touch-screen-driver required this option
config BFIN_JTAG_COMM
tristate "Blackfin JTAG Communication"
depends on BLACKFIN
help
like this , we added the ADC to the kernel Driver, now execute the command line in the kernel source code directory: make menuconfig, select the following submenu items in turn, and find the ADC driver configuration option you just added:
Device Drivers --->
Character devices --->
Press the space bar to select the ADC configuration option , then exit to save the selected configuration, execute in the command line: make zImage, arch/arm/boot/zImage will be generated, use supervivi's "k" command to burn it to the development board.

3 ADC test program
Here we use the file system that comes with Friendly Arm, which contains an adc-test command. Its source code is as follows:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(void)
{

[1] [2]
Keywords:linux  mini2440 Reference address:Linux-2.6.32 ported to add ADC driver on mini2440 development board

Previous article:Linux-2.6.32 transplanted on mini2440 development board - modify the Linux boot logo
Next article:Linux-2.6.32 ported to add touch screen driver on mini2440 development board

Recommended ReadingLatest update time:2024-11-16 09:43

Linux Device Driver Development - Platform Device Drivers
A new device driver model - platform device driver - was introduced into the Linux 2.6 kernel. Platform device drivers are divided into platform devices (platform_device) and platform drivers (platform_driver). The introduction of platform devices makes Linux device drivers easier to port. 1. Platform equ
[Microcontroller]
LCD driver terminal based on ARM9 and Linux
1 Introduction The LCD driver terminal integrates the LCD controller, microcontroller, etc., and encapsulates the LCD control and graphical interface display functions through software, opens the operation interface to the user, shields the control details of the LCD display, and allows the user to send predefined c
[Microcontroller]
LCD driver terminal based on ARM9 and Linux
ARM-Linux cross-compilation tool under Linux platform
The following is the compilation of ARM under Ubuntu platform: 1. Disassembly tools arm-linux-objdump -D -S hello log //View the assembly code of hello 2. ELF file viewing tool arm-linux-readelf -a hello log //View the hello file arm-linux-readelf -d hello log //View the dynamic library used by hello 3. De
[Microcontroller]
mini2440 make menuconfig cannot find the solution for Flash CFI support
Today I am going to try the norflash driver that comes with the kernel, but I can’t find it in the configuration items. Later I found out that it was caused by some options not being selected. Just select all the following options. Device Drivers ---     Memory Technology Device (MTD) support ---     RAM/ROM/Flash
[Microcontroller]
mini2440 make menuconfig cannot find the solution for Flash CFI support
Analysis of debugging scripts in MDK
I am going to write a simple bare metal program to run in mini2440. I saw two ways to start the chip in the manual: 1. Start from Nor Flash 2. Start from Nand Flash. After several days of intermittent work, I still can't burn it in. I remember that I usually burn and run the debugging program directly into the memor
[Microcontroller]
Analysis of debugging scripts in MDK
OK6410A Development Board (VIII) 90 linux-5.11 OK6410A Linux File System Introduction
What is a file system? The file system is In order to process information, the information is displayed in the form of a directory, and users can add, delete, modify and check And the user interface is the file name Linux real file system classification Information is stored in the kernel: sysfs, procfs, rootfs,
[Microcontroller]
A bug about arm-linux-gcc using the static keyword
# arm-linux-gcc -v xxx 4.3.3 /* main.c */ static unsigned *p = (unsigned*) (0x0000); /* When the external initialization is 0, everything is OK int main (void) { xxxxx; ...... ; } # arm-linux-gcc -O0 main.c -g -c -Wall When we do not add optimization, the file b
[Microcontroller]
Design of sensor network gateway system based on Linux
introduction Sensor network is a new research field in computer science and technology. The sensor network formed by integrating sensors, micro-electromechanical systems and networks is a new information acquisition and processing technology. In recent years, research on sensor network management, query and data distr
[Microcontroller]
Design of sensor network gateway system based on Linux
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
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号