The first driver written by micro2440 - LED

Publisher:leader5Latest update time:2022-07-08 Source: csdnKeywords:micro2440 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

This is the first driver written on the MICRO 2440 development board in the process of learning driver development. It realizes the control of S3C2440's GPIO and is the simplest driver on ARM-LINUX. This driver controls 4 LEDs through S3C2440's GPB5~8 and is a MISC (mixed) driver. In fact, MISC is also a special character driver, but the character driver with the main device number 10 is classified as a MISC driver.


The MISC class driver structure is as follows:


static struct miscdevice misc = {

.minor = MISC_DYNAMIC_MINOR,

.name = DEVICE_NAME,

.fops = &dev_fops,

  };


minor is the specified minor device number. If it is equal to MISC_DYNAMIC_MINOR, it means the minor device number is obtained dynamically.


name is the device name.


fops is a file_operations structure, a set of device operation function pointers.


file_operations structure:


static struct file_operations dev_fops = {

.owner = THIS_MODULE,

.ioctl = sbc2440_leds_ioctl,

  };


The device omits the OPEN and RELESE operation functions, which means it is in the open state by default. We only need to operate the IO port to turn the LED on and off, so only one IOCTL operation function is needed to meet the requirements.


GPIO port settings:


The S3C2440 GPIO port setting mainly involves setting three registers, namely GPxCON, GPxDAT, and GPxUP (x=A….J).


GPxCON is used to set the function of the IO port. Every two bits correspond to one IO port, input = 00, output = 01; special function = 10;


GPxDAT is the data register of the IO port, and each bit corresponds to one IO port.


GPxUP indicates whether to use pull-up resistors. 0 indicates use. Note that not every IO port has internal integrated pull-up resistors. If not, there is no such register.


The corresponding functions for setting these three registers are: s3c2410_gpio_cfgpin, s3c2410_gpio_setpin.


Driver code:


Loading function:


static int __init dev_init(void)

{

int ret;

 

int i;

for (i = 0; i < 4; i++) {

s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);

s3c2410_gpio_setpin(led_table[i], 0);

}

 

ret = misc_register(&misc);

 

printk (DEVICE_NAME "tinitializedn");

 

return ret;

}


In the loading function, the main tasks are to initialize the IO port and register a MISC class device. In the misc_register call, the MISC class will help us register a character device based on the members in struct miscdevice, so our MISC driver loading function is relatively short.


Uninstall function:


static void __exit dev_exit(void)

  {

misc_deregister(&misc);

  }


In the uninstall function, just call misc_deregister to uninstall the MISC device.


IOCTL function:


static int sbc2440_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;

}

s3c2410_gpio_setpin(led_table[arg], !cmd);

return 0;

default:

return -EINVAL;

}

}


In this MISC device, the main function used is the control function. Through the functions of operating IO registers introduced earlier, we can easily control the IO port.


Compile and load:


Put the source code into /drivers/char.


Modify the Kconfig file in the kernel source directory linux-2.6.32.2/drivers/char and add the following text to add the driver to the source tree.


config LOCKER_LEDS             


tristate "Locker_Liang leds"


depends on MACH_MINI2440


default m if MACH_MINI2440


help


Locker_Liang leds.


"config" defines a new configuration option. Tristate is the option name. depends on is based on which type of processor. Default means that if the previous processor is not available, this one is selected by default. Help is the help information, and the next line is the help information. For a detailed description of Kconfig syntax, see the Kconfig document.


Modify Makefile and add


obj-$(CONFIG_LOCKER_LEDS)+= MY_leds.o


Note that LOCKER_LEDS must be the same as on Kconfig, and the .o file must also be the same as the source file name.


Enter make menuconfig in the linux-2.6.32.2 directory, select the module we added in Device Drivers -> Character devices, and select M, which means compiling it as a module.


Type make modules to compile the module. A MY_leds.ko file will be generated in /drivers/char. Copy the file to the development board and type insmod MY_leds.ko to load the module into the kernel. The device file will be automatically generated. Type rmmod MY_leds.ko to uninstall the module.


This will allow you to operate the device, but there is another problem: after resetting, you need to reload the driver module and regenerate the device file. At this time, we can add commands to load the driver module and generate the device file in the /etc/init.d/rcS file, so that the settings will be automatically completed every time you start the computer.


Complete code:


#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

 

#define DEVICE_NAME "MY_leds"

 

static unsigned long led_table[] = {

S3C2410_GPB(5),

S3C2410_GPB(6),

S3C2410_GPB(7),

S3C2410_GPB(8),

};

 

static unsigned int led_cfg_table[] = {

S3C2410_GPIO_OUTPUT,

S3C2410_GPIO_OUTPUT,

S3C2410_GPIO_OUTPUT,

S3C2410_GPIO_OUTPUT,

};

 

static int sbc2440_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;

}

s3c2410_gpio_setpin(led_table[arg], !cmd);

return 0;

default:

return -EINVAL;

}

}

 

static struct file_operations dev_fops = {

.owner = THIS_MODULE,

.ioctl = sbc2440_leds_ioctl,

};

 

static struct miscdevice misc = {

.minor = MISC_DYNAMIC_MINOR,

.name = DEVICE_NAME,

.fops = &dev_fops,

};

 

static int __init dev_init(void)

{

int ret;

 

int i;

for (i = 0; i < 4; i++) {

s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);

s3c2410_gpio_setpin(led_table[i], 0);

}

 

ret = misc_register(&misc);

 

printk (DEVICE_NAME "tinitializedn");

 

return ret;

}

 

static void __exit dev_exit(void)

{

misc_deregister(&misc);

}

 

module_init(dev_init);

module_exit(dev_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("Locker_Liang Inc.");


test program:


  #include

  #include

  #include

  #include

  

  #define IOCTL_LED_ON 1

  #define IOCTL_LED_OFF 0

  

  void usage(char *exename)

  {

      printf("Usage:n");

      printf(" %s n", exename);

      printf(" led_no = 1, 2, 3 or 4n");

  }

  

  int main(int argc, char **argv)

  {

      unsigned int led_no;

      int fd = -1;

  

      if (argc != 3)

          goto err;

          

      fd = open("/dev/MY_leds", 0); // Open the device

      if (fd < 0) {

          printf("Can't open /dev/ledsn");

          return -1;

      }

      

      led_no = strtoul(argv[1], 0, 0) - 1; // Which LED to operate?

      if (led_no > 3)

          goto err;

      

      if (!strcmp(argv[2], "on")) {

          ioctl(fd, IOCTL_LED_ON,led_no); // turn it on

      } else if (!strcmp(argv[2], "off")) {

          ioctl(fd, IOCTL_LED_OFF,led_no); // turn it off

      } else {

          goto err;

      }

      

      close(fd);

      return 0;

      

  err:

      if (fd > 0) 

          close(fd);

      usage(argv[0]);

      return -1;

  }


Test command ./test 1 on 


Keywords:micro2440 Reference address:The first driver written by micro2440 - LED

Previous article:Linux (AT91SAM9260) adds support for UBIFS file system
Next article:Porting U-BOOT-2.14.07 to MICRO2440 development board

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号