Micro2440 uses LEDS and BUTTONS drivers to realize button control of LED lights [Development Summary]

Publisher:DreamBig123Latest update time:2024-06-28 Source: elecfansKeywords:micro2440  LEDS Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

I recently played with the micro2440 of Friendly Arm and realized the function of controlling the LED light on and off with a button. I would like to summarize it here. If there are any errors, I hope experts can point them out. I also hope to help novices who have just learned to drive.

First post the LEDs driver:

  1. #include 

  2. #include 

  3. #include 

  4. #include 

  5. #include 

  6. #include 

  7. #include 

  8. #include 

  9. #include 

  10. #include 

  11. #include 

  12. #include 

  13. #include 

  14. #include 

  15. #include 

  16. #include 

  17. #include 

  18. #include 

  19. #include 

  20. #include 

  21. #include 

  22. #include 

  23. #include 

  24. #define DEVICE_NAME "leds"

  25. static unsigned long led_table [] = {

  26. S3C2410_GPB5,

  27. S3C2410_GPB6,

  28. S3C2410_GPB7,

  29. S3C2410_GPB8,

  30. };

  31. static unsigned int led_cfg_table [] = {

  32. S3C2410_GPB5_OUTP,

  33. S3C2410_GPB6_OUTP,

  34. S3C2410_GPB7_OUTP,

  35. S3C2410_GPB8_OUTP,

  36. };

  37. static int sbc2440_leds_ioctl(

  38. struct inode *inode,

  39. struct file *file,

  40. unsigned int cmd,

  41. unsigned long arg)

  42. {

  43. switch(cmd) {

  44. case 0:

  45. case 1:

  46. if (arg > 4) {

  47. return -SINGLE SELECT;

  48. }

  49. s3c2410_gpio_setpin(led_table[arg], !cmd);

  50. return 0;

  51. default:

  52. return -SINGLE SELECT;

  53. }

  54. }

  55. static struct file_operations dev_fops = {

  56. .owner  =   THIS_MODULE,

  57. .ioctl  =   sbc2440_leds_ioctl,

  58. };

  59. static struct miscdevice misc = {

  60. .minor = MISC_DYNAMIC_MINOR,

  61. .name = DEVICE_NAME,

  62. .fops = &dev_fops,

  63. };

  64. static int __init dev_init(void)

  65. {

  66. int ret;

  67. int i;

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

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

  70. s3c2410_gpio_setpin(led_table[i], 0);

  71. }

  72. ret = misc_register(&misc);

  73. printk (DEVICE_NAME"tinitializedn");

  74. return ret;

  75. }

  76. static void __exit dev_exit(void)

  77. {

  78. misc_deregister(&misc);

  79. }

  80. module_init(dev_init);

  81. module_exit(dev_exit);

  82. MODULE_LICENSE("GPL");

  83. MODULE_AUTHOR("FriendlyARM Inc.");


The key point of this driver is to provide an ioctl device method. When the ioctl (leds' fd, cmd, arg) system call is used in the application, the system will enter the kernel state and call sbc2440_leds_ioctl() to control the on and off of the light.

The buttons driver is posted below:

  1. #include 

  2. #include 

  3. #include 

  4. #include 

  5. #include 

  6. #include 

  7. #include 

  8. #include 

  9. #include 

  10. #include 

  11. #include 

  12. #include 

  13. #include 

  14. #include 

  15. #include 

  16. #define DEVICE_NAME     "buttons"

  17. struct button_irq_desc {

  18. int irq;

  19. int pin;

  20. int pin_setting;

  21. int number;

  22. char *name;

  23. };

  24. #if !defined (CONFIG_QQ2440_BUTTONS)

  25. static struct button_irq_desc button_irqs [] = {

  26. {IRQ_EINT8 , S3C2410_GPG0 ,  S3C2410_GPG0_EINT8  , 0, "KEY0"},

  27. {IRQ_EINT11, S3C2410_GPG3 ,  S3C2410_GPG3_EINT11 , 1, "KEY1"},

  28. {IRQ_EINT13, S3C2410_GPG5 ,  S3C2410_GPG5_EINT13 , 2, "KEY2"},

  29. {IRQ_EINT14, S3C2410_GPG6 ,  S3C2410_GPG6_EINT14 , 3, "KEY3"},

  30. {IRQ_EINT15, S3C2410_GPG7 ,  S3C2410_GPG7_EINT15 , 4, "KEY4"},

  31. {IRQ_EINT19, S3C2410_GPG11,  S3C2410_GPG11_EINT19, 5, "KEY5"},

  32. };

  33. #else /* means QQ */

  34. static struct button_irq_desc button_irqs [] = {

  35. {IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_EINT19, 0, "KEY0"},

  36. {IRQ_EINT11, S3C2410_GPG3,  S3C2410_GPG3_EINT11,  1, "KEY1"},

  37. {IRQ_EINT2,  S3C2410_GPF2,  S3C2410_GPF2_EINT2,   2, "KEY2"},

  38. {IRQ_EINT0,  S3C2410_GPF0,  S3C2410_GPF0_EINT0,   3, "KEY3"},

  39. {       -1,            -1,                 -1,    4, "KEY4"},

  40. {       -1,            -1,                 -1,    5, "KEY5"},

  41. };

  42. #endif

  43. static volatile char key_values [] = {'0', '0', '0', '0', '0', '0'};

  44. static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

  45. static volatile int ev_press = 0;

  46. static irqreturn_t buttons_interrupt(int irq, void *dev_id)

  47. {

  48. struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;

  49. int down;

  50. // delay(0);

  51. down = !s3c2410_gpio_getpin(button_irqs->pin);

  52. if (down != (key_values[button_irqs->number] & 1)) { // Changed

  53. key_values[button_irqs->number] = '0' + down;

  54. ev_press = 1;

  55. wake_up_interruptible(&button_waitq);

  56. }

  57. return IRQ_RETVAL(IRQ_HANDLED);

  58. }

  59. static int s3c24xx_buttons_open(struct inode *inode, struct file *file)

  60. {

  61. int i;

  62. int err = 0;

  63. for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {

  64. if (button_irqs[i].irq < 0) {

  65. continue;

  66. }

  67. err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_BOTH,

  68. button_irqs[i].name, (void *)&button_irqs[i]);

  69. if (err)

  70. break;

  71. }

  72. if (err) {

  73. i--;

  74. for (; i >= 0; i--) {

  75. if (button_irqs[i].irq < 0) {

  76. continue;

  77. }

  78. disable_irq(button_irqs[i].irq);

  79. free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);

  80. }

  81. return -EBUSY;

  82. }

  83. ev_press = 1;

  84. return 0;

  85. }

  86. static int s3c24xx_buttons_close(struct inode *inode, struct file *file)

  87. {

  88. int i;

  89. for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {

  90. if (button_irqs[i].irq < 0) {

  91. continue;

  92. }

  93. free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);

  94. }

  95. return 0;

  96. }

  97. static int s3c24xx_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)

  98. {

  99. unsigned long err;

  100. if (!ev_press) {

  101. if (filp->f_flags & O_NONBLOCK)

  102. return -EAGAIN;

  103. else

  104. wait_event_interruptible(button_waitq, ev_press);

  105. }

  106. ev_press = 0;

  107. err = copy_to_user(buff, (const void *)key_values, min(sizeof(key_values), count));

  108. return err ? -EFAULT : min(sizeof(key_values), count);

  109. }

  110. static unsigned int s3c24xx_buttons_poll( struct file *file, struct poll_table_struct *wait)

  111. {

  112. unsigned int mask = 0;

  113. poll_wait(file, &button_waitq, wait);

  114. if (ev_press)

  115. mask |= POLLIN | POLLRDNORM;

  116. return mask;

  117. }

  118. static struct file_operations dev_fops = {

  119. .owner   =   THIS_MODULE,

  120. .open    =   s3c24xx_buttons_open,

  121. .release =   s3c24xx_buttons_close,

  122. .read    =   s3c24xx_buttons_read,

  123. .poll    =   s3c24xx_buttons_poll,

  124. };

  125. static struct miscdevice misc = {

  126. .minor = MISC_DYNAMIC_MINOR,

  127. .name = DEVICE_NAME,

  128. .fops = &dev_fops,

  129. };

  130. static int __init dev_init(void)

  131. {

  132. int ret;

  133. ret = misc_register(&misc);

  134. printk (DEVICE_NAME"tinitializedn");

  135. return ret;

  136. }

  137. static void __exit dev_exit(void)

  138. {

  139. misc_deregister(&misc);

  140. }

  141. module_init(dev_init);

  142. module_exit(dev_exit);

  143. MODULE_LICENSE("GPL");

  144. MODULE_AUTHOR("FriendlyARM Inc.");

The key to this driver (For a detailed analysis of the button driver, please see my other article mini2440_buttons.c driver interpretation http://www.linuxidc.com/Linux/2011-07/38768.htm ) linux


1. It is the device method of s3c24xx_buttons_read. When the read (buttons fs, key status array, how many bits to read) system call is used in the application, the kernel state will be entered to call the s3c24xx_buttons_read function. This function will enter the interruptible sleep state through wait _event_interruptible() and wait for the arrival of the interrupt.

2. The buttons_interrupt interrupt service function is defined, which processes the corresponding key value and wakes up the sleep state.


The application is as follows:

  1. #include 

  2. #include 

  3. #include 

  4. #include 

  5. #include 

  6. #include 

  7. #include 

  8. #include 

  9. #include 

[1] [2]
Keywords:micro2440  LEDS Reference address:Micro2440 uses LEDS and BUTTONS drivers to realize button control of LED lights [Development Summary]

Previous article:Interpretation of mini2440_buttons.c driver
Next article:About the serial port number of S3C2440

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号