kernel Module for fleshing LED

Thread Starter

Parth786

Joined Jun 19, 2017
642
I wanted to learn kernel module programming. I have been looking some tutorials but still having some issues. so I though I should started to write simple kernel module for fleshing LED. I have raspberry Pi board and I am using Rasbain operating system and I have gcc compiler installed. I want to write kernel module in c programming language.

While searching on internet I found some program but I think this program help me to get starting http://derekmolloy.ie/kernel-gpio-programming-buttons-and-leds/
C:
*
* @brief  A kernel module for controlling a simple LED
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/gpio.h>       // Required for the GPIO functions
#include <linux/kobject.h>    // Using kobjects for the sysfs bindings
#include <linux/kthread.h>    // Using kthreads for the flashing functionality
#include <linux/delay.h>      // Using this header for the msleep() function

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Derek Molloy");
MODULE_DESCRIPTION("A simple Linux LED driver LKM for the BBB");
MODULE_VERSION("0.1");

static unsigned int gpioLED = 49;           ///< Default GPIO for the LED is 49
module_param(gpioLED, uint, S_IRUGO);       ///< Param desc. S_IRUGO can be read/not changed
MODULE_PARM_DESC(gpioLED, " GPIO LED number (default=49)");     ///< parameter description
static unsigned int blinkPeriod = 1000;     ///< The blink period in ms
module_param(blinkPeriod, uint, S_IRUGO);   ///< Param desc. S_IRUGO can be read/not changed
MODULE_PARM_DESC(blinkPeriod, " LED blink period in ms (min=1, default=1000, max=10000)");
static char ledName[7] = "ledXXX";          ///< Null terminated default string -- just in case
static bool ledOn = 0;                      ///< Is the LED on or off? Used for flashing
enum modes { OFF, ON, FLASH };              ///< The available LED modes -- static not useful here
static enum modes mode = FLASH;             ///< Default mode is flashing

/** @brief A callback function to display the LED mode
*  @param kobj represents a kernel object device that appears in the sysfs filesystem
*  @param attr the pointer to the kobj_attribute struct
*  @param buf the buffer to which to write the number of presses
*  @return return the number of characters of the mode string successfully displayed
*/
static ssize_t mode_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf){
   switch(mode){
      case OFF:   return sprintf(buf, "off\n");       // Display the state -- simplistic approach
      case ON:    return sprintf(buf, "on\n");
      case FLASH: return sprintf(buf, "flash\n");
      default:    return sprintf(buf, "LKM Error\n"); // Cannot get here
   }
}

/** @brief A callback function to store the LED mode using the enum above */
static ssize_t mode_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count){
   // the count-1 is important as otherwise the \n is used in the comparison
   if (strncmp(buf,"on",count-1)==0) { mode = ON; }   // strncmp() compare with fixed number chars
   else if (strncmp(buf,"off",count-1)==0) { mode = OFF; }
   else if (strncmp(buf,"flash",count-1)==0) { mode = FLASH; }
   return count;
}

/** @brief A callback function to display the LED period */
static ssize_t period_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf){
   return sprintf(buf, "%d\n", blinkPeriod);
}

/** @brief A callback function to store the LED period value */
static ssize_t period_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count){
   unsigned int period;                     // Using a variable to validate the data sent
   sscanf(buf, "%du", &period);             // Read in the period as an unsigned int
   if ((period>1)&&(period<=10000)){        // Must be 2ms or greater, 10secs or less
      blinkPeriod = period;                 // Within range, assign to blinkPeriod variable
   }
   return period;
}
/** Use these helper macros to define the name and access levels of the kobj_attributes
*  The kobj_attribute has an attribute attr (name and mode), show and store function pointers
*  The period variable is associated with the blinkPeriod variable and it is to be exposed
*  with mode 0666 using the period_show and period_store functions above
*/
static struct kobj_attribute period_attr = __ATTR(blinkPeriod, 0666, period_show, period_store);
static struct kobj_attribute mode_attr = __ATTR(mode, 0666, mode_show, mode_store);

/** The ebb_attrs[] is an array of attributes that is used to create the attribute group below.
*  The attr property of the kobj_attribute is used to extract the attribute struct
*/
static struct attribute *ebb_attrs[] = {
   &period_attr.attr,                       // The period at which the LED flashes
   &mode_attr.attr,                         // Is the LED on or off?
   NULL,
};

/** The attribute group uses the attribute array and a name, which is exposed on sysfs -- in this
*  case it is gpio49, which is automatically defined in the ebbLED_init() function below
*  using the custom kernel parameter that can be passed when the module is loaded.
*/
static struct attribute_group attr_group = {
   .name  = ledName,                        // The name is generated in ebbLED_init()
   .attrs = ebb_attrs,                      // The attributes array defined just above
};

static struct kobject *ebb_kobj;            /// The pointer to the kobject
static struct task_struct *task;            /// The pointer to the thread task
/** @brief The LED Flasher main kthread loop
*
*  @param arg A void pointer used in order to pass data to the thread
*  @return returns 0 if successful
*/

static int flash(void *arg){
   printk(KERN_INFO "EBB LED: Thread has started running \n");
   while(!kthread_should_stop()){           // Returns true when kthread_stop() is called
      set_current_state(TASK_RUNNING);
      if (mode==FLASH) ledOn = !ledOn;      // Invert the LED state
      else if (mode==ON) ledOn = true;
      else ledOn = false;
      gpio_set_value(gpioLED, ledOn);       // Use the LED state to light/turn off the LED
      set_current_state(TASK_INTERRUPTIBLE);
      msleep(blinkPeriod/2);                // millisecond sleep for half of the period
   }
   printk(KERN_INFO "EBB LED: Thread has run to completion \n");
   return 0;
}

/** @brief 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
*  @return returns 0 if successful
*/
static int __init ebbLED_init(void){
   int result = 0;
   printk(KERN_INFO "EBB LED: Initializing the EBB LED LKM\n");
   sprintf(ledName, "led%d", gpioLED);      // Create the gpio115 name for /sys/ebb/led49
   ebb_kobj = kobject_create_and_add("ebb", kernel_kobj->parent); // kernel_kobj points to /sys/kernel
   if(!ebb_kobj){
      printk(KERN_ALERT "EBB LED: failed to create kobject\n");
      return -ENOMEM;
   }
   // add the attributes to /sys/ebb/ -- for example, /sys/ebb/led49/ledOn
   result = sysfs_create_group(ebb_kobj, &attr_group);
   if(result) {
      printk(KERN_ALERT "EBB LED: failed to create sysfs group\n");
      kobject_put(ebb_kobj);                // clean up -- remove the kobject sysfs entry
      return result;
   }
   ledOn = true;
   gpio_request(gpioLED, "sysfs");          // gpioLED is 49 by default, request it
   gpio_direction_output(gpioLED, ledOn);   // Set the gpio to be in output mode and turn on
   gpio_export(gpioLED, false);  // causes gpio49 to appear in /sys/class/gpio
                                 // the second argument prevents the direction from being changed
   task = kthread_run(flash, NULL, "LED_flash_thread");  // Start the LED flashing thread
   if(IS_ERR(task)){                                     // Kthread name is LED_flash_thread
      printk(KERN_ALERT "EBB LED: failed to create the task\n");
      return PTR_ERR(task);
   }
   return result;
}
/** @brief 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.
*/
static void __exit ebbLED_exit(void){
   kthread_stop(task);                      // Stop the LED flashing thread
   kobject_put(ebb_kobj);                   // clean up -- remove the kobject sysfs entry
   gpio_set_value(gpioLED, 0);              // Turn the LED off, indicates device was unloaded
   gpio_unexport(gpioLED);                  // Unexport the Button GPIO
   gpio_free(gpioLED);                      // Free the LED GPIO
   printk(KERN_INFO "EBB LED: Goodbye from the EBB LED LKM!\n");
}
/// This next calls are  mandatory -- they identify the initialization function
/// and the cleanup function (as above).
module_init(ebbLED_init);
module_exit(ebbLED_exit);

I have basic knowledge of embedded c programming and I have been written some programs in embedded c programming but I have never written kernel module program. I don't understand how to get starting on kernel module programming.

As beginner I think its very big task for me. So I just want to divide program into small pieces for easy understanding. Please help me in correct way to get starting to kernel module programming on raspberry ?
 
Last edited:

simozz

Joined Jul 23, 2017
128
Last edited:

philba

Joined Aug 17, 2017
959
Writing kernel code is definitely not for the beginning programmer. For some one who was struggling to write simple min/max code 3 months ago, I'd think a bit more general experience programming is called for.
 

nsaspook

Joined Aug 27, 2009
13,315
There are many ways to build off-tree kernel modules but I think you should first do this as it has clear instructions, shows the complete kernel rebuild process and is pretty fast on a RPi3..

Build a new kernel from source: Local building not Cross
https://www.raspberrypi.org/documentation/linux/kernel/building.md

This process makes every configured kernel module. Once this works you can easily modify (replace the code completely) a configured but unused kernel module source code as your own.
 

simozz

Joined Jul 23, 2017
128
Can you help me to write program in small parts.
You have to do it mainly by your self.
There are a tons of tutorials about how to compile a kernel, how to compile drivers is also mentioned in the book I linked.

However, you may learn first how to compile open source codes, how to use make and how to use a linux distribution.

For the latter, I strongly suggest to start using seriously Debian or even better Slackware on your local PC. I am pretty sure you will learn how to use Linux with this last one, because it's less user friendly but well documented as well and you will learn how to compile codes and how to administrate a Linux system.
 

Thread Starter

Parth786

Joined Jun 19, 2017
642
For some one who was struggling to write simple min/max code 3 months ago, I'd think a bit more general experience programming is called for.
I think we should try to keep effort continue In the beginning everyone struggle. My signature motivate me every time "Do even there is little hope"
You have to do it mainly by your self.There are a tons of tutorials about how to compile a kernel, how to compile drivers is also mentioned in the book I linked.I am pretty sure you will learn how to use Linux with this last one, because it's less user friendly but well documented as well and you will learn how to compile codes and how to administrate a Linux system.
There are many programs on the internet. First of all I want to run one sample programs that will flesh LED. I think if I write my first program, then I will not have much problem in writing the rest of the program. Then I can try to understand the program and I can modify according to needs. First I want to make simple program structure for kernel module easy understanding.
 

spinnaker

Joined Oct 29, 2009
7,830
I think we should try to keep effort continue In the beginning everyone struggle. My signature motivate me every time "Do even there is little hope"
Hope doesn't get you anything. It is just a myth. What gets you there is hard work, determination and being wise enough to know you need to walk before you can crawl. You have barerealy learned to crawl and now you are try to run, bypassing walking.
 

Thread Starter

Parth786

Joined Jun 19, 2017
642
now you are try to run, bypassing walking.
Is not basic to write programs for led?

I think there is no better alternative than get started with led blinking program. I thought it's right, That's why I started with led program.I just need your help to write my first program I strongly believe that if I write one program with understanding then I will not have problems in writing the all of the program's

I found this basic program structure of kernel module and I want to modify it for led blinking. What I have to do?
C:
#include <linux/module.h>
#include <linux/kernel.h>

/** Module init function */
static int __init basicmod_init(void)
{
    printk(KERN_INFO "%s\n", __func__);

    /* * A non 0 return means init_module failed; module can't be loaded.  */
    return 0;
}

/* * Module exit function*/
static void __exit basicmod_exit(void)
{
    printk(KERN_INFO "%s\n", __func__);
}

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stefan Wendler");
MODULE_DESCRIPTION("Basic Linux Kernel module");

module_init(basicmod_init);
module_exit(basicmod_exit);
 

spinnaker

Joined Oct 29, 2009
7,830
Is not basic to write programs for led?

I think there is no better alternative than get started with led blinking program. I thought it's right, That's why I started with led program.I just need your help to write my first program I strongly believe that if I write one program with understanding then I will not have problems in writing the all of the program's

I found this basic program structure of kernel module and I want to modify it for led blinking. What I have to do?
C:
#include <linux/module.h>
#include <linux/kernel.h>

/** Module init function */
static int __init basicmod_init(void)
{
    printk(KERN_INFO "%s\n", __func__);

    /* * A non 0 return means init_module failed; module can't be loaded.  */
    return 0;
}

/* * Module exit function*/
static void __exit basicmod_exit(void)
{
    printk(KERN_INFO "%s\n", __func__);
}

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Stefan Wendler");
MODULE_DESCRIPTION("Basic Linux Kernel module");

module_init(basicmod_init);
module_exit(basicmod_exit);
You are not just turning on an LED.
 

simozz

Joined Jul 23, 2017
128
What I have to do?
Go step by step. That code is the simplest skeleton of a driver (same code can be found in the book I linked).
First of all try to compile it.
Download the kernel sources for the version you want to. (i.e. the same kernel version of your board), again the instructions are into the book.
Once you have compiled it, it means that you have all the requirements to proceed, so add the gpio structures and go on.

Don't you want to study the relevant parts of that book ? Good luck.

Tasks become simple when you know how to do them.
 

be80be

Joined Jul 5, 2008
2,072
You sure going about this backward do you even know what kernel modules are for ?
And then have you even looked at the them where are they hiding.
You better make a backup because you go wrong and you'll be looking at a non working pi.

Just start here https://blog.fazibear.me/the-beginn...dule-raspberry-pi-and-led-matrix-790e8236e8e9

But to use a module for led not the thing I would think you would want to do seeing you done have modules for gpio. Your bloating the kernel when it could do useful stuff.
I could see this being fun but it's waste of time too because you can blink a led with bash .sh and not be slowing down your pi.
learn the more useful stuff Linux programming would be better time spent.
Learn Java better time spent
Learn networking better time spent
You done have a gpio module that works and handles the gpio.
I just think fun is a waste of time when it's been done and there are more important stuff to learn that get you to your goal's
 
Last edited:

Thread Starter

Parth786

Joined Jun 19, 2017
642
You sure going about this backward do you even know what kernel modules are for ?
I just think fun is a waste of time when it's been done and there are more important stuff to learn that get you to your goal's
I thought I should learn kernel development programming because I have seen in many job application they ask for kernel programming. that's why I was trying to learn kernel programming.

I am reading about Linux command and Networking. Now I am thinking that I should learn java programming first. My friends told me that java take more time to learn. There is a lot reads in Java advanced java core java. They said at least I have to spend 6 month's

My first priority is getting job in embedded / IOT domain.

I have done some research and found following important skills for embedded / IOT Developer
  • Hardware - 8051, ARM, ESP-8266 Raspberry PI
  • Programming - c programming, embedded c , c++ programming
  • Operating system - Linux Application development, Kernel development
  • HTML, Python, java script, Node.js
In my place there is very less chance for getting job as fresher. Everyone want's experience person. I don't have work experience in any company but I bought the some board's (raspberry Pi.ESP-8266, 8051) and started working on it. I am not expert in embedded system but I am sure by spending few time I can make any project in embedded system. still I am trying to improve my programming skills

I have just started studying about internet of things a few days ago. I know that I am struggling in programming language and I have to learn a lot of but I am very happy to doing some real work on internet of things.
 
Last edited:

be80be

Joined Jul 5, 2008
2,072
Lot of people want a lot of things sounds big to them.
But they all are really just wanting results
Lot of them say they need Kernel development because they based that on what they hear
Only reason I would see the need is you need a driver that's not there but the linux kernel
is probably more plug and play then windows ever was.
Today.
Bottom line before you set off to make something new learn about it first.
see whats there first before you head out to do something new.
I've messed with kernel modules back years ago to get video cards to work
but now most everything works without that and its not fun watching a 4 hour comply end up with a computer that does not boot to find out I had to download 24 hours to get the thing to work again over the old phone modem at blazing fast 56k.
Today is a way better day 3g in way less then a hour.
 
Last edited:
Top