S3C2440-based linux-3.6.6 transplant--led Drive "turn"

Source: Internet
Author: User
Tags strcmp

This article was reproduced from: http://www.voidcn.com/blog/lqxandroid2012/article/p-625005.html

Many of the drivers for the current Linux version are based on the device model, and LEDs are no exception.

Simply put, the device model is that the system thinks all the devices are hooked up on the bus, and to make the device work, it needs the corresponding driver. The device model generates a virtual file system--SYSFS, which gives the user a way to access the kernel device from the user's space, and its path in Linux is/sys. If you are writing programs to access SYSFS, you can manipulate files in the/sys directory just as you would read and write normal files.

For s3c2440-based boards, the linux-3.6.6 automatic led driver only needs to change the IO port of the connected LEDs, and the high and low level response. The four LEDs on my development Board are connected to the 5 to 8 pins on the B port, and when the output is low, it is lit, consistent with the LED driver for Linux, so there is no need to make any changes.

Using Menuconfig to configure the kernel, add the contents of the LED module, namely:

Device Drivers--->

[*] LED Support--->

<*>led Class Support

<*>led support for Samsung s3c24xx GPIO LEDs

Compile the kernel and download the compiled kernel to the Development Board and run:

[[email protected]/] #ls

Bin etc lib Proc sys usr

Dev Home linuxrc sbin Temp

[[email protected]/] #cd sys

[[email protected]/sys] #ls

Block Class devices FS module

Bus Dev firmware kernel power

Entering the SYS directory, we see some subdirectories under this directory.

[[email protected]/sys] #cd class

[[email protected] class] #ls

Backlight Hidraw LEDs RTC VC

BDI Hwmon Mem Sound Video_output

Block I2c-adapter misc Spi_master vtconsole

Firmware I2c-dev Mmc_host Spidev watchdog

Gpio Input MTD TTY

Graphics LCD Net UDC

Go to the class directory and we'll see some devices in that directory, where LEDs are the LEDs we're going to operate on.

[[email protected] class] #cd LEDs

[[email protected] LEDs] #ls

Backlight led1 Led2 Led3 led4

In the LEDs catalog, you will see a catalogue of four LEDs, which is the four LEDs on the Development Board. In addition the backlight directory is about the LCD backlight, independent of the LEDs.

[[email protected] LEDs] #cd led1

[[email protected] led1] #ls

Brightness max_brightness Subsystem

Device Power Uevent

Brightness file is led equipment, the operation of it can complete the control of the LED.

[[email protected] led1] #cat brightness


You can see that the current state of led1 is off. (0 means off, 1 means open)

[[email protected] led1] #cat >brightness<<eof

> 1


#[[email protected] led1]#

Write 1 to brightness, which indicates the LED is turned on. Then the led1 will be lit.

Of course, we can also write a user program to control the four LEDs on the Development Board




#include <stdint.h>

#include <string.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include < linux/input.h> #include <unistd.h> int main (int argc, char *argv[]) {int FD, no;/* determines which led to control and opens the corresponding file */no= (int ) argv[1][3]-48; Switch (NO) { Case 1: FD = open ("/sys/class/leds/led1/brightness", O_RDWR); Break ; Case 2: FD = open ("/sys/class/leds/led2/brightness", O_RDWR); Break ; Case 3: FD = open ("/sys/class/leds/led3/brightness", O_RDWR); Break ; Case 4: FD = open ("/sys/class/leds/led4/brightness", O_RDWR);Break default:return-1;}      if (fd<0) {printf ("Can not open file.\n");    return-1; }/* Complete turn on or off led operation */if (!STRCMP (argv[2], "on") write (FD, "1", 1);   else if (!strcmp (argv[2], "off")) write (FD, "0", 1);  Close (FD); return 0;}

The above program is for simple testing purposes only. Compile the file:

Arm-linux-gcc-o LEDs LEDS.C

Download the LEDs file to the Temp directory and run:

[Email protected]/temp]#/leds led2 on

The led2 is lit.

[Email protected]/temp]#/leds led2 off

The led2 is turned off.

Let me briefly analyze the LED subsystem that comes with Linux.

In the mach-zhaocj2440.c file, the LED device was created, as follows:

/* LEDS */

static struct S3c24xx_led_platdata Zhaocj2440_led1_pdata = {

. Name = "Led1",

. Gpio = S3C2410_GPB (5),

. Flags = S3c24xx_ledf_actlow | S3c24xx_ledf_tristate,

. Def_trigger = "Heartbeat",


static struct S3c24xx_led_platdata Zhaocj2440_led2_pdata = {

. Name = "Led2",

. Gpio = S3C2410_GPB (6),

. Flags = S3c24xx_ledf_actlow | S3c24xx_ledf_tristate,

. Def_trigger = "Nand-disk",


static struct S3c24xx_led_platdata Zhaocj2440_led3_pdata = {

. Name = "Led3",

. Gpio = S3C2410_GPB (7),

. Flags = S3c24xx_ledf_actlow | S3c24xx_ledf_tristate,

. Def_trigger = "Mmc0",


static struct S3c24xx_led_platdata Zhaocj2440_led4_pdata = {

. Name = "Led4",

. Gpio = S3C2410_GPB (8),

. Flags = S3c24xx_ledf_actlow | S3c24xx_ledf_tristate,

. Def_trigger = "",


Four LED data are defined, named Led1~led4, which is the four subdirectories we see in the LEDs directory. The pins they are connected to are the 5~8 of the B port, which is defined by the S3C2410_GPB () macro. The identity s3c24xx_ledf_actlow indicates that the low level is active and the three states represented by the s3c24xx_ledf_tristate are invalid. In addition, Def_trigger is the trigger control, as we read and write to the NAND, LED2 will keep flashing, here we do not use this function, temporarily ignore.

static struct Platform_device zhaocj2440_led1= {

. Name = "S3c24xx_led",

. id = 1,

. Dev = {

. Platform_data = &zhaocj2440_led1_pdata,



static struct Platform_device zhaocj2440_led2= {

. Name = "S3c24xx_led",

. id = 2,

. Dev = {

. Platform_data = &zhaocj2440_led2_pdata,



static struct Platform_device zhaocj2440_led3= {

. Name = "S3c24xx_led",

. id = 3,

. Dev = {

. Platform_data = &zhaocj2440_led3_pdata,



static struct Platform_device zhaocj2440_led4= {

. Name = "S3c24xx_led",

. id = 4,

. Dev = {

. Platform_data = &zhaocj2440_led4_pdata,



The above is the creation of a bus platform device, the four LED device name is s3c24xx_led, the sub-device ID from 1 to 4, the device data is defined above the four led data. The four LED devices are then added to the device array in the development Board, namely:

static struct Platform_device *zhaocj2440_devices[]__initdata = {








Finally, during the initialization of the Development Board system, the devices in the device array are registered to the system bus, namely:

static void __init zhaocj2440_init (void)



Platform_add_devices (Zhaocj2440_devices,array_size (zhaocj2440_devices));



This completes the creation of the LED device.

Light equipment is not working, and the operation of any one of the equipment needs to be the corresponding driver. For S3C24XX-based LEDs, the driver is created within the leds-s3c24xx.c file in the Drivers/leds directory, i.e.:

static struct Platform_driver S3c24xx_led_driver = {

. Probe = S3c24xx_led_probe,

. remove = S3c24xx_led_remove,

. Driver = {

. Name = "S3c24xx_led",

. Owner = This_module,



How does the device and the driver match? How does the device find the driver it corresponds to? is by name. We will find that both Platform_device and Platform_driver have element name, and if their content is consistent, the device and driver will be paired successfully. For LEDs, their name is s3c24xx_led. When the device and the driver are matched, it is necessary to run the function specified by probe, which is simply to do some initialization work. When you need to remove a device, you need to run the function specified by remove, which completes the task of unregistering the device. This is especially important for devices that support hot swapping.

Now, let's take a look at the S3c24xx_led_probe function:

static int s3c24xx_led_probe (struct platform_device *dev)


Structs3c24xx_led_platdata*pdata = dev->dev.platform_data;

Structs3c24xx_gpio_led *led;


/* For allocating memory space to LEDs */

LED =devm_kzalloc (&dev->dev, sizeof (struct s3c24xx_gpio_led),


if (led = = NULL) {

Dev_err (&dev->dev, "No Memory for device\n");



/* Save the LED device structure */

Platform_set_drvdata (dev,led);

/* Assign a value to the LED structure, where S3c24xx_led_set is the function that is responsible for operating the LED */

Led->cdev.brightness_set= S3c24xx_led_set;

Led->cdev.default_trigger= pdata->def_trigger;

Led->cdev.name= pdata->name;

Led->cdev.flags|= Led_core_suspendresume;

Led->pdata = pdata;

/* Assign IO Pins to LEDs */

RET =devm_gpio_request (&dev->dev, Pdata->gpio, "s3c24xx_led");

if (Ret < 0)


/*no point in Have a pull-up if we is always driving */

/* No pull-up */

S3c_gpio_setpull (Pdata->gpio, S3c_gpio_pull_none);

/* Set IO pin as input */

if (Pdata->flags & S3c24xx_ledf_tristate)

Gpio_direction_input (Pdata->gpio);


Gpio_direction_output (Pdata->gpio,

pdata->flags& S3c24xx_ledf_actlow? 1:0);

/*register our new LED device */

/* Register a new LED device class object

This function is defined in the LED-CLASS.C file in the drivers/leds directory */

Ret= Led_classdev_register (&dev->dev, &led->cdev);

if (Ret < 0)

Dev_err (&dev->dev, "Led_classdev_register failed\n");

return ret;


From the above analysis, we can see that the S3c24xx_led_probe function is mainly to complete some initialization work of LED equipment. The LED task is responsible for the S3c24xx_led_set function, within the function, Gpio_set_value (Pd->gpio, State), is the specific completion of the corresponding PIN set 1 or zeroed task.

The led-class.c file in the Drivers/leds directory is the underlying core file of the LED subsystem, which is primarily responsible for creating the LED class and creating the device node, which is defined in the Led_classdev_register function described in this file. In order to better understand the LED subsystem, we will briefly analyze the file.

When the subsystem is initialized, the Leds_init function is called, its first code:

Leds_class = Class_create (This_module, "LEDs");

is to create the LEDs class, which is the list of LEDs we see in the Sys/class directory. Other than that

Leds_class->dev_attrs = Led_class_attrs;

Is the attribute that is given to the class. So let's look at the first code of the LED_CLASS_ATTRS structure:

__attr (Brightness, 0644, Led_brightness_show,led_brightness_store)

Where brightness is our device file name for the specific operation of the LED, 0644 is the permission of the file, Led_brightness_show is the function called by the read file, Led_brightness_store is the function called by the write file. Reading the file is to read the status of the LED (is off or on), write the file is to complete the open led or turn off the LED operation.

Finally, we analyze the Led_classdev_register function mentioned earlier. Within the function, the Device_create function was first used to create the device node, that is, in the LEDs directory, generate the Led1~led4 four directories. Another important task is to add device nodes to the list of LEDs.

The analysis of the LED subsystem that comes with Linux comes here. I think as long as I understand the subsystem, then I can completely write about the Gpio read and write operation of any driver.

S3C2440-based linux-3.6.6 transplant--led Drive "turn"

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.