Showing posts with label Symbian OS. Show all posts
Showing posts with label Symbian OS. Show all posts

Monday, December 29, 2008

Key flows in Symbian OS (keypad)

Keypad Architecture and key Flow in Symbian OS


--->Symbian OS is open because updating new HW is very easy for example I will discuss about the keypad. How Symbian supports different vendor’s architecture. Symbian doesn’t know about how the third party keypad HW is going to work, because Kern’s class AddEvent() function is the bridge between the keypad and kernel. It’s quite interesting right?


--->It’s a simple formula used C++. That’s called modularity. While designing any type of application we will think about the input to the module and output of that module. This will reduce the maintenance change requirement time. I.e. changing the keypad HW doesn’t affect the kernel so no need to recompile the kernel. Now it’s time to explore, what is the output of keypad driver and what is the input to kernel keypad queue.





--->TRawEvent type is the output of the keypad PDD and input of the kernel. What TRawEvent contains? This object tells the event type which is generated by keypad. The kernel work is to dispatch this object to the window server. After that, kernel job is over. Window server has to take care to dispatch the event to the correct plug-in or application. It has to translate the key to identify the particular key. For example pressing the number key 2 continuously three times should result in displaying character “c”. Window server’s CKeyTranslator does this job.


--->Window server gets the TRawEvent from kernel, and it passes to all the plug-in which are all registered with window server. If no plug-ins are consumed the key events then it passes to the application. Passing the key events to the application is very easy because it will get the current focus window and window server passes to that application. Its just overall about the key flow architecture. Once you got interested in that just explore the code you will understand clearly….:-)




Friday, October 24, 2008

Symbian OS Thread - Internals

-----------------------------------Symbian OS Thread Internals----------------------------------


This small code tells how to create a thread. From the example code we will explore how it works.


//code for creating thread.
RThread thread;
thread.Create(KThreadName, threadFunction, 4096, KMinHeapSize, 256*KMinHeapSize, NULL);
thread.Resume();


//This function is called when thread created successfully.
TInt threadFunction(TAny *aPtr)
{
RDebug::Printf(“Thread created successfully”);
RDebug::Printf(“You can add Trap and active scheduler support for this thread”);
}


---->RThread is the class for creating thread in the user side. Create function of the RThread class is responsible for Generating software interrupt. Before generating software interrupt, it has to construct SThreadCreateInfo8 structure object. This object will contain stack size, min heap size and max heap size and call back function for this thread creation. This call back function is called when thread created successfully.


struct SThreadCreateInfo8
{
TAny* iHandle;
TInt iType;
TThreadFunction iFunction;
TAny* iPtr;
TAny* iSupervisorStack;
TInt iSupervisorStackSize;
TAny* iUserStack;
TInt iUserStackSize;
TInt iInitialThreadPriority;
TPtrC8 iName;
TInt iTotalSize;
};


Role of Create Function:


1. Checks stack is negative or not if it is negative, it will panic.
2. Checks the minimum heap size is more than 0x100 bytes or not else it will panic.
3. Checks the max heap size is less than min heap size or not else it will panic.
4. Validates the Thread name is proper or not else it will return error.


ExecHandler::ThreadCreate


---->This function is the actual code for creating thread for our process. This will call NewThread() function of currently running DThread object’s member variable DProcess . How the kernel will know the current process’s DProcess Object? Kernel gets this information using TheCurrentThread macro this macro will contain current Thread’s DThread object. Using this, kernel creates the DThread object and kernel assigns new handle for this particular thread. All these stuff will run under critical section. So kernel should enter into critical section before doing all these stuff. once it done it should leave using NKern::ThreadEnterCS() and NKern::ThreadLeavesCS(); Finally this function returns the Handle to the caller(Exec::ThreadCreate()).


Tuesday, September 16, 2008

Thread on Symbian

-------------------------------Threads on Symbian OS--------------------------------
---- Threads are basic entity of a process. How do we create a thread in Symbian? Before going to discuss about threads on Symbian we should first understand thread structure. What are the minimum requirements for creating a thread?

---- Thread is called single execution unit of a process. It’s necessary to have a stack for each thread because without stack we cannot create thread in application.

Why I cannot create a thread without stack?
---- Thread is nothing but, collection of function or single function. Function is for processing data. Thread has to store those data somewhere in the memory, it can store in data block so that the life time of that variable will be until the program termination. But for local manipulation thread should use stack for storing or retrieving data temporally. Every function call is using stack, how? Compiler stores the return address in the stack before transferring control to that function. So it’s mandatory, that each thread should have stack. Otherwise programming is not possible.


Process structure:



Threads in Symbian
----Class RThread is used to create thread in Symbian. RThread class has a function is called create() is used to create a thread. What and all I have to pass to create a thread? Yes we will see one by one this

RThread iThread;
iThread.Create(Threadname, function pointer, stack size, Heap pointer, thread arguments,thread ownership)

Agruments:
TBufC iThreadName(_L(“ExampleThread”));
TInt ThreadInit(TAny *obj);
TInt iStackSize = 32000;
NULL
NULL
Default it will take EOwnerProcess

Thread Creation:
Class CThreadExample
{
RThread iThread;
Public:
CThreadExample();
Friend TInt ThreadInit(TAny *obj);
};
CThreadExample::CThreadExample()
{
TInt err = iThread.Create(iThreadName, ThreadInit, iStackSize, NULL, NULL);
If (err != KErrNone)
{
RDebug::Printf(“Thread creation Failed\n”);
User::Leave(err);
}
iThread.Resume();
}

The function which we register in create call will be called once the thread has been created successfylly.

TInt ThreadInit(TAny *obj)
{
RDebug::Printf(“Thread successfully created Its now ready to run\n”);
iThread.Kill(KErrNone);
}
....:-)

Sunday, September 7, 2008

Theory On RMutex

----------------------------------Theory on RMutex--------------------------------------

---->What is Mutex? Mutual exclusion object is called Mutex. When you are going to handle a particular non sharable resource, it’s necessary to use mutex to support non sharable resource sharing feature. For example in our system, UART port is non sharable. Only one thread can hold at any point of time. Consider this situation; In Symbian phone a thread is holding a UART port for transferring data to system. After some time another thread needs to use UART port for some other purpose, but already a thread holding the UART port so unless until the thread releases the port this particular thread cannot access the UART port. How does the second thread come to know once the first thread released the UART? Here RMutex comes into picture. When a thread or process is going to use the non-sharable resource it should create or use (already exiting Mutex object of that particular resource) a mutual exclusion object and who are all waiting for a particular resource, they should also use the same mutex, because when a thread releasing a non sharable resource the kernel will notify to all other thread which are all waiting for that resource (i.e.) which are all waiting on the RMutex object. If multiple objects are waiting for a particular resource that time priority and scheduling will come into picture.





----> Consider already kernel created an RMutex object for UART resource. If a thread wants to use the UART resource it should first wait on that Mutex object before acquiring the UART resource, it means, it should check, weather the UART resource is free or other thread is holding the UART.

Openning a MUTEX object:
RMutex iMutexname ;
Err = iMutexname .OpenGlobal(UART_Mutext_Name);
If (Err == KErrNone)
{
RDebug::Printf(“UART mutex open failed\n”);
}

---->Before going to use the UART that particular thread should check, weather the UART resource is free or not

iMutexname.Wait();

---->The above function will not return unless until other thread releases the UART resource. Once this thread acquired the UART resource it can do its work. If this thread wants to free UART resource it should call
iMutexname.Signal();

---->This SWI call will inform other threads, who all are waiting for the UART resource.

NOTE: Before signaling the resource to free, programmer should check weather this thread acquired the resource or not using IsHeld() function

If (iMutexname.IsHeld())
iMutexname.Signal();


---->If you are not checking, sometime it will end up with KERN-EXEC 1, It means, the thread is not acquired the mutext but it’s trying to free the mutex that it not possible by kernel.
Ohhhhhhhhhhhh:-)

Sunday, June 29, 2008

Kernel Extension, Interrupts and Hooks

----------------------------------Kernel Extension, Interrupts and Hooks--------------


Kernel Extension

This is just a DLL. Why we need to call it as Kernel Extension? What is the difference between Kernel extension and Device Drivers?

-----User application can load the device drivers and unload, but Kernel extension is not like that. User cannot load or unload it. Once kernel is loaded into memory then Kernel will responsible to load the kernel extensions into memory, Extensions are permanently resides in memory along with kernel, but user cannot call the kernel extension(it is possible but need to give interrupt framework or something like that). But user can load, call & unload device drivers dynamically


How can I write a Kernel Extension?

----- Writing Kernel extension is very simple we need to add a macro in our source file. The macro is


DECLARE_STANDARD_EXTENSION ()
{
// Create Object for your extension class
//return the object
}

The above macro will be replaced by preprocessor like,


#define DECLARE_STANDARD_EXTENSION()
GLREF_C TInt InitExtension();
TInt KernelModuleEntry(TInt aReason)
{
if (aReason==KModuleEntryReasonExtensionInit0)
return KErrNone;
if (aReason!=KModuleEntryReasonExtensionInit1)
return KErrArgument;
return InitExtension();
}
GLDEF_C TInt InitExtension()


-----Inside this InitExtension function we need to create object for our class. This function will be called by kernel once kernel is in upstate. Now kernel extension is ready. How to use the kernel extension?


Kernel Extension code example:


Example obj;
void newISRMain()
{
Obj->newISR();
}
Class Example
{
Public:
Example();
void newISR();
};
void Example::newISR()
{

}
Example::Example()
{
Kern::setNewISR();
}
DECLARE_STATDARD_EXTENSION()
{
Obj = new Example();
}


This is the layout of kernel extension.


-----This Kernel extension is in Kernel space, how can we use this kernel extension? This is the place Kernel HOOKs coming into picture. Before going to discuss about HOOK, we need to revise DOS operating system’s interrupt handling.


About TSR:


https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0YhvHC_VlIbnlmx7j3weyJBm7dw51qC62SaC2ywgNe5MqsOEnJyfm3TJm4gr6VQ5TCRRX-K2MfcEqf_66TvyervWVPE9mmTJsXybNIpoc9BziUkdjngboj_gEJ82ftjS_d0CtTSsulr09/s1600-h/Slide36.GIF


TSR Concepts:


https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh63O_Wz1bNwGK8_q6-ZRnOcwLEzCuQM66g9deSuQBuHMCBkVQy_ZPXKtOKKPbwxzZXJqNai2vwC3UJAb9xMegJUIXFvCz58lKMGJ30q3iFCmOBI2RkAjoXEqp2u68PWQkJq5tph9JsiqzW/s1600-h/Slide37.GIF


Interrupt Vector Table:


https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjrNdq8yFQcm1pr0iyWUWkI_O3phLxh6Iz_ZmSmAKHldL2h3GehbkR9Lk1CGp0RAn4qp8v_RIQDvWYBEuWJ3dqBnWcC7W_QZFs5oOOFoxPiXoZ7-7mbhxZRUxzZo0IebruuQPqy0oqA7WUd/s1600-h/Slide40.GIF


Simple Example Program for setting UP New ISR and removing old one


https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4v88v78HATTartJC2sQ9xa1wX1p9Sbv-MMcPFqom_-n01WR02gu9aDRywAfFFzl8b6Q9RX7qv2irs57wBTyNgR4S75GzdV40s2YPMmVOy0eXTtjiA4FBq3v5WBwmH1HiGZRsT1-OrC9o1/s1600-h/Slide41.GIF



----- If you would have read the above last two links, you will understand this. IVT table is the place to store all ISR address. Whenever interrupt occurs, interrupt number will be multiplied by 4 and then control will go to that location, that will contain the corresponding ISR’s address, through that pointer we can call the ISR.


For example:


----- 0x33 is mouse interrupt number. Whenever you move or click the mouse cursor, interrupt 0x33 will be generated and this interrupt number multiplied by 4 so the result is CC (51(0x33) * 4 = 204(CC)). Control will go to this (CC) location, this location contains the ISR's function of mouse. We got the address of the mouse's ISR and we can call the ISR. (Open the third link for understanding this example).
----- If you want to add a new ISR into IVT table, we need to find out the Empty space in IVT table, there we can place our own ISR, This is the way to create new ISR in DOS operating system, and we can remove the address from one IVT’s cell, after that we can place our own ISR's address there. If we like we can also take backup of the previous one.


In Symbian


----- Symbian Kernel HOOKs is equivalent to IVT in DOS and WINDOWS Operating system. Instead of calling IVT, here we are calling it as Kernel HOOKs. We can also set our own function into Kernel Hooks. There is a table of function pointer maintained by Symbian OS called KernelHook. There we need to add the new cell for our ISR.
----- If you have ready met address of the function, then you can set the address in this Kernel hook function pointer array otherwise, you can use the sethook() function to set the function pointer dynamically. Its like TSR program in Turboc compiler


#include
void interrupt (*prev)();
main()
{
Prev = getvect(0x33);
Setvect(0x33, fun);
Keep(0,500);
}
Void interrupt fun()
{
//do your stuff
}


In symbian we will use like


TKernelHookFn SetHook(TKernelHookType, TKernelHookFn, TBool);


TKernelHookType This one tells the cell address need to replace with the new function address.
TKernelHookFn This the actual function pointer.
TBool tells weather it is over rid able or not.

Steps to remember:


1. Create a Kernel extension
-----Just write a C++ class and add the declaration “DECLARE_STANDARD_EXTENSION() , In the constructor of your class call a kernel utility function to set up the kernel hook table.


2. Before that you need to add a kernel utility function in Kern’s class. Use this function in -------your kernel extension’s constructor for setting up the kernel hook function handler.


3. If user application wants to access this function, then we can give a framework like interrupt to access this function from user side.


4. How to add a new interrupt?

How to access Kernel extension via Interrupt (coming soon)... :-)

Friday, May 30, 2008

IBY and OBY Files

-----------------------------------IBY and OBY Files --------------------------

-------IBY and OBY are text files. There is no fantastic architecture behind it; it’s all for understanding purpose. Suppose consider a situation writing a C++ application, we are placing all declaration in the header file and finally including the header file in the “.cpp” file, instead of doing that we can directly place all the declaration in the “.cpp” file itself but it is not recommended because time to understand the code is based on coding guidelines so we are doing like that.

Consider that, we have five modules, that to be added in ROM build. How we will tell this information to ROM build tool?
Module1
--------IBY = (information) (Needed files for rom build)
Module2
--------IBY = (information) (Needed files for rom build)
Module3
--------IBY = (information) (Needed files for rom build)
Module4
--------IBY = (information) (Needed files for rom build)
Module5
--------IBY = (information) (Needed files for rom build)

-------- Each module contains an IBY file, Its only for storing information about that particular module, so that build tool can use the information for creating CORE or ROFS image, Whenever kernel executing a program it needs some resource file in some particular directory, those files and where it should be copied, all these information is provided by this (IBY) file. When kernel executing a program it will get all the resources from there.

-------- IBY is mainly focused to a particular module. OBY file is nothing; it just contains all IBY files. Don’t argue why we should maintain that because as I said before, it’s all for understanding. Suppose consider a situation that u need to update a module, finally its necessary to change something in IBY file that time we no need to disturb the OBY file just modifying IBY file will reflect in OBY. It’s totally Object oriented concept that means “Reducing programmers work burden” nothing else.

Friday, May 16, 2008

MMU’s Address translation in Symbian

MMU’s Address translation in Symbian

-----x86 Family of microprocessor are segmented memory model. It means, operating system will take care to assign segment address when executing programs. For example when compiler compiles a program for x86 family of processor, it will use offset address for generating code. Here offset address is called virtual address. Consider this example


org 0x100
mov ax, 10
mov bx 20
push ax
push bx


-----Consider the above code, it doesn’t mean anything but we can understand how processor finds physical address. When processor executes “push” instruction, It combines SS (Stack Segment) and SP (Stack Pointer) for finding the physical address and it stores the value on that location after it decrements SP by 2. But while writing program we are not at all specifying the segments address because OS will decide where to load this program based on where free space available, according to that it will assign segment address to Segment register.


(http://stalintechnologies.blogspot.com/search/label/Advanced%20C%20presentation) x86 processor register and how to use in Turbo C compiler

ARM:


But In ARM it’s not like that, In ARM, program’s virtual address is divided into three parts


1. Page directory entry
2. Page table
3. Physical block offset


-----MMU has a register called TTBR (Translation Table Base Register). It holds the base address of the Page directory. This is the entry point for all virtual to physical address translation.


-----Whenever processor trying to read data from memory, it goes via MMU (If it is enabled). MMU interprets the virtual address,

how it interprets?

-----First it takes the most significant 12 bit from that virtual address; it uses this for finding the base address of page table. This 12-bit is used to traverse into page directory for finding the correct page table’s base address, then it takes next 8 bit for finding the physical 4kb block’s base address, this 8 bit is used for traverse into page table for finding 4Kb’s physical block’s base address, once it got the base address of 4kb block, it will be pointing the physical base address of actual block but not actual data that we need, so it takes the next 12 bit from virtual address generated by compiler for finding the actual location of the variable. This is how MMU translates the virtual address to physical address. It will make slow down the process execution so recently referred block will be maintained in cache to fast up the execution.

-----consider the below example program

TInt E32main()

{

TInt a;

a = 40;

}

suppose compiler generates the virtual address for that particular variable "a" is 0x03c20046

When a = 40, when executing this statement, what and all MMU will perform for processor executing this statement?...

----Most significant 12 bit's decimal value is 60 this is the offset of page directory, next 8 bit's decimal value is 32, this is the offset value of page table and least 12 bit's decimal value is 70, this is the offset value of actual physical block's offset for storing the value 40.

-----------------------------------------------END------------------------------------------------