Transplantation of Linux-2.6.32.2 Kernel on mini2440 (15th)-porting LED driver

Source: Internet
Author: User

Port Environment (Bold font in redIs the modified content,Blue bold ChineseFor special attention)

1. host environment: centos 5.5 and 1 GB memory in vmare.

2. Integrated Development Environment: Elipse ide

3. compiling environment: Arm-Linux-GCC v4.4.3 and arm-None-Linux-gnueabi-GCC v4.5.1.

4. Development Board: mini2440, 2 m nor flash, 128 m nand Flash.

5, U-boot version: u-boot-2009.08

6, Linux: linux-2.6.32.2

7. References:

Complete embedded Linux application development manual, edited by Wei Dongshan.

Mini2440 Linux porting Development Practice Guide

Embedded Linux-LED driver instance development in 2440

[1] principle and writing of LED Driver

The LED driver introduced here is actually a very typical character device driver, just like the "Hello, world" program when learning C language, it represents your understanding of the embedded Linux driver, so we will give a detailed introduction and analysis of this driver, in order to have a deep understanding of
Method and principle.
Note: In the mini2440 user manual, we have already introduced the LED driver. The following content is also based on the user manual.
To write the actual driver, you must understand the relevant hardware resources, such as registers, physical addresses, and interruptions used. In the schematic of mini2440, we can see that the hardware connection of the LED is as follows:

Check the S3C2440 Data Manual. The following table lists their hardware resources.

Led serial number Corresponding gpio

Corresponding CPU pin

Led1 Gpb5 K2
Led2 Gpb6 L5
Led3 Gpb7 K7
Led4 Gpb8 K5

Gpio is short for general input and output ports. In the S3C2440 chip, many ports are reusable. gpio is only one function, such as the gpb5 port, it can be used as either a common gpio or a dedicated nxback function, so we need to set the corresponding port register to change the usage of the pin.
Here, four LEDs use four groups of 2bit bits in the gpbcon register to configure the purpose of the corresponding pins. The functions of the four groups of 2bit bits are the same: 00 indicates input, 01 indicates output, 10 indicates special functions, and 11 indicates reserved. See the following:

On the mini2440 Development Board,
Led1 corresponds to gpb5, and gpb5 uses the [] bits.
Led2 corresponds to gpb6, and gpb6 uses the [] bits.
Led3 corresponds to gpb7, and gpb7 uses the [] bits.
Led4 corresponds to gpb8, and gpb8 uses the [16: 17] bits.
Therefore, you must first set the led to the output state in the driver, that is, set the corresponding gpbx to 01.

The gpbdat register is used to correspond to the numerical states of four LEDs. gpbdat5 corresponds to gpb5, and gpbdat6 corresponds to gpb6, and so on. According to the schematic diagram, it can be seen that when the gpio output is low, it is effective, that is, when the position of the gpbdat register is 0, gpb5, 6, 7, 8 will output a low level, and the corresponding led will emit light.

In software, to operate the I/O Ports used, we usually call some ready-made functions or macros, such as: s3c2410_gpio_cfgpin. Why is it S3C2410? Because the Register names and resource allocation used by Samsung's S3C2440 chip are mostly the same as those of S3C2410, the same function definition and macro definition are mostly used in various versions of Linux systems.
Where are they defined? Careful users may soon think that they are related to the architecture, so you can
Linux-2.6.32.2/ARCH/ARM/plat-s3c24x/gpio. in the c file, find the definition and implementation of the function. The definition and implementation of the function may also change due to the kernel version change, but we only need to know about it here, because the name of the function is generally not changed, we can find the header file containing the function in other driver source code, and then copy it here, in gpio. in the c file, the implementation of the s3c2410_gpio_cfgpin function is as follows:

Void s3c2410_gpio_cfgpin (unsigned int pin, unsigned int function)
{
Void _ iomem * base = s3c24xx_gpio_base (PIN );
Unsigned long mask;
Unsigned long con;
Unsigned long flags;

If (PIN <s3c2410_gpio_bankb ){
Mask = 1 <s3c2410_gpio_offset (PIN );
} Else {
Mask = 3 <s3c2410_gpio_offset (PIN) * 2;
}

Switch (function ){
Case s3c2410_gpio_leave:
Mask = 0;
Function = 0;
Break;

Case s3c2410_gpio_input:
Case s3c2410_gpio_output:
Case s3c2410_gpio_sfn2:
Case s3c2410_gpio_sfn3:
If (PIN <s3c2410_gpio_bankb ){
Function-= 1;
Function & = 1;
Function <= s3c2410_gpio_offset (PIN );
} Else {
Function & = 3;
Function <= s3c2410_gpio_offset (PIN) * 2;
}
}

/* Modify the specified register wwith irqs off */

Local_irq_save (flags );

Con = _ raw_readl (base + 0x00 );
Con & = ~ Mask;
Con | = function;

_ Raw_writel (con, base + 0x00 );

Local_irq_restore (flags );
}

In fact, we don't need to care about this. When writing a driver, we only need to use them. Unless the CPU system platform you are using is not supported by Linux, because most common embedded platforms have well-defined similar definitions, you do not need to write them yourself. In the driver list below, you can see the situation where s3c2410_gpio_cfgpin is called. In addition, you also need to call some basic functions closely related to the device driver, such as registering the device misc_register, entering the driver function structure file_operations, and hello, Module (see the user manual example) module_init and
Module_exit function. Some functions are not necessary. As you learn more about Linux driver development and read more code, you will naturally understand.

Here the LED will be registered as a misc device, and the code will be placed in the drivers/MISC directory. The driver file mini2440_leds.c is as follows:

# Include <Linux/miscdevice. h>
# Include <Linux/delay. h>
# Include <ASM/IRQ. h>
# Include <Mach/regs-gpio.h>
# Include <Mach/hardware. h>
# Include <Linux/kernel. h>
# Include <Linux/module. h>
# Include <Linux/init. h>
# Include <Linux/mm. h>
# Include <Linux/fs. h>
# Include <Linux/types. h>
# Include <Linux/delay. h>
# Include <Linux/moduleparam. h>
# Include <Linux/slab. h>
# Include <Linux/errno. h>
# Include <Linux/IOCTL. h>
# Include <Linux/cdev. h>
# Include <Linux/string. h>
# Include <Linux/list. h>
# Include <Linux/PCI. h>
# Include <Linux/gpio. h>
# Include <ASM/uaccess. h>
# Include <ASM/Atomic. h>
# Include <ASM/unistd. h>
# Define device_name "LEDs"
// Device name (/dev/LEDs)
// List of gpio ports corresponding to the LED
Static unsigned long led_table [] = {
S3c2410_gpb (5 ),
S3c2410_gpb (6 ),
S3c2410_gpb (7 ),
S3c2410_gpb (8 ),
};
// List of the statuses to be output by the corresponding led Port
Static unsigned int led_cfg_table [] = {
S3c2410_gpio_output,
S3c2410_gpio_output,
S3c2410_gpio_output,
S3c2410_gpio_output,
};
/* Ioctl function implementation
* At the application/user layer, parameters are passed to the kernel through the ioctl function to control the output status of the LED.
*/
Static int leds_ioctl (struct inode * inode,
Struct file * file,
Unsigned int cmd,
Unsigned long Arg)
{
Switch (CMD ){
Case 0:
Case 1:
If (Arg> 4 ){
Return-einval;
}
// Set the port register of the LED Based on the parameters passed by the application/user layer (reverse) through the s3c2410_gpio_setpin Function
S3c2410_gpio_setpin (led_table [Arg],! CMD );
Return 0;
Default:
Return-einval;
}
}
/*
* The device function operation set. Here, only the ioctl function is available. Generally, there are read, write, open, close, and so on, because the LED driver has
* Register as a misc device, so you do not need to open/close
*/
Static struct file_operations dev_fops = {
. Owner = this_module,
. IOCTL = leds_ioctl,
};
/*
* Register the LED driver as a misc device.
*/
Static struct miscdevice MISC = {
. Minor = misc_dynamic_minor,
// Dynamic device number
. Name = device_name,
. Fops = & dev_fops,
};
/*
* Device Initialization
*/
Static int _ init dev_init (void)
{
Int ret;
Int I;
For (I = 0; I <4; I ++ ){
// Set the port register corresponding to the led to the output)
S3c2410_gpio_cfgpin (led_table [I], led_pai_table [I]);
// Set the port register corresponding to the led to the low-level output. After the module is loaded, all the four LEDs will be in the light-emitting status.
S3c2410_gpio_setpin (led_table [I], 0 );
}
Ret = misc_register (& MISC );
// Register the device

If (Ret <0)
{
Printk (device_name "register falid! \ N ");
Return ret;
}

Printk (device_name "\ tinitialized \ n ");// Print the initialization information
Return 0;
}
Static void _ exit dev_exit (void)
{
Misc_deregister (& MISC );
}
// Module initialization. It is only useful when the insmod/podprobe command is used for loading. If the device is not loaded by the module, it will not be called here
Module_init (dev_init );
// Uninstall the module. After the device is loaded as a module, you can run the rmmod command to uninstall the device and call this function.
Module_exit (dev_exit );
Module_license ("GPL ");
// Copyright information
Module_author ("singleboy .");// Developer information

[2] Add the Kernel configuration option of the LED device to the kernel, open the drivers/MISC/kconfig file, locate the path near line 16, and add the following red content:

If misc_devices

Config leds_mini2440
Tristate "led support for mini2440 gpio LEDs"
Depends on mach_mini2440
Default y if mach_mini2440
Help
This option enables support for LEDs connected to gpio lines
On mini2440 boards.

[3] Add the driver target file to the kernel

Next, according to the definition of the driver configuration, add the corresponding driver target file to the kernel, open the linux-2.6.32.2/Drivers/MISC/MAKEFILE file, locate near 24 lines, add the following red content:

OBJ-$ (config_c2port) + = c2port/
OBJ-$ (config_leds_mini2440) + = mini2440_leds.o
OBJ-$ (config_mini2440_adc) + = mini2440_adc.o
OBJ-y + = EEPROM/

In this way, we have added the LED driver in the kernel.

[4] configure and compile the new kernel and test the LED

Next, execute make menuconfig in the kernel source code directory to reconfigure the kernel, and select the following sub-menu items in sequence:

Device Drivers --->
[*] MISC devices --->

<*> The led support for mini2440 gpio LEDs // option is selected by default. If it is not selected, press the Space key to select it.

Exit and save the Kernel configuration.

Then exit and save the selected configuration. Execute make uimage on the command line to generate ARCH/ARM/boot/uimage, copy it to the/nfsboot directory, and start the development board. You can see the startup information in the serial port terminal:

......

BRD: module loaded
LEDs initialized!
S3c24xx NAND driver, (c) 2004 simtec Electronics

......

[5] LEDs Testing

Run make uimage in the root directory of the kernel source code, copy the generated uimage to the/nfsboot/kernel directory, and restart the Development Board.

To test the driver, we also need to write a simple test program to call the ioctl function in the driver to control the led through the application, the source code of the test program has been provided in the CD provided by the friendly official website. It is located in the \ Linux sample code \ examples \ LEDs directory and the file name is led. c. Copy it to the host/root/Linux-test/codetest directory. The following code is used:

# Include <stdio. h>
# Include <stdlib. h>
# Include <unistd. h>
# Include <sys/IOCTL. h>

Int main (INT argc, char ** argv)
{
Int on;
Int led_no;
Int FD;
If (argc! = 3 | sscanf (argv [1], "% d", & led_no )! = 1 | sscanf (argv [2], "% d", & on )! = 1 |
On <0 | on> 1 | led_no <0 | led_no> 3 ){
Fprintf (stderr, "Usage: LEDs led_no 0 | 1 \ n ");
Exit (1 );
}
FD = open ("/dev/leds0", 0 );
If (FD <0 ){
FD = open ("/dev/LEDs", 0 );
}
If (FD <0 ){
Perror ("open device LEDs ");
Exit (1 );
}
IOCTL (FD, on, led_no );
Close (FD );
Return 0;
}
Enter the codetest directory in the terminal, and then execute:

[Root @ localhost codetest] # ls
Adc_test adc_test.c ~ Backlight_test.cLed. cTstest. c
Adc_test.c backlight_test I2C tstest
[Root @ localhost codetest] # arm-Linux-gcc-O led. c
[Root @ localhost codetest] # cp led/nfsboot/nfs
[Root @ localhost codetest] #
Copy the generated executable target file led to nfsboot/nfs shared with the Development Board, and run the following command on the command line terminal of the Development Board:
#./Led 3 0; Disable led3
#./Led 3 1; Enable led3
The first parameter is the LED number to be controlled (0 ~ 3. Corresponding to led1 ~ on the development board respectively ~ Led4). The second parameter indicates that the LED corresponding to (0) or (1) is disabled. The procedure is as follows:

[Root @ mini2440/] # ls-L/dev/LEDs
CrW-RW ---- 1 Root 10, 63 Jan 1 00:00/dev/LEDs
[Root @ mini2440 NFS] # ls
Adc_test bigworld.wavLEDTstest
Backlight_test I2C test1.wav yesterday.pdf
[Root @ mini2440 NFS] #./led 0 0
[Root @ mini2440 NFS] #./led 0 1
[Root @ mini2440 NFS] #./led 1 0
[Root @ mini2440 NFS] #./led 1 1
[Root @ mini2440 NFS] #./led 2 0
[Root @ mini2440 NFS] #./led 2 1
[Root @ mini2440 NFS] #./led 3 0
[Root @ mini2440 NFS] #./led 3 1
[Root @ mini2440 NFS] #

You can see the led1 ~ On the Development Board ~ Led4 is replaced and highlighted accordingly.

Next, we will transplant the interrupt-based key driver.

Related Article

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.