Exploring BeagleBone: LKMs (by Derek Molloy)  V1.0
This project describes how you can build loadable kernel modules (LKMs) on your BeagleBone platform
 All Files Functions Variables Enumerations Enumerator Macros
Functions | Variables
gpio_test.c File Reference

A kernel module for controlling a GPIO LED/button pair. The device mounts devices via sysfs /sys/class/gpio/gpio115 and gpio49. Therefore, this test LKM circuit assumes that an LED is attached to GPIO 49 which is on P9_23 and the button is attached to GPIO 115 on P9_27. There is no requirement for a custom overlay, as the pins are in their default mux mode states. More...

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
Include dependency graph for gpio_test.c:

Functions

 MODULE_LICENSE ("GPL")
 
 MODULE_AUTHOR ("Derek Molloy")
 
 MODULE_DESCRIPTION ("A Button/LED test driver for the BBB")
 
 MODULE_VERSION ("0.1")
 
static irq_handler_t ebbgpio_irq_handler (unsigned int irq, void *dev_id, struct pt_regs *regs)
 Function prototype for the custom IRQ handler function – see below for the implementation. More...
 
static int __init ebbgpio_init (void)
 The LKM initialization function The static keyword restricts the visibility of the function to within this C file. The __init macro means that for a built-in driver (not a LKM) the function is only used at initialization time and that it can be discarded and its memory freed up after that point. In this example this function sets up the GPIOs and the IRQ. More...
 
static void __exit ebbgpio_exit (void)
 The LKM cleanup function Similar to the initialization function, it is static. The __exit macro notifies that if this code is used for a built-in driver (not a LKM) that this function is not required. Used to release the GPIOs and display cleanup messages. More...
 
 module_init (ebbgpio_init)
 
 module_exit (ebbgpio_exit)
 

Variables

static unsigned int gpioLED = 49
 hard coding the LED gpio for this example to P9_23 (GPIO49) More...
 
static unsigned int gpioButton = 115
 hard coding the button gpio for this example to P9_27 (GPIO115) More...
 
static unsigned int irqNumber
 Used to share the IRQ number within this file. More...
 
static unsigned int numberPresses = 0
 For information, store the number of button presses. More...
 
static bool ledOn = 0
 Is the LED on or off? Used to invert its state (off by default) More...
 

Detailed Description

A kernel module for controlling a GPIO LED/button pair. The device mounts devices via sysfs /sys/class/gpio/gpio115 and gpio49. Therefore, this test LKM circuit assumes that an LED is attached to GPIO 49 which is on P9_23 and the button is attached to GPIO 115 on P9_27. There is no requirement for a custom overlay, as the pins are in their default mux mode states.

Author
Derek Molloy
Date
19 April 2015
See also
http://www.derekmolloy.ie/

Function Documentation

static void __exit ebbgpio_exit ( void  )
static

The LKM cleanup function Similar to the initialization function, it is static. The __exit macro notifies that if this code is used for a built-in driver (not a LKM) that this function is not required. Used to release the GPIOs and display cleanup messages.

82  {
83  printk(KERN_INFO "GPIO_TEST: The button state is currently: %d\n", gpio_get_value(gpioButton));
84  printk(KERN_INFO "GPIO_TEST: The button was pressed %d times\n", numberPresses);
85  gpio_set_value(gpioLED, 0); // Turn the LED off, makes it clear the device was unloaded
86  gpio_unexport(gpioLED); // Unexport the LED GPIO
87  free_irq(irqNumber, NULL); // Free the IRQ number, no *dev_id required in this case
88  gpio_unexport(gpioButton); // Unexport the Button GPIO
89  gpio_free(gpioLED); // Free the LED GPIO
90  gpio_free(gpioButton); // Free the Button GPIO
91  printk(KERN_INFO "GPIO_TEST: Goodbye from the LKM!\n");
92 }
static unsigned int gpioLED
hard coding the LED gpio for this example to P9_23 (GPIO49)
Definition: gpio_test.c:23
static unsigned int numberPresses
For information, store the number of button presses.
Definition: gpio_test.c:26
static unsigned int gpioButton
hard coding the button gpio for this example to P9_27 (GPIO115)
Definition: gpio_test.c:24
static unsigned int irqNumber
Used to share the IRQ number within this file.
Definition: gpio_test.c:25
static int __init ebbgpio_init ( void  )
static

The LKM initialization function The static keyword restricts the visibility of the function to within this C file. The __init macro means that for a built-in driver (not a LKM) the function is only used at initialization time and that it can be discarded and its memory freed up after that point. In this example this function sets up the GPIOs and the IRQ.

Returns
returns 0 if successful
39  {
40  int result = 0;
41  printk(KERN_INFO "GPIO_TEST: Initializing the GPIO_TEST LKM\n");
42  // Is the GPIO a valid GPIO number (e.g., the BBB has 4x32 but not all available)
43  if (!gpio_is_valid(gpioLED)){
44  printk(KERN_INFO "GPIO_TEST: invalid LED GPIO\n");
45  return -ENODEV;
46  }
47  // Going to set up the LED. It is a GPIO in output mode and will be on by default
48  ledOn = true;
49  gpio_request(gpioLED, "sysfs"); // gpioLED is hardcoded to 49, request it
50  gpio_direction_output(gpioLED, ledOn); // Set the gpio to be in output mode and on
51 // gpio_set_value(gpioLED, ledOn); // Not required as set by line above (here for reference)
52  gpio_export(gpioLED, false); // Causes gpio49 to appear in /sys/class/gpio
53  // the bool argument prevents the direction from being changed
54  gpio_request(gpioButton, "sysfs"); // Set up the gpioButton
55  gpio_direction_input(gpioButton); // Set the button GPIO to be an input
56  gpio_set_debounce(gpioButton, 200); // Debounce the button with a delay of 200ms
57  gpio_export(gpioButton, false); // Causes gpio115 to appear in /sys/class/gpio
58  // the bool argument prevents the direction from being changed
59  // Perform a quick test to see that the button is working as expected on LKM load
60  printk(KERN_INFO "GPIO_TEST: The button state is currently: %d\n", gpio_get_value(gpioButton));
61 
62  // GPIO numbers and IRQ numbers are not the same! This function performs the mapping for us
63  irqNumber = gpio_to_irq(gpioButton);
64  printk(KERN_INFO "GPIO_TEST: The button is mapped to IRQ: %d\n", irqNumber);
65 
66  // This next call requests an interrupt line
67  result = request_irq(irqNumber, // The interrupt number requested
68  (irq_handler_t) ebbgpio_irq_handler, // The pointer to the handler function below
69  IRQF_TRIGGER_RISING, // Interrupt on rising edge (button press, not release)
70  "ebb_gpio_handler", // Used in /proc/interrupts to identify the owner
71  NULL); // The *dev_id for shared interrupt lines, NULL is okay
72 
73  printk(KERN_INFO "GPIO_TEST: The interrupt request result is: %d\n", result);
74  return result;
75 }
static unsigned int gpioLED
hard coding the LED gpio for this example to P9_23 (GPIO49)
Definition: gpio_test.c:23
static irq_handler_t ebbgpio_irq_handler(unsigned int irq, void *dev_id, struct pt_regs *regs)
Function prototype for the custom IRQ handler function – see below for the implementation.
Definition: gpio_test.c:104
static bool ledOn
Is the LED on or off? Used to invert its state (off by default)
Definition: gpio_test.c:27
static unsigned int gpioButton
hard coding the button gpio for this example to P9_27 (GPIO115)
Definition: gpio_test.c:24
static unsigned int irqNumber
Used to share the IRQ number within this file.
Definition: gpio_test.c:25
static irq_handler_t ebbgpio_irq_handler ( unsigned int  irq,
void *  dev_id,
struct pt_regs *  regs 
)
static

Function prototype for the custom IRQ handler function – see below for the implementation.

The GPIO IRQ Handler function This function is a custom interrupt handler that is attached to the GPIO above. The same interrupt handler cannot be invoked concurrently as the interrupt line is masked out until the function is complete. This function is static as it should not be invoked directly from outside of this file.

Parameters
irqthe IRQ number that is associated with the GPIO – useful for logging.
dev_idthe *dev_id that is provided – can be used to identify which device caused the interrupt Not used in this example as NULL is passed.
regsh/w specific register values – only really ever used for debugging. return returns IRQ_HANDLED if successful – should return IRQ_NONE otherwise.
104  {
105  ledOn = !ledOn; // Invert the LED state on each button press
106  gpio_set_value(gpioLED, ledOn); // Set the physical LED accordingly
107  printk(KERN_INFO "GPIO_TEST: Interrupt! (button state is %d)\n", gpio_get_value(gpioButton));
108  numberPresses++; // Global counter, will be outputted when the module is unloaded
109  return (irq_handler_t) IRQ_HANDLED; // Announce that the IRQ has been handled correctly
110 }
static unsigned int gpioLED
hard coding the LED gpio for this example to P9_23 (GPIO49)
Definition: gpio_test.c:23
static unsigned int numberPresses
For information, store the number of button presses.
Definition: gpio_test.c:26
static bool ledOn
Is the LED on or off? Used to invert its state (off by default)
Definition: gpio_test.c:27
static unsigned int gpioButton
hard coding the button gpio for this example to P9_27 (GPIO115)
Definition: gpio_test.c:24
MODULE_AUTHOR ( "Derek Molloy"  )
MODULE_DESCRIPTION ( "A Button/LED test driver for the BBB"  )
module_exit ( ebbgpio_exit  )
module_init ( ebbgpio_init  )

This next calls are mandatory – they identify the initialization function and the cleanup function (as above).

MODULE_LICENSE ( "GPL"  )
MODULE_VERSION ( "0.1"  )

Variable Documentation

unsigned int gpioButton = 115
static

hard coding the button gpio for this example to P9_27 (GPIO115)

unsigned int gpioLED = 49
static

hard coding the LED gpio for this example to P9_23 (GPIO49)

unsigned int irqNumber
static

Used to share the IRQ number within this file.

bool ledOn = 0
static

Is the LED on or off? Used to invert its state (off by default)

unsigned int numberPresses = 0
static

For information, store the number of button presses.