EmbLogic's Blog

Embedded Linux With ARM Processor

What is Embedded Linux?
Embedded Linux is one of the emerging fields in Embedded Systems allowing the engineers to be flexible in implementation of bigger tasks.
It is mingled with day to day life such as mobile phones, home security systems and house hold equipments. It also has a great impact on achieving difficult tasks such as missile launching.
To make it clear, it is nothing but the implementation of RTOS Linux kernel (core) in the processor for doing difficult tasks.

Systems

There are two types of system

1. General Purpose Systems
These systems refer to the computers which we are using in the houses and offices. General purpose systems act as a general platform for programming and performing certain other tasks.
General purpose systems prefer an operating system which may be UNIX, GNU/LINUX or Windows.
Here are some of the advantages of LINUX over other Operating System:
• Free of cost (usually called open source).
• Supports multi-user (First operating system to support multi user. In olden days one server carried an OS while other shares the same processor in the server).
• Flexible for programming.
• Better Security (It has the best security than any other operating system).
General purpose systems can perform any task but in small applications there
Is no need for bigger OS and hardware system. To overcome this concept Embedded System came, which is explained in the following section.
2 . Embedded Systems
Embedded Systems are different from that of the general purpose system. This system is generally of resources constrained. The resources refer to the hardware components.
Embedded Systems may or may not require an RTOS, whereas general purpose systems always do need an OS.

Difference between RTOS and OS
In general we hear the term OS which is nothing but the Operating System. Most of us are familiar in using the Operating Systems such as Windows 98, Windows XP etc. There is a new term used in the Embedded Systems named RTOS which is a Real Time OS.

Embedded OS
Operating systems are widely used in general purpose systems which may be LINUX or Windows. All operating systems uses an important concept called Time Sharing.
Time Sharing is nothing but performing many operations at a time, this has been take care by the OS.
The concept of time sharing can be best understood from the following figure.

The concept of DMA also comes into the picture in time sharing. In general purpose systems the tasks are allocated at different time slots. The user does not have any idea when the task will be completed.

Embedded RTOS
The RTOS are similar to the operating system but has smaller kernel (core of the operating system) size. It also uses the time sharing concept.
In general purpose the allocation of time can be adjusted by the OS, but in RTOS the time cannot be adjusted.

Processors
The General purpose systems use x86 processor.
Embedded Systems use controllers or processors such as ARM, FPGA etc.

Compiling and Cross Compiling
The RTOS cannot be used as such like an operating system. It has to be cross compiled for the particular processor. Other packages such as BIOS programming, Boot loader and Root file system also has to be used in Embedded linux environment.

BIOS
Basic Input Output System is the firmware that initializes the system. BIOS Programming has to be written and stored in to the flash memory.

Boot loader
An important package which is responsible for the kernel on the memory.
In General Purpose System Linux uses GRUB boot loader whereas the Embedded Linux system uses the U-boot bootloader.

Linux kernel
Lot of Linux kernel versions are available which can be cross-compiled for particular processor.

Root file system
Root file system contains all the binaries of the operating system.

Steps to make an Embedded Linux System to boot up
Hardwares used
Processor – s3c2440
Nor flash
Nand flash
SDRAM
Software packages
Linux kernel 2.6.29
u-boot bootloader
busy box

Compilation steps for linux kernel
Step 1:
tar –xvvzf arm-linux-gcc.tar.gz
unpacking the gcc compiler.
Step 2:
Export PATH=$PATH:~/usr/local/arm/4.3.2/bin
The tool chain for compiler is set
Step 3:
Tar –xvzf linux-2.6.29.tar.gz.
Unpacking the kernel
Step 4:
Make ARCH=arm CROSS_COMPILE=~/usr/local/arm/4.3.2/bin/
Step 5:
Make ARCH=arm CROSS_COMPILE=~/usr/local/arm/4.3.2/bin/ uImage

Posted in Uncategorized | Leave a comment

Block driver : Disk On RAM

-> Load the driver using insmod. This would create the block device files representing the disk on 512 KiB of RAM, with three primary and three logical partitions.
–> Check out the automatically created block device files (/dev/sd*). /dev/sdb is the entire disk, which is 512 KiB in size. sdb1, sdb2 and sdb3 are the primary partitions.
–> Read the entire disk (/dev/sdb) using the disk dump utility dd.
–> Zero out the first sector of the disk’s first partition (/dev/sdb1), again using dd.
–> Write some text into the disk’s first partition (/dev/sdb1) using cat.
–> Display the initial contents of the first partition (/dev/sdb1) using the xxd utility.
–> Display the partition information for the disk using fdisk.
–> Quick-format the third primary partition (/dev/sdb3) as a vfat filesystem (like your pen drive), using mkfs.vfat
–> Mount the newly formatted partition using mount, say at /mnt
–> The disk usage utility df would now show this partition mounted at /mnt . You may go ahead and store files there, but remember that this is a disk on RAM, and so is non-persistent.
Unload the driver using rmmod dor after unmounting the partition using umount /mnt. All data on the disk will be lost.

The block driver basics

Conceptually, the block drivers are very similar to character drivers, especially with regards to the following:

Usage of device files
Major and minor numbers
Device file operations
Concept of device registration

So, if you already know character driver implementation, it would be easy to understand block drivers.

However, they are definitely not identical. The key differences are as follows:

Abstraction for block-oriented versus byte-oriented devices.
Block drivers are designed to be used by I/O schedulers, for optimal performance. Compare that with character drivers that are to be used by VFS.
Block drivers are designed to be integrated with the Linux buffer cache mechanism for efficient data access. Character drivers are pass-through drivers, accessing the hardware directly.

And these cause the implementation differences. Let’s analyse the code .
The first step is to register for an 8-bit (block) major number (which implicitly means registering for all 256 8-bit minor numbers associated with it). The function for that is as follows:
int register_blkdev(unsigned int major, const char *name);

Here, major is the major number to be registered, and name is a registration label displayed under the kernel window /proc/devices. Interestingly, register_blkdev() tries to allocate and register a freely available major number, when 0 is passed for its first parameter major; on success, the allocated major number is returned. The corresponding de-registration function is as follows:
void unregister_blkdev(unsigned int major, const char *name);

Both these are prototyped in .

The second step is to provide the device file operations, through the struct block_device_operations (prototyped in ) for the registered major number device files.

However, these operations are too few compared to the character device file operations, and mostly insignificant. To elaborate, there are no operations even to read and write, which is surprising. But as we already know that block drivers need to integrate with the I/O schedulers, the read-write implementation is achieved through something called request queues. So, along with providing the device file operations, the following need to be provided:

The request queue for queuing the read/write requests
The spin lock associated with the request queue to protect its concurrent access
The request function to process the requests in the request queue

Also, there is no separate interface for block device file creations, so the following are also provided:

The device file name prefix, commonly referred to as disk_name (sdb in the my driver)
The starting minor number for the device files, commonly referred to as first_minor.

Finally, two block-device-specific things are also provided, namely:

The maximum number of partitions supported for this block device, by specifying the total minors.
The underlying device size in units of 512-byte sectors, for the logical block access abstraction.

All these are registered through the struct gendisk using the following function:
void add_disk(struct gendisk *disk);

The corresponding delete function is as follows:
void del_gendisk(struct gendisk *disk);

Prior to add_disk(), the various fields of struct gendisk need to initialised, either directly or using various macros/functions like set_capacity(). major, first_minor, fops, queue, disk_name are the minimal fields to be initialised directly. And even before the initialisation of these fields, the struct gendisk needs to be allocated, using the function given below:
struct gendisk *alloc_disk(int minors);

Here, minors is the total number of partitions supported for this disk. And the corresponding inverse function would be:
void put_disk(struct gendisk *disk);

All these are prototyped in .

Request queue and the request function

The request queue also needs to be initialised and set up into the struct gendisk, before add_disk(). The request queue is initialised by calling:
struct request_queue *blk_init_queue(request_fn_proc *, spinlock_t *);

We provide the request-processing function and the initialised concurrency protection spin-lock as parameters. The corresponding queue clean-up function is given below:
void blk_cleanup_queue(struct request_queue *);

The request (processing) function should be defined with the following prototype:
void request_fn(struct request_queue *q);

It should be coded to fetch a request from its parameter q, for instance, by using the following:
struct request *blk_fetch_request(struct request_queue *q);

Then it should either process it, or initiate processing. Whatever it does should be non-blocking, as this request function is called from a non-process context, and also after taking the queue’s spin-lock. Moreover, only functions not releasing or taking the queue’s spin-lock should be used within the request function.

A typical example of request processing, is given below:
while ((req = blk_fetch_request(q)) != NULL) /* Fetching a request */
{
/* Processing the request: the actual data transfer */
ret = rb_transfer(req); /* Our custom function */
/* Informing that the request has been processed with return of ret */
__blk_end_request_all(req, ret);
}

Posted in Uncategorized | Leave a comment

sculls

in sculls do we have to make a linked representation of a queue and then insert elements into that queue by changing the rear pointerie that rear pointer will subsequently point to the location of the node of the linked list which is represented as a queue and then we will store the characters in that node and move on to the next rear pointer location

Posted in Uncategorized | Leave a comment

The gendisk interface in Block driver

In 2.6 kernel the gendisk is at the core of the block subsystem; if you need to work with or find something out about a disk, struct gendisk probably has what you need.
The best way of looking at the contents of a gendisk structure from a block driver’s point of view is to examine what that driver must do to set the structure up in the first place. If your driver makes a disk (or disk-like) device available to the system, it will have to provide an associated gendisk structure. The first step is to create the gendisk structure itself; the function you need is alloc_disk() .
struct gendisk *alloc_disk(int minors);
The argument minors is the maximum number of minor numbers that this disk can have. Minor numbers correspond to partitions.If a single minor number is requested, the device cannot be partitioned at all.
There are several fields of the gendisk structure which must be initialized by the block driver. They include:

int major;
The major number of this device; either a static major assigned to a specific driver, or one that was obtained dynamically from register_blkdev()

int first_minor;
The first minor device number corresponding to this disk. This number will be determined by how your driver divides up its minor number space.

char disk_name[32];
The name of this disk (i.e. hda). This name is used in places like /proc/partitions and in creating a sysfs directory for the device.

struct block_device_operations *fops;
The device operations (open, release, ioctl, media_changed, and revalidate_disk) for this device. Each disk has its own set of operations in 2.6.

struct request_queue *queue;
The request queue which will handle the list of pending operations for this disk. The queue must be created and initialized separately.

int flags;
A set of flags controlling the management of this device. They include GENHD_FL_REMOVABLE for removable devices, GENHD_FL_CD for CDROM devices, and GENHD_FL_DRIVERFS which certainly means something interesting, but which is not actually used anywhere.

void *private_data;
This field is reserved for the driver; the rest of the block subsystem will not touch it. Usually it holds a pointer to a driver-specific data structure describing this device.

The gendisk structure also holds the size of the disk, in sectors. As part of the initialization process, the driver should set that size with:

void set_capacity(struct gendisk *disk, sector_t size);

The size value should be in 512-byte sectors, even if the hardware sector size used by your device is different. For removable disks, setting its capacity to zero indicates to the block subsystem that there is currently no media present in the device. Once you have your gendisk structure set up, you have to add it to the list of active disks; that is done with:

void add_disk(struct gendisk *disk);

After this call, your device is live.

There are a few things worth keeping in mind about add_disk():

–>add_disk() can create I/O to the device (to read partition tables and such). You should not call add_disk() until your driver is sufficiently initialized to handle requests.

–> If you are calling add_disk() in your driver initialization routine, you should not fail the initialization process after the first call.

–> The call to add_disk() increments the disk’s reference count; if the disk structure is ever to be released, the driver is responsible for decrementing that count (with put_disk()).

To remove a disk from the system, that is accomplished with:

void del_gendisk(struct gendisk *disk);

This function cleans up all of the information associated with the given disk, and generally removes it from the system. After a call to del_gendisk(), no more operations will be sent to the given device. Your driver’s reference to the gendisk object remains, though; you must explicitly release it with:

void put_disk(struct gendisk *disk);
That call will cause the gendisk structure to be freed, as long as no other part of the kernel retains a reference to it.

Note–>sbd_request() uses the blk_fetch_request(), blk_rq_pos(), blk_rq_cur_sectors() and __blk_end_request_cur() functions rather than elv_next_request(), req->sector, req->current_nr_sectors and end_request() respectively. The structure of the loop also changes so we handle each sector from the request individually.

Posted in Uncategorized | Leave a comment

command line arguments

int main(int argc,char *argv[])

why  size of string which each pointer in argv[] array point is of 4 bytes irrespective of sizeof string??

Posted in Data Structures with C | Leave a comment

memory allocation by malloc

int num = 10;

ptr  = malloc(sizeof(int)* number);

if memory is allocated like this then the any input statement(scanf,gets,fgets) is not running , compiler jumps these stmts whyyy??

Posted in Data Structures with C | Leave a comment

free(start);

NODE *start : pointer pointing to starting of link list.

after free(start)

how compiler is accessing whole link list??

Posted in Data Structures with C | Leave a comment

Functions

Functions assignment now completed

Posted in Data Structures with C | Leave a comment

what is meaning of “i+1″ in pf statment

#include
#define MONTHS 12
int main()
{
int days[MONTHS]={31,28,[4]=31,30,31,[1]=29};
int i;
for(i=0;i<MONTHS;i++)
printf("%2d %d\n",i+1,days[i]);
return 0;
}

Posted in Uncategorized | 1 Comment

Implementation of CVS and RCS

Both CVS and RCS have been implemented successfully.

Posted in Project Management Tools | Leave a comment

To run any command on system boot

I found it only 4 fedora 14…

just put the command in a file called /etc/rc.local

or put in /etc/rc.d/rc.local

or write a script in /etc/init.d/

and reboot the system…. that command will work.

Still searching a common method for all the versions of fedora.. if anyone know it.. plz let me know..

thank you

 

Posted in Linux Internals and System Programming | Leave a comment

Pointers

Pointers assignment almost complete with two three problems

Posted in Data Structures with C | Leave a comment

this program on pipes is not wroking , can anyone tell me why ??

#include
#include
#include

int main()
{
char buff[10];
char tx[]=”hello wor\n”;
int fd[2],t;
pid_t pd;
printf(“\n %s”,tx);

pipe(fd);
pd = fork();
if (pd == 0 )
{
printf(“\n parent cerated : %d”,getpid());
close(fd[0]);
write (fd[1],tx,sizeof(tx));
}
else if(pd == 1)
{
printf(“\n child cerated : %d”,getpid());
close(fd[1]);

printf(“\n %s”,buff);
read(fd[0],buff,sizeof(buff));
printf(“the received string is :%s”,buff);
}
return (0);

}

Posted in Linux Internals and System Programming | 3 Comments

what’s going on here????printing x=1 and y=1

#include<stdio.h>
int main()
{
int x=1,y=1,z;
if(y<0) if(y>0) x=3;
else x=5;
printf(“%d\n”,x);
printf(“%d\n”,y);
return 0;

Posted in Uncategorized | 2 Comments

both are printing same?????

 i=l=f=d=100/3;
printf(“%.8g\t”,(double)i);
printf(“%.8g\t”,(double)f);
printf(“%.8g\t”,(double)d);
d=f=l=i=100/3;
printf(“%.8g\t”,(double)i);
printf(“%.8g\t”,(double)f);
printf(“%.8g\t”,(double)d);

Posted in Uncategorized | Leave a comment