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
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
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
- Popular Resources
- Popular amplifiers
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- Design and implementation of temperature control system based on MSP430
- [Erha Image Recognition Artificial Intelligence Vision Sensor] Evaluation 2: Built-in 7 functions, face recognition and other tests
- 【TouchGFX Design】Decomposition of the generated project directory structure and recommendation of two C++ introductory books
- consult
- Nuvoton's new development board Chili allows you to complete Linux application development in 40 minutes
- Common basic knowledge of 4G DTU
- [NXP Rapid IoT Review] + Alternative Experience Rapid IoT Studio online IDE
- LIS25BA package and evaluation board files
- L298N output voltage problem
- KiCad KiCost GOOD