Professional Documents
Culture Documents
www.aeslab.com/class_notes/DeviceDrivers.txt
LinuxDeviceDriverDevelopment
Day1:
LinuxKernelModuleProgramming
CharDriverDevelopment
ImplementationofLEDCharDriveronWEGA
Day2:
LinuxInterruptHandling&Programming
ImpleentationofSwitchInterruptonWEGA
Interrupts(BottomHalfsMechanisms)
SoftIRQs,WorkQueues,Tasklets
KernelSyncronizationMechanisms
(AtomicOperations,SpinLocks,Mutex)
IntrotoBlock,USB,NetworkDrivers
FirstKernelModule
geditmod1.c&
#include<linux/kernel.h>
#include<linux/module.h>
voidprint_greetings(void)
{
printk(KERN_ALERT"WelcometoKernelProgramming\n");
}
EXPORT_SYMBOL(print_greetings);
intinit_module(void)
{
printk(KERN_ALERT"HelloWorldsimplemoduleisloaded\n");
print_greetings();
return0;
}
voidcleanup_module(void)
{
printk(KERN_ALERT"simplemoduleisunloaded\n");
}
MODULE_LICENSE("GPL");
geditMakefile&
KERN_SRC=/lib/modules/`unamer`/build
objm+=mod1.o
objm+=mod2.o
all:
makeC${KERN_SRC}M=${PWD}modules
clean:
rmfmod1.komod1.o
http://www.aeslab.com/class_notes/Device%20Drivers.txt
1/6
8/9/2016
www.aeslab.com/class_notes/DeviceDrivers.txt
ls/lib/module/`unamer`/build
sudoaptgetinstalllinuxheaders$(unamer)kernelsource$(unamer)
lsmod
cat/proc/modules
sudoinsmodmod1.ko
lsmod
dmesg|tail
sudormmodmod1
lsmod
dmesg|tail
externvoidprint_greetings(void);
KernelModulesParameters:
sudoinsmodmod1.koblock_size=512block_name="RootFS"
#include<linux/moduleparam.h>
#include<linux/stat.h>
staticintblock_size=0;
staticchar*block_name="None";
module_param(block_size,int,S_IRUGO);
module_param(block_name,charp,S_IRUGO);
#defineBUFF_SZ80
#defineGPIO_P3_9
105
unsignedintmaj_num=0;
charlbuff[BUFF_SZ];
intmy_led_open(structinode*in,structfile*fs)
{
led_init(GPIO_P3_9);
printk(KERN_ALERT"Thisismydeviceopenfunc\n");
return0;
}
inmy_led_write(structfile*fp,char*ubuff,intsz,loff_toffset)
{
copy_from_user(lbuff,ubuff,sz);
printk(...
if(lbuff[0]=='O'&&lbuff[1]=='N')
led_on(GPIO_P3_9);
else
if(lbuff[0]=='O'&&lbuff[1]=='F'&&lbuff[2]=='F')
led_off(GPIO_P3_9);
else
printk(KERN_ALERT"InvalidLEDstatevalue\n");
http://www.aeslab.com/class_notes/Device%20Drivers.txt
2/6
8/9/2016
www.aeslab.com/class_notes/DeviceDrivers.txt
.....
.....
structfile_operationsmy_led_fops={
.owner=THIS_MODULE,
.open=my_led_open,
.release=my_led_close,
.read =my_led_read,
.write=my_led_write};
initfunc
cleanupfunc
unregister_chrdev(maj_num,"MY_LED_DRV");
maj_num=register_chrdev(0,"MY_LED_DRV",&my_led_fops);
printk(KERN_ALERT"ChrDevregisteredwithMajNum%d\n",maj_num);
my_led.c>my_led.ko>insmodmy_led.ko>
cat/proc/devices>245MY_LED_DRV>sudomknod/dev/my_ledc2450
blinky.c
#defineLED_ON 105
#defineLED_OFF106
main()
{
intfd;
intloop=20;
fd=open("/dev/my_led",0666);
while(loop)
{
ioctl(fd,LED_ON,0);
sleep(2)
ioctl(fd,LED_OFF,0);
sleep(2);
}
close(fd);
//ioctl(fd,LED_CNTL,1);write(fd,"ON",3);
//ioctl(fd,LED_CNTL,0);write(fd,"OFF",4);
1.fd=open("/dev/my_led",0666);user_space
VFS
>open_250()
>my_led_fops>open()
>my_led_open()
http://www.aeslab.com/class_notes/Device%20Drivers.txt
maj_numdev_namefops*
12
abc
fo1
250
my_led_dev
my_led_fops
3/6
8/9/2016
www.aeslab.com/class_notes/DeviceDrivers.txt
register_chrdev(.....)
intled_init(intgpio_num)
{
intretVal=0;
retVal=
gpio_request(gpio_num,"sled");
if(retVal<0)returnretVal;
retVal=gpio_direction_output(gpio_num,1);
returnretVal;
voidled_on(intgpio_num)
{
gpio_set_value(gpio_num,1);
}
voidled_off(intgpio_num)
{
gpio_set_value(gpio_num,0);
}
voidled_deinit(intgpio_num)
{
gpio_free(gpio_num);
}
ioctl:
longmy_led_ioctl(structfile*fs,unsignedintcmd,unsignedlongargp)
{
printk()
//printthecmd
switch(cmd)
{
caseLED_ON:
//Processthecmd
caseLED_OFF:
default:
printk(KERN_ALERT"InvalidIOCTLCmd...\n");
#defineLED_IOCTL_SETVAL_IOR('r',1,structdirent[2])
#defineIOCTL_SET_GPIO_IOWR(IOC_MAGIC,2,int)
http://www.aeslab.com/class_notes/Device%20Drivers.txt
4/6
8/9/2016
www.aeslab.com/class_notes/DeviceDrivers.txt
Interrupts:
kernel/irq/manage.c
structirq_chip
arch/arm/machomap2/irq.c
arch/arm/platomap/include/plat/irqs.h
#include<linux/interrupt.h>
#include<linux/irq.h>
#include<asm/irq.h>
1.
//request_irq(irq_num,handler_func,flags,name,dev_id);
request_gpio(gpio_num);
gpio_direction_input(gpio_num);
request_irq(gpio_to_irq(gpio_num),my_switch_handler,0,"WEGA_SW1",0);
2.
free_irq(gpio_to_irq(gpio_num),0);
3.irqreturn_tmy_switch_handler(intirq_num,void*devid)
led_toggle();
printk(KERN_ALERT"Interruptoccured%d\n",irq_num);
returnIRQ_HANDLED;
voidled_toggle(void)
{
staticintled_status=0;
if(led_status=(!led_status))
led_on();
else
led_off();
BottolHalfs:(softirq,workqueue,tasklets)
WorkQueues:
vidrivers/input/keyboard/lm8323.c
staticstructwork_structled_workq;
1.
InInit_func:
INIT_WORK(&led_workq,led_toggle_work_handle);
2.
InIRQ_Handler:
schedule_work(&led_workq);
3.
voidled_toggle_work_handle(structwork_struct*work)
http://www.aeslab.com/class_notes/Device%20Drivers.txt
5/6
8/9/2016
www.aeslab.com/class_notes/DeviceDrivers.txt
TASKLETS:
drivers/input/keyboard/omapkeypad.c
1.
//DECLARE_TASKLET(tasklet_name,tasklet_function,tasklet_data);
DECLARE_TASKLET(tasklet_led,tasklet_led_toggle_function,0);
2.
tasklet_schedule(&tasklet_led);
3.
voidmy_tasklet_function(unsignedlongdata)
{
KernelSync:
AtomicOperations
Mutex/Semaphores
DEFINE_MUTEX(mutex_name);
mutex_lock(&mutex_name);
mutex_unlock(&mutex_name);
SpinLock
spinlock_tmy_spinlock;
spin_lock(&my_spinlock);
spin_unlock(&my_spinlock);
Block/MTD/NetworkDrivers:
Contact:
Support:
H/W
:
vasu@easyarm.com(9535504414)
info@easyarm.com
support@phytec.in
http://www.aeslab.com/class_notes/Device%20Drivers.txt
6/6