Many of my friends are concerned about the driver, but most of them are cainiao. I/O drivers are changed to a simpler LED driver.
The work is very simple, is to make the led on the GPC0-GPC2 flash 10
The purpose is to demonstrate the driver process.
You don't need to read the basic knowledge first.
Concept of embedded driver
The device driver is the interface between the operating system kernel and the hardware of the machine. The device driver shields the hardware details from the application. In this way, the hardware device is just a device file, applications can operate on hardware devices like normal files. The device driver is a part of the kernel. It provides the following functions: Initialize and release the device, transfer data from the kernel to the hardware, and read data from the hardware; read the data that the application sends to the device file, send back the data requested by the application, and detect and process device errors.
Linux classifies devices into two basic categories: character devices and Block devices. The main difference between a character device and a block device is that when a read/write request is sent to a character device, the actual hardware I/O usually follows. Character devices perform sequential read/write operations in a single byte, without using the buffer technology. Block devices store and read/write data blocks of a fixed size, such as hard disks and floppy disks, A system memory is used as the buffer. To improve efficiency, the system provides a caching mechanism for block device read/write. The implementation is much more complex than that of character devices due to issues such as buffer management, scheduling, and synchronization. LCD is accessed and managed by character devices. Linux regards the display driver as a character device and sends the data to be displayed in one byte to the LCD driver.
Linux device management is closely integrated with the file system. Various devices are stored in the/dev directory as files, which are called device files. Applications can open, close, and read/write these device files to complete operations on the device, just like operating a common data file. To manage these devices, the system numbers the devices. Each device number is divided into the primary device number and secondary device number. The primary device number is used to distinguish different types of devices, while the secondary device number is used to distinguish multiple devices of the same type. For common devices, Linux has a conventional number, for example, the master device Number of the hard disk is 3. Linux provides a unified operation function interface for all device files by using the data structure struct file_operations. This data structure includes the pointers of many operation functions, such as open (), close (), read (), and write (). However, due to the many types of peripherals, the operation methods are different. The members in the struct file_operations struct are a series of interface functions, such as the read/write function for read/write and IOCTL for control. To open a file, call the open operation in file_operations. Different types of files have different file_operations member functions, such as common disk data files and interface functions to complete disk data block read/write operations. For various device files, then, I/O functions in the respective drivers are called to perform operations on specific devices. In this way, applications do not have to consider devices or common files. They can be processed as files with clear and unified I/O interfaces. Therefore, file_operations is an I/O interface at the file level.
I started writing
I used the method of adding comments to the Code, and uploaded several files at the same time. My favorite friends can download them as templates. Each file is separated by =
Three files, one driver header file, one driver file, and one driver testing program file must be written.
They are test. H, test. C, and ledtest. C.
Let's briefly talk about what drivers do and how to do it.
1. system load driver
2. Open the device (File) in the application)
3. The application operates on the device.
4. The application closes the device (file)
5. Disable the device.
How do applications operate on devices?
Do you remember how to write files in C? This is very similar. For general character devices (Block devices, network devices, and so on), there are three main functions (there are many, you can see) llseek read: Write: IOCTL: here only IOCTL: control function, of course, I/O ports can also be operated using read/write functions, but IOCTL: seems more suitable.
For specific implementation, see the ledtest. c file.
In test. C, there are several main functions responsible for initialization, cleaning, opening, and closing. And IOCTL writes some data to the serial port register.
There is a main sentence in the initialization and clearing, opening and closing functions, which has been commented out separately. Just remember.
Register operations are not mentioned separately. You need to read the 44b0 Data Manual. Let's see the rest of the code.
====================================
=========== Test. h ====================================
====================================
/*************************************** * Copyright (c) **************************************** **********
** Free
**
** -------------- File info -------------------------------
** File name: config. h
** Last modified Date: 2006-9-9
** Last version: 1.0
** Descriptions: User retriable File
**
**----------------------------------------------------
** Created by: zlg chenmingji
** Created Date: 2006-9-9
** Version: 1.0
** Descriptions: first version
**
**-------------------------------------------------
** Modified by: mamajinco
** Modified Date: 2006-9-9
** Version: 1.0
** Descriptions: I would like to express my sincere gratitude to zlg for its template. My high quality programming consciousness originated from this.
**
**************************************** *************/
// Prevent repeated macros set to include this file
# Ifndef _ config_h
# DEFINE _ config_h
// Include necessary header files
# I nclude <Linux/config. h>
# I nclude <Linux/module. h> // header file required by the module
# I nclude <Linux/kernel. h>/* printk () function, used to output information to the kernel */
# I nclude <Linux/fs. h>/* It is very important to include structures such as file_opration. This structure is used for file layer interfaces */
# I nclude <Linux/errno. h>/* error code */
# I nclude <ASM/uaccess. h>
# I nclude <Linux/types. h>
# I nclude <Linux/mm. h>
# I nclude <ASM/ARCH/jx44b0x. h>
/********************************/
/* Application configuration */
/********************************/
// The following changes are required
// Define the device name of the master device number
# Define led_major_nr 231 // 231 ~ 239 240 ~ 255
# Define device_name "led"/* name for messaging */
# Define set_led_off 0
# Define set_led_on 1
# Endif
/************************* End of File
**************************************** *****************/
================ End ========================
====================================
=============== Test. c ==============================
====================================
/************* Copyright (c) **************************
** Free
**
** -------------- File info -----------------------------------------
** File name: Test. c
** Last modified Date: 2006-9-9
** Last version: 1.0
** Descriptions: User retriable File
**
**----------------------------------------------------
** Created by: zlg chenmingji
** Created Date: 2006-9-9
** Version: 1.0
** Descriptions: first version
**
**--------------------------------------------------------
** Modified by: mamajinco
** Modified Date: 2006-9-9
** Version: 1.0
** Descriptions: I would like to express my sincere gratitude to zlg for its template. My high quality programming consciousness originated from this.
**
**************************************** *******************/
# I nclude "test. H" // contains the driver header file
/*************************************** *********************
Function announce
**************************************** **************/
// The following is the declaration of key functions
Static int led_open (struct inode * inode, struct file * filp );
// Use Linux to enable the device as a file management device. It is best not to enable the device before it is used.
Static int led_release (struct inode * inode, struct file * filp );
Static int led_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
Unsigned Long Param );
// The control function is used to control the LED light-on and off.
Int led_init (void); // when registering, note that the module registers as early as possible.
Void led_cleanup (void); // used for uninstallation
/*************************************** **********************
** "Global and static variables are defined here"
** Global variables and static variables define here
/*************************************** *************************/
Static struct file_operations led_fops =/* Important struct mentioned in the basic section */
{
Owner: this_module,
# If 0/* Note: # If 0-# The code in endif is not compiled, but the integrity of the driver template is still added here */
Llseek: gpio_llseek,
Read: gpio_read,
Write: gpio_write,
# Endif
IOCTL: led_ioctl, // Control Function
Open: led_open, // open the function and initialize it when opening the file
Release: led_release, // release function, called when disabled
};
/*************************************** ***********************
** Function name: led_open
** Descriptions: open device
** Input: inode: Information of Device
** Filp: pointer of File
** Output 0: OK
** Other: Not OK
** Created by: chenmingji
** Created Date: 2006-9-9
**-------------------------------------------------------------
** Modified by: mamajinco
** Modified Date: 2006-9-9
**--------------------------------------------------------------
**************************************** **********************/
Static int led_open (struct inode * inode, struct file * filp)
{
/* Put the initialization in open */
(* (Volatile unsigned *) jx44b0x_pconc) & = 0xffffffc0;
(* (Volatile unsigned *) jx44b0x_pconc) | = 0xffffffd5;/* gpio C port 0 ~ 2 set to output */
(* (Volatile unsigned *) jx44b0x_pupc) & = 0xffffffc0;/* gpio C port 0 ~ 2 set to pull up */
Mod_inc_use_count;
Return 0;
}
**************************************** *****************
** Function name: led_release
** Descriptions: Release Device
** Input: inode: Information of Device
** Filp: pointer of File
** Output 0: OK
** Other: Not OK
** Created by: chenmingji
** Created Date: 2006-9-9
**-----------------------------------------------------
** Modified by: mamajinco
** Modified Date: 2006-9-9
**--------------------------------------------------------
**************************************** ************/
Static int led_release (struct inode * inode, struct file * filp)
{
Mod_dec_use_count;
Return (0 );
}
/*************************************** *************
** Function name: led_ioctl
** Descriptions: Io Control Function
** Input: inode: Information of Device
** Filp: pointer of File
** Cmd: Command
** Arg: additive Parameter
** Output 0: OK
** Other: Not OK
** Created by: chenmingji
** Created Date: 2006-9-9
**-------------------------------------------------------
** Modified by: mamajinco
** Modified Date: 2006-9-9
**----------------------------------------------------------
**************************************** *******************/
Static int led_ioctl (struct inode * inode, struct file * filp,
Unsigned int cmd, unsigned long Arg)
{
If (Arg> 2) // determine whether Io belongs to 0-2
Return-1;
Switch (CMD)
{
Case 0: // convert the IO port number from Arg to register data, and set the corresponding IO port to a lower value.
(* (Volatile unsigned *) jx44b0x_pdatc) | = 0x1 <ARG;
Break;
Case 1: // convert the IO port number from Arg into register data and set the corresponding IO port to a high value.
(* (Volatile unsigned *) jx44b0x_pdatc) & = 0x0 <ARG;
Break;
Default:
Return-1;
Break;
}
Return 0;
}
/*************************************** ***********
** Function name: led_init
** Descriptions: init driver
** Input: None
** Output 0: OK
** Other: Not OK
** Created by: chenmingji
** Created Date: 2006-9-9
**------------------------------------------------
** Modified by: mamajinco
** Modified Date: 2006-9-9
**-----------------------------------------------------
**************************************** *********/
Int led_init (void)
{
Int result;
Result = register_chrdev (231, "led", & led_fops );
/* Key statements are used for registration.
** Note! This is a traditional registration method. In Linux 2.4 and later versions, the devfs device file system is added to make registration easier. However, the old method is still used here for the convenience of most documents **. */
If (result <0) // used for exception detection
{
Printk (kern_err device_name ": Unable to get Major % d/N", led_major_nr); // printk is used to output information to the kernel
Return (result );
}
Printk (kern_info device_name ": init OK/N ");
Return (0 );
}
/*************************************** **********************
** Function name: led_cleanup
** Descriptions: Exit driver
** Input: None
** Output none
** Created by: chenmingji
** Created Date: 2006-9-9
**--------------------------------------------------------
** Modified by: mamajinco
** Modified Date: 2006-9-9
**-----------------------------------------------------
**************************************** **********/
Void led_cleanup (void)
{
Unregister_chrdev (231, "led"); // pair with register_chrdev for clear driver
}
/*************************************** ********************
** End of File
**************************************** ************/
==================== End ================
============================================
=============== Ledtest. c ==========================
==========================================
/********************** Copyright (c) **************************
** Free
**
** -------------- File info ----------------------------
** File name: LED. c
** Last modified Date: 2006-9-9
** Last version: 1.0
** Descriptions: User retriable File
**
**-------------------------------------------------------
** Created by: zlg chenmingji
** Created Date: 2006-9-9
** Version: 1.0
** Descriptions: first version
**
**--------------------------------------------------------
** Modified by: mamajinco
** Modified Date: 2006-9-9
** Version: 1.0
** Descriptions: I would like to express my sincere gratitude to zlg for its template. My high quality programming consciousness originated from this.
**
**************************************** ****************/
# I nclude <stdio. h>
# I nclude <stdlib. h>
# I nclude <unistd. h>
# I nclude <fcntl. h>
# I nclude <sys/types. h>
# I nclude <sys/STAT. h>
Void delay (INT delay) // latency Function
{
Int I;
For (; delay> 0; delay --)
{
For (I = 0; I <5000; I ++ );
}
}
Int main ()
{
Int fd1;
Int J;
Fd1 = open ("/dev/led", o_rdwr);/* Open the device, just as easy as opening a file */
If (fd1 =-1)/* Exception Handling */
{
Printf ("file can not be open ");
Return-1;
}
For (j = 0; j <10; j ++)/* repeat 10 times */
{
IOCTL (fd1, 1, 0);/* led on gpc0 */
Delay (1000 );
IOCTL (fd1, 0, 0);/* led off on gpc0 */
IOCTL (fd1, 1, 1);/* led on gpc1 */
Delay (1000 );
IOCTL (fd1, 0, 1);/* led off on gpc1 */
IOCTL (fd1, 1, 2);/* led on gpc2 */
Delay (1000 );
IOCTL (fd1, 0, 2);/* led off on gpc2 */
Delay (1000 );
}
Close (fd1);/* close the device (File )*/
Return 0;
}
==================== End ====================
Three drivers are compiled into the kernel
Notes for cainiao during compilation
1 is typed incorrectly, including the above function!
Even if you throw bricks, it takes a lot of time to compile them into the kernel ~~ The most important thing is that the "make" error prompt is a concern for cainiao. Do not set obstacles for yourself! In our team, we often encounter such errors, especially the commands and characters copied from the book, l, 1, and I. How do you score? The last one is an uppercase I :)
2. Do not use the Chinese file name including ABC (duplicate)
Otherwise make errors
3. Modify existing files in the original format. Otherwise, it is difficult for cainiao to avoid making low-level errors.
Let me remember the IBM Rule Summary Test Question: 6 13 7 14 8 what is the next number?
Now, start modifying!
==================== Start =======================
UClinux-Dist/linux-2.4.x/Drivers/Char/makefile
----------------------------------------------
OBJ-$ (config_c5471_wdt) + = wdt_c5471.o and then add
OBJ-$ (config_test) + = led. o
====================== End ==============
======================== Start ==============
UClinux-Dist/linux-2.4.x/Drivers/Char/config. In
-----------------------------------------
If ["$ config_cpu_jx44b0x" = "Y"]; then
Bool 'samsung 44b0x serial ports support 'config_serial_jx44b0x and then add
Bool 'test LED driver 'config_test
====================== End =============================
======================== Start ===================
UClinux-Dist/linux-2.4.x/Drivers/Char/MEM. c
-----------------------------------------
Get together at the beginning
# Ifdef config_ledtest
Extern void led_init (void );
# Endif
Int _ init chr_dev_init (void) followed
# Ifdef config_test
Led_init ();
# Endif
====================== End ==================
======================== Start ==================
UClinux-Dist/vendors/Samsung/44b0/makefile
-----------------------------------------
Ttypc, C, 3,12 ttypd, C, 3,13 tType, C, 3,14 ttypf, C, 3,15/
/
Led, C, 231,0/
====================== End ==================
4. Compile the program into the kernel
Nothing to say, just like a simple program written in the past, but I will repeat it here.
====================== Start ==================
UClinux-Dist/user/makefile
-----------------------------------------
Add the following to the heap.
Dir _ $ (config_user_ledtest) + = ledtest
========================== End ======================
====================== Start ==================
UClinux-Dist/config/configure. Help
-----------------------------------------
Add the following to the heap.
Config_user_ledtest
Test the LED Driver
======================== End ================
====================== Start ===========================
UClinux-Dist/config/configure. In
-----------------------------------------
##############################
Mainmenu_option next_comment
Comment 'led driver test PG'
Bool 'ledtest' config_user_ledtest
Endmenu
###############################
======================== End ================
5. Compile and write ...... Let's skip the 200 words and read my helloworld compilation notes.
Perform the following operations on the board
1 CD/dev
2 ls
Did you see an LED in it?
3 CD/proc
4 cat Devices
See the driver list?
Led 231 should also be in it
5 ledtest
Execute this statement anywhere.
Check the C port level of gpio later :)