Design of ADS8364 Driver in Embedded Data Acquisition System

Publisher:幸福约定123Latest update time:2012-03-23 Source: 微计算机信息 Keywords:Linux Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

1 Introduction

The working principle of the data acquisition system is to convert various parameters (which can be physical quantities, chemical quantities, or biological quantities) of the measured object (external world or field) through various sensor elements, and then go through signal conditioning, sampling, quantification, encoding, transmission and other steps, and finally send them to the server for data processing and storage and recording. The complete set of equipment used for data acquisition is called a data acquisition system (DAS).

The data acquisition system generally includes sensors, amplifiers, filters, A/D sampling conversion circuits, microprocessors and other components. The basic composition diagram of the data acquisition system is shown in Figure 1. The A/D conversion circuit plays a vital role in the data acquisition system. Its conversion accuracy and working reliability are directly related to the working performance of the entire acquisition system. Due to limited space, this article only summarizes the driver development process of the A/D conversion chip ADS8364 in the data acquisition system.

Figure 1 Schematic diagram of data acquisition system composition

2 ADS8364 Functional Overview

ADS8364 is a high-performance analog-to-digital conversion chip produced by TI in the United States. It has high speed, low energy consumption, 6 channels of synchronous sampling and conversion, single +5V power supply, and 16-bit high-speed parallel interface. It also has 6 fully differential input channels with 80dB common mode rejection, 6 4μs continuous approximation analog-to-digital converters, and 6 differential sampling/holding amplifiers [1]. The 6 analog inputs of ADS8364 are divided into 3 groups (A, B and C). Each input has an ADCs hold signal to ensure that several input channels can be sampled and converted at the same time, so that the phase difference between the signals of different analog input channels can be preserved. When the 3 hold signals are selected at the same time, the 6 ADCs are converted synchronously, and the conversion results will be stored in 6 registers. The sampling frequency is up to 250KHz, and the noise resistance is good.

3 Basic Principles of Device Driver Development

The device driver is the interface between the operating system kernel and the machine hardware. It shields the application from the hardware details and converts the application's operation on the device into the operation on the corresponding device file, so that the application can open, close, read and write the device like operating ordinary files, using the standard system calls for processing ordinary files. As part of the kernel, the device driver mainly completes the following functions: initialize and release the device; complete the data exchange between the hardware and the kernel; complete the data exchange between the kernel and the application layer; detect and handle possible errors.

In the Linux system, the opened device is identified by the device file structure inside the kernel, and the kernel uses the file_operations structure to access the driver's functions. Each file is associated with its own set of functions (implemented by a pointer to the file_operations structure contained in the device), which is mainly responsible for the implementation of system calls. When the user process uses the system call to operate the device file, the system call finds the corresponding device driver through the device's major device number, then reads the corresponding function pointer of this data structure, and then transfers control to the function. This is the basic principle of the Linux device driver. It can be seen that the main task of writing a device driver is to write the sub-function in file_operations to complete the operation of the device.

In order to achieve device independence, Linux divides devices into three types: character devices, block devices, and network devices [2]. Each type of device has a unique management and control method and different drivers. This allows the drivers that control different devices to be separated from other parts of the operating system. This not only facilitates the management of different devices, but also provides a lot of convenience for adding and removing certain devices in the system. Here, we regard ADS8364 as a character device driver, and its driver is the character device driver. [page]

4 ADS8364 Driver Design Overview

4.1 Driver LKM Implementation Mechanism

The Linux kernel provides two mechanisms for developing device drivers. One is to compile the driver directly into the kernel and make it part of the Linux kernel. The other is to develop a driver module that can be dynamically loaded and unloaded through LKM (Loadable Kernel Module) [3]. If the driver is compiled into the kernel, the kernel size will increase, and the kernel source files will need to be modified. In addition, it cannot be dynamically unloaded, which is not conducive to debugging. Therefore, this system writes the ADS8364 driver as an LKM driver (that is, the ADS8364 driver is used as an independent unit module, which can be loaded into the kernel using the insmod command when in use, and unloaded using the rmmod command after use).

4.2 Driver Registration and Deregistration

Adding a driver to the system means assigning it a major device number, which is done during the initialization of the driver module. The initialization entry function of ADS8364 is defined as follows:

int _init ads8364_init_module(void) Full-featured version of J-LINK ARM emulator V6.0

{ …..

ret = register_chrdev(11, ADS8364, &ad_fops);

……}

When the compiled module is loaded into memory using the insmod command, the ads8364_init_module() function is called. Here, ads8364_init_module() does only one thing, it calls the register_chrdev() function to register the character device with the kernel. The register_chrdev() function is defined in . register_chrdev requires three parameters. The first parameter is the device number you want to obtain. If it is zero, the system will automatically select an unoccupied device number as the major device number of the character device and return it. The second parameter is the device file name. This name must be inserted into the /dev directory and connected to the major and minor device numbers of the driver. The third parameter is used to register the pointer to the function that actually performs the operation of the driver. If the registration is successful, the major device number of the device is returned. If it is unsuccessful, a negative value is returned. Here, we choose the currently unused device number 11 as the major device number of ADS8364, and the device name is ADS8364.

When closing a character device or block device, you also need to unregister the device from the kernel and release the major device number using unregister_chrdev(). When uninstalling the driver module using rmmod, the cleanup_module function is called, which releases the entry occupied by the character device ADS8364 in the system character device table.

void ads8364_cleanup_module(void)

{ unregister_chrdev(11, ADS8364); info("ADS8364 cleanup module ok!"); }

4.3 Design of file_operations structure

In Linux, the interface function set provided by character devices to the kernel is the file operation set file_operations structure. In the Linux system, the opened device is identified by the device file file structure inside the kernel, and the kernel uses the file_operations structure to access the driver's functions. Each file is associated with its own set of functions (implemented by the f_ops pointer segment containing the file_operations structure), which is mainly responsible for the implementation of system calls [4]. In order to make the driver more portable when the definition of the structure changes, and to make the code more compact and easier to read, we first use the tokenized format to declare the file_operations structure of ADS8364:

static struct file_operations ad_fops = {Full-function version J-LINK ARM emulator V6.0

owner: THIS_MODULE, /* the device module to which ad_fops belongs*/

read: ads8364_read, /*read data from the device*/

poll: ads8364_poll, /*Query device status*/

ioctl: ads8364_ioctl, /*Device I/O control*/Full-function version J-LINK ARM emulator V6.0

open: ads 8364_open, /*Open device operation*/

release: ads 8364_release, /*release operation*/

};

The file_operations structure associates system calls with drivers. The name of each member of this structure corresponds to a system call. When the user process uses the system call to perform operations such as read, write, open, etc. on the device file, the system call finds the corresponding device driver through the major device number of the device file, then reads the corresponding function pointer of this data structure, and then transfers control to the function. This is the basic principle of the ADS8364 driver. In this case, the main task of writing a device driver is to write sub-functions and fill in the various fields of file_operations. Next, we will introduce the functions of each field of file_operations and the main calling functions.

1) Device I/O control operation function

Compared with ordinary files, the operation of device files is much more complicated and cannot be simply implemented through read, write, and llseek, etc. All other types of operations can be performed through VFS ioctl calls. The function definition is as follows:

static int ads8364_ioctl(struct inode * inode, struct file *filp, unsigned int cmd, unsigned long arg)

ads8364_ioctl is a function in the ADS8364 driver that manages the I/O channels of the device. The parameter inode is the file identifier returned by the open function when the user program opens ADS8364, and cmd is the control command of the user program to ADS8364. It is the only way to connect the user program command and the driver support. This function distinguishes operations through cmd and passes parameters and results through arg. In the body of the ads8364_ioctl function implemented in the driver, there is a switch{case} structure. Each case corresponds to a command code and performs some corresponding operations. The key to the design of ads8364_ioctl is how to generate the cmd command code in the user program and parse it in the driver. Therefore, the switch{case} structure is crucial in ads8364_ioctl, because the I/O control of the device is implemented through this part of the code. [page]

The contents of the cmd parameter are mainly as follows: by calling the copy_from_user() kernel function, the data structure passed by the parameter arg in the application is transferred to the same type of structure in the kernel; sampling start control command, by calling the sampling start function, enable the AD start control pin to start sampling, this function passes the data structure passed by the parameter arg in the application to the same type of structure in the kernel by calling the copy_from_user() kernel function; obtain the sampling frequency, and control the ADS8364 to sample according to the sampling frequency required by the user.

2) Query device status operation

static unsigned int ads8364_poll(struct file * filp, poll_table * wait)

This function is used to query the status of ADS8364 so that the user program can know whether it can access the device non-blockingly. Its design is relatively simple. It calls the API function poll_wait() to add the currently blocked process to the waiting list (poll_table) specified by the wait parameter.

3) Read data from the device

static ssize_t ads8364_read(struct file * filp, char * buf, size_t count, loff_t * l) Full-featured version of J-LINK ARM emulator V6.0

This function is called by the user program. It mainly reads the converted data in the kernel space into the user space by calling the kernel function copy_to_user(). This is the interface function for exchanging data between the kernel and the user.

4) Open the device operation

static int ads8364_open(struct inode * inode, struct file * filp)

The ads8364_open() function must do the necessary preparations for the upcoming I/O operation, such as calling the kernel function memset() to clear the buffer, enabling interrupts, etc. If the device is exclusive, that is, only one program can access this device at the same time, the open() subroutine must set some flags to indicate that the device is "busy". When it is a NULL pointer, the device open operation will always succeed, but the system will not notify your driver.

5) Release device operation

static int ads8364_release(struct inode * inode, struct file * filp) Full-featured version of J-LINK ARM emulator V6.0

ads8364_release is the reverse operation of ads8364_open, and is mainly used to release the space occupied by the driver, disable interrupts, etc.

4.4 Interrupt Handler

The program that responds to interrupts and provides corresponding services is called an interrupt handler. In the driver of ADS8364, the main function of the interrupt handler is to control ADS8364 to sample and put the sampled data into the buffer, waiting for the application to call the read function to read. We register the interrupt handler to the system, and the operating system calls the interrupt handler of the driver after the hardware interrupt occurs. The function definition is as follows:

static void ads8364_interrupt(int irq, void *dev_id, struct pt_regs *regs)

{…..

stat = AT91_SYS->PIOB_PDSR; //Read the interrupt level. If it is low, control ADS8364 to start sampling.

/*Single chip acquisition 6 channels*/Full-function version of J-LINK ARM emulator V6.0

for(j=0;j<6;j++) { tmpdata=*(volatile u16 *)(ADOFFSET[i][j]+RtPara.remapptr); *(ad_priv->head_ptr++)= tmpdata;}

…..}

5 Loading the driver into the Linux kernel

After the programming design of the above parts, our ADS8364 driver has been designed. The above parts of the program are combined into a source program file and named ADS8364drv.c. Then, after the following steps, it is loaded into the kernel. Then our ADS8364 chip can work under the control of the driver. The specific loading operation is as follows: Full-featured version of J-LINK ARM emulator V6.0

1) Copy the driver source code ADS8364drv.c to the arm/linux/drives/char/directory.

2) Modify the Makefile file in the arm/linux/drives/char/ directory and add the following statement in the file: obj-$(ADS8364_drv)+= ADS8364drv.o.

3) Modify the config.in file in the arm/linux/drives/char/ directory and add the following statement.

bool 'ADS8364_drive' ADS8364_drv.

6 Conclusion

This article describes the design of AD driver in embedded data acquisition system, and explains the method and process of developing ADS8364 character device driver. The author's innovation is: this embedded data acquisition system uses embedded ARM chip AT91RM9200 as processor and high-precision ADS8364 as AD conversion chip, realizing multi-channel, high-precision data acquisition and AD conversion. The ADS8364 driver designed with LKM mechanism can reduce kernel space, which has certain guiding significance for the study and development design of other character devices.

References

1ADS8364 Technical Document. Texas Instruments. 2002.6http://www.51kaifa.com/shop/read.php?ID=4823

2 Zheng Wei, Wang Qinruo, Wu Naiyou. Development of Linux kernel space device driver [J]. Full-featured version of J-LINK ARM emulator V6.0 Microcomputer Information, 2003, 12: 85-87

3. Sun Tianze, Yuan Wenju, Zhang Haifeng. Embedded Design and Linux Driver Development Guide - Based on ARM9 Processor [M]. Beijing: Publishing House of Electronics Industry, 2005

4 Wei Yongming, Luo Gang et al. Translated. Linux Device Drivers (Second Edition) [M]. Beijing: China Electric Power Press, 2002

Keywords:Linux Reference address:Design of ADS8364 Driver in Embedded Data Acquisition System

Previous article:Embedded Application in Small Network Video Server
Next article:Research on Embedded Hardware System Model Based on UML

Recommended ReadingLatest update time:2024-11-16 19:50

ARMLinux driver transplantation Watch Dog Timer (watchdog) driver transplantation
Hardware platform: FL2440 (S3C2440) Kernel version: 2.6.28 Software platform: Ubuntu 11.04 Kernel version: 2.6.39 Cross compiler: arm-linux-gcc 3.4.1 Original work, please indicate the source when reprinting 1. Load the watchdog driver insmod wdt.ko wdt.ko is the driver file name. If no parameters are ad
[Microcontroller]
ARMLinux driver transplantation Watch Dog Timer (watchdog) driver transplantation
Tiny 6410 Linux learning summary!
1. Modify the IP address of Tiny6410 Linux system: vi /etc/eth0-setting 2. Ubuntu14.04 automatically logs in to the system as root: /etc/lightdm/lightdm.conf Change to the following: Automatically log in as Root after reboot autologin-guest=false
[Microcontroller]
ARM Knowledge--"Some Problems with ARM and Linux" Chapter 1: ARM Working Mode
=====================================================     Early ARM cores had state (ARM or Thumb) switching (using BX and other instructions to modify the T control bit in the CPSR register (current program status register, which stores condition code flags, interrupt disable bits, current processor mode, and other s
[Microcontroller]
Establishing ARM+Linux operating environment
In the previous stage, I mainly edited and debugged the code under Windows XP through ADS1.2, H-JTAG and DNW. Now I switch to Linux and use RedHat9.0+ virtual machine as the development environment. Here I will summarize the configuration of the environment and the problems encountered in the past two days.         
[Microcontroller]
Object-oriented driver programming - interrupt (linux system, s3c6410 development board)
/*------------------------- *First of all, I am a novice and just started to write driver programs. I will explain the development environment (host system redhat6.3, development board ARM-s3c6410) Take watchdog (commonly known as dog interrupt) as an example to write a simple interrupt (driver) -----
[Microcontroller]
Research on frequency sweeper based on Linux multi-task operating system
1 Introduction The frequency sweeper is an instrument suitable for measuring the frequency response of a system. The frequency response of a system includes two aspects: amplitude-frequency response and phase-frequency response. At present, in the implementation of the frequency sweeper, the hardware platfo
[Test Measurement]
Research on frequency sweeper based on Linux multi-task operating system
ARM-Linux S5PV210 UART driver (3) ----Serial port core layer, key structures, interface relationships
Although a specific UART device driver can be designed according to the design method of tty driver, that is, defining tty_driver and implementing the member functions of tty_operations, Linux has implemented a general tty driver layer for UART devices in the file serial_core.c, called the serial port core layer. In
[Microcontroller]
ARM-Linux S5PV210 UART driver (3) ----Serial port core layer, key structures, interface relationships
Design of multifunctional integrated communication control system based on ARM9
    With the rapid development of computer technology, industrial data acquisition has evolved from traditional measurement and control circuits to modern data acquisition and control systems consisting of microcomputers, interface circuits, external general equipment, and industrial production objects. However, data a
[Microcontroller]
Design of multifunctional integrated communication control system based on ARM9
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号