-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathc_dd_os_question.c
executable file
·5431 lines (4453 loc) · 281 KB
/
c_dd_os_question.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
Multicore processor:
Will increasing the number of cores, increase the throughput of your system ?
What are the general methods of communication between the cores ?
When is it better to use single core processor compared to multi-core processor ?
If the CPU in a multi-core processor updates the data in the cache, copies of data in caches associated with other cores will become stale. How is the multicore processor designed to handle this scenario ?
What is 'Run to Completion' software architecture ?
What is a 'Pipelined' software architecture ?
What is the difference between 'Run to Completion' and 'Pipelined' software architecture ?
How is the debugging and testing environment in the case of multithreaded/multiprocessing applications ?
At what point does adding more processors or computers to the computation pool slow things down instead of speeding them up?
Is there an optimal number of processors for any given parallel program?
How Many Processes or Threads are enough for an application ?
What is difference between micro processor & micro controller?
Kernel:
What are monolithic and micro kernels and what are the differences between them?
Monolithic kernel is a single large processes running entirely in a single address space.
It is a single static binary file. All kernel services exist and execute in kernel address space.
Monolithic kernels are UNIX , LINUX.
In Microkernels, the kernel is broken down into separate processes, known as servers.
Some of the servers run in kernel space and some run in user-space.Microkernel are QNX , L4 , HURD.
Monolithic kernel are faster than microkernel . While The first microkernel Mach is 50% slower than Monolithic
kernel while later version like L4 only 2% or 4% slower than the Monolithic kernel .
Monolithic kernel generally are bulky . While Pure monolithic kernel has to be small in size even fit in s into
processor first level cache (first generation microkernel).
Monolithic kernel device driver reside in the kernel space . While In the Microkernel device driver reside in the user space.
Since the device driver reside in the kernel space it make monolithic kernel less secure than microkernel . (Failure in the
driver may lead to crash) While Microkernels are more secure than the monolithic kernel hence used in some military devices.
Monolithic kernels use signals and sockets to ensure IPC while microkernel approach uses message queues .
1 gen of microkernel poorly implemented IPC so were slow on context switches.
Adding new feature to a monolithic system means recompiling the whole kernel While You can add new feature or patches
without recompiling.
Normal OS vs RTOS ? What is the difference between hard real-time and soft real-time OS? What type of scheduling is there in RTOS?
RTOS: http://careerride.com/embedded-systems-interview-questions.aspx
In an operating system, there is a module called the scheduler, which schedules different tasks and determines when a process
will execute on the processor. This way, the multi-tasking is achieved.
The scheduler in a Real Time Operating System (RTOS) is designed to provide a predictable execution pattern. In an embedded
system, a certain event must be entertained in strictly defined time.
To meet real time requirements, the behaviour of the scheduler must be predictable. This type of OS which have a scheduler
with predictable execution pattern is called Real Time OS(RTOS).
The features of an RTOS are:
Context switching latency: Context switching latency should be short.
Context switch latency is the time from one context switching to another and it should be short. In other words, the time taken
while saving the context of current task and then switching over to another task should be short. In general, switching context
involved saving the CPU's registers and loading a new state, flushing the caches, and changing the virtual memory mapping.Context
switch latency is highly architecture dependent and different hardware may get different results.
Interrupt latency: Interrupt latency should be short.
Interrupt latency is the time from interrupt generation until the interrupt service routine starts executing.
Factors that affect interrupt latency include the processor architecture, the processor clock speed, the particular OS employed,
and the type of interrupt controller used.
Minimum interrupt latency depends mainly on the configuration of the interrupt controller, which combines interrupts onto
processor lines, and assigns priority levels (visit Priority Inversion) to the interrupts.
Maximum interrupt latency depends mainly on the OS.
For more on Interrupt and Interrupt Latency, please visit my another page Interrupt & Interrupt Latency
Dispatch latency: Interrupt dispatch latency should be short.
The time between when a thread is scheduled and when it begins to execute. Theoretically, in a preemptive OS the dispatch latency
for a high-priority thread should be very low. However, in practice preemptive OSs are non-preemptive at times; for example,
while running an interrupt handler. The duration of the longest possible non-preemptive interval is said to be the worst-case
dispatch latency of an OS.
Reliable and time bound inter process mechanisms should be in place for processes to communicate with each other in a timely manner.
Multitasking and task preemption:
An RTOS should have support for multitasking and task preemption. Preemption means to switch from a currently executing task to a
high priority task ready and waiting to be executed.
Kernel preemption: Should support kernel preemption.
Most modern systems have preemptive kernels, designed to permit tasks to be preempted even when in kernel mode.
The bright side of the preemptive kernel is that sys-calls do not block the entire system.
However, it introduces more complexity to the kernel code, having to handle more end-cases, perform more fine grained locking
or use lock-less structures and algorithms.
Note: Preemptive:
Preemptive means that the rules governing which processes receive use of the CPU and for how long are determined by the
kernel process scheduler.
Hard real time RTOS vs Soft realtime RTOS.
A Hard real-time system strictly adheres to the deadline associated with the task. If the system fails to meet the deadline,
even once, the system is considered to have failed.
In case of a soft real-time system, missing a deadline is acceptable. In this type of system, a critical real-time task
gets priority over other tasks and retains that priority until it completes
Linux Device Driver :
what is zimage and bzimage.
Image: the generic Linux kernel binary image file.
zImage: a compressed version of the Linux kernel image that is self-extracting.
uImage: an image file that has a U-Boot wrapper (installed by the mkimage utility) that includes the OS type and loader information.
A very common practice (e.g. the typical Linux kernel Makefile) is to use a zImage file. Since a zImage file is
self-extracting (i.e. needs no external decompressors), the wrapper would indicate that this kernel
is "not compressed" even though it actually is.
what is thrashing, segmentation and fragmentation.
what is preempt_count and what is the need of that.
How can we allocate device number statically and dynamically and how to free device number? whichone is batter?
Explain about about ksets, kobjects and ktypes. How are they related?
mmap() and munmap(), ioremap() ?
Thread switching and process switching in linux kernel ?
Context switches can occur only in kernel mode.
A process switch is a operating system scheduler change from one running program to another. This requires saving all of the state of the currently executing program,
including its register state, associated kernel state, and all of its virtual memory configuration. All of the state of the new program is then loaded and execution continues.
A thread switch shifts from one thread to another, within one program. Threads within a program are full execution contexts, but they share one address space with other threads in the program.
A thread switch is cheaper than a full context switch since the memory management unit does not need to be reconfigured.
A context switch can informally mean either a process or thread switch, depending on the context (pun intended).
How context switching is handled in linux?
Compare I2C and SPI protocols?
SPI protocol requires more hardware(I²C needs 2 lines and that’s it, while SPI formally defines at least 4 Signals).
SPI procol is faster than I2C, it works in full duplex mode, can transmit upto 10Mbps whereas I2C is limited to 1Mbps
in normal mode and 3.4Mbps in fast mode.
SPI can have only one master whereas I2C supports more than one masters.
In SPI there is no limitation to the number of bits transmitted in one frame(I2c 8bits).
SPI is non standard whereas I2C is standard protocol.
What is process kernel stack and process user stack? What is the size of each and how are they allocated?
What all happens during context switch?
Can we have same major number for more than one device file ?
http://www.tutorialsdaddy.com/courses/linux-device-driver/lessons/major-and-minor-number/?content-item-only=yes
Traditionally, the major number identifies the driver associated with the device. The minor number is used by the kernel to determine exactly which device is being referred to.
Modern Linux kernels allow multiple drivers to share major numbers, but most devices that you will see are still organized on the one-major-one-driver principle.
Each device file has a major ID number and a minor ID number. The major ID identifies the general class of device, and is used by the kernel to look up the appropriate driver for this type of device.
The minor ID uniquely identifies a particular device within a general class. The major and minor IDs of a device file are displayed by the ls -l command.
Each device driver registers its association with a specific major device ID, and this association provides the connection between the device special file and the device.
The name of the device file has no relevance when the kernel looks for the device driver.
sudo mknod 0666 /dev/device_name [c,b,p] [MAJOR MINOR]
How to retrieve major and minor number from dev_t type ?
#include <sys/types.h>
makedev(dmajor, dminor)
major(devnum)
minor(devnum)
How to attach file operations to sysfs attribute in platform driver?
https://stackoverflow.com/questions/37237835/how-to-attach-file-operations-to-sysfs-attribute-in-platform-driver
http://opensourceforu.com/2015/05/talking-to-the-kernel-through-sysfs/
https://unix.stackexchange.com/questions/4884/what-is-the-difference-between-procfs-and-sysfs
How do you build only a static (.a) library for kernel modules.
I have the following Makefile for a kernel module:
EXTRA_CFLAGS+=-DLINUX_DRIVER -mhard-float
obj-m += main.o
other-objs := Obj.o Obj1.o Obj2.o Obj2.o ...
Question:
How can I first make a static lib from all the objects and only then link with the main object with the created static lib?
I know how to make this process manually in two steps. First I call the version above. then I call:
ar rcs libother.a Obj.o Obj1.o ...
And then I change the makefile to:
EXTRA_CFLAGS+=-DLINUX_DRIVER -mhard-float
obj-m += main.o libother.a
Since I don't master Makefiles I wonder if anyone knows a quick and clean solution for this.
solution:
EXTRA_CFLAGS+=-DLINUX_DRIVER -mhard-float
obj-m += main.o lib.a
lib-y := Obj.o Obj1.o Obj2.o Obj2.o ...
How to implement a Linux Device Driver for Data Acquisition Hardware?
https://stackoverflow.com/questions/15792144/how-to-implement-a-linux-device-driver-for-data-acquisition-hardware
https://stackoverflow.com/questions/31876296/linux-driver-and-api-architecture-for-a-data-acquisition-device
What is the use of ioctl(inode,file,cmd,arg) ApI ?
What is the use of the poll(file, polltable) API ?
difference between epoll and poll and select?
https://daniel.haxx.se/docs/poll-vs-select.html
https://www.ulduzsoft.com/2014/01/select-poll-epoll-practical-difference-for-system-architects/
What is the use of file->private_data in a device driver structure ?
http://www.haifux.org/lectures/89/intro_linux_device_drivers.pdf
The difference between device_info and private_data?
private_data is exactly what it says. Data that's private to device driver. Application or library can use this field to communicate data that is very specific for the device driver.
http://www.circlemud.org/jelson/software/fusd/docs/node29.html
private_data is stored per file descriptor
device_info is kept per device.
What is a Loadable Kernel Module?
Modules are pieces of code that can be loaded and unloaded into the kernel upon demand. They extend the functionality
of the kernel without the need to reboot the system.
insmod vs modeprobe ?
modprobe: reads the modules from /lib/modules/$(uname -r)/modules.dep.bin (or without the .bin suffix if the other file is not
available). From the same file, dependencies are loaded.
modprobe accepts the name of a .ko file in /lib/modules/$(uname -r) and aliases (modules.alias.bin).
Builtins (modules.alias.bin) are recognized as well, but since these modules are loaded by default, there is not
point in modprobing this kind of modules.
insmod: on the other hand accepts paths to files. The module does not have to reside in /lib/modules/$(uname -r), but dependencies
are not automatically loaded. This is the lower program used by modprobe to load modules.
rmmod: removes a kernel name based on the name from /proc/modules. This name does not necessarily have to be the same as
the one passed to modprobe.
modinfo: accepts a filename, or the filename without .ko suffix in /lib/modules/$(uname -r).
depmod : Creates the data base of module dependencies. This is created based on the information present
in /lib/modules/module.dep file.
lsmod : lists the modules already loaded into kernel.
Explain the module loading in Linux?
A module can be loaded to Linux Kernel in two ways
1. Statically
2. Dynamically
Static loading means that the module is loaded in the memory with the kernel loading itself.
Dynamic loading means that the module is loaded into the kernel at the run time.
The command that is used to achieve it is insmod.
The user must have the root permission to do so.
e.g sudo insmod test.ko
How to Pass Command Line Arguments to a Kernel Module?
http://learnlinuxconcepts.blogspot.in/2014/03/how-to-pass-command-line-arguments-to.html
The module_param() macro takes 3 arguments:
arg1 : The name of the variable.
arg2 : Its type
arg3 : Permissions for the corresponding file in sysfs.
module_param_array(myarr, int, &arr_argc, 0);
MODULE_PARM_DESC() macro used for giving the description of variable.
command: insmod *.ko variable=value
Use Cases of Module Parameters:
When there is a need to change the irq line of the module then its the best way to pass the irq number
as command line argument using module parameter concept.
Base address of the register map of a module can be passed at module load time using insmod based on this command line arguments.
what does the probe() method, that the driver provides, do? How different is it from the driver init function,
i.e. why cant the probe() functions actions be performed in the driver init function ?
Different device types can have probe() functions. For example, PCI and USB devices both have probe() functions.
Shorter answer, assuming PCI: The driver init function calls pci_register_driver() which gives the kernel a list of devices it
is able to service, along with a pointer to the probe() function. The kernel then calls the driver probe() function once for each
device.
This probe function starts the per-device initialization: initializing hardware, allocating resources, and registering the
device with the kernel as a block or network device or whatever it is.That makes it easier for device drivers, because
they never need to search for devices or worry about finding a device that was hot-plugged. The kernel handles that part
and notifies the right driver when it has a device for you to handle.
What is the difference beteween kernel modules and kernel drivers?
A kernel module is a bit of compiled code that can be inserted into the kernel at run-time, such as with insmod or modprobe.
A driver is a bit of code that runs in the kernel to talk to some hardware device. It drives the hardware. Most every bit
of hardware in your computer has an associated driver[*]. A large part of a running kernel is driver code; the rest of the
code provides generic services like memory management, IPC, scheduling, etc.
A driver may be built statically into the kernel file on disk. (The one in /boot, loaded into RAM at boot time by the boot
loader early in the boot process.)
A driver may also be built as a kernel module so that it can be dynamically loaded later. (And then maybe unloaded.)
Standard practice is to build drivers as kernel modules where possible, rather than link them statically to the kernel,
since that gives more flexibility.
There are good reasons not to, however:
Sometimes a given driver is absolutely necessary to help the system boot up. That doesn't happen as often as you might imagine,
due to the initrd feature.
Statically built drivers may be exactly what you want in a system that is statically scoped, such as an embedded system.
That is to say, if you know in advance exactly which drivers will always be needed and that this will never change,
you have a good reason not to bother with dynamic kernel modules.
Not all kernel modules are drivers. For example, a relatively recent feature in the Linux kernel is that you can load a
different process scheduler.
[*] One exception to this broad statement is the CPU chip, which has no driver per se. Your computer may also contain hardware
for which you have no driver.
Courtesy: http://unix.stackexchange.com/questions/47208/what-is-the-difference-between-kernel-drivers-and-kernel-modules
what is a platform driver? how to bind a driver to a devive? how to get platfrom resource and private data?
https://sysplay.in/index.php?pagefile=linux_drivers
However, could you point me out where the kernel actually detects the device? Is it keep polling with the driver's name which was given
at compile time? Or Is there other mechanism to detect the device? Basically, how the
kernel detects those devices, which calls "probe"?
Platform devices represent devices that are usually integrated into a given chip and therefore are always there.
The platform-specific initialization code statically initializes such arrays of platform devices and then registers them in
a row using platform_register. Therefore there is no need for sophisticated probing. Instead, the string contained
in platform_device.name is compared platform_driver.driver.name and a match is assumed if they are equal.
Other buses have more sophisticated detection/probing methods. For more information about platform devices, including the places
where these functions are called, see drivers/base/platform.c. Read Documentation/driver-model/platform.txt.
Why is the probe method needed in Linux device drivers in addition to init?
The driver's init function calls pci_register_driver() which gives the kernel a list of devices it is able to service, along with
a pointer to the probe() function. The kernel then calls the driver's probe() function once for each device.
This probe function starts the per-device initialization: initializing hardware, allocating resources, and registering the
device with the kernel as a block or network device or whatever it is.
That makes it easier for device drivers, because they never need to search for devices or worry about finding a device that was
hot-plugged. The kernel handles that part and notifies the right driver when it has a device for you to handle.
For a "platform" device the probe function is invoked when a platform device is registered and it's device name matches with the
compatible string or name specified on the device driver and device tree.
https://www.kernel.org/doc/Documentation/i2c/writing-clients.
1. The starting trigger function for the driver -> probe() callback is the module_init() macro called while loading the driver;
the macro is defined in `include/linux/module.h`.
2. module_init(my_driver_init) has the callback to my_driver_init() function. my_driver_init() function should have a call
to platform_driver_register(my_driver).
3. platform_driver_register(my_driver) assigns my_driver -> probe() handle to generic drv -> probe() and calls the
driver_register(my_driver) function.
4. driver_register(my_driver) function adds my_driver to the platform bus and calls driver_attach() function.
5. In the same way, even the platform_device needs to attach to the platform bus.
6. Finally, only if the driver_match_device() returns success based on the .name & .id_table of the driver matches in the platform
devices list that comes either from ACPI/DTS, then the driver_probe_device() gets called that has the drv -> probe() callback.
Explain about the Linux Device Model (LDM)? how mudules are loaded in linux?
Explain about about ksets, kobjects and ktypes. How are they related?
http://linuxburps.blogspot.in/2013/12/linux-device-model.html
The device model provides a single mechanism for representing devices and describing their topology in the system.
Such system provide several benefits:-
1. Minimization of code duplication
2. A mechanism for providing common facility such as reference counting.
3. The capability to enumerate all the devices in the system, view their status and see to what bus they attach.
4. The capability to generate a complete and valid tree of the entire device structure of the system, including all buses and interconnections.
5. The capability to link devices to their drivers and vice-versa.
6. The capability to categorise devices by their class, such as input device, without the need to understand the
physical device topology.
7. The capability to walk the tree of devices from the leaves up to the root, powering down devices in the correct order.
The device model brings with it a whole new vocabulary to describe its data structures. A quick overview of some device model
terms appears below; much of this stuff will be looked at in detail later on.
device:
A physical or virtual object which attaches to a (possibly virtual) bus.
driver:
A software entity which may probe for and be bound to devices, and which can perform certain management functions.
bus: The Bus-Device-Driver Model.
A device which serves as an attachment point for other devices.
Device class:
Allows system to discover types of devices that are related.
A particular type of device which can be expected to perform in certain ways. Classes might include disks, partitions,
serial ports, etc.
subsystem:
A top-level view of the system's structure. Subsystems used in the kernel include devices (a hierarchical view of all
devices on the system), bus (a bus-oriented view), class(devices by class), net (the networking subsystem), and others.
The best way to think of a subsystem, perhaps, is as a particular view into the device model data structure rather than a
physical component of the system. The same objects (devices, usually) show up in most subsystems, but they are organized differently
Kobjects:
At the heart of the device model is the kobjects, short for kernel objects, which is represented by struct object and
defined /include/linux/kobject.h
http://lxr.free-electrons.com/source/include/linux/kobject.h
It provides basic facilities such as reference counting, a name, a parent pointer, enabling creation of the hierarchy.
->Name pointer points to the name of this kobject.
-> The parent pointer points to this kobject's parent. In this way it developed hierarachy.
(Sysfs is a user-space filesystem representation of the kobject hierarchy inside the kernel
ksets:
ktypes:
Device model core:
generic bus driver:
generic controler driver:
Device drivers and platfrom drivers:
class driver:
Hotplug and Coldplug:
Used to handle and communicate the plugging and unplugging of devices.
sysfs:
How to add a new module in kernel build system?
1. Create a directory like my_drvr inside drivers(which is in the Linux source code) for your driver and put your driver
(my_driver.c) file inside this directory. It will looks like /linux_source_code/drivers/my_drvr/my_driver.c
2. Create one Makefile inside your driver directory (using vi any editor) and inside this put
obj-$(CONFIG_MY_DRIVER) += my_driver.o and save this file. This will appears like /linux_source_code/drivers/my_drvr/Makefile
3. Create one Kconfig file inside your driver directory (using vi any editor) and inside this put
config MY_DRIVER
tristate "my driver" //gives your driver description like vendor name etc.
depends on ARM
default y if ARM
help
my driver module.
4. Save this file, this will appears like /linux_source_code/drivers/my_drvr/Kconfig
5. Add both Makefile and Kconfig file in the Linux source drivers Makefile and Kconfig file which are at
/linux_source_code/drivers/Makefile and /linux_source_code/drivers/Kconfig
6. In the Makefile add below in last line
obj-y += my_drvr/
or
obj-$(CONFIG_MY_DRIVER) += my_drvr/
7. In Kconfig file add below in last line
source "drivers/my_drvr/Kconfig"
8. Finally have to add Kconfig file into architecture specific config file which will be at
kernel_source/arch/arm/configs/--defconfig in this add below line in the last
CONFIG_MY_DRIVER=y
9. Note:- Last step will differ according to your architecture, so that you have take care. Now you can compile your driver
by using make command. (eg: sun7i_defconfig).
make menuconfig ARCH=arm
10. Verify that your driver module entry is visible under Device Drivers —>
For module entry it shows <M> HelloTest App
Now recompile the kernel with your requirement and give
sudo make ARCH=arm CROSS_COMPILE=/toolchainpath
How to make a module as loadable module? How to make a module as in-built module?
how parameters are shared between driver modules?
what is syscalls.what are the benefits of syscalls?
what is init and exit function of a driver.how and when init and exit function of driver get called?
The __init macro indicates to compiler that that associated function is only used during initialization.
Compiler places all code marked with __init into a special memory section that is freed after initialization for other uses.
__exit* macro:
The exit macro tells the compiler to put the function in the ".exit.text" section. The exit_data macro tells the compiler
to put the function in the ".exit.data" section.
exit.* sections make sense only for the modules : exit functions will never be called if compiled statically. That's why there
is a ifdef : exit.* sections will be discarded only if modules support is disabled.
What is the use of ioctl fuction ?how to add new ioctl inkernel?
The major use of this is in case of handling some specific operations of a device for which the kernel does not have a system
call by default. For eg: Ejecting the media from a "cd" drive. An ioctl command is implemented to give the eject
system call to the cd drive.
To implement a new ioctl command we need to follow the following steps:
1. Define the ioctl code in a header file and include the same in the application as well as the module.
The definition is done as follows
#define "ioctl name" __IOX("magic number","command number","argument type")
where IOX can be :
"IO": If the command neither reads any data from the user nor writes any data to the userspace.
"IOW": If the commands needs to write some to the kernel space. copy_from_user.
"IOR": If the command needs to read some thing from the kernel space. copy_to_user.
"IOWR": If the command does both read as well as write from the user.( copy_from_user, copy_to_user)
The Magic Number is a unique number or character that will differentiate our set of ioctl calls from the other ioctl calls.
some times the major number for the device is used here.
Command Number is the number that is assigned to the ioctl .It is this number that is used to differentiate the commands
from one another .
The last is the type of data that will be written in case of __IOW or read in case of __IOR or both read as well as write
in case of __IOWR. In the case of _IO we need not pass any thing.
2. Add the header file linux/ioctl.h to make use of the above mentioned calls.
vim ioctl_basic.h
#include <linux/ioctl.h>
#define IOC_MAGIC k // defines the magic number
#define IOCTL_ HELLO _IO(IOC_MAGIC,0) // defines our ioctl call
3. The next step is to implement the ioctl call we defined in to the corresponding driver. First we will need to
#include the header file ioctl_basic.h
Following this convention is good because:
(1) Keeping the ioctl's globally unique helps error checking:
if a program calls an ioctl on the wrong device, it will get an
error rather than some unexpected behaviour.
(2) The 'strace' build procedure automatically finds ioctl numbers
defined with _IO, _IOW, _IOR, or _IOWR.
(3) 'strace' can decode numbers back into useful names when the
numbers are unique.
(4) People looking for ioctls can grep for them more easily when
this convention is used to define the ioctl numbers.
(5) When following the convention, the driver code can use generic
code to copy the parameters between user and kernel space.
What is the difference between Platform driver and normal device driver..?
Platform devices are inherently not discoverable, i.e. the hardware cannot say "Hey! I'm present!" to the software.
Typical examples are i2c devices, kernel/Documentation/i2c/instantiating-devices states:
Unlike PCI or USB devices, I2C devices are not enumerated at the hardware level (at run time). Instead, the software must know
(at compile time) which devices are connected on each I2C bus segment.
So USB and PCI are not platform devices.
Platform devices are bound to drivers by matching names,
Platform devices should be registered very early during system boot. Because they are often critical to the rest of the
system (platform) and its drivers.
So basically, the question "is it a platform device or a standard device?" is more a question of which bus it uses.
To work with a particular platform device, you have to:
register a platform driver that will manage this device. It should define a unique name,
register your platform device, defining the same name as the driver.
Are platform drivers for those devices that are on chip ??
Not true (in theory, but true in practice). i2c devices are not onChip, but are platform devices because they are not discoverable. Also we can think of onChip devices which are normal devices.
Example: an integrated PCI GPU chip on a modern x86 processor. It is discoverable, thus not a platform device.
Are normal device drivers for those that are interfaced to the processor chip. before coming across one i2c driver ??
Not true. Many normal devices are interfaced to the processor, but not through an i2c bus. Example: a USB mouse
what is platform devices and device driver.
https://www.kernel.org/doc/Documentation/driver-model/platform.txt
Platform devices are given a name, used in driver binding, and a list of resources such as addresses and IRQs.
struct platform_device {
const char *name;
u32 id;
struct device dev;
u32 num_resources;
struct resource *resource;
};
Platform drivers:
Platform drivers follow the standard driver model convention, where discovery/enumeration is handled outside the drivers,
and drivers provide probe() and remove() methods. They support power management and shutdown notifications using the
standard conventions.
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*suspend_late)(struct platform_device *, pm_message_t state);
int (*resume_early)(struct platform_device *);
int (*resume)(struct platform_device *);
struct device_driver driver;
};
Note: that probe() should in general verify that the specified device hardware actually exists; sometimes platform setup
code can't be sure. The probing can use device resources, including clocks, and device platform_data.
Registration:
int platform_driver_register(struct platform_driver *drv);
Note: in common situations where the device is known not to be hot-pluggable, the probe() routine can live
in an init section to reduce the driver's runtime memory footprint:
int platform_driver_probe(struct platform_driver *drv, int (*probe)(struct platform_device *))
Unregistration:
void platform_unregister_drivers(struct platform_driver * const *drivers, unsigned int count);
Device Enumeration:
Legacy Drivers: Device Probing:
You can use platform_device_alloc() to dynamically allocate a device, which you will then initialize with resources
and platform_device_register().
You can use platform_device_register_simple() as a one-step call to allocate and register a device
Device Naming and Driver Binding:
* platform_device.name ... which is also used to for driver matching.
* platform_device.id ... the device instance number, or else "-1" to indicate there's only one.
Driver binding is performed automatically by the driver core, invoking driver probe() after finding a match between device
and driver. If the probe() succeeds, the driver and device are bound as usual.There are three different ways to find such a match:
Whenever a device is registered, the drivers for that bus are checked for matches. Platform devices should be registered very
early during system boot.
When a driver is registered using platform_driver_register(), all unbound devices on that bus are checked for matches. Drivers
usually register later during booting, or by module loading.
Registering a driver using platform_driver_probe() works just like using platform_driver_register(), except that the driver won't
be probed later if another device registers. (Which is OK, since this interface is only for use with non-hotpluggable devices.)
platform_get_drvdata();
platform_set_drvdata();
platform_device_put();
platform_device_del();
platform_device_add();
What is the difference between early init and late init?
module_init() vs. core_initcall() vs. early_initcall() ?
init/main.c
Actually the main point of the initcall mechanism is to determine correct order of the built-in modules
and subsystems initialization.
The Linux kernel calls all architecture-specific initcalls before the fs related initcalls.
Linux kernel provides eight levels of main initcalls:
static char *initcall_level_names[] __initdata = {
"early",
"core",
"postcore",
"arch",
"subsys",
"fs",
"device",
"late",
};
Linux kernel boot-up:
1. early_initcall()
2. core_initcall()
3. postcore_initcall()
4. arch_initcall()
5. subsys_initcall()
6. fs_initcall()
7. device_initcall()
8. late_initcall()
end of built-in modules
9. modprobe or insmod of *.ko modules.
the order of execution of initcall is from top to bottom as shown in the above array.
Early init:
Early init functions are called when only the boot processor is online.
Run before initializing SMP.
Only for built-in code, not modules.
Late init:
Late init functions are called _after_ all the CPUs are online.
module_init(): in a device driver is equivalent to registering a device_initcall().
include/linux/init.h):
#define module_init(x) __initcall(x);
and then we follow this:
#define __initcall(fn) device_initcall(fn)
#define device_initcall(fn) __define_initcall(fn, 6)
So, now, module_init(my_func) means __define_initcall(my_func, 6).
level 6, which represents all the built-in modules initialized with module_init
fn - callback function which will be called during call of initcalls of the certain level;
id - identifier to identify initcall to prevent error when two the same initcalls point to the same handler.
What is the use of file->private_data in a device driver structure ?
Macro vs inline; Explain each of them; and which one is better why?
What's the difference between “static” and “static inline” function? why we should defined static inline function in header files?
inline:
The inline keyword is intended to optimize the execution of functions by embeding the code of the function into the code of
its callers. The Linux kernel uses mainly inline functions that are also declared as static. A static inline function results
in the compiler attempting to incorporate the function's code into all its callers and, if possible, it discards the assembly
code of the function.
Rule of thumb: header files should only contain extern declarations, static const variable definitions and static inline
function definitions
likely() and unlikely()?
likely() and unlikely() are macros that Linux kernel developers use to give hints to the compiler and chipset. Modern CPUs
have extensive branch-prediction heuristics that attempt to predict incoming commands in order to optimize speed.
The likely() and unlikely() macros allow the developer to tell the CPU, through the compiler, that certain sections of code
are likely, and thus should be predicted, or unlikely, so they shouldn't be predicted. They are defined in include/linux/compiler.h:
37: #define likely(x) __builtin_expect(!!(x), 1)
38: #define unlikely(x) __builtin_expect(!!(x), 0)
IS_ERR and PTR_ERR?
The IS_ERR macro encodes a negative error number into a pointer,
while the PTR_ERR macro retrieves the error number from the pointer. Both macros are defined in include/linux/err.h
how to know frequesntly used comman function ?
Take any kernel modules and identify all the symbols within, extracting only the API that is NOT declared inside the
kernel modules: nm xxx.ko | grep “ U “, where “U” indicate that the function is not declared in the kernel module, thus belong
to the generic class of external kernel API function.
nm *.ko | grep “ U “ | sort | uniq -c | sort -n (number on the left indicate the frequency count).
what are the common encountered issues while devplopment of device driver ?
https://www.quora.com/Linux-Kernel-What-are-the-commonly-encountered-issues-in-development-of-Device-Drivers
There are quite a lot of issues that can pop up especially in device driver development, few of the prominent ones are:
Timing /Device Initialization issues
Driver Lock up/Synchronization issues
Interrupt/GPIO handling
Performance Issues
Memory issues
Timing /Device Initialization issues:
Most of the peripheral devices have specific timing requirement on various operations such as power on/off, IO, initialization etc.
This shows timing constraints on power sequence for this IC, w.r.t the display data, interfacing bus line status, power lines
and so, if these constraints are not met from the corresponding driver, it may result in quite a few problem; for instance
the IC may send invalid data to the LVDS connected display hence making it show some garbage screen - momentarily
Or the power consumption by IC may go for a toss
or even the IC power on/off may not happen properly causing it to enter an indeterminate state and so on
Similar timing constraint will be there on I/O Operations as well.
Another key factor would be initialization sequence or commands, of a particular device - certain commands should be sent to the
IC to initialize its operational modes(for e.g: in case of displays, its refresh rates, resolution etc.)So the driver developer
need to ensure that these timing & initialization sequences are also met .
Driver Lockup:
Most of the driver are makes use of threads or workqueue - which would be initiated to process some requests from userspace
or events/interrupts from peripheral.
For synchronization between each thread/work-queue some primitives such as mutex would be used.
With poor implementation , of synchronization primitives or corner cases, this would result in lock up between threads and
worst cases complete stall of the process or even panic(if watchdog or any debug system is being used)
So while driver implementation put in effort for identifying such pain points for careful design ensuring proper synchronization
(Consider points on performance issues as well) .
Interrupt/GPIO handling:
Most of external peripherals (to an SoC or processor) will have an interrupt line connected - via a GPIO interface
The behaviour of this line would differ across peripherals. For e.g.:
Trigger - Level or edge triggered
Edge - rising or falling edge
If the GPIO interupt controller is configured with wrong interrupt detection logic, it would result in either no interrupt being
detected or spurious interrupts to be triggered.
Another similar problem would be wrong configuration for a pin e.g.
configuring as an input while the intended function was to be output
configuring alternate function for the pin when it is expected to be a GPIO
Performance issues:
performance issues in driver can be addressed with proper design decisions i.e. when to use polling an interrupt modes of
operation on devices
Some devices will have limited buffers (or FIFO) registers to hold data in I/O operations, so in order to properly handle
I/O requests from userspace we need to carefully design data structures and associated processing in kernel drivers. For e.g:
In case of GPU interface driver in kernel, the driver will play some role in process context management as well as per
process command queue management
This may also have associated buffer queue handling, prioritization and synchronization as well.
So the driver need to be designed & implemented considering all the necessary points.
If not done properly, the application through put (in case of GPU - FPS ) will be affected.
Memory Issues:
excessive usage of kernel memory APIs for granular allocation will result in fragmentation
In case the hardware has any IOMMU for address translation in a peripheral device - take care of memory mapping and unmapping
via provided API set - otherwise will result in page fault for memory operations by the designated peripheral
When buffers are shared between userspace or kernel (such as overlays or frame buffer), proper
Synchronization of buffer access between kernel & userspace
Allocation API usage
IOMMU or related api usage
Caching parameters
There are even more issues, like:
Peripheral lock up - firmware malfunction
Bus hang up (if a peripheral is holding a shared bus in case of malfunction) or arbitration issue - which might have
resulted because of improper request or sequence from driver
Improper LDO or power supply configuration in terms of - voltage level or related parameters
IO memory mapping
handling hardware errors: If your device is interrupt driven, then there are chances of excessive spurious interrupts when
device starts misbehaving. Interrupt handler should be written in such a way that spurious interrupts are either ignored or
blocked(if possible). Otherwise system will spend all its time processing interrupts.
Memory : If you are expecting lots of operations with each operation requiring some memory to hold data structures,
use slab allocator instead f kmalloc all the time. Using kmalloc excessively for different size requests will fragment
kernel address space. Using slab will reduce external fragmentation to minimum.
Performance: Choose interrupt v/s polling wisely. If your device has DMA capabilities, it is better to switch to polling
and look for all completed requests at once rather than getting interrupt for each completed request.
How is a data sheet important, while developing Linux Device Driver, and how is it used?
When does the control passes from user mode to kernel mode in a Linux System?
System calls ,H/w Interrupts and last which I did not mention was Exceptions
What are the generic system call that is used to transfer data from user space to kernel space and vice versa?
http://wiki.tldp.org/kernel_user_space_howto
File system based communication:
Procfs, Sysfs, Configfs, Debugfs, Sysctl, Character Devices.
socket based communication:
netlink socket, TCP/IP, UDP
http://amsekharkernel.blogspot.in/2012/01/what-are-ways-of-communication-bw-user.html
Procfs:
procfs.c: legacy procfs API
Seq_file: API https://lwn.net/Articles/22355/
https://kernelnewbies.org/Documents/SeqFileHowTo
sysfs:
Sysfs was designed to represent the whole device model as seen from the Linux kernel. It contains information about devices,
drivers and buses and their interconnections.
sys/block/ all known block devices such as hda/ ram/ sda/
sys/bus/ all registered buses. Each directory below bus/ holds by default two subdirectories:
o device/ for all devices attached to that bus o driver/ for all drivers assigned with that bus.
sys/class/ for each device type there is a subdirectory: for example /printer or /sound
sys/device/ all devices known by the kernel, organised by the bus they are connected to
sys/firmware/ files in this directory handle the firmware of some hardware devices
sys/fs/ files to control a file system, currently used by FUSE, a user space file system implementation
sys/kernel/ holds directories (mount points) for other filesystems such as debugfs, securityfs.
sys/module/ each kernel module loaded is represented with a directory.
sys/power/ files to handle the power state of some hardware
debugfs:
Debugfs is a simple to use RAM based file system especially designed for debugging purposes. Developers are encouraged to use
debugfs instead of procfs in order to obtain some debugging information from their kernel code. Debugfs is quite flexible: it
provides the possibility to set or get a single value with the help of just one line of code but the developer is also allowed
to write its own read/write functions, and he can use the seq_file interface.
mount -t debugfs none /sys/kernel/debug
debugfs.c kernel module that implements the "one line" API for a variable of type u8 as well as the API
with which you can specify your own read and write functions.
Sysctl:
The sysctl infrastructure is designed to configure kernel parameters at run time. The sysctl interface is heavily used by the
Linux networking subsystem. It can be used to configure some core kernel parameters; represented as files in /proc/sys/.
In order to change the values permanently they have to be written to the file /etc/sysctl.conf.
sysctl.c sysctl example module: write an integer to /proc/sys/net/test/value1 and value2 respectively
Socket Based Mechanisms:
AF_INET: designed for network communication, but UDP sockets can also be used for the communication between a kernel module
and the user space. The use of UDP sockets for node local communication involves a lot of overhead.
AF_NETLINK (netlink sockets): They are especially designed for the communication between the kernel space and the user space.
There are different netlink socket types currently implemented in the kernel, all of which deal with a specific subset of
the networking part of the Linux kernel.
Ioctl: ioctl is used along with put_user and get_user to transfer the data from user space to kernel space.
ioctl.c kernel module that uses ioctl in combination with a character device.The ioctl allows to send a message of up to 200 bytes.
ioctl_user.c user space program that uses ioctl to send a message to the kernel
Kernel System Calls:
System calls are used when a user space program wants to use some data or some service provided by the Linux kernel.
Sending Signals from the Kernel to the User Space:
since only the kernel can send a signal to the user space, but not vice versa.
signal_kernel.c kernel module that sends a signal to a user space process. The kernel needs to know the PID of the user space
process. Therefore the user space process writes its PID in the debugfs file signalconfpid.
signal_user.c user space program that receives the signal.
Upcall:
The upcall functionality of the Linux kernel allows a kernel module to invoke a function in user space. It is possible to start a
program in user space, and give it some command line arguments, as well as setting environment variables.
usermodehelper.c kernel module that starts a process
callee.c user space program that will be executed on behalf of the kernel
Mmap:
Memory mapping is the only way to transfer data between user and kernel spaces that does not involve explicit copying, and is
the fastest way to handle large amounts of data.
/dev/mem is a character device file that is an image of the main memory of the computer. It may be used.
Byte addresses in mem are interpreted as physical memory addresses.
mmap_simple_kernel.c kernel module that provides the mmap system call based on debugfs.
mmap_user.c user space program that will share a memory area with the kernel module
Kernel Module:
charcater driver
kernel API : https://www.ibm.com/developerworks/library/l-kernel-memory-access/index.html
access_ok Checks the validity of the user space memory pointer
get_user Gets a simple variable from user space
put_user Puts a simple variable to user space
clear_user Clears, or zeros, a block in user space
copy_to_user Copies a block of data from the kernel to user space
copy_from_user Copies a block of data from user space to the kernel
strnlen_user Gets the size of a string buffer in user space
strncpy_from_user Copies a string from user space into the kernel
What is the differance b/w platform driver and device driver or kernel driver ?
http://www.atmel.com/Images/doc32098.pdf
How context switching is handled in linux.
what is user preemption and kernel preemption?
what is task_struct thread_info?
how system calls are implemented in linux.
What happens when recursive functions are declared inline?
What is a stack frame, stack pointer & frame pointer ?
interrupt:
Explain Minimizing Latency Scheduling of Soft Real Time Systems.
When an event occurs, the system must respond to and service it as quickly as possible. We refer to event latency as the amount
of time that elapses from when an event occurs to when it is serviced.
Two types of latencies affect the performance of real time systems, they are as follow:
Interrupt Latency
Dispatch Latency
Interrupt Latency refers to the period of time from the arrival of an interrupt at the CPU to the start of the routine
that services the interrupt. When an interrupt occurs, the operating system must first complete the instruction it is executing
and determine the type of interrupt that occurred. It must then save the state of the current process before servicing
the interrupt using the specific Interrupt Service Routine (ISR). The total time required to perform these tasks is the
interrupt latency.
The amount of time required for the scheduling dispatcher to stop one process and start another is known as dispatch latency.
Providing real time tasks with immediate access to the CPU mandates that real time operating system minimize this latency.
The most effective technique for keeping dispatch latency low is to provide preemptive kernels.
How do you register an interrupt handler on a shared IRQ line?
How does the Linux kernel handle shared IRQs?
When interrupts occurs on shared IRQ line, kernel invokes each and every interrupt handler registered with it by passing each
its own dev_id. Shared IRQ handler should quickly check the dev_id with its own to recognize its interrupts and it should quickly
return with return value of IRQ_NONE if own device has not interrupted(dev_id does not match). If dev_id matches ISR should
return IRQ_HANDLE so kernel stops calling nest interrupt handler. In addition to this, driver using shared IRQs should not enable
or diable IRQ. If it does, things might go wrong for other devices sharing the line; disabling another device’s interrupts for
even a short time may create latencies that are problematic for that device.
While writing interrupt handlers(ISR), which are points needed to be considered?
What is ISR? Can they be passed any parameter and can they return a value? can we use printf, break point, function call or any blocking or sleep call or floating operation in ISR?
Advantages and disadvantages of Polling & Interrupt drivers.
Both Polling and Interrupts have their place and usefulness in Production code. Using the right method at the right
place reduces code complexity and increases reliability.
polling:
Continuously poll IOs for change of value.
cons:
most polls are unneeded - value did not change.
hihg cpu usgae
Reaction time depends on IOs
interrupts:
normal execution is interrupted when events occurs.
pros:
processors resurces are used when ever required.
cons:
program execution is interrupted in a non-deteministic manner.
diff b/w system calls, exceptions, interrupt, signal,isr(interrupt handler) and callback ?
When should we re-enable the interrupts in an ISR and why ?
How do you measure the latency of your system ?
what is interrupt context.
what is ksoftirqd
If same interrupts occurs in two cpu how are they handled?
How nested interrupts are handled in ARM?
Explain about the concurrent work queues and wait queues.
How to debug GPIO interrupt functions?
Timer interrrupts vs Dummy loops ?
ARM interrupt service procedure vs function call procedure
How do I write to a __user memory from within the top half of an interrupt handler?
Are the Interrupt Stack and the Kernel Stack the same stack?
Difference between Timer Softirq and Tasklet Softirq ?
Is it possible for two devices to share an interrupt request line but have different ISR for those two devices ?
what is preemption disabling and what is the use of this.
Explain about the notifier chains.
How do I identify which interrupt line shown in /proc/interrupts list is shared?
What happens to the idle thread when a core is taken offline logically?
Data sharing between ISR and threads?
what actually does a system does in a tick?
How many interrupt lines you have been used in your driver development.
UART : 1 (RX)
Ethernet: 2 (RX & TX)
I2C : what is I2C Clock Stretch, Bus line clear.
Why Kernel Code running in interrupt context cannot sleep?
This is because the kernel design architecture wants it to be like this. Why so?
This is because interrupt context is not considered to be a process.So, it can't sleep.The interrupt code is
doing some work on behalf of process and if slept then it will not only lead to the blocking of interrupt code
but also the process that has called it .
When should one use Polling and when should one use Interrupts?
Both the mechanisms have their own pluses and minuses.
We should use interrupts when we know that our event of interest is-
1. Asynchronous
2. Important(urgent).
3. Less frequent
We should use polling when we know that our event of interest is-
1. Synchronous
2. Not so important
3. Frequent(our polling routine should encounter events more than not)
What is the difference between IRQ and FIQ in case of ARM?
ARM treats FIQ(Fast interrupt request) at a higher priority as compared to IRQ(interrupt request).
When an IRQ is executing an FIQ can interrupt it while vice versa is not true.
ARM uses a dedicated banked out register for FIQ mode ; register numbers R8-R12.
http://learnlinuxconcepts.blogspot.in/2014/06/arm-architecture.html
So when an FIQ comes these registers are directly swapped with the normal working register and the CPU need not take
the pain of storing these registers in the stack. So it makes it faster.
One more point worth noting is that the FIQ is located at the end of exception vector table(0X1c) which means that
the code can run directly from 0X1C and this saves few cycles on entry to the ISR.