Make Own LED blinking Driver for Raspberry pi ….

In this post, i am going to explain step by step procedure to make simple driver which can blink led on Linux powered raspberry pi. Raspberry pi is a credit-card sized computer developed by Raspberry pi Foundation ,UK. The Raspberry pi is equipped by Brodcom BCM2835 SoC, which includes an ARM1176JZF-S core clocked with 700 MHz. Raspberry pi was originally shipped with 256 MB of RAM, later upgraded to 512 MB of RAM. This card sized computer uses the SD card for booting and data storing purpose.

This tutorial demonstrates how to develop and debug a basic hardware driver for Raspberry PI. It will demonstrate the following techniques:

  • Controlling the BCM2708/BCM2835 peripherals by accessing their hardware registers
  • Handling of interrupts in Device driver
  • Creating a sysfs device object to provide user-mode control interface

Here, for my setup i am using raspberry pi model-A. I have compiled kernel(with my led blinking driver) for raspberry pi.

Compilation of Linux kernel for Raspberry pi

1. Get the kernel Source  code for here.

2. Get the tools(cross-compiler) from here.

3. Extract both files in your home directory. Here, i have extracted in /home/bhargav/rpi/.

3. Set the environment variable CCPREFIX:
export CCPREFIX= /home/bhargav/rpi/tools-master/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-

4. Set the environment variable KERNEL_SRC:
export KERNEL_SRC=/home/bhargav/rpi/linux-rpi-3.2.27

5. In KERNEL_SRC: execute “make mrproper” to ensure you have a clean kernel source tree

6. In KERNEL_SRC: execute below command  to configure  kernel source tree for raspberry pi

make ARCH=arm CROSS_COMPILE=${CCPREFIX} bcmrpi_defconfig

7. In KERNEL_SRC: execute below compile  kernel source tree for raspberry pi

make ARCH=arm CROSS_COMPILE=${CCPREFIX}

This process will give you kernel Image file at < KERNEL_SRC>/arch/arm/boot/  which can be places as kernel.img in boot partition of MMC.

Adding LED blinking device in board file

To add led blinking driver support in your build, you have to register your device in the board file of your board.

Board file for raspberry pi is located at <KERNEL_SRC>/arch/arm/mach-bcm2708/bcm2708.c which includes the subroutines for registering of all devices.

First, you need to add your header file of driver in to <KERNEL_SRC>/include/linux/ directory.

Here i am adding blinkled.h in the same directory. The below image will provide you more details about contain of file.

Header file for led blink driver

Header file for led blink driver

Include this header file in board file for raspberry pi. Add the below code in board file.

Defining a device in board file

Defining a device in board file

Here, i am declaring device named “LED_Blink” which has gpio number as a platform data on which it is connected.

Its time to register this declared device. In board file, bcm2708_init is a function which register all the peripherals devices with the kernel.

So, in this function we need to registered our device with the kernel platform bus.  Add the below line in in bcm2708_init function which register our device(“LED_Blink”) with kernel.

This device is added as platform device. I am not going in to much details of platform device, explanation can be found here.

Registration of Drivice

Registration of Device

At this stage we have registered our Led_Blink device to Linux kernel virtual bus. Now its time to write a driver for “Led_Blink” Device.

Writing driver for LED Blinking device

In the driver file, we need to declare one driver and register it with the kernel virtual bus with the same name which we gave to register device(“Led_Blink”). Linux kernel will compare the name of device and driver which is available on virtual bus and call the probe function of same driver. This is the basic concept of platform bus which is explained in the previous post.

Registration of Driver

Registration of Driver

Here, driver is declared with the  probe and remove function. Important thing is the name of the driver which is same as the device which we declared in device( In board file). Init function is the first function, which will be called on the successfully insertion of driver in the kernel. In our init function we have registered the platform driver to the bus.

On availability of the same device on the bus, kernel will calls the probe function of the same driver. So, after init function, probe will get called by the Kernel subsystem. Basically, probe will do all the initialization of device(GPIO) .

According to the BCM2835 peripheral  manual, the GPIO pins can be controlled by first configuring them as output by writing to one of GPFSELx registers and then writing to GPFSETx/GPFCLRx registers. We will define a structure describing the GPIO registers and provide functions for controlling GPIO pins using it.

Probe routine of LED blink driver

Probe routine of LED blink driver

Above snippet shows the body of probe function. In the probe function, there are three impotent things  are done.

1. Configure Pin as GPIO

The below snippet shoes the routines for set pin functionality and set output value of pin.  This functions uses the structure pointer to access the registers of SoC.

Gpio Routines

Gpio Routines

2. Setup time for On and Off timing of LED

When timer elapse, state of pin will get changed and again timer will be re initialized from timer subroutine. The snipped below shows the body of time handler.

This subroutine causes the blinking of the LED.

Timer handler subroutine

Timer handler subroutine

3. Register /sys interface  to change blink period from user domain

Sys interface is used to change the blinking period from user space. From the probe function BlinkLed_attr is registered for sys interface which has only one attribute name “period”.  User can get and set time interval using this interface. s_BlinkPeriod variable is used to store blanking period. The snippet below shows the subroutines for same.

Sys interface routines

Sys interface routines

You can download full driver code from here.

You have to add this add this module to linux source code. Here are the steps to do that.

Now, its time to compile your tweaked kernel using the steps shows above. Repeat from steps #5.

Enjoy your driver  !!!

21 Comments

Filed under Linux Device Driver

21 responses to “Make Own LED blinking Driver for Raspberry pi ….

  1. Andre

    Thank you for tutorial Bhargav, is very informative!!

  2. your init method should have
    platform_driver_register(&LedBlink_driver);

    instead of :
    platform_driver_register(&drivertest_driver);

  3. Rich

    Any examples on how to use the sysfs interface?

    • shah.b

      Sysfs interfaces are like a normal file.
      U can get read and write call backs in driver with appropriate buffers from user space.
      U can handle that callbacks in ur driver.

      The below link will provide you usage of it more clearly.
      http://guillermoamaral.com/read/rpi-gpio-c-sysfs/

      • Rich

        Thanks for the reply. I can see how to access sys devices, but it looks like you sample is missing some code as it does not create the sys device to access? I think there are some Create_Device calls that need to be made, correct? I think I can work that out.

        -Rich

      • shah.b

        I have created sysfs interface from probe finction.
        Just take a look at LedBlinkDev_probe().

        At last i have registred sysfs interface.

  4. dj

    Not able to find the code on given link!! How can I have it?

  5. Anil Kumar

    when i open make menuconfig its showing me this error..
    drivers/media/radio/Kconfig:22: can’t open file “drivers/media/radio/si470x/Kconfig”
    can you tell mw the solution please

    thanks

    • shah.b

      Check the permission of your drivers/media/radio/si470x/Kconfig file.
      Else you can take fresh source code of kernel and try to do the same.

  6. c9

    platform_driver_register(&LedBlink_driver);
    shows
    bcm2709.c:221:9: error: implicit declaration of function ‘platform_register_device’ [-Werror=implicit-function-declaration]
    platform_register_device(&LedBlink_device);
    How to solve that… I am using rpi2

  7. Deathscare

    why are we using board file? My understanding is we have device tree in pi.
    Can you tell how to do changes in that instead of board file?
    Thanks

    • shah.b

      This post is old so it discuss about board file. Now things moved from board file to DT.
      I will try to add support for DT if time permits.

  8. Deathscare

    There are multiple errors in the code that you have shared on dropbox,please fix them.
    Thanks

  9. Deathscare

    Probably you should try to run the code you have provided…rectify it..and then upload again. Also show led connectivity and sysfs path in pic.
    This is half baked solution.
    Anyways thanks for the information.

  10. Pingback: How do I resolve this error in the Raspberry Pi Kernel file bounds.c? – TheInstaPreneur

Leave a comment