Kernel Module 3 GPIO - FrankBau/meta-marsboard-bsp GitHub Wiki

Implementing the module

A typical kernel module function is to set some GPIO pins or to query their value. In this example the user_led is used as a gpio.

Prerequisites:

Notes:

  • The user_led pin is possibly marked as a led, not a gpio, in the device tree, The device tree must be first changed to not define this pin as a LED.

  • The chip pad must be configured as a GPIO and the output pad driver must be set accordingly. This is also done in the device tree under "iomuxc":

    MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x80000000

The first value "MX6QDL_PAD_EIM_A25__GPIO5_IO02" defines the multiplexed pin function see http://lxr.free-electrons.com/source/arch/arm/boot/dts/imx6q-pinfunc.h?v=3.10

The second configures the pad IO driver see http://lxr.free-electrons.com/source/Documentation/devicetree/bindings/pinctrl/fsl,imx6q-pinctrl.txt?v=3.10

Note, that linux uses number 130 for this GPIO. See Using GPIO for how this number is calculated.

Add the following lines to my_module.c at global scope:

#include <linux/gpio.h>

const int my_gpio = 130;
int my_value = 0;

Extend my_init function:

    int rc;

    rc = gpio_request( my_gpio, "my_gpio" );
    if(rc < 0)
    {
        printk(KERN_ERR "gpio_request failed, error %d\n", rc );
        return -1;
    }

    rc = gpio_direction_output( my_gpio, 0 );
    if(rc < 0)
    {
        printk(KERN_ERR "gpio_direction_output failed, error %d\n", rc );
        return -1;
    }

Extend the my_write function such that the LED is switched:

    ...
    case 's':
        gpio_set_value( my_gpio, 1 );
        ...
    case 'c':
        gpio_set_value( my_gpio, 0 );
        ...

Extend the my_exit function such that the kernel resources are freed and the module can be loaded again:

static void __exit my_exit(void)
{
  gpio_free( my_gpio );
  ...
}

Cross-compile the kernel module, copy it to the target and load the module on the target:

insmod my_module.ko

Accessing the module from a shell

Now, you can set and clear the LED using the device /dev/cse3 exposed by the module:

echo s > /dev/cse3 
echo c > /dev/cse3 

You may also read the response from your module:

cat /dev/cse3 

The response should be OK when you issued a valid command and ERROR else. Each response is only given once per command.

Accessing the module form a C program

Use the device /dev/cse3 exposed by your loaded module my_module.ko with the usual Posix IO functions:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
    int f = open( "/dev/cse3", O_RDWR );
    write( f, "s", 1 );
    sleep(1000);
    write( f, "c", 1 );
    close(f);
}

Checking of return codes of all IO functions is omitted here for simplicity but should be present in your code! You might also read the response produced by the module and print it out for debugging.

Note, the the printk output from your module does not appear here. It is usually added to the kernel log and printed on the Linux console. The kernel log can be retrieved and configured in a shell by using the dmesg command.

You may only use the IO functions that you have implemented. In advanced scenarios you might want to implement ioctl to communicate to your module via customized C data structures (struct) instead of the simple char based IO.

What's next

Kernel Module 4 - Timer shows how to add a timer to the kernel module and execute periodic tasks.

⚠️ **GitHub.com Fallback** ⚠️