[Original] How to Write a dynamic loaded uClinux driver

Source: Internet
Author: User

The precondition is that the working directory is under/usr/local/src. Write the de0_led.c driverProgram, As follows:

# Include <Linux/module. h>

# Include <Linux/kernel. h>

# Include <Linux/version. h>

# Include <Linux/init. h>

# Include <Linux/types. h>

# Include <Linux/string. h>

# Include <Linux/slab. h>

# Include </usr/local/src/uClinux-Dist/linux-2.6.x/include/asm-nios2nommu/IO. h>

# Include </usr/local/src/uClinux-Dist/linux-2.6.x/include/asm-nios2nommu/page. h>

# Include </usr/local/src/uClinux-Dist/linux-2.6.x/include/asm-nios2nommu/uaccess. h>

# Include <Linux/sched. h>

# Include <Linux/fs. h>

# Include <Linux/proc_fs.h>

# Include </usr/local/src/uClinux-Dist/linux-2.6.x/include/Linux/sysctl. h>

// # Include </usr/local/src/uClinux-Dist/linux-2.6.x/include/asm-nios2nommu/nios2.h>

# Include </usr/local/src/uClinux-Dist/linux-2.6.x/include/nios2_system.h>

 

# Define de0_led_major 120 // major number 120

Static char de0_led_name [] = "de0_led ";

Static int de0_led_open (struct inode * inode, struct file * file)

{

Printk ("Open the de0_led device, Major: % d, minor: % d \ n", Major (inode-> I _rdev), minor (inode-> I _rdev ));

Try_module_get (this_module );

Return 0;

}

Static int de0_led_release (struct inode * inode, struct file * file)

{

Printk ("Release the de0_led device! \ N ");

Module_put (this_module );

Return 0;

}

Static ssize_t de0_led_read (struct file * filp, char _ User * buff, size_t Len, loff_t * PPOs) // 32

{

Printk ("read de0_led device \ n ");

Int bytes_read = 0;

Bytes_read = na_led-> np_piodata; // 36

Printk ("bytes_read = % d \ n", bytes_read );

If (copy_to_user (buff, (char *) & bytes_read, sizeof (INT )))

{

Return-efault;

}

Return Len;

}

Static ssize_t de0_led_write (struct file * file, const char _ User * buff, size_t Len, loff_t * Off)

{

Unsigned int data_write = 0;

If (copy_from_user (char *) & data_write, buff, sizeof (INT) // 47

Return-efault;

Na_led-> np_piodata = data_write;

Return Len;

}

Static struct file_operations de0_led_fops = {

Owner: this_module,

Open: de0_led_open,

Release: de0_led_release,

Read: de0_led_read,

Write: de0_led_write // 57

};

Static int _ init led_init (void)

{

Printk ("init the module! \ N ");

Int err;

If (ERR = register_chrdev (de0_led_major, de0_led_name, & de0_led_fops) <0)

{

Printk ("register_chrdev failed! Error code = % d \ n ", err );

Return err;

}

Return 0;

}

Static void _ exit led_exit (void)

{

Printk ("Exit module !! \ N ");

Unregister_chrdev (de0_led_major, de0_led_name );

}

Module_init (led_init );

Module_exit (led_exit );

Module_license ("GPL ");

 

Put the written driver file under the linux-2.6/Drivers/Char and modify the kconfig and makefile files under the folder.

Add:

Config de0_led

Tristate "Nio led support"

Help

De0_led driver

 

Add the following in makefile:

OBJ-$ (config_de0_led) + = de0_led.o

 

Run make menuonfig to configure the kernel. To allow the operating system to support dynamic loading, You must select loadable module support in Linux Kernel configuration, then enter the device drivers option in Linux Kernel configuration, find character devices, and enter, find the newly added NiO led support and select m to dynamically load it. Save and exit.

The processing of user programs is the same as that of Hello world. Now, the SRC folder is compiled with a cross tool chain to copy the generated executable files to romfs/bin.

The next step is to compile the kernel, make.

Here we will summarize the steps for writing the drivers:

    1. Define the master device number and device name
    2. Define the functions implemented by the driver, and initialize the file_operations struct variable according to the defined functions.
    3. Compile the corresponding function bodies according to the defined functions, such as reading and writing functions, and turn on and off functions. When enabling function execution, you must first add a device counter to inform the system that the device is in use. You can also complete some hardware register settings in the open function. This is generally the first time you open the device. The function is used to reduce the device counter by one and inform the kernel that this process is no longer using this device.
    4. Compile the device Loading Function, also called the initialization function. In the initialization function, the device registration and some hardware-related register settings are completed.
    5. Compile the device uninstall function, which acts on the opposite of the load function.
    6. Use a macro to define the loading and unloading functions of a specified module.
    7. Other optional macro definitions.

After the driver program is compiled, use the user program to verify whether it works normally. User programs do not show hardware registers, but open files, read and write files, close files and other operations. All devices are processed as files. The LED driver test procedure is as follows:

# Include <stdio. h>

// # Include <linux-2.6.x/include/ASM/nios2.h>

# Include <string. h>

# Include <malloc. h>

# Include <sys/types. h>

# Include <sys/STAT. h>

# Include <fcntl. h>

# Include <unistd. h>

# Include <signal. h>

# Include <sys/IOCTL. h>

 

Void mydelay (INT count)

{

Int I;

Int J;

J = 0;

For (I = 0; I <count; I ++)

{

J = J + I;

}

}

 

Int main ()

{

Int FD;

Int count;

Char I = 0;

Unsigned char buff [] = {0xfe, 0xfe, 0xfe, 0xfe };

 

If (FD = open ("/dev/de0_led", o_rdwr) =-1)

{

Perror ("Open eror ");

Exit (1 );

}

While (1)

{

/* If (COUNT = read (FD, (char *) buff, 4 )! = 4)

{

Perror ("read error ");

Exit (1 );

}*/

 

Mydelay (100000 );

 

If (COUNT = write (FD, (char *) buff, 4 )! = 4)

{

Perror ("write error ");

Exit (1 );

}

 

Mydelay (100000 );

I ++;

Buff [4] = I;

 

 

}

}

After running the uClinux system, run the Altera nioii eds 11.0 command to communicate with the system. The path of the loadable module in uClinux is/lib/modules/2.6.19-uc1/kernel/Drivers/Char/

Go to this directory and run insmod de0_led.ko to install the kernel module.

Then create a device node and run mknod/dev/de0_led C 120 0

120 indicates the master device number, 0 indicates the secondary device number, and C indicates the char device.

After successfully registering the device and establishing the device node, return to the root directory: CD/

Run the user program and enter the command led_app.

The LED light turns on to prove that the driver works properly.

Note: The function of the user test program is endless, and the light should flash, but the actual effect is not blinking, but always on. Later, I checked the driver carefully and found the problem. After changing the device write function to the following driving mode, the LED will flash as specified by the user program.

Static ssize_t de0_led_write (struct file * file, const char _ User * buff, size_t Len, loff_t * Off)

{

Char data_write [4] = {0 };

If (copy_from_user (data_write, buff, sizeof (INT) // 47

Return-efault;

Na_led-> np_piodata = (data_write [0] | (data_write [1] <8) | (data_write [2] <16) | (data_write [3] <24 ));

Return Len;

}

The previous driver was copied from another user. If there is a problem with the driver, it will be wrong to forcibly convert the address of the int variable to the char * type, if the address value of the int variable is greater than 8 bits, after it is forcibly converted to char *, only the last 8 bits are retained, and all the preceding values are gone. For example, if this address is used to write data, will not respond to the LED. In addition, the system program may crash. UClinux has no memory protection, that is, users may accidentally access the system's memory space and modify the system'sCodeThe memory does not matter, so you should be very careful when writing the program.

 

 

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.