 Welcome back. When we came here we thought that you guys are aware about basic hardware and we just want to write something for the Beagle board. But we will step back and just we first know that what is the use case and what is the general operating system concept where this device drivers fits in into and then we can talk about that how to write device drivers and so is going to tell you that how to write a basic device driver. So now I am not talking about this Beagle board. Now I will just like you boot a normal Linux box and you boot right and then you can open a file you can read and write to a file right. So basically what happens in the background? So like is it too basic or it is okay to cover that? It is okay? Okay. So here it is general Linux component wise what comes into when you read and write to a particular file. So when you open a file there is a file system which gives you this facility that you can open read and write a particular file. So you do any editor open a given file and you say that you want to write something and then you want to save. The minute you save there you issue a system call that is called write. So you issue a write system call write system calls takes your data into a buffer goes to the kernel. It transfers data from the user land. So you have allocated memory in the user land and kernel land has a different memory. So you first you write your data into the user buffer transfer it to the kernel buffer file system takes that particular kernel buffer and give it to the block layer. Okay. So this is and block layer finally gives it to the like there will be transport. So like think about this that you attach a hardest to a system you attach SD card to a system you can see it as a device right. They have SDA they have SDB something like that right. So now this SDA or SDB who gives you this there is interface. So this is the block layer block layer and the lower layer gives you the interface that this is the SDA this is the hardest SDB this is the USB device the SDC it can be a flash. So you so yeah coming back to write. So finally file system transfer the data buffers from user land to the kernel land and it will give you give that particular buffer to the block layer that I want to write this particular data on this particular device. Now from file system perspective everything is a device SDA SDB SDC it does not care that it is a USB device or it is a SATA device right. It all it knows that I want to write on dev SDA on this particular offset starting from this particular offset this is the length of the data I want to write that is all that this is all it file system need to know. Block layer of the like this block layer understand that this is the SDA this request has come for the SDA. So there will be basically when your device driver boots up it says that I am the device driver for this particular device SDA right. Similarly like if you plug in USB device so there will be another driver running in your kernel it will tell kernel that I am the driver of this particular device that is called SDB. So block layer knows that oh this is the device driver of the SDA it if you want to transfer data on the SDA it will give that particular buffer to SDA device driver the device driver of the SDA. Now this device driver will take that as a data and now it understand the lower layer that whether it is a USB device it is a SATA device so let us take example of a SATA device. So you this device driver understand that this data buffer I want to send it on this particular disk so it translate this particular request into a SATA request which you are underlying it underlying hard disk understand it just understand SATA request right SATA request read and write request it just understand that this hard particular hard disk right it does not understand anything about the file system or the way you are writing in the in a editor. So this device driver has responsibility to convert your read and write request into a SATA request and send it to the hard disk and hard disk will save your data similar thing like you when you read in read what you do is that you allocate some buffer into a memory in user land and tell that I want to read from this offset on this on a particular files files ok file system will convert that particular request to a device request saying that this file is stored on this particular SDA on this offset starting from offset x. So it will say that I want to read file system will convert your read request to a that I want to read from but particular device SDA from offset x then it will give it that particular request to the block layer now block layer will is just a transport it sees that request has come for SDA device and there is a device driver already registered for SDA. So it will give that request to the SDA device driver now SDA device driver will again convert it into a SATA request fetch the data from the hard disk and then give it to the block layer block layer will ultimately give it to the file system file system will transport data to the user land and then you see the data. So is that what clear? So now you understand that why why we need the device driver right? So till block layer everything is generate it does not understand any anything about underlying device ok you can have USB device you can have a SATA device you can have a SCSI device SAS device you have heard about SAS disk. So like normal SATA disk similarly there comes the SAS disk and then you have a flash like your NAND flash or your SD cards this and so this device driver basically has the responsibility to understand convert a request to a USB request or a SATA request and so this works as a interface device driver ok underlying device it need it knows that underlying device how what is the interface of the underlying device if it is a USB device it will convert a request into the USB request send it to the device when it comes back any request response comes from the device. So this device driver understand that oh this is a USB response has come from the device it converts into the more generic response and send it to the upper layer. So all hardware related stuff has been coded into the device driver itself no upper layer understand anything about hardware ok. So now we know that why why do we need the device drivers right? So now what kernel basically what kernel does how the kernel basically understand that you boot your Linux image and you see that all the disk has been automatically identified right or when kernel goes to your device driver. So that part I can cover basically what I am now we know that how what is the device driver functionality is now we are going to cover that basically that how the kernel understand and how the kernel interact with the device driver. The first time when the kernel boots up when it passes the control to a device driver ok. So let us assume that in a like in a hardware monosystem you have seen that PCI slots right and you plug in any device that particular PCI slot like you can plug in your disk and you can plug in any PCI device ok. So PCI has a standard format so all device which is support saying that I am PCI device it has to expose certain information on a device will have certain information on a given memory location ok. So if it is let us assume that this is the device memory. So here at some memory location X and that is true for all the PCI devices if anyone is claiming any device is claiming that it is a PCI device it has to follow this protocol that it has to give this information that what is like PCI ID and what is vendor ID and then device revision or something device information device info. So on a PCI it says that so this is a PCI device and on a given memory location X it will have information that this PCI device is from vendor let us say call it LSI and this is the device ID ok. Now what happens that kernel will have a generic PCI layer which will just go and prop on this particular PCI link and look at the each slot and sees that oh there is a device. So it goes and read particular memory location from that device and then it sees that it does not kernel does not understand that what is this vendor ID or what is this device ID. So what it does is that it just broadcast that I found a particular device and is there any driver. So in your driver what use so this is called PCI probe. So when you register your driver you provide some interfaces to the kernel that if you find any new device call me on this call my this particular interface let us say that we call that particular interfaces my PCI probe ok. So when kernel detected that there is a PCI device connected to slot 1 so it will and it will send that request to all the drivers which has been registered with the kernel as a PCI driver ok. Now any particular driver will look that oh this is the vendor some let us assume that LSI has given you a PCI driver. So when it sees that oh this is the string vendor ID is matching with the vendor ID of my driver for which this driver is supposed to be. So when it sees that then it is tell kernel that yes I am the driver for this and other drivers will reject that it will just they will not send any response. So once so once kernel knows that oh for this so now on what kernel knows that this is the when for this particular device PCI there is a driver that this driver is the main handler for this particular device. Now any request comes like go back here. So now if any request comes to the block layer which is a part of the kernel itself and now it knows that oh for this particular PCI device we have a registered device driver LSI driver and it will send that request to that particular driver is that part clear. So there can be other drivers as well like we have a I2C driver I2C devices have you heard about I2C? So this is just wire right. So on wire also so kernel this I2C devices also has to follow a certain protocol ok. So when the kernel boots up it just sees that oh on this particular I2C we have some device attached to this particular slot kernel does not understand that what this device is. So you are going to write a driver for this device I2C device right and you register with yourself your driver with kernel saying that I am the driver for this particular I2C device. So whenever kernel a request comes to that particular device kernel will automatically send that request to your driver. Ansel will tell you about how to write a driver and what all the components basically required in the driver memory management how you can do locking and those like basic stuff which is required for a general operating general driver. So this is very much hardware specific that those hardware specific details are contained in this device so that it does not get scattered in whole kernel. So from above you say you are watching a movie right. So your movie is stored in on this hard disk. Now so when you are watching a movie this movie is being read from hard disk right. Now so your say Windows media player or VLC player whatever it is starts reading this movie but this movie resides here hard disk. Now I mean so it say it issues operation read. Now this read gets translated it goes to the now you have say four disk four drives say drive D E F CD E F. Now movie resides in drive D so I mean who has this information that this movie is this particular read request belongs to drive D not E. So that is the file system. File system knows okay this read request should go to the device D. Then it goes to the block layer as Divesh mentioned and transport the device driver contains all those hardware specific details right because sometime you buy a hard disk from so you must have bought this external hard disks right. So I mean vendor could be different right sometime you buy it of western digital sometime it is of Fujitsu or whatever. So those details are understand by specific device driver only. So I mean have you seen this when you connect a device right and it says Windows says that unable to find the hardware driver right see this. So because it does not have that driver which can understand this the language in which this hard disk can be talked to. So that is why you require you put in the CD or specify the location okay here is the device driver for this okay. So these all the details I mean he is covered. Now alongside he has written this memory manager. So memory is another component of the OS right. So when you want to perform certain operations you want to say okay I want to send a command to now you are sending a read request to hardware hard disk sorry. So you require certain memory right you require some amount of memory which will in which will write your command say suppose the hard disk say the read opcode sorry I should write bigger say the read opcode is hex 1 okay. So and after that you write offset. Offset is the because hard disk is say 32 GB. So from where I should read. So offset is say I am writing it MB though it is in sectors 1M and say length how much is to read. Length is say read 1KB okay. Suppose the format now the 0X1 this value then 1M is the offset and then 1K. So this kind of request will travel to hard disk. In the format hard disk understands right. Suppose hard disk says okay first thing should be the opcode whatever is defined by the hardware. So now this request travels to the hard disk it understands okay 0X1 is the read that is why it will read. Now but all these things require memory right because you are going to write somewhere and that memory address will travel to the hardware. So that is why he mentioned this memory component okay. Now what is a hardware driver? So hardware driver is like understand it is translator between two talking entities not knowing the same language. Now these two talking entities are one is the kernel and other is the hardware. So hardware driver sits between that. Now kernel wants to talk to hardware driver but cannot directly talk because it does not understand the language of it. So it requires some translator some you know someone who can understand language of hardware. So that part is you know done by hardware driver. So what does it do? First of all it talks I mean it can communicate with the hardware and as well as it hides the complexity of accessing the hardware. You can put the same code into kernel right every time for all I mean hardware existing in this world you can always put code in kernel but little clutter everything. So it hides the complexity of accessing the driver very common example is disk driver right. So your CPUs you must have bought SSD right go and you say SATA hard disk I want to purchase say 500 GB SATA hard disk I want to purchase SATA what is SATA? SATA is the protocol by which this hard disk communicates okay. So whenever you want to talk to hard disk you will send a SATA command whenever it wants to send a response okay I have read it will send a SATA response. So this device driver it is again and when as we mentioned that it sits between OS and hardware. So this is what you know this is the hardware this is the kernel driver sits between communication is both ways. Kernel sends a request hardware translates it in the language which is understood by hardware sends it to the hardware. Again hardware completes the request sends the response back to driver translates in the you know language which kernel understands and sends the response back. So Android you know it was so now the whole idea is to write a driver for Beagle board so now we are porting Android on Beagle board that is why I am in this slide for completion you know sake of completion that what is Android we know this mobile phone software platform and I mean as we have covered in last session that based on Linux kernel it is mainly you know rewritten or probably the bugs are fixed and this things are included into this the code which is included in this only to suit it to the mobile phone platforms. So what all changes again we have described what all changes have gone into Android from Linux kernel to Android you know hardware which for which you do not need a very huge operating system right because on a x86 box you have huge data stores big desk you can store very big kernel over there you can have a very big root file system but on mobile thing just you have a one SD card of some initial it was some MBs now it is available in GBs as well so on that and then you need to store your information as well like you want to store your music files on the same SD card so that is why this Android is basically cut down version the trim down version of the Linux okay so and like as I also said you can go back yeah this one yeah so it is you know trim down version of Linux which is change to suit requirement for mobile application development or mobile driver developments now we know there are we should have be aware of two things if you want to write a device first is the kernel other is the hardware now I will cover what is the resources which driver requires from kernel you know this for this interaction first of all driver should be able to register itself with the kernel it should be able to tell it to the kernel that hey I am exist I exist so that we call registration process so every kernel provides certain API's so for I to C driver if you go to the Android you see I to C underscore add underscore driver that is the API if you call this API with the necessary parameters parameters will be your proof function and so and you call this API so kernel will register your driver with itself now every time it will find a new device it will send you also hey I have got this new device are you the owner of this so this is the part you know kernel should be aware of the presence of device driver so how do we do it we register driver with the kernel in this registration process we provide probe and attach method what are probe and attach method probe is a method by which if kernel report some new device to you should be able to identify the I own this device or not and then as we mentioned in last session that I mean could be a loadable module or a statically linked driver so loadable module is as you mentioned that I mean it is fast forward or statically linked I mean we want to build your driver into kernel only every time I want to compile kernel so that is why we call statically linked driver and yeah now so for interaction every driver requires certain you say memory it requires memory that is the resource of the kernel and it requires you know locking so locks and okay I will come again water locks it requires memory it will require locks and it will require a notification you know interrupts water interrupts right so it requires okay if I get a if a interrupt is received then driver provides a handler okay I mean call my this handler okay so driver needs to tell kernel this is my interrupt handler okay and it require memories as well as locking primitives so I will also come in why do we require locks what are locks locks are you know in general they are protecting mechanism right you protect something you lock it under something so in general we lock say we lock something inside our room so that is protected right same concept is extended here so but you know not because of someone is going to steal something but you know you know preemption also what is preemption you know okay so kernels are preemptive by nature what is preempt is you know if suppose one process is running right if suppose you are writing a word document if that process is doesn't yield the CPU so only that process will be running everything else will stop you know so to increase responsiveness interactiveness kernel provides this preemption so say after say every five milliseconds it will preempt process which is running and bring a new process so that every process will get a fair chance you know this thing is called preemption so now if you are in middle of something you are writing a word document okay and kernel preempts you right and then the new process which was you know basically in the new process that tries to access the same thing or take the example of your copying a movie okay your copying a movie to hard disks and kernel preempts you in between but and your another process is VLC media player which is trying to access the same movie if you are not protected you know it will things will get corrupted right because I mean you are in middle of a process and it's on a higher granularity so you are in middle of a process and you are kicked out someone else comes and tries to access the same thing which you are in middle of modifying so to restrict again or to safeguard against these kind of preemptions these kind of kicking out kernel provides logs so what you do so if you want to protect something you will take the lock do step one whatever is your steps whatever you want to do do it and unlock so now it's guaranteed that I mean if you are holding a lock and you are kicked out from here okay nobody else can take the lock because lock is still held if somebody else is trying to do now these locks are designed in such a way that only one guy can take it there are different type of lock but currently assume the only one guy can take it okay so if you have taken a lock and you are it is step one you're kicked out the other guy who is trying to come he cannot take a lock he'll try to take the lock will not be able to succeed and he'll be kicked out you again after sometime you will again be restored your process will be restored you execute step two and unlock so we require locks to safeguard against this you know preemption or the unplanned yielding of CPU I would say synchronization is the term actually which is used so synchronization of data accesses across multiple processes that is called this thing you know that is again done by done using locks driver request certain system resources memory locks and all interrupt handle it registers kernel is made aware of the presence of the device driver and kernel also need to know if I want to perform a certain tasks task how do I you know indicated to a driver so for that driver provides a method or say in case of example if a disk driver disk driver will say okay if you want to read this is the method you should call that is the thing which is required so driver provides a method for request to perform a task kernel also perform a task it will provide a method there are standard ways for this you know depending on the kernel Android has a way so for a disk driver you provide a Q Q command yeah so you provide a Q command function for freebies it could be different but concept is across the OS it's same then another interaction which is required which is which happens between driver and the hardware for that you need to understand the hardware specification I mean how do you communicate with the hardware and the language in which hardware talks to we call it a protocol right so in case of SATA devices the protocol is SATA in case of I2C devices protocol is I2C okay so what is this interaction this driver and hardware interaction is driver converts kernel request into request which hardware understands now one kernel request may convert into many hardware requests so suppose now you have sent this kernel request kernel sends suppose a request of 1MB kernel wants to read a 1MB data from hard disk support the hardware is hard disk now the suppose hard this hard disk is not capable of returning 1MB data at a time its capability is only say it can read only 1k data at a time so whose responsibility is this to split this request into you know multiple request that's the responsibility the hardware driver so if it's it has sent a 1MB data what it will do it will split into so maximum is 1k it will split into 1024 request and send it to the hardware it will again get these 1024 response at a time and prepare the combined response and send it to the kernel so this you know basically you know splitting merging all these you know job all these responsibilities rather are lying with the hardware driver could another example could be say our hard disk cannot handle say more than 20 requests at a time but you I mean while I mean running your applications you open a word document open a text file watch a movie so you never really care I mean how many applications you are running whose job is this again the hardware driver if hard disk cannot serve more than 20 disks at a time kernel send say 25 request so these hardware driver will queue 5 requests send only 20 and response of 5 will come back it will send another 5 so all these you know hardware limitations will be overcome by the hardware driver so now driver and hardware so as I mentioned you know it mentioned it converts kernel request into request which hardware understands one kernel request make convert into many hardware request as we have seen just now and develop a hardware driver you require a hardware specification so if you want to access a hard disks I mean what is the language it understands so that is again defined by the hardware vendor so for Beagle board as it's as I mentioned it's open source hardware so you get the these specifications online okay if you want to access these NAND flash in what register you should write so all these specifications you require in if you wish to develop a hardware driver and then interaction with hardware depends on the type of hardware very much true hard disk need not be accessed in the same way USB devices are accessed they need not be accessed in the same way in which you access your serial console every hardware accesses accesses are depend on the type of the hardware now again I mean how do you write a driver first of all I mean I think I mean you should be able to you know understand this that now what all do we require we require a hardware specification we require a register specification register specification I mean in what register you should write in order to get a certain operation performed so that is again given by the hardware vendors then protocol to communicate with hardware what is protocol I mean the language which hardware understands so if you're writing a protocol for SATA device you should understand how SATA protocol works if you're writing a protocol for SPI flash you should understand how this you know SPI flash works and then again how does it ask this kernel expects it to be informed so when a certain request completes how does kernel expects that if a disk has read something how it will be notified how the kernel will be notified that this read request has been completed this is specific to the kernel so now this sequence is now how do we write a driver yeah be careful about the sequence in which we write so as I mentioned first we register our driver with the kernel then we do the initialization initialization is in order to get ready hardware has to you know it has to allocate certain resources it has to be prepared before it can accept request right so that preparedness is called initialization right and then when your hardware initialization is done it's prepared to request prepared for receiving requests it will notify kernel hey I'm ready okay so this registration so for example I mean so for I2C device it's I2C add driver initialization is very much hardware specific for disk device you would allocate the memory certain memory which you will require to send to the disk you will you know initialize your disks whatever disks you have say you want to power up those disks which are which you own so all those initialization will do and finally as a notify process you will enable your interrupts so when we say enable interrupts means now if kernel sends any request hardware is I mean driver is ready to send it to the hardware and ready to receive the response okay so clear steps and the sequence is important I mean you cannot first notify to the kernel hey I am ready to receive the request and you are not prepared right it cannot happen because you have to be prepared first only then you can notify kernel I am ready so step is register initialization and notify I'm ready then these are I mean how do you do these steps these are very much kernel specific I mean just say for any component you want to write a device I just search for it so API might be different depending on the driver you are trying to write but steps will be the same okay few things you have to keep in mind while writing a driver first of all this thing is you know very critical generally people you know it can cause issues which are very hard to detect memory coherency so what is memory coherency you know about CPU hardware caches right CPU has hardware caches L1 L2 right so these are caches for memory main memory right aware so CPU has hardware caches L1 L2 this is the cache for main memory now if you are suppose you are sending a request to hardware and that memory location is cached into CPU cache so if that memory location is cached into CPU cache and you are sending that memory location to you know hardware and but since that memory is not updated because data is in L1 cache or L2 cache whatever so hardware will get the incorrect data so before sending this request to the hardware you should make sure there is nothing in the cache there are two ways either you flush the memory flush the cache sorry CPU cache or you allocate the non-cacheable memory non-cacheable is the type of memory that will not be cached so OS provides a mechanism say for I mean this Android if you go and you'll allocate a memory D a lock DMA coherent so that means that memories that will not be cached okay so this thing you have to be careful yeah but if your system does not have cache hardware cache you need not worry about this if you don't have memory management unit available then other issues synchronization as I mentioned you don't protect against something so you know one thing is you are submitting a request but if interrupt comes so suppose you have two requests first request you have submitted and second request you are in process of submitting but since you are in process of submitting the first request gets completed now you'll get a interrupt for the request which just got completed and interrupts are always high priority in system so whatever is running that will be stopped and interrupt will come right so if you are not and you know safeguarding appropriately you might compromise with the correctness how come say suppose in interrupt you are accessing a data structure you're accessing certain variable which is also being accessed in the submission path so assume there are so suppose this is a disk this is request to which is your submitting request one we just got completed so the case was you first submitted request one and now at this point you are just submitting request two and this request get complete completed in interrupt context what do I mean by interrupt context interrupt context means system notifies you by raising an interrupt that a request has completed now this interrupt context is always a higher priority than these normal contacts so whatever request you were submitting this thing will be will get preempted this submission path and interrupt will raise now if you are accessing a variable say where x in this path and same variable you are accessing in interrupt path also so you if you just you know finished writing x equal to set two and in request path in response path this path you basically change it to three now after this interrupt I mean if this response is sent you will see that x will be modified you know these kind of you know simultaneous accesses these time type of common accesses you should safeguard against so be careful about these things so it's not really possible to list down all cases because as in when you are going to ride drivers you will see just keep in mind whatever you know accesses are you know susceptible to these these type of synchronization issues you should you know carefully protect them I mean kernel again provides multiple ways of lock multiple type of locks so one lock so you require you know threads right so there are threads in system if you want to protect against between two threads just provide a simple spin lock there are variants one is a spin lock another is a spin lock IRQ save so that spin lock IRQ save is it will provide you again it will safeguard you against interrupt if you have taken a spin lock IRQ save then system will not raise an interrupt even if it's pending so that way you safeguard against interrupts there is third type of variant which is called bottom half spin underscore lock underscore BH that is safeguarding against bottom half so what is bottom half probably I'll cover a little later but just keep in mind there are these three variants simple spin lock spin lock bottom half and spin lock IRQ save simple spin lock is required when you have two threads and you want to protect a variable or a data structure which is being accessed only from these two threads or only from third context but if you want some to protect something from interrupt context then you have spin lock IRQ save available and if you want to protect something from bottom half that will cover little later it will you should take spin lock BH but yeah I mean if you take spin lock IRQ save always it will always protect you against everything but you know taking this spin lock IRQ save is heavy so I mean we are just you don't generally over protect because of performance reasons so if you replace your all locks by spin lock IRQ save you are very much safe but problem is it will hurt your performance a lot because even even if because if you delay your interrupts in system unnecessarily then it will increase latency of your system so by that way your performance will be hurting a lot so you should know your code I mean and understand what needs to be protected against also so if it needs to protect against only a thread then probably just take a simple spin lock right and the last thing in interrupt context doesn't allow sleeping calls so when we say sleeping calls what do they mean sleeping calls is the call with sleeps you must have seen the sleep operation right SLWP in the next so it sleeps the thread again so same way there are certain calls which are sleeping so suppose you do malloc in user space right so it can sleep though you might not be knowing because system is you know multi-threaded so you might not notice this behavior but user space program malloc can sleep because if system does not have memory okay I'll wake it up after some time and system has enough memory so those kind of calls are not allowed from interrupt context because if you sleep in interrupt context that is the highest context who will wake you up right that's one reason so these calls are not allowed from so this is one thing which you should be careful of these are few tips you know when you start writing skip in mind I mean these all issues can you know come up it will help you in debugging and so I mean before and if you know that okay what all issues can arise so it will I mean help you in debugging then again another major issues performance so we I mean writing a driver is one part and but you know you can do it two ways it's optimized driver good driver or it's a pathetic driver pathetic in the sense so if you're trying to access a disc so we have two drivers one is very well written in the terms of performance it will it's rest it be various responsive it's you know it has it reduces the latency of the in the system and another driver is though disc ads so the disc response time is say one millisecond but your driver adds another one millisecond to it you know these kind of issues are very important and since you know I mean if you're in embedded system especially you know it's very important to understand this these performance issues otherwise you know you find I mean you'll this driver is just a you know piece of you know just say whatever bad code I would say because I have seen this I mean open source we have seen these kind of drivers which are just even if you don't require to protect anything take IRQ lock IRQ lock from start and leave it at the end though you don't require it so I mean these are so there are few tips and these are all from experience I mean nothing so first thing is longer the interrupt context higher the latency for pending interrupts so if your interrupt context is longer you are unnecessary delaying your interrupts so you're not getting the response so it will increase your latency then another thing is so it as a remedy to this use deferred work technique so what is deferred work this Linux Android all these OSS provide deferred work technique so it means do whatever is necessary in interrupt context what whatever is very much a necessary in interrupt context and defer rest of the things so how do you defer so there are certain API is available so we call it tasklets bottom halves all these are comes under deferred work technique so in interrupt context say we have minimally we will do ok acknowledge the interrupt we have handled the interrupt and schedule a tasklet so just acknowledging in scheduling and come out of the interrupt context so when you come out of an interrupt context interrupt will be enabled so rest you know again few more interrupts can come and when system will have time it will execute the scheduled bottom half or scheduled tasklet in the in the you know whenever it gets time or whenever it is free from interrupts then again don't overly protect as I just mentioned I mean just you know it is always safe to take lock everywhere it will protect you against everything but your performance will be I mean you know very bad you I mean just try to I mean when you are going to write this just try to take IRQ save lock from a start to the end and see the impact it will have on the performance of the system then this don't overly protect means this I mean protect only the part which is necessary don't protect everything ok then last thing is static fields of a request should be initialized once I mean there are if you are sending a request to the hardware you know and a field which is always fixed you know read off code if you all know that ok your requests are only going to be read and read off code is one so keep it fixed I mean you don't need to change it every time so only because embedded systems the more instructions you execute you know more penalty you're going to pay so better thing is if something which is fixed keep it you know initialize it once and whatever is changing just change it with the incoming request then few more thing is exploit underlying hardware I mean this thing is very very critical I mean generally people write the code is you generally write the code and don't really care about the hardware see what is underlying hardware but it really hurts performance a lot so if you are working on arm you should understand how arm works I mean there are certain things about arm ok so if we pass more than three arguments to a function the four so three arguments to a function are passed into the registers but the fourth argument is passed on the stack so that means the four for fourth argument in memory excess is going to happen all those things about your hardware you should understand so better you understand your hardware you will be in a better position to write a better hardware driver or better program these things you know really matters a lot because I myself I mean we myself I mean we ourselves have seen this these things you know a simple program I can give an example a what was that was 1024 cross 1024 matrix multiplication program ok so we have allocated memory from the kernel in Linux kernel that was taking around 300 odd seconds ok then same program we have run run into free BSD we are allocating this mem these 1024 cross 1024 memory from Linux kernel the first test case second test case we say ran same test case on free BSD ok so it took around 600 some seconds ok program is same everything is same processor is same but and then third thing we have written our own memory management in the sense that you know because because we were using ARM 6 so there are certain you know strength to ARM 6 which we try we try to exploit and it took around 140 seconds so even half of the Linux so understand your hardware I mean so I mean you might not be understand everything today only but have that goal in mind ok so I will keep improving so that will that way you will be in a better position to you know write that software and at last I mean most importantly know your code so it should be very clear I mean what you are doing because my guide used to say I mean I mean code are for human not for machines generally we tend to think these are for machines and machines will understand them but when you know are going to you know probably improve them that is for you to understand probably someone else will understand so you should be very clear on what you are doing why you are doing I mean why you have taken this decision thank you