EmbLogic's Blog

U-Boot environment

The U-Boot environment is a block of memory that is kept on persistent storage and copied to RAM when U-Boot starts. It is used to store environment variables which can be used to configure the system. The environment is protected by a CRC32 checksum.

This section lists the most important environment variables, some of which have a special meaning to U-Boot. You can use these variables to configure the behaviour of U-Boot to your liking.

autoload: if set to “no” (or any string beginning with ‘n’), the rarpb, bootp or dhcp commands will perform only a configuration lookup from the BOOTP / DHCP server, but not try to load any image using TFTP.
autostart: if set to “yes”, an image loaded using the rarpb, bootp, dhcp, tftp, disk, or docb commands will be automatically started (by internally calling the bootm command).
baudrate: a decimal number that selects the console baudrate (in bps). Only a predefined list of baudrate settings is available.
When you change the baudrate (using the “setenv baudrate …” command), U-Boot will switch the baudrate of the console terminal and wait for a newline which must be entered with the new speed setting. This is to make sure you can actually type at the new speed. If this fails, you have to reset the board (which will operate at the old speed since you were not able to saveenv the new settings.)
If no “baudrate” variable is defined, the default baudrate of 115200 is used.
bootargs: The contents of this variable are passed to the Linux kernel as boot arguments (aka “command line”).
bootcmd: This variable defines a command string that is automatically executed when the initial countdown is not interrupted.
This command is only executed when the variable bootdelay is also defined!
bootdelay: After reset, U-Boot will wait this number of seconds before it executes the contents of the bootcmd variable. During this time a countdown is printed, which can be interrupted by pressing any key.
Set this variable to 0 boot without delay. Be careful: depending on the contents of your bootcmd variable, this can prevent you from entering interactive commands again forever!
Set this variable to -1 to disable autoboot.
bootfile: name of the default image to load with TFTP
cpuclk: (Only with MPC859 / MPC866 / MPC885 processors) On some processors, the CPU clock frequency can be adjusted by the user (for example to optimize performance versus power dissipation). On such systems the cpuclk variable can be set to the desired CPU clock value, in MHz. If the cpuclk variable exists and its value is within the compile-time defined limits (CONFIG_SYS_8xx_CPUCLK_MIN and CONFIG_SYS_8xx_CPUCLK_MAX = minimum resp. maximum allowed CPU clock), then the specified value is used. Otherwise, the default CPU clock value of CONFIG_8xx_CPUCLK_DEFAULT is used.
ethaddr: Ethernet MAC address for first/only ethernet interface (= eth0 in Linux).
This variable can be set only once (usually during manufacturing of the board). U-Boot refuses to delete or overwrite this variable once it has been set.
eth1addr: Ethernet MAC address for second ethernet interface (= eth1 in Linux).
eth2addr: Ethernet MAC address for third ethernet interface (= eth2 in Linux).

initrd_high: used to restrict positioning of initrd ramdisk images:
If this variable is not set, initrd images will be copied to the highest possible address in RAM; this is usually what you want since it allows for maximum initrd size. If for some reason you want to make sure that the initrd image is loaded below the CFG_BOOTMAPSZ limit, you can set this environment variable to a value of “no” or “off” or “0″. Alternatively, you can set it to a maximum upper address to use (U-Boot will still check that it does not overwrite the U-Boot stack and data).
For instance, when you have a system with 16 MB RAM, and want to reserve 4 MB from use by Linux, you can do this by adding “mem=12M” to the value of the “bootargs” variable. However, now you must make sure that the initrd image is placed in the first 12 MB as well – this can be done with
=> setenv initrd_high 00c00000

Setting initrd_high to the highest possible address in your system (0xFFFFFFFF) prevents U-Boot from copying the image to RAM at all. This allows for faster boot times, but requires a Linux kernel with zero-copy ramdisk support.
ipaddr: IP address; needed for tftp command
loadaddr: Default load address for commands like tftp or loads.
loads_echo: If set to 1, all characters received during a serial download (using the loads command) are echoed back. This might be needed by some terminal emulations (like cu), but may as well just take time on others.
mtdparts: This variable (usually defined using the mtdparts command) allows to share a common MTD partition scheme between U-Boot and the Linux kernel.
pram: If the “Protected RAM” feature is enabled in your board’s configuration, this variable can be defined to enable the reservation of such “protected RAM”, i. e. RAM which is not overwritten by U-Boot. Define this variable to hold the number of kB you want to reserve for pRAM. Note that the board info structure will still show the full amount of RAM. If pRAM is reserved, a new environment variable “mem” will automatically be defined to hold the amount of remaining RAM in a form that can be passed as boot argument to Linux, for instance like that:
=> setenv bootargs ${bootargs} mem=\${mem}
=> saveenv

This way you can tell Linux not to use this memory, either, which results in a memory region that will not be affected by reboots.
serverip: TFTP server IP address; needed for tftp command.
serial#: contains hardware identification information such as type string and/or serial number.
This variable can be set only once (usually during manufacturing of the board). U-Boot refuses to delete or overwrite this variable once it hass been set.
silent: If the configuration option CONFIG_SILENT_CONSOLE has been enabled for your board, setting this variable to any value will suppress all console messages. Please see doc/README.silent for details.
verify: If set to n or no disables the checksum calculation over the complete image in the bootm command to trade speed for safety in the boot process. Note that the header checksum is still verified.
The following environment variables may be used and automatically updated by the network boot commands (bootp, dhcp, or tftp), depending the information provided by your boot server:

bootfile: see above
dnsip: IP address of your Domain Name Server
gatewayip: IP address of the Gateway (Router) to use
hostname: Target hostname
ipaddr: see above
netmask: Subnet Mask
rootpath: Pathname of the root filesystem on the NFS server
serverip: see above
filesize: Size (as hex number in bytes) of the file downloaded using the last bootp, dhcp, or tftp command.

Posted in Uncategorized | Leave a comment

U-Boot: Quick reference

Information commands

bdinfo – print Board Info structure
coninfo – print console devices and information
flinfo – print FLASH memory information
help – print online help
Memory commands

base – print or set address offset
crc32 – checksum calculation
cmp – memory compare
cp – memory copy
md – memory display
mm – memory modify (auto incrementing)
mtest – simple RAM test
mw – memory write (fill)
nm – memory modify (constant address)
loop – infinite loop on address range
Flash memory commands

cp – memory copy
flinfo – print FLASH memory information
erase – erase FLASH memory
protect – enable or disable FLASH write protection
Image commands

iminfo – print header information for application image
imxtract – extract a part of a multi-image
Execution control commands

autoscr – run script from memory
source – run script from memory
bootm – boot application image from memory
go – start application at address ‘addr’
loop – infinite loop on address range
exit – exit script
Download commands

bootp – boot image via network using BOOTP/TFTP protocol
dhcp – invoke DHCP client to obtain IP/boot params
loadb – load binary file over serial line (kermit mode)
loady – load binary file over serial line (ymodem mode)
loads – load S?Record file over serial line
rarpboot – boot image via network using RARP/TFTP protocol
tftpboot – boot image via network using TFTP protocol
nfs – boot image via network using NFS protocol
ping – send ICMP ECHO REQUEST to network host
Environment variables commands

env – environment handling commands
editenv – edit environment variable
printenv – print environment variables
saveenv – save environment variables to persistent storage
setenv – set environment variables
run – run commands in an environment variable
bootd – boot default, i.e., run ‘bootcmd’
boot – boot default, i.e., run ‘bootcmd’
File system support commands

fatinfo – print information about a FAT file system
fatload – load binary file from a FAT file system
fatls – list files in a FAT file system directory (default /)
ext2load – load binary file from a Ext2 filesystem
ext2ls – list files in a directory (default /)
fsinfo – print information about JFFS2 file system
fsload – load binary file from a JFFS2 file system image
ls – list files in a JFFS2 file system directory (default /)
NAND flash support

nand – NAND sub-system control
nandecc – switch OMAP3 NAND ECC calculation algorithm
nboot – boot from NAND device
Partition commands

mtdparts – define flash/nand partitions
chpart – change active partition
FDT support

fdt – flattened device tree utility commands
MMC support

mmc – MMC sub system
mmcinfo – display MMC information
I2C support

i2c – I2C sub-system control
USB support

usb – USB sub-system control
usbboot – boot from USB device
Cache support

icache – enable or disable instruction cache
dcache – enable or disable data cache
Bitmap support

bmp – manipulate BMP image data
GPIO support

gpio – manipulate gpios
Miscellaneous commands

echo – echo arguments to console
reset – Perform RESET of the CPU
sleep – delay execution for some time
version – print monitor version
test – minimal test, like /bin/bash
? – alias for help
showvar – print local hushshell variables
true – do nothing, successfully
false – do nothing, unsuccessfully
cls – clear screen
itest – return true/false on integer compare

Posted in Uncategorized | Leave a comment

The Linux Kernel Sources

How The Kernel Sources Are Arranged

At the very top level of the source tree /usr/src/linux you will see a number of directories:
The arch subdirectory contains all of the architecture specific kernel code. It has further subdirectories, one per supported architecture, for example i386 and alpha.
The include subdirectory contains most of the include files needed to build the kernel code. It too has further subdirectories including one for every architecture supported. The include/asm subdirectory is a soft link to the real include directory needed for this architecture, for example include/asm-i386. To change architectures you need to edit the kernel makefile and rerun the Linux kernel configuration program.
This directory contains the initialization code for the kernel and it is a very good place to start looking at how the kernel works.
This directory contains all of the memory management code. The architecture specific memory management code lives down in arch/*/mm/, for example arch/i386/mm/fault.c.
All of the system’s device drivers live in this directory. They are further sub-divided into classes of device driver, for example block.
This directory contains the kernels inter-process communications code.
This is simply a directory used to hold built modules.
All of the file system code. This is further sub-divided into directories, one per supported file system, for example vfat and ext2.
The main kernel code. Again, the architecture specific kernel code is in arch/*/kernel.
The kernel’s networking code.
This directory contains the kernel’s library code. The architecture specific library code can be found in arch/*/lib/.
This directory contains the scripts (for example awk and tk scripts) that are used when the kernel is configured.
Where to Start Looking

A large complex program like the Linux kernel can be rather daunting to look at. It is rather like a large ball of string with no end showing. Looking at one part of the kernel often leads to looking at several other related files and before long you have forgotten what you were looking for. The next subsections give you a hint as to where in the source tree the best place to look is for a given subject.
System Startup and Initialization

On an Intel based system, the kernel starts when either loadlin.exe or LILO has loaded the kernel into memory and passed control to it. Look in arch/i386/kernel/head.S for this part. Head.S does some architecture specific setup and then jumps to the main() routine in init/main.c.
Memory Management

This code is mostly in mm but the architecture specific code is in arch/*/mm. The page fault handling code is in mm/memory.c and the memory mapping and page cache code is in mm/filemap.c. The buffer cache is implemented in mm/buffer.c and the swap cache in mm/swap_state.c and mm/swapfile.c.

Most of the relevent generic code is in kernel with the architecture specific code in arch/*/kernel. The scheduler is in kernel/sched.c and the fork code is in kernel/fork.c. The bottom half handling code is in include/linux/interrupt.h. The task_struct data structure can be found in include/linux/sched.h.

The PCI pseudo driver is in drivers/pci/pci.c with the system wide definitions in include/linux/pci.h. Each architecture has some specific PCI BIOS code, Alpha AXP’s is in arch/alpha/kernel/bios32.c.
Interprocess Communication

This is all in ipc. All System V IPC objects include an ipc_perm data structure and this can be found in include/linux/ipc.h. System V messages are implemented in ipc/msg.c, shared memory in ipc/shm.c and semaphores in ipc/sem.c. Pipes are implemented in ipc/pipe.c.
Interrupt Handling

The kernel’s interrupt handling code is almost all microprocessor (and often platform) specific. The Intel interrupt handling code is in arch/i386/kernel/irq.c and its definitions in include/asm-i386/irq.h.
Device Drivers

Most of the lines of the Linux kernel’s source code are in its device drivers. All of Linux’s device driver sources are held in drivers but these are further broken out by type:
block device drivers such as ide (in ide.c). If you want to look at how all of the devices that could possibly contain file systems are initialized then you should look at device_setup() in drivers/block/genhd.c. It not only initializes the hard disks but also the network as you need a network to mount nfs file systems. Block devices include both IDE and SCSI based devices.
This the place to look for character based devices such as ttys, serial ports and mice.
All of the CDROM code for Linux. It is here that the special CDROM devices (such as Soundblaster CDROM) can be found. Note that the ide CD driver is ide-cd.c in drivers/block and that the SCSI CD driver is in scsi.c in drivers/scsi.
This are the sources for the PCI pseudo-driver. A good place to look at how the PCI subsystem is mapped and initialized. The Alpha AXP PCI fixup code is also worth looking at in arch/alpha/kernel/bios32.c.
This is where to find all of the SCSI code as well as all of the drivers for the scsi devices supported by Linux.
This is where to look to find the network device drivers such as the DECChip 21040 PCI ethernet driver which is in tulip.c.
This is where all of the sound card drivers are.
File Systems

The sources for the EXT2 file system are all in the fs/ext2/ directory with data structure definitions in include/linux/ext2_fs.h, ext2_fs_i.h and ext2_fs_sb.h. The Virtual File System data structures are described in include/linux/fs.h and the code is in fs/*. The buffer cache is implemented in fs/buffer.c along with the update kernel daemon.

The networking code is kept in net with most of the include files in include/net. The BSD socket code is in net/socket.c and the IP version 4 INET socket code is in net/ipv4/af_inet.c. The generic protocol support code (including the sk_buff handling routines) is in net/core with the TCP/IP networking code in net/ipv4. The network device drivers are in drivers/net.

The kernel module code is partially in the kernel and partially in the modules package. The kernel code is all in kernel/modules.c with the data structures and kernel demon kerneld messages in include/linux/module.h and include/linux/kerneld.h respectively. You may want to look at the structure of an ELF object file in include/linux/elf.h.

Posted in Uncategorized | Leave a comment

Linux Data Structures


block_dev_struct data structures are used to register block devices as available for use by the buffer cache. They are held together in the blk_dev vector.
struct blk_dev_struct {
void (*request_fn)(void);
struct request * current_request;
struct request plug;
struct tq_struct plug_tq;

The buffer_head data structure holds information about a block buffer in the buffer cache.
/* bh state bits */
#define BH_Uptodate 0 /* 1 if the buffer contains valid data */
#define BH_Dirty 1 /* 1 if the buffer is dirty */
#define BH_Lock 2 /* 1 if the buffer is locked */
#define BH_Req 3 /* 0 if the buffer has been invalidated */
#define BH_Touched 4 /* 1 if the buffer has been touched (aging) */
#define BH_Has_aged 5 /* 1 if the buffer has been aged (aging) */
#define BH_Protected 6 /* 1 if the buffer is protected */
#define BH_FreeOnIO 7 /* 1 to discard the buffer_head after IO */

struct buffer_head {
/* First cache line: */
unsigned long b_blocknr; /* block number */
kdev_t b_dev; /* device (B_FREE = free) */
kdev_t b_rdev; /* Real device */
unsigned long b_rsector; /* Real buffer location on disk */
struct buffer_head *b_next; /* Hash queue list */
struct buffer_head *b_this_page; /* circular list of buffers in one
page */

/* Second cache line: */
unsigned long b_state; /* buffer state bitmap (above) */
struct buffer_head *b_next_free;
unsigned int b_count; /* users using this block */
unsigned long b_size; /* block size */

/* Non-performance-critical data follows. */
char *b_data; /* pointer to data block */
unsigned int b_list; /* List that this buffer appears */
unsigned long b_flushtime; /* Time when this (dirty) buffer
* should be written */
unsigned long b_lru_time; /* Time when this buffer was
* last used. */
struct wait_queue *b_wait;
struct buffer_head *b_prev; /* doubly linked hash list */
struct buffer_head *b_prev_free; /* doubly linked list of buffers */
struct buffer_head *b_reqnext; /* request queue */

Every network device in the system is represented by a device data structure.
struct device

* This is the first field of the “visible” part of this structure
* (i.e. as seen by users in the “Space.c” file). It is the name
* the interface.
char *name;

/* I/O specific fields */
unsigned long rmem_end; /* shmem “recv” end */
unsigned long rmem_start; /* shmem “recv” start */
unsigned long mem_end; /* shared mem end */
unsigned long mem_start; /* shared mem start */
unsigned long base_addr; /* device I/O address */
unsigned char irq; /* device IRQ number */

/* Low-level status flags. */
volatile unsigned char start, /* start an operation */
interrupt; /* interrupt arrived */
unsigned long tbusy; /* transmitter busy */
struct device *next;

/* The device initialization function. Called only once. */
int (*init)(struct device *dev);

/* Some hardware also needs these fields, but they are not part of
the usual set specified in Space.c. */
unsigned char if_port; /* Selectable AUI,TP, */
unsigned char dma; /* DMA channel */

struct enet_statistics* (*get_stats)(struct device *dev);

* This marks the end of the “visible” part of the structure. All
* fields hereafter are internal to the system, and may change at
* will (read: may be cleaned up at will).

/* These may be needed for future network-power-down code. */
unsigned long trans_start; /* Time (jiffies) of
last transmit */
unsigned long last_rx; /* Time of last Rx */
unsigned short flags; /* interface flags (BSD)*/
unsigned short family; /* address family ID */
unsigned short metric; /* routing metric */
unsigned short mtu; /* MTU value */
unsigned short type; /* hardware type */
unsigned short hard_header_len; /* hardware hdr len */
void *priv; /* private data */

/* Interface address info. */
unsigned char broadcast[MAX_ADDR_LEN];
unsigned char pad;
unsigned char dev_addr[MAX_ADDR_LEN];
unsigned char addr_len; /* hardware addr len */
unsigned long pa_addr; /* protocol address */
unsigned long pa_brdaddr; /* protocol broadcast addr*/
unsigned long pa_dstaddr; /* protocol P-P other addr*/
unsigned long pa_mask; /* protocol netmask */
unsigned short pa_alen; /* protocol address len */

struct dev_mc_list *mc_list; /* M’cast mac addrs */
int mc_count; /* No installed mcasts */

struct ip_mc_list *ip_mc_list; /* IP m’cast filter chain */
__u32 tx_queue_len; /* Max frames per queue */

/* For load balancing driver pair support */
unsigned long pkt_queue; /* Packets queued */
struct device *slave; /* Slave device */
struct net_alias_info *alias_info; /* main dev alias info */
struct net_alias *my_alias; /* alias devs */

/* Pointer to the interface buffers. */
struct sk_buff_head buffs[DEV_NUMBUFFS];

/* Pointers to interface service routines. */
int (*open)(struct device *dev);
int (*stop)(struct device *dev);
int (*hard_start_xmit) (struct sk_buff *skb,
struct device *dev);
int (*hard_header) (struct sk_buff *skb,
struct device *dev,
unsigned short type,
void *daddr,
void *saddr,
unsigned len);
int (*rebuild_header)(void *eth,
struct device *dev,
unsigned long raddr,
struct sk_buff *skb);
void (*set_multicast_list)(struct device *dev);
int (*set_mac_address)(struct device *dev,
void *addr);
int (*do_ioctl)(struct device *dev,
struct ifreq *ifr,
int cmd);
int (*set_config)(struct device *dev,
struct ifmap *map);
void (*header_cache_bind)(struct hh_cache **hhp,
struct device *dev,
unsigned short htype,
__u32 daddr);
void (*header_cache_update)(struct hh_cache *hh,
struct device *dev,
unsigned char * haddr);
int (*change_mtu)(struct device *dev,
int new_mtu);
struct iw_statistics* (*get_wireless_stats)(struct device *dev);

device_struct data structures are used to register character and block devices (they hold its name and the set of file operations that can be used for this device). Each valid member of the chrdevs and blkdevs vectors represents a character or block device respectively.
struct device_struct {
const char * name;
struct file_operations * fops;

Each open file, socket etcetera is represented by a file data structure.
struct file {
mode_t f_mode;
loff_t f_pos;
unsigned short f_flags;
unsigned short f_count;
unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin;
struct file *f_next, *f_prev;
int f_owner; /* pid or -pgrp where SIGIO should be sent */
struct inode * f_inode;
struct file_operations * f_op;
unsigned long f_version;
void *private_data; /* needed for tty driver, and maybe others */

The files_struct data structure describes the files that a process has open.
struct files_struct {
int count;
fd_set close_on_exec;
fd_set open_fds;
struct file * fd[NR_OPEN];

struct fs_struct {
int count;
unsigned short umask;
struct inode * root, * pwd;

The gendisk data structure holds information about a hard disk. They are used during initialization when the disks are found and then probed for partitions.
struct hd_struct {
long start_sect;
long nr_sects;

struct gendisk {
int major; /* major number of driver */
const char *major_name; /* name of major driver */
int minor_shift; /* number of times minor is shifted to
get real minor */
int max_p; /* maximum partitions per device */
int max_nr; /* maximum number of real devices */

void (*init)(struct gendisk *);
/* Initialization called before we
do our thing */
struct hd_struct *part; /* partition table */
int *sizes; /* device size in blocks, copied to
blk_size[] */
int nr_real; /* number of real devices */

void *real_devices; /* internal use */
struct gendisk *next;

The VFS inode data structure holds information about a file or directory on disk.
struct inode {
kdev_t i_dev;
unsigned long i_ino;
umode_t i_mode;
nlink_t i_nlink;
uid_t i_uid;
gid_t i_gid;
kdev_t i_rdev;
off_t i_size;
time_t i_atime;
time_t i_mtime;
time_t i_ctime;
unsigned long i_blksize;
unsigned long i_blocks;
unsigned long i_version;
unsigned long i_nrpages;
struct semaphore i_sem;
struct inode_operations *i_op;
struct super_block *i_sb;
struct wait_queue *i_wait;
struct file_lock *i_flock;
struct vm_area_struct *i_mmap;
struct page *i_pages;
struct dquot *i_dquot[MAXQUOTAS];
struct inode *i_next, *i_prev;
struct inode *i_hash_next, *i_hash_prev;
struct inode *i_bound_to, *i_bound_by;
struct inode *i_mount;
unsigned short i_count;
unsigned short i_flags;
unsigned char i_lock;
unsigned char i_dirt;
unsigned char i_pipe;
unsigned char i_sock;
unsigned char i_seek;
unsigned char i_update;
unsigned short i_writecount;
union {
struct pipe_inode_info pipe_i;
struct minix_inode_info minix_i;
struct ext_inode_info ext_i;
struct ext2_inode_info ext2_i;
struct hpfs_inode_info hpfs_i;
struct msdos_inode_info msdos_i;
struct umsdos_inode_info umsdos_i;
struct iso_inode_info isofs_i;
struct nfs_inode_info nfs_i;
struct xiafs_inode_info xiafs_i;
struct sysv_inode_info sysv_i;
struct affs_inode_info affs_i;
struct ufs_inode_info ufs_i;
struct socket socket_i;
void *generic_ip;
} u;

The ipc_perm data structure describes the access permissions of a System V IPC object .
struct ipc_perm
key_t key;
ushort uid; /* owner euid and egid */
ushort gid;
ushort cuid; /* creator euid and egid */
ushort cgid;
ushort mode; /* access modes see mode flags below */
ushort seq; /* sequence number */

The irqaction data structure is used to describe the system’s interrupt handlers.
struct irqaction {
void (*handler)(int, void *, struct pt_regs *);
unsigned long flags;
unsigned long mask;
const char *name;
void *dev_id;
struct irqaction *next;

Each binary file format that Linux understands is represented by a linux_binfmt data structure.
struct linux_binfmt {
struct linux_binfmt * next;
long *use_count;
int (*load_binary)(struct linux_binprm *, struct pt_regs * regs);
int (*load_shlib)(int fd);
int (*core_dump)(long signr, struct pt_regs * regs);

The mem_map_t data structure (also known as page) is used to hold information about each page of physical memory.
typedef struct page {
/* these must be first (free area handling) */
struct page *next;
struct page *prev;
struct inode *inode;
unsigned long offset;
struct page *next_hash;
atomic_t count;
unsigned flags; /* atomic flags, some possibly
updated asynchronously */
unsigned dirty:16,
struct wait_queue *wait;
struct page *prev_hash;
struct buffer_head *buffers;
unsigned long swap_unlock_entry;
unsigned long map_nr; /* page->map_nr == page – mem_map */
} mem_map_t;

The mm_struct data structure is used to describe the virtual memory of a task or process.
struct mm_struct {
int count;
pgd_t * pgd;
unsigned long context;
unsigned long start_code, end_code, start_data, end_data;
unsigned long start_brk, brk, start_stack, start_mmap;
unsigned long arg_start, arg_end, env_start, env_end;
unsigned long rss, total_vm, locked_vm;
unsigned long def_flags;
struct vm_area_struct * mmap;
struct vm_area_struct * mmap_avl;
struct semaphore mmap_sem;

Every PCI bus in the system is represented by a pci_bus data structure.
struct pci_bus {
struct pci_bus *parent; /* parent bus this bridge is on */
struct pci_bus *children; /* chain of P2P bridges on this bus */
struct pci_bus *next; /* chain of all PCI buses */

struct pci_dev *self; /* bridge device as seen by parent */
struct pci_dev *devices; /* devices behind this bridge */

void *sysdata; /* hook for sys-specific extension */

unsigned char number; /* bus number */
unsigned char primary; /* number of primary bridge */
unsigned char secondary; /* number of secondary bridge */
unsigned char subordinate; /* max number of subordinate buses */

Every PCI device in the system, including PCI-PCI and PCI-ISA bridge devices is represented by a pci_dev data structure.
* There is one pci_dev structure for each slot-number/function-number
* combination:
struct pci_dev {
struct pci_bus *bus; /* bus this device is on */
struct pci_dev *sibling; /* next device on this bus */
struct pci_dev *next; /* chain of all devices */

void *sysdata; /* hook for sys-specific extension */

unsigned int devfn; /* encoded device & function index */
unsigned short vendor;
unsigned short device;
unsigned int class; /* 3 bytes: (base,sub,prog-if) */
unsigned int master : 1; /* set if device is master capable */
* In theory, the irq level can be read from configuration
* space and all would be fine. However, old PCI chips don’t
* support these registers and return 0 instead. For example,
* the Vision864-P rev 0 chip can uses INTA, but returns 0 in
* the interrupt line and pin registers. pci_init()
* initializes this field with the value at PCI_INTERRUPT_LINE
* and it is the job of pcibios_fixup() to change it if
* necessary. The field must not be 0 unless the device
* cannot generate interrupts at all.
unsigned char irq; /* irq generated by this device */

request data structures are used to make requests to the block devices in the system. The requests are always to read or write blocks of data to or from the buffer cache.
struct request {
volatile int rq_status;
#define RQ_INACTIVE (-1)
#define RQ_ACTIVE 1
#define RQ_SCSI_BUSY 0xffff
#define RQ_SCSI_DONE 0xfffe

kdev_t rq_dev;
int cmd; /* READ or WRITE */
int errors;
unsigned long sector;
unsigned long nr_sectors;
unsigned long current_nr_sectors;
char * buffer;
struct semaphore * sem;
struct buffer_head * bh;
struct buffer_head * bhtail;
struct request * next;

Each rtable data structure holds information about the route to take in order to send packets to an IP host. rtable data structures are used within the IP route cache.
struct rtable
struct rtable *rt_next;
__u32 rt_dst;
__u32 rt_src;
__u32 rt_gateway;
atomic_t rt_refcnt;
atomic_t rt_use;
unsigned long rt_window;
atomic_t rt_lastuse;
struct hh_cache *rt_hh;
struct device *rt_dev;
unsigned short rt_flags;
unsigned short rt_mtu;
unsigned short rt_irtt;
unsigned char rt_tos;

Semaphores are used to protect critical data structures and regions of code. y
struct semaphore {
int count;
int waking;
int lock ; /* to make waking testing atomic */
struct wait_queue *wait;

The sk_buff data structure is used to describe network data as it moves between the layers of protocol.
struct sk_buff
struct sk_buff *next; /* Next buffer in list */
struct sk_buff *prev; /* Previous buffer in list */
struct sk_buff_head *list; /* List we are on */
int magic_debug_cookie;
struct sk_buff *link3; /* Link for IP protocol level buffer chains */
struct sock *sk; /* Socket we are owned by */
unsigned long when; /* used to compute rtt’s */
struct timeval stamp; /* Time we arrived */
struct device *dev; /* Device we arrived on/are leaving by */
struct tcphdr *th;
struct ethhdr *eth;
struct iphdr *iph;
struct udphdr *uh;
unsigned char *raw;
/* for passing file handles in a unix domain socket */
void *filp;
} h;

/* As yet incomplete physical layer views */
unsigned char *raw;
struct ethhdr *ethernet;
} mac;

struct iphdr *ip_hdr; /* For IPPROTO_RAW */
unsigned long len; /* Length of actual data */
unsigned long csum; /* Checksum */
__u32 saddr; /* IP source address */
__u32 daddr; /* IP target address */
__u32 raddr; /* IP next hop address */
__u32 seq; /* TCP sequence number */
__u32 end_seq; /* seq [+ fin] [+ syn] + datalen */
__u32 ack_seq; /* TCP ack sequence number */
unsigned char proto_priv[16];
volatile char acked, /* Are we acked ? */
used, /* Are we in use ? */
free, /* How to free this buffer */
arp; /* Has IP/ARP resolution finished */
unsigned char tries, /* Times tried */
lock, /* Are we locked ? */
localroute, /* Local routing asserted for this frame */
pkt_type, /* Packet class */
pkt_bridged, /* Tracker for bridging */
ip_summed; /* Driver fed us an IP checksum */
#define PACKET_HOST 0 /* To us */
#define PACKET_BROADCAST 1 /* To all */
#define PACKET_MULTICAST 2 /* To group */
#define PACKET_OTHERHOST 3 /* To someone else */
unsigned short users; /* User count – see datagram.c,tcp.c */
unsigned short protocol; /* Packet protocol from driver. */
unsigned int truesize; /* Buffer size */
atomic_t count; /* reference count */
struct sk_buff *data_skb; /* Link to the actual data skb */
unsigned char *head; /* Head of buffer */
unsigned char *data; /* Data head pointer */
unsigned char *tail; /* Tail pointer */
unsigned char *end; /* End pointer */
void (*destructor)(struct sk_buff *); /* Destruct function */
__u16 redirport; /* Redirect port */

Each sock data structure holds protocol specific information about a BSD socket. For example, for an INET (Internet Address Domain) socket this data structure would hold all of the TCP/IP and UDP/IP specific information.
struct sock
/* This must be first. */
struct sock *sklist_next;
struct sock *sklist_prev;

struct options *opt;
atomic_t wmem_alloc;
atomic_t rmem_alloc;
unsigned long allocation; /* Allocation mode */
__u32 write_seq;
__u32 sent_seq;
__u32 acked_seq;
__u32 copied_seq;
__u32 rcv_ack_seq;
unsigned short rcv_ack_cnt; /* count of same ack */
__u32 window_seq;
__u32 fin_seq;
__u32 urg_seq;
__u32 urg_data;
__u32 syn_seq;
int users; /* user count */
* Not all are volatile, but some are, so we
* might as well say they all are.
volatile char dead,
unsigned long lingertime;
int proc;

struct sock *next;
struct sock **pprev;
struct sock *bind_next;
struct sock **bind_pprev;
struct sock *pair;
int hashent;
struct sock *prev;
struct sk_buff *volatile send_head;
struct sk_buff *volatile send_next;
struct sk_buff *volatile send_tail;
struct sk_buff_head back_log;
struct sk_buff *partial;
struct timer_list partial_timer;
long retransmits;
struct sk_buff_head write_queue,
struct proto *prot;
struct wait_queue **sleep;
__u32 daddr;
__u32 saddr; /* Sending source */
__u32 rcv_saddr; /* Bound address */
unsigned short max_unacked;
unsigned short window;
__u32 lastwin_seq; /* sequence number when we last
updated the window we offer */
__u32 high_seq; /* sequence number when we did
current fast retransmit */
volatile unsigned long ato; /* ack timeout */
volatile unsigned long lrcvtime; /* jiffies at last data rcv */
volatile unsigned long idletime; /* jiffies at last rcv */
unsigned int bytes_rcv;
* mss is min(mtu, max_window)
unsigned short mtu; /* mss negotiated in the syn’s */
volatile unsigned short mss; /* current eff. mss – can change */
volatile unsigned short user_mss; /* mss requested by user in ioctl */
volatile unsigned short max_window;
unsigned long window_clamp;
unsigned int ssthresh;
unsigned short num;
volatile unsigned short cong_window;
volatile unsigned short cong_count;
volatile unsigned short packets_out;
volatile unsigned short shutdown;
volatile unsigned long rtt;
volatile unsigned long mdev;
volatile unsigned long rto;

volatile unsigned short backoff;
int err, err_soft; /* Soft holds errors that don’t
cause failure but are the cause
of a persistent failure not
just ‘timed out’ */
unsigned char protocol;
volatile unsigned char state;
unsigned char ack_backlog;
unsigned char max_ack_backlog;
unsigned char priority;
unsigned char debug;
int rcvbuf;
int sndbuf;
unsigned short type;
unsigned char localroute; /* Route locally only */
* This is where all the private (optional) areas that don’t
* overlap will eventually live.
struct unix_opt af_unix;
#if defined(CONFIG_ATALK) || defined(CONFIG_ATALK_MODULE)
struct atalk_sock af_at;
#if defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE)
struct ipx_opt af_ipx;
struct inet_packet_opt af_packet;
struct tcp_opt af_tcp;
} protinfo;
* IP ‘private area’
int ip_ttl; /* TTL setting */
int ip_tos; /* TOS */
struct tcphdr dummy_th;
struct timer_list keepalive_timer; /* TCP keepalive hack */
struct timer_list retransmit_timer; /* TCP retransmit timer */
struct timer_list delack_timer; /* TCP delayed ack timer */
int ip_xmit_timeout; /* Why the timeout is running */
struct rtable *ip_route_cache; /* Cached output route */
unsigned char ip_hdrincl; /* Include headers ? */
int ip_mc_ttl; /* Multicasting TTL */
int ip_mc_loop; /* Loopback */
char ip_mc_name[MAX_ADDR_LEN]; /* Multicast device name */
struct ip_mc_socklist *ip_mc_list; /* Group array */

* This part is used for the timeout functions (timer.c).
int timeout; /* What are we waiting for? */
struct timer_list timer; /* This is the TIME_WAIT/receive
* timer when we are doing IP
struct timeval stamp;
* Identd
struct socket *socket;
* Callbacks
void (*state_change)(struct sock *sk);
void (*data_ready)(struct sock *sk,int bytes);
void (*write_space)(struct sock *sk);
void (*error_report)(struct sock *sk);


Each socket data structure holds information about a BSD socket. It does not exist independently; it is, instead, part of the VFS inode data structure.
struct socket {
short type; /* SOCK_STREAM, … */
socket_state state;
long flags;
struct proto_ops *ops; /* protocols do most everything */
void *data; /* protocol data */
struct socket *conn; /* server socket connected to */
struct socket *iconn; /* incomplete client conn.s */
struct socket *next;
struct wait_queue **wait; /* ptr to place to wait on */
struct inode *inode;
struct fasync_struct *fasync_list; /* Asynchronous wake up list */
struct file *file; /* File back pointer for gc */

Each task_struct data structure describes a process or task in the system.
struct task_struct {
/* these are hardcoded – don’t touch */
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
long counter;
long priority;
unsigned long signal;
unsigned long blocked; /* bitmap of masked signals */
unsigned long flags; /* per process flags, defined below */
int errno;
long debugreg[8]; /* Hardware debugging registers */
struct exec_domain *exec_domain;
/* various fields */
struct linux_binfmt *binfmt;
struct task_struct *next_task, *prev_task;
struct task_struct *next_run, *prev_run;
unsigned long saved_kernel_stack;
unsigned long kernel_stack_page;
int exit_code, exit_signal;
/* ??? */
unsigned long personality;
int dumpable:1;
int did_exec:1;
int pid;
int pgrp;
int tty_old_pgrp;
int session;
/* boolean value for session group leader */
int leader;
int groups[NGROUPS];
* pointers to (original) parent process, youngest child, younger sibling,
* older sibling, respectively. (p->father can be replaced with
* p->p_pptr->pid)
struct task_struct *p_opptr, *p_pptr, *p_cptr,
*p_ysptr, *p_osptr;
struct wait_queue *wait_chldexit;
unsigned short uid,euid,suid,fsuid;
unsigned short gid,egid,sgid,fsgid;
unsigned long timeout, policy, rt_priority;
unsigned long it_real_value, it_prof_value, it_virt_value;
unsigned long it_real_incr, it_prof_incr, it_virt_incr;
struct timer_list real_timer;
long utime, stime, cutime, cstime, start_time;
/* mm fault and swap info: this can arguably be seen as either
mm-specific or thread-specific */
unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap;
int swappable:1;
unsigned long swap_address;
unsigned long old_maj_flt; /* old value of maj_flt */
unsigned long dec_flt; /* page fault count of the last time */
unsigned long swap_cnt; /* number of pages to swap on next pass */
/* limits */
struct rlimit rlim[RLIM_NLIMITS];
unsigned short used_math;
char comm[16];
/* file system info */
int link_count;
struct tty_struct *tty; /* NULL if no tty */
/* ipc stuff */
struct sem_undo *semundo;
struct sem_queue *semsleeping;
/* ldt for this task – used by Wine. If NULL, default_ldt is used */
struct desc_struct *ldt;
/* tss for this task */
struct thread_struct tss;
/* filesystem information */
struct fs_struct *fs;
/* open file information */
struct files_struct *files;
/* memory management info */
struct mm_struct *mm;
/* signal handlers */
struct signal_struct *sig;
#ifdef __SMP__
int processor;
int last_processor;
int lock_depth; /* Lock depth.
We can context switch in and out
of holding a syscall kernel lock… */

timer_list data structure’s are used to implement real time timers for processes.
struct timer_list {
struct timer_list *next;
struct timer_list *prev;
unsigned long expires;
unsigned long data;
void (*function)(unsigned long);

Each task queue (tq_struct) data structure holds information about work that has been queued. This is usually a task needed by a device driver but which does not have to be done immediately.
struct tq_struct {
struct tq_struct *next; /* linked list of active bh’s */
int sync; /* must be initialized to zero */
void (*routine)(void *); /* function to call */
void *data; /* argument to function */

Each vm_area_struct data structure describes an area of virtual memory for a process.
struct vm_area_struct {
struct mm_struct * vm_mm; /* VM area parameters */
unsigned long vm_start;
unsigned long vm_end;
pgprot_t vm_page_prot;
unsigned short vm_flags;
/* AVL tree of VM areas per task, sorted by address */
short vm_avl_height;
struct vm_area_struct * vm_avl_left;
struct vm_area_struct * vm_avl_right;
/* linked list of VM areas per task, sorted by address */
struct vm_area_struct * vm_next;
/* for areas with inode, the circular list inode->i_mmap */
/* for shm areas, the circular list of attaches */
/* otherwise unused */
struct vm_area_struct * vm_next_share;
struct vm_area_struct * vm_prev_share;
/* more */
struct vm_operations_struct * vm_ops;
unsigned long vm_offset;
struct inode * vm_inode;
unsigned long vm_pte; /* shared mem */

Posted in Uncategorized | Leave a comment

How the Command Line Parsing Works

How the Command Line Parsing Works
There are two different command line parsers available with U-Boot: the old “simple” one, and the much more powerful “hush” shell:

Old, simple command line parser
supports environment variables (through setenv / saveenv commands)
several commands on one line, separated by ‘;’

variable substitution using “… ${_variablename_} …” syntax
ALERT! NOTE: Older versions of U-Boot used “$(…)” for variable substitution. Support for this syntax is still present in current versions, but will be removed soon. Please use “${…}” instead, which has the additional benefit that your environment definitions are compatible with the Hush shell, too.
special characters (‘$’, ‘;’) can be escaped by prefixing with ‘\’, for example:
setenv bootcmd bootm \${address}
You can also escape text by enclosing in single apostrophes, for example:
setenv addip ‘setenv bootargs ${bootargs} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off’

Hush shell

similar to Bourne shell, with control structures like if…then…else…fi, for…do…done, while…do…done, until…do…done, …
supports environment (“global”) variables (through setenv / saveenv commands) and local shell variables (through standard shell syntax name=value ); only environment variables can be used with the run command, especially as the variable to run (i. e. the first argument).
In the current implementation, the local variables space and global environment variables space are separated. Local variables are those you define by simply typing like name=value. To access a local variable later on, you have to write ‘$name’ or ‘${name}’; to execute the contents of a variable directly you can type ‘$name’ at the command prompt. Note that local variables can only be used for simple commands, not for compound commands etc.
Global environment variables are those you can set and print using setenv and printenv. To run a command stored in such a variable, you need to use the run command, and you must not use the ‘$’ sign to access them.
To store commands and special characters in a variable, use single quotation marks surrounding the whole text of the variable, instead of the backslashes before semicolons and special symbols.
Be careful when using the hash (‘#’) character – like with a “real” Bourne shell it is the comment character, so you have to escape it when you use it in the value of a variable.

setenv bootcmd bootm \$address
setenv addip ‘setenv bootargs $bootargs ip=$ipaddr:$serverip:$gatewayip:$netmask:$hostname:$netdev:off’

Hush shell scripts
Here are a few examples for the use of the advanced capabilities of the hush shell in U-Boot environment variables or scripts:


=> setenv check ‘if imi $addr; then echo Image OK; else echo Image corrupted!!; fi’
=> print check
check=if imi $addr; then echo Image OK; else echo Image corrupted!!; fi
=> addr=0 ; run check

## Checking Image at 00000000 …
Bad Magic Number
Image corrupted!!
=> addr=40000 ;run check

## Checking Image at 00040000 …
Image Name: ARM Linux-2.4.18
Created: 2003-06-02 14:10:54 UTC
Image Type: ARM Linux Kernel Image (gzip compressed)
Data Size: 801609 Bytes = 782.8 kB
Load Address: 0c008000
Entry Point: 0c008000
Verifying Checksum … OK
Image OK
Instead of “echo Image OK” there could be a command (sequence) to boot or otherwise deal with the correct image; instead of the “echo Image corrupted!!” there could be a command (sequence) to (load and) boot an alternative image, etc.


=> addr1=0
=> addr2=10
=> bootm $addr1 || bootm $addr2 || tftpboot $loadaddr $loadfile && bootm
## Booting image at 00000000 …
Bad Magic Number
## Booting image at 00000010 …
Bad Magic Number
TFTP from server; our IP address is
Filename ‘/tftpboot/TRAB/uImage’.
Load address: 0xc400000
Loading: #################################################################
Bytes transferred = 801673 (c3b89 hex)
## Booting image at 0c400000 …
Image Name: ARM Linux-2.4.18
This will check if the image at (flash?) address “addr1″ is ok and boot it; if the image is not ok, the alternative image at address “addr2″ will be checked and booted if it is found to be OK. If both images are missing or corrupted, a new image will be loaded over TFTP and booted. General rules
If a command line (or an environment variable executed by a run command) contains several commands separated by semicolons, and one of these commands fails, the remaining commands will still be executed.
If you execute several variables with one call to run (i. e. calling run with a list of variables as arguments), any failing command will cause run to terminate, i. e. the remaining variables are not executed.

Posted in Uncategorized | Leave a comment

U-Boot Standalone Applications

U-Boot Standalone Applications
U-Boot supports “standalone” applications, which are loaded dynamically; these applications can have access to the U-Boot console I/O functions, memory allocation and interrupt services.

A couple of simple examples are included with the U-Boot source code:

5.12.1. “Hello World” Demo
examples/hello_world.c contains a small “Hello World” Demo application; it is automatically compiled when you build U-Boot. It’s configured to run at address 0×00040000, so you can play with it like that:

TIP Note that the entry point of the program is at 0×40000 for the PowerPC architecture. It may be different for other architectures. See the CONFIG_STANDALONE_LOAD_ADDR define in your U-Boot tree if problems are encountered.

=> loads
## Ready for S-Record download …
1 2 3 4 5 6 7 8 9 10 11 …
[file transfer complete]
## Start Addr = 0×00040000

=> go 40000 Hello World! This is a test.
## Starting application at 0×00040000 …
Hello World
argc = 7
argv[0] = “40000″
argv[1] = “Hello”
argv[2] = “World!”
argv[3] = “This”
argv[4] = “is”
argv[5] = “a”
argv[6] = “test.”
argv[7] = “”
Hit any key to exit …

## Application terminated, rc = 0×0
Alternatively, you can of course use TFTP to download the image over the network. In this case the binary image (hello_world.bin) is used.

=> tftp 40000 /tftpboot/hello_world.bin

=> go 40000 This is another test.
## Starting application at 0×00040000 …
Hello World
argc = 5
argv[0] = “40000″
argv[1] = “This”
argv[2] = “is”
argv[3] = “another”
argv[4] = “test.”
argv[5] = “”
Hit any key to exit …

## Application terminated, rc = 0×0
5.12.2. Timer Demo
ALERT! This example is only available on MPC8xx CPUs.

TIP This example, which demonstrates how to register a CPM interrupt handler with the U-Boot code, can be found in examples/timer.c. Here, a CPM timer is set up to generate an interrupt every second. The interrupt service routine is trivial, just printing a ‘.’ character, but this is just a demo program. The application can be controlled by the following keys:

? – print current values of the CPM Timer registers
b – enable interrupts and start timer
e – stop timer and disable interrupts
q – quit application

=> loads
## Ready for S-Record download …
1 2 3 4 5 6 7 8 9 10 11 …
[file transfer complete]
## Start Addr = 0×00040000

=> go 40000
## Starting application at 0×00040000 …
Using timer 1
tgcr @ 0xfff00980, tmr @ 0xfff00990, trr @ 0xfff00994, tcr @ 0xfff00998, tcn @ 0xfff0099c, ter @ 0xfff009b0

Hit ‘b’:
[q, b, e, ?] Set interval 1000000 us
Enabling timer
Hit ‘?’:
[q, b, e, ?] ……..
tgcr=0×1, tmr=0xff1c, trr=0x3d09, tcr=0×0, tcn=0xef6, ter=0×0
Hit ‘?’:
[q, b, e, ?] .
tgcr=0×1, tmr=0xff1c, trr=0x3d09, tcr=0×0, tcn=0x2ad4, ter=0×0
Hit ‘?’:
[q, b, e, ?] .
tgcr=0×1, tmr=0xff1c, trr=0x3d09, tcr=0×0, tcn=0x1efc, ter=0×0
Hit ‘?’:
[q, b, e, ?] .
tgcr=0×1, tmr=0xff1c, trr=0x3d09, tcr=0×0, tcn=0x169d, ter=0×0
Hit ‘e’:
[q, b, e, ?] …Stopping timer
Hit ‘q’:
[q, b, e, ?] ## Application terminated, rc = 0×0
5.12.3. Processor cache considerations
Some processors have data and/or instruction caches. For some of these processors (e.g. MPC85xx), the operation of the cache(s) must be considered whenever data transferred to RAM is later executed as instructions. For these processors, data transferred to RAM might not be be represented correctly in the instruction cache without special treatment. This could result in incorrect execution of that data when it is considered an instruction stream. Multi core and multi processor systems with caches can also show this erroneous behaviour. To avoid this extremely difficult to debug type of problem, any instruction stream transferred to RAM as data should be flushed from any enabled data cache and the corresponding part of any enabled instruction cache should be invalidated.

In the “Hello World” example previously shown, the example program might be transferred to RAM by TFTP and then executed with the go command. While this procedure may work in most situations, it makes no provisions for cache behaviour as was just discussed. That is, obviously, there is no explicit cache management, nor does the go command do any cache management. This leaves open the possibility of malfunction.

The bootm command, which is normally used to start Linux, does implement the required cache flushes and invalidations, in ways that are appropriate for the particular processor.

To prepare an image of the “Hello World” example that is appropriate for the bootm command, the IMG target in the Makefile will wrap the executable in the appropriate U-Boot image header. An example addition to the Makefile might look like

IMG = $(BOARD)_standalone.img
IMG := $(addprefix $(obj),$(IMG))
$(obj)%.img: $(BIN)
$(MKIMAGE) -n “Hello stand alone” -A ppc -O u-boot -T standalone -C none -a $(LOAD_ADDR) -d $(BIN) -v $@
With this preparatory step added to the Makefile, the previously given “Hello World” console output example becomes

=> tftp 600000 helloworld.img

=> bootm 600000 Hello World! This is a test.
WARNING: adjusting available memory to 30000000
## Booting kernel from Legacy Image at 600000 …
Image Name: Hello stand alone
Image Type: PowerPC U-Boot Standalone Program (uncompressed)
Data Size: 25391 Bytes = 24.8 KiB
Load Address: 00040000
Entry Point: 00040000
Verifying Checksum … OK
Hello World
argc = 7
argv[0] = “600000″
argv[1] = “Hello”
argv[2] = “World!”
argv[3] = “This”
argv[4] = “is”
argv[5] = “a”
argv[6] = “test.”
argv[7] = “”
Hit any key to exit …

Of course, more is done by bootm in this example than is done by go in the original example. This additional work requires additional time, which may, or may not, be significant in any particular situation.

5.12.4. Running on core other than core 0
For Freescale PowerPC-based multi-core system, the following can be said.

U-Boot facilities are not available to stand alone applications, since U-Boot runs only on core 0

From Scott Wood ():

If you have true standalone code, you can release it on other CPUs using the
“cpu release” command. That code will not have access to any U-Boot
functionality. Its entry state will be as described for secondary CPUs in [the]
ePAPR [specification]. It will be the same as if an OS were spinning up its
secondary cores by writing directly to the spin table.
The ePAPR specification can be found at https://www.power.org/documentation/epapr-version-1-1/.

This implies that use of the normal stand alone stubs (e.g. stdio, I2C) will not work for stand alone applications running on any core other than core 0.

Posted in Uncategorized | Leave a comment

The Universal Boot Loader (“Das U-Boot”)

The Universal Boot Loader (“Das U-Boot”)
Table of contents:
1. Abstract
? 1.1. Introduction
? 1.2. History
? 1.3. Supported Hardware
? 1.4. Design Principles
? 1.5. User Interface
? 1.6. Basic Command Set
1.7. Advanced Commands
? 1.7.1. Logbuffer Manipulation Commands
? 1.7.2. Bedbug Embedded Debugger Commands
? 1.7.3. POST – Hardware Diagnose Commands
? 1.8. Environment Variables
? 1.9. Boot Options
? 1.10. Command Interpreters
? 1.11. Standalone Programs
1.12. Special Features
? 1.12.1. Bitmap and Splash Screen Support
? 1.12.2. Boot Count Limit
? 1.12.3. Keyboard Support
? 1.12.4. Automatic Updates

1.1. Introduction
• The “Universal Bootloader” (“Das U-Boot”) is a monitor program.
• Free Software: full source code under GPL
• hosted on SourceForge: http://sourceforge.net/projects/u-boot
• production quality: used as default boot loader by several board vendors
• portable and easy to port and to debug
• many supported architectures: PPC, ARM, MIPS, x86, m68k, NIOS, Microblaze
• more than 216 boards supported by public source tree
• many, many features
1.1. Introduction 1
1.2. History
• Oct 22, 1999: fadsrom – Dan Malek => PPCBoot rev. 1.1
• Dec 18, 1999: 8xxrom-0.3.0 – Magnus Damm, Raphael Bossek => PPCBoot rev. 1.2
• Jul 07, 2000: Wolfgang Denk => PPCBoot rev. 1.3
Jul 19, 2000: Wolfgang Denk => PPCBoot-0.4.1
first public version of PPCBoot

Siemens PSE, Vienna: Development of a Bluetooth LAN Access Point with a MPC850 Processor that
needed to be able to boot over Ethernet => first commercial sponsor

Aug 08, 2000: PPCBoot rev. 1.4 = PPCBoot-0.4.2
(only PPC, only MPC8xx, 4 boards)

• Oct 01, 2000: added network support => PPCBoot-0.4.4
• Oct 01, 2000: Stefan Roese: add support for IBM PPC401/403/405GP processors => PPCBoot-0.5.1
• Nov 16, 2000: Murray Jensen: add support for MPC8260 => PPCBoot-0.6.2
• Nov 20, 2000: Rob Taylor: add support for MPC8240 => PPCBoot-0.6.3
• End 2000: PPCBoot-0.7.1 (MPC8xx, MPC8240, MPC8260, PPC401/403/405GP; 27 boards)
• End 2001: PPCBoot-1.1.3 (MPC8xx, MPC8240, MPC8260, 7xx, 74xx, IBM 4xx, 63 boards)
• Mar 2002: SYSGO: split ARMBoot project, separate (incompatible) source tree
• Jul 2002: begin merging with ARMBoot tree
Nov 2002: PPCBoot-2.0.0 (last release of PPCBoot)
(PPC: 8xx, 824x, 826x, 7xx, 74xx, 4xx; ARM: StrongARM, ARM7, ARM9, XScale; >106 boards)
=> Start U-Boot project: PPCBoot-2.0.0 = U-Boot-0.1.0

• Nov 2002: x86 support
• Mar 2003: MIPS32
• Apr 2003: MIPS64
• Oct 2003: Altera NIOS-32
• Dec 2003: Coldfire
• Apr 2004: Microblaze
today (31 May 2004): U-Boot-1.1.2
(PPC: 5xx, 5xxx, 8xx, 824x, 826x, 85xx, 7xx, 74xx, 4xx;
ARM: StrongARM, ARM720T, ARM92xT, S3C44B0, AT91RM9200, XScale;
x86: SC520; m68k: Coldfire; MIPS32: 4Kc, Au1x00; MIPS64: 5Kc; NIOS32; Microblaze;
>216 boards in public tree; many more not submitted back

• several board manufacturers use U-Boot as default firmware on some or all of their boards
1.3. Supported Hardware
Architecture Processor Number of Boards
PPC 5xx 2
5xxx 6
8xx 71
824x 15
826x 26
85xx 3
1.3. Supported Hardware 2
7xx/74xx 11
4xx 38
ARM StrongARM 5
ARM720T 3
ARM92xT 11
S3C44B0 1
AT91RM9200 1
XScale 8
x86 SC520 2
m68k Coldfire 2
MIPS32 4Kc 2
Au1x00 3
MIPS64 5Kc 1
NIOS32 3
Microblaze 1
Blackfin BF5xx 18
1.4. Design Principles
• easy to port to new architectures, new processors, and new boards
• easy to debug: serial console output as soon as possible
• features and commands configurable
• as small as possible
• as reliable as possible
1.5. User Interface
U-Boot uses a simple command line interface (CLI), usually over a serial console port.
Two different command interpreters are available:
• simple CLI
• Bourne compatible shell (HUSH shell from Busybox)
Configuration parameters and commands / command sequences (scripts !) can be stored in “environment
variables” which can be saved to non-volatile storage (flash, EEPROM, NVRAM, etc.)
1.5. User Interface 3
1.6. Basic Command Set
Information Commands
? bdinfo – print Board Info structure
? coninfo – print console devices and informations
? flinfo – print FLASH memory information
? iminfo – print header information for application image
? imls – list all images found in flash
? help – print online help

Memory Commands
? base – print or set address offset
? crc32 – checksum calculation
? cmp – memory compare
? cp – memory copy
? md – memory display
? mm – memory modify (auto-incrementing)
? mtest – simple RAM test
? mw – memory write (fill)
? nm – memory modify (constant address)
? loop – infinite loop on address range

Flash Memory Commands
? cp – memory copy (program flash)
? flinfo – print FLASH memory information
? erase – erase FLASH memory
? protect – enable or disable FLASH write protection

Execution Control Commands
? autoscr – run script from memory
? bootm – boot application image from memory
? bootelf – Boot from an ELF image in memory
? bootvx – Boot vxWorks from an ELF image
? go – start application at address ‘addr’

Network Commands
? bootp – boot image via network using BOOTP/TFTP protocol
? cdp – Perform Cisco Discovery Protocol network configuration
? dhcp – invoke DHCP client to obtain IP/boot params
? loadb – load binary file over serial line (kermit mode)
? loads – load S-Record file over serial line
? nfs – boot image via network using NFS protocol
? ping – send ICMP ECHO_REQUEST to network host
? rarpboot- boot image via network using RARP/TFTP protocol
? tftpboot- boot image via network using TFTP protocol

Environment Variables Commands
? printenv- print environment variables
? saveenv – save environment variables to persistent storage
? askenv – get environment variables from stdin
? setenv – set environment variables
? run – run commands in an environment variable
? bootd – boot default, i.e., run ‘bootcmd’

Filesystem Support (FAT, cramfs, JFFS2, Reiser)
? chpart – change active partition

1.6. Basic Command Set 4
? fsinfo – print information about filesystems
? fsload – load binary file from a filesystem image
? ls – list files in a directory (default /)
? fatinfo – print information about filesystem
? fatls – list files in a directory (default /)
? fatload – load binary file from a dos filesystem
? nand – NAND flash sub-system
? reiserls- list files in a directory (default /)
? reiserload- load binary file from a Reiser filesystem
Special Commands
? i2c – I2C sub-system
? doc – Disk-On-Chip sub-system
? dtt – Digital Thermometer and Themostat
? eeprom – EEPROM sub-syste
? fpga – FPGA sub-system
? ide – IDE sub-system
? kgdb – enter gdb remote debug mode
? diskboot- boot from IDE device
? icache – enable or disable instruction cache
? dcache – enable or disable data cache
? diag – perform board diagnostics (POST code)
? log – manipulate logbuffer
? pci – list and access PCI Configuraton Space
? regdump – register dump commands
? usb – USB sub-system
? sspi – SPI utility commands

Miscellaneous Commands
? bmp – manipulate BMP image data
? date – get/set/reset date & time
? echo – echo args to console
? exit – exit script
? kbd – read keyboard status
? in – read data from an IO port
? out – write datum to IO port
? reset – Perform RESET of the CPU
? sleep – delay execution for some time
? test – minimal test like /bin/sh
? version – print monitor version
? wd – check and set watchdog
? ? – alias for ‘help’

1.7. Advanced Commands
Some of the following commands depend on certain hardware features and may not be available on all boards.
1.7. Advanced Commands 5
1.7.1. Logbuffer Manipulation Commands
Use a reserved area of system memory as log buffer;
can be re-used by syslogd in Linux;
content will survive reset / warm boot
• log info – show pointer details
• log log reset – clear contents
• log log show – show contents
• log log append – append to the logbuffer
• setenv stdout log – redirect standard output to log buffer
Used for example to pass POST results to Linux application code or for post-mortem checking of the Linux
system logs.
1.7.2. Bedbug Embedded Debugger Commands
• ds – disassemble memory
• as – assemble memory
• break – set or clear a breakpoint
• continue – continue from a breakpoint
• step – single step execution.
• next – single step execution, stepping over subroutines.
• where – Print the running stack.
• rdump – Show registers.
1.7.3. POST – Hardware Diagnose Commands
• cache – Cache test
• watchdog – Watchdog timer test
• i2c – I2C test
• rtc – RTC test
• memory – Memory test
• cpu – CPU test
• uart – UART test
• ethernet – ETHERNET test
• spi – SPI test
• usb – USB test
• spr – Special register test
• sysmon – SYSMON test
• dsp – DSP test
1.8. Environment Variables
Environment Variables (EV) can be used to configure the system and to store parameters for commands, and
1.8. Environment Variables 6
even commands and sequences of commands (simple scripts).
Board Configuration
baudrate, ethaddr, serial#, cpuclk

Startup Behaviour
bootdelay, bootcmd

Network Parameters
ipaddr, serverip, gatewayip, dnsip, netmask, hostname, rootpath, bootfile

autoload (network lookup without download); autostart (start downloaded image); pram
(reserve “protected RAM” area); silent (supress console messages); verify (disable CRC32
checks); …

User Defined
=> setenv name word1 word2 word3
=> saveenv

The real power of EVs results from the fact that Unix shell like variable expansion is available. For example:
=> setenv ipaddr
=> setenv serverip
=> setenv netdev eth0
=> setenv hostname testbox
=> setenv rootpath /opt/eldk/ppc_8xx
=> setenv ramargs setenv bootargs root=/dev/ram rw
=> setenv nfsargs ‘setenv bootargs root=/dev/nfs rw nfsroot=${serverip}:${rootpath}’
=> setenv addip ‘setenv bootargs ${bootargs} ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}:${netdev}:off’
=> setenv kernel_addr 40040000
=> setenv ramdisk_addr 40100000
=> setenv flash_ram ‘run ramargs addip;bootm ${kernel_addr} ${ramdisk_addr}’
=> setenv flash_nfs ‘run nfsargs addip;bootm ${kernel_addr}’
=> setenv net_nfs ‘tftp 200000 ${bootfile};run nfsargs addip;bootm’
=> setenv net_ram ‘tftp 200000 ${bootfile};run ramargs addip;bootm 200000 ${ramdisk_addr}’
Boot Kernel Image in flash with ramdisk in flash:
=> run flash_ram
Boot Kernel Image in flash with root filesystem over NFS:
=> run flash_nfs
Download Kernel Image over network and use root filesystem over NFS:
=> run net_nfs
Download Kernel Image over network with ramdisk in flash:
=> run net_ram
Step by step:
=> run flash_nfs
1.8. Environment Variables 7
Step Action Result in bootargs
setenv bootargs root=/dev/nfs rw
root=/dev/nfs rw
run addip
setenv bootargs ${bootargs}
root=/dev/nfs rw
40040000 boot Linux kernel
Example: simple recovery strategy:
=> setenv bootcmd ‘run flash_ram; setenv kernel_addr ${alt_kernel}; run flash_ram; run net_ram’
1.9. Boot Options
U-Boot supports many different ways to load and boot an image.
Basic command:
“bootm” – Boot Image in memory (RAM, flash)
Header + Payload
? Creation Timestamp
? Data Load Address
? Entry Point Address
? Data CRC Checksum
? Operating System
? CPU architecture
? Image Type
? Compression Type
? Image Name
? test CPU architecture and OS
? test checksum (optional)
? if compressed, uncompress
? copy to load address
? prepare boot arguments
? start at entry point
Load image in memory:
? Serial Port: “loads” (S-Record), “loadb” (Kermit binary protocol)
1.9. Boot Options 8
? Ethernet: “tftp”, “bootp”, “dhcp”, “nfs”, …
? Harddisk, CDROM: “ide read”
? CompactFlash card etc.: “ide read”
? USB Mass Storage Device: “usb read”
? SCSI Disk and CDROM: “scsi read”
? NAND flash with JFFS2 filesystem: “nboot”
? Disk on Chip: “doc read”
? PCI Bus: copy
? …
Supported Filesystems (read-only):
? Reiser
1.10. Command Interpreters
Two command line interfaces:
Simple (old) command interpreter:
? sequential statements
? statements separated by newline or ‘;’
no conditional execution except simple builtin rules:
“run cmd1; run cmd2; run cmd3″
will always run all three commands
“run cmd1 cmd2 cmd3″
will stop when a command fails
? “scripts” (canned sequences of commands) avaialble using “autoscr” command

Hush Shell (from Busybox, see http://www.busybox.net/):
? Bourne Shell compatible
(local) shell variables (“name=val”), (global) environment variables (“setenv name
? Conditionals: “if … then … else … fi”
Control loops: “for … do … done”, “while … do done”, “until …
do … done”
? Control operators: && and || (AND and OR lists: “command1 && command2″)
? real shell scripts
? no functions
? no command substitution
? no backquotes

1.11. Standalone Programs
1.11. Standalone Programs 9
U-Boot can dynamically load independent software modules, called “standalone programs”. Standalone
programs have a standard C calling environment, and can use standard services like printf(), malloc(),
Used for:
• special test software that is used in bring-up but shall not be included with customer release
• software that is needed only occasionally
• code that performs special actions that were not foreseen (software updates)
• code that shall not be made available under GPL
int hello_world (int argc, char *argv[])
int i;
printf (“Example expects ABI version %d\n”, XF_VERSION);
printf (“Actual U-Boot ABI version %d\n”, (int)get_version());
printf (“Hello World\n”);
printf (“argc = %d\n”, argc);
for (i=0; i<=argc; ++i) {
printf ("argv[%d] = \"%s\"\n",
argv[i] ? argv[i] : "”);
return (0);
=> tftp 40000 /tftpboot/hello_world.bin

=> go 40004 Hello World! This is a test.
## Starting application at 0×00040004 …
Hello World
argc = 7
argv[0] = “40004″
argv[1] = “Hello”
argv[2] = “World!”
argv[3] = “This”
argv[4] = “is”
argv[5] = “a”
argv[6] = “test.”
argv[7] = “”
## Application terminated, rc = 0×0
1.12. Special Features
• Bitmap and Splash Screen Support
• Boot Count Limit
• Keyboard Support
1.12. Special Features 10
• Automatic Updates
1.12.1. Bitmap and Splash Screen Support
Problem: booting Linux and starting a GUI takes a couple of seconds, but the user expects to see something
“immediately” after power-on.
Solution: display a static splash screen as soon as possible; available commands:
• bmp info – print Bitmap info
• bmp display – display bitmap image on screen
• setenv splashimage addr – display spash screen image at address addr
1.12.2. Boot Count Limit
The Open Source Development Labs Carrier Grade Linux Requirements Definition says:
CGL shall provide support for detecting a repeating reboot cycle due to recurring failures and will go to an
offline state if this occurs.
U-Boot allows to run an arbitrary command in such a case:
• bootcount (EV) – number of reboots since power-on
• bootlimit (EV) – maximum number of reboot cycles
• altbootcmd (EV) – alternate boot action
1.12.3. Keyboard Support
Problem: make system behaviour dependent on keys pressed at power-on
Solution: in U-Boot you can define one or more keys or key combinations and commands which are executed
when these keys are pressed at power-on:
“magic_keys” (EV) – List of characters for keys; for example:
=> setenv magic_keys 0123CB*

“key_magic_?_” (EV) – Key code or list of key codes for this action; scanned in the order as
listed in magic_keys; for example:
=> setenv key_magic0 3a+3b
=> setenv key_magic1 3c
=> setenv key_magic2 4a
=> setenv key_magic3 4c+51
=> setenv key_magicC 3a+4a+5a
=> setenv key_magicB 52+53
=> setenv key_magic* 55+56

• “key_cmd?” (EV) – Action to be performed when corresponding key(s) are pressed; for example:
1.12.3. Keyboard Support 11
=> setenv key_cmd0 setenv bootdelay 10
=> setenv key_cmd1 setenv addcons ‘console=ttyS0,${baudrate}’
=> setenv key_cmd2 setenv memtest on
=> setenv key_cmd3 setenv bootcmd run old_version
=> setenv key_cmdC setenv bootcmd run recovery
=> setenv key_cmdB setenv bootcmd run usb_update
=> setenv key_cmd* setenv bootcmd run demo_mode
Example: after a software update, the user can select to boot the old software version (“run old_version”) by
holding the keys with keycodes “4c” and “51″ at power-on.
1.12.4. Automatic Updates
Distribute Software Updates to customers
use cheap standard media like USB memory sticks
• Keep BOM (Versions, Timestamps etc.) in persistent memory (EEPROM etc.)
• When booting, check whether a USB memory stick is plugged in.
If one is found:
If prepare.img is found load it into memory.
If it is valid then run it (always).
If preinst.img is found load it into memory.
If it is valid then run it. Update the EEPROM.
If firmware.img is found load it into memory.
If it is valid, burn it into FLASH and update the EEPROM.
If kernel.img is found load it into memory.
If it is valid, burn it into FLASH and update the EEPROM.
If app.img is found load it into memory.
If it is valid, burn it into FLASH and update the EEPROM.
If disk.img is found load it into memory.
If it is valid, burn it into FLASH and update the EEPROM.
If postinst.img is found load it into memory.
If it is valid then run it. Update the EEPROM.

1.13. Resources, Summary
• The U-Boot project is hosted at Sourceforge: http://sourceforge.net/projects/u-boot
• Tarballs can be found either at sourceforge.net or at the DENX ftp server.
• There is a pretty active u-boot-users mailing list.
The Mailing list archive can be viewed at sourceforge.net (if it works – it is regularly broken, so don’t
get discouraged and try again later).

The DENX U-Boot and Linux Guide is a Wiki based documentation documenting U-Boot and its
interaction with Linux. It can be viewed (and improved) at www.denx.de. The whole DULG web

1.13. Resources, Summary 12
packed into a single HTML page or a PDF file is also available (TQM8xxL version, i.e. PowerPC
• The current README file can be viewed through viewcvs at sourceforge.net
Sample configuration files for the Abatron BDI2000 debugger are available at the FTP Server at

• Even more useful links can be found in the DENX Training wiki documentation at www.denx.de.
• U-Boot is a very active community project.
It lives from the spritit of Free Software. It would be impossible without the numberless contributions
of other developers.

1.13. Resources, Summary 13

Posted in Uncategorized | Leave a comment

Tricky C interview questions

1.Give a fastest way to multiply any number by 9.
void main()
int n;
printf(“Enter a number:”);
printf(“%d”, (n<<3)+n);
2. How to measure the size of any variable without “sizeof” operator?
#define size_of(x) ((char *)(&x+1) – (char *)&x)
void main()
Short int x;

By using the &x, we get the base address of the variable x and by adding 1 to it we get the base address of next short int type. Hence the resulting address of (&x+1) will be 2 bytes more than the base address of the variable x. But if we just display the difference between the base address of x and the incremented address, then the difference will be ‘1’, means “1 block of short int type has been added” but we need the result of size of variable in terms of bytes not in terms of blocks. This can be achieved if we typecast the address into char *, because the address of char data type will always be in block of one byte, hence if the difference between the base address of x and the incremented address is displayed in terms of char type, then the difference will be displayed as 2, because the difference is actually 2 blocks or 2 bytes in terms of char type representation.

3. How to measure the size of any variable without using “sizeof” operator?
#define SIZE_OF(T) (((T *)0)+1)
void main()
printf(“%d”,SIZE_OF(long int));


Whenever we typecast any constant, it converts the constants into a base address of specified data type and as we know (address+1) will always return the next address of its type or we can say the address of next block of memory of that type, so accordingly if 1 will be added with the address ‘0’, then it will return the size of any data type in bytes. For example 1 for char, 2 for short int, 4 for long int or float and so on.

4. Write code snippets to swap two variables in five different ways.
a. /* swapping using three variables*/ (Takes extra memory space)
Int a=5, b=10, c;

b. /* using arithmetic operators */

c. /* using bit-wise operators */

Value of a
Value of b

Initial values


values after swapping

d. /* one line statement using bit-wise operators */ (most efficient)

The order of evaluation is from right to left. This is same as in approach (c) but the three statements are compounded into one statement.

e. /* one line statement using arithmetic & assignment operators */
a=(a+b) – (b=a);
In the above axample, parenthesis operator enjoys the highest priority & the order of evaluation is from left to right. Hence (a+b) is evaluated first and replaced with 15. Then (b=a) is evaluated and the value of a is assigned to b, which is 5. Finally a is replaced with 15-5, i.e. 10. Now the two numbers are swapped.

5. How to swap between first & 2nd byte of an integer in one line statement?
int x=0×1234;
x = x<>8;

Let x = 0×1234

x = 00010010 00110100
x<>8 = 00000000 00010010
x<>8 = 00110100 00010010 i.e. value of ‘x’ after swap is 0×3412

6. What is the efficient way to divide a no. by 4?
x = x>>2;

7. Suggest an efficient method to count the no. of 1’s in a 32 bit no. Remember without using loop & testing each bit.
(i) int count_set_bits (long n)
int count = 0;
while (n)
count ++;
n & = n-1;
return (count);
(ii) int count_set_bits (long n)
return (n ? 1+ count_set_bits (n&n-1) : 0);


The logic is that the while loop continues as long as there are set bits (1) in the no. If all the bits became 0, that means no. is ‘0’ & the loop terminates. The logic needs conversion of every 1 to 0, which can be achieved by making a bitwise ‘&’ operation between the no. (n) and its previous no. (n-1) and assigning the resulting value back to n. If this is done, then with every run of the loop each set bit (1) will be reset. ( i.e. converted to 0).
Let n= 30
30 = 00011110
29 = 00011101
(30 & 29) = 00011100

We can see that the 2nd bit of 30 is reset to 0 which gives the no 28 which is now assigned to n (n &=n-1). This step is repeated until n becomes ‘0’.

8. Test whether a no. is power of 2 or not.
void main ()
int n;
printf (“\n Enter any no:”);
scanf (“%d”, & n);
if (n & & ((n & n-1) = = 0))
printf (“It is power of 2”);
printf (“It is not power of 2”);
Enter any no: 32
It is power of 2

Enter any no: 56
It is not power of 2


The logic says that if a no. is power of 2, then in the binary representation, only one bit of the no. can be ‘1’ & rest are must be ‘0’.
For example the number 32 has a binary representation of 00100000.

9. How to check endianness of the computer.

void main ()
int x = 300;
if ((* ((unsigned char *) & x) == 1)
&& (*(unsigned char*) & x+1) == 44))
printf (“BIG ENDIAN”);
printf (“LITTLE ENDIAN”);

void main ()
union xxx
unsigned int x;
unsigned char ch[2];
union xxx p = {300};
if ((p.ch [0] = = 1) && (p. ch [1] == 44))
printf (“BIG ENDIAN”);
printf (“LITTLE ENDIAN”);

Big Endian:

Little Endian:

Address are always created in memory in the form of ABCD format, but the data can be stored in memory either in DCBA format, which is little endian system or in the ABCD format in case of big-endian system.
Lets store 300 in the memory location of an integer. Now if we visit the memory location byte by byte we will find that the contents at first byte will be 1 & the content of the other will be 44. In a Big-endian system the 1st byte will contain 1, and the 2nd byte will be 44 according to the ABCD data storage format where as the little-endian system the 1st will contain 44 & the 2nd byte will be 1 according to the DCBA data storage format.
First we have to extract the base address of x by type casting it i.e. (unsigned char *). Then by using de-referencing operator ‘*’, we can get the value of the low or 1st byte. If that is found to be equal to 1 & the value of the high / 2nd byte obtained in the same method by adding 1 to the base address of x is equal to 44, then the system is “Big-endian” or else it is “Little-endian”.
In this logic, we have taken the union called xxx with 2 members – one is an integer x and the other is an array of 2 unsigned characters i.e. ch [2]. As in a union all data members share the same memory location, as the largest data member of the union, hence in this case, ch[0] will be accessing the 1st/low byte of x and ch[1] will be accessing the 2nd/high byte of x. So we can compare p.ch[0] with 1 & p.ch[1] with 44. If it matches, its “Big-endian”, else “little endian”.

10. Write a C-program which does the addition of two integers without using ‘+’ operator.

c = a – (-b);
as a+b is equivalent to a – (-b), binary ‘+’ operator is replaced by one unary ‘-‘ & one binary ‘-‘ operator.

void main ()
int a,b,c;
printf (“\n Enter any two numbers”);
scan f (“%d %d”, &a, &b);
asm mov ax, a;
asm mov bx, b;
asm aad ax, bx;
asm mov c, ax;
printf ( “%d”, c);

11. Write a C-program to find the smallest of three integers without using any of the comparision operators.

void main ()
int a,b,c;
printf (“\n Enter three numbers”);
scan f (“%d %d %d”, &a, &b, &c);
if ((a-b) & 32768)
if ((a-c) & 32768)
printf (“ %d”, a);
printf (“ %d”, c);
if ((b-c) & 32768)
printf (“ %d”, b);
printf (“ %d”, c);


When we substract a number from another number we can find out which one is greater than other. If the result is positive then the first number is greater else the second one is greater. This is known by doing a bitwise & operator with the sign bit (i.e. 32768 or 15th bit).

12. Find the maximum & minimum of two numbers in a single line without using any condition & loop.

void main ()
int a=15, b=10;
printf (“ max = %d, min = %d”, ((a+b) + abs(a-b)) /2, ((a+b) – abs (a-b)) /2);

13. What “condition” expression can be used so that the following code snippet will print Hello world.

if “condition”
printf (“ Hello”);
printf (“ world !”);

void main ()
if ( ! printf (“Hello”));
printf (“Hello”);
printf (“world !”);

As we know the printf function displays the string & returns an integer. So here printf (“Hello”) will print Hello as well as return 5. Then !5 is evaluated which is false. As the condition is false world is printed on the screen. By this we can get Hello world on the screen.

14. How to print number from 1 to 100 without using conditional operators.

void main ()
int i=0;
while (100 – i++)
printf (“ %d”, i);

15. WAP to print 100 times “Hello” without using loop & goto statement.

void main()
show (1, 100);
show (int x, int y)
if (x>=y)
printf (“\n Hello”);
show (x+1, y);
i.e. Recursive function

16. Write the equivalent expression for x%8.

x & 7;

x = 21 = 00010101
7 = 00000111
x & 7 = 00000101 (which is 5)

Posted in Uncategorized | Leave a comment

How to Replace a Switch-Statement with function pointer

float Plus (float a, float b) { return a+b; }
float Minus (float a, float b) { return a-b; }
float Multiply(float a, float b) { return a*b; }
float Divide (float a, float b) { return a/b; }

// Solution with a switch-statement – specifies which operation to execute
void Switch(float a, float b, char opCode)
float result;

// execute operation
case ‘+’ : result = Plus (a, b); break;
case ‘-’ : result = Minus (a, b); break;
case ‘*’ : result = Multiply (a, b); break;
case ‘/’ : result = Divide (a, b); break;

cout << "Switch: 2+5=" << result << endl; // display result

// Solution with a function pointer – is a function pointer and points to
// a function which takes two floats and returns a float. The function pointer
// “specifies” which operation shall be executed.
void Switch_With_Function_Pointer(float a, float b, float (*pt2Func)(float, float))
float result = pt2Func(a, b); // call using function pointer

cout << "Switch replaced by function pointer: 2-5="; // display result
cout << result << endl;

// Execute example code
void Replace_A_Switch()
cout << endl << "Executing function 'Replace_A_Switch'" << endl;

Switch(2, 5, /* '+' specifies function 'Plus' to be executed */ '+');
Switch_With_Function_Pointer(2, 5, /* pointer to function 'Minus' */ &Minus);

Posted in Character Driver | Leave a comment

What is Function Pointer

A function pointer (or subroutine pointer or procedure pointer) is a type of pointer supported by third-generation programming languages (such as PL/I, COBOL, Fortran,[1] dBASE dBL, and C) and object-oriented programming languages (such as C++ and D).[2]

Instead of referring to data values, a function pointer points to executable code within memory. When dereferenced, a function pointer can be used to invoke the function it points to and pass its arguments just like a normal function call. Such an invocation is also known as an “indirect” call, because the function is being invoked indirectly through a variable instead of directly through a fixed name or address.

Function pointers can be used to simplify code by providing a simple way to select a function to execute based on run-time values.

The simplest implementation of a function (or subroutine) pointer is as a variable containing the address of the function within executable memory. Older third-generation languages such as PL/I and COBOL, as well as more modern languages such as Pascal and C generally implement function pointers in this manner.[3]

The following C program illustrates the use of two function pointers:

func1 takes one double-precision (double) parameter and returns another double, and is assigned to a function which converts centimetres to inches
func2 takes a pointer to a constant character array as well as an integer and returns a pointer to a character, and is assigned to a string library function which returns a pointer to the first occurrence of a given character in a character array

#include /* for printf */
#include /* for strchr */

double cm_to_inches(double cm) {
return cm / 2.54;

int main(void) {
double (*func1)(double) = cm_to_inches;
char * (*func2)(const char *, int) = strchr;
printf(“%f %s”, func1(15.0), func2(“Wikipedia”, ‘p’));
/* prints “5.905512 pedia” */
return 0;

The next program uses a function pointer to invoke one of two functions (sin or cos) indirectly from another function (compute_sum, computing an approximation of the function’s Riemann integration). The program operates by having function main call function compute_sum twice, passing it a pointer to the library function sin the first time, and a pointer to function cos the second time. Function compute_sum in turn invokes one of the two functions indirectly by dereferencing its function pointer argument funcp multiple times, adding together the values that the invoked function returns and returning the resulting sum. The two sums are written to the standard output by main.


// Function taking a function pointer as an argument
double compute_sum(double (*funcp)(double), double lo, double hi) {
double sum = 0.0;

// Add values returned by the pointed-to function ‘*funcp’
int i;
for(i = 0; i <= 100; i++) {
double x, y;

// Use the function pointer 'funcp' to invoke the function
x = i / 100.0 * (hi – lo) + lo;
y = (*funcp)(x);
sum += y;
return sum / 101.0;

int main(void) {
double (*fp)(double); // Function pointer
double sum;

// Use 'sin()' as the pointed-to function
fp = sin;
sum = compute_sum(fp, 0.0, 1.0);
printf("sum(sin): %f\n", sum);

// Use 'cos()' as the pointed-to function
fp = cos;
sum = compute_sum(fp, 0.0, 1.0);
printf("sum(cos): %f\n", sum);
return 0;

Posted in Data Structures with C | Leave a comment

What are the different types of C pointers?

NULL Pointer
Dangling Pointer
Generic Pointers
Wild Pointer
Complex Pointers
Near Pointer
Far Pointer
Huge Pointers

NULL Pointer :

Literal meaning of NULL pointer is a pointer which is pointing to nothing. NULL pointer points the base address of segment.

Examples of NULL pointer:

int *ptr=(char *)0;
float *ptr=(float *)0;
char *ptr=(char *)0;
double *ptr=(double *)0;
char *ptr=’’;
int *ptr=NULL;

NULL is macro constant which has been defined in the heard file as :
#define NULL 0

Dangling pointer :

If any pointer is pointing the memory address of any variable but after some variable has deleted from that memory location while pointer is still pointing such memory location. Such pointer is known as dangling pointer and this problem is known as dangling pointer problem.

Generic pointer :

void pointer in c is known as generic pointer. Literal meaning of generic pointer is a pointer which can point type of data.

void *ptr;

Here ptr is generic pointer.

We cannot dereference generic pointer.
We can find the size of generic pointer using sizeof operator.
Generic pointer can hold any type of pointers like char pointer, struct pointer, array of pointer etc without any typecasting.
Any type of pointer can hold generic pointer without any typecasting.
Generic pointers are used when we want to return such pointer which is applicable to all types of pointers. For example return type of malloc function is generic pointer because it can dynamically allocate the memory space to stores integer, float, structure etc. hence we type cast its return type to appropriate pointer type.

Wild pointer :

A pointer in c which has not been initialized is known as wild pointer.

Complex pointer :

Pointer to function
Pointer to array
Pointer to array of integer
Pointer to array of function
Pointer to array of character
Pointer to array of structure
Pointer to array of union
Pointer to array of array
Pointer to two dimensional array
Pointer to three dimensional array
Pointer to array of string
Pointer to array of pointer to string
Pointer to structure
Pointer to union
Multilevel pointers

In TURBO C there are three types of pointers. TURBO C works under DOS operating system which is based on 8085 microprocessor.

1. Near pointer
2. Far pointer
3. Huge pointer

The pointer which can points only 64KB data segment or segment number 8 is known as near pointer.

The pointer which can point or access whole the residence memory of RAM i.e. which can access all 16 segments is known as far pointer.

The pointer which can point or access whole the residence memory of RAM i.e. which can access all the 16 segments is known as huge pointer.

Posted in Uncategorized | Leave a comment

Pointers Questions

1) What will be the output of following program ?
int main()
char *str=”IncludeHelp”;
return 0;

Correct Answer
& is a reference operator, * is de-reference operator, We can use these operators any number of times. str points the first character of IncludeHelp, *str points “I”, * & again reference and de-reference the value of str.

int main()
int iVal;
char cVal;
void *ptr; // void pointer
iVal=50; cVal=65;

printf(“value =%d,size= %d\n”,*(int*)ptr,sizeof(ptr));

printf(“value =%d,size= %d\n”,*(char*)ptr,sizeof(ptr));
return 0;

Correct Answer
value =50,size= 4
value =65,size= 4
void pointer can be type casted to any type of data type, and pointer takes 4 bytes (On 32 bit compiler).
to print value using void pointer, you will have to write like this *(data_type*)void_ptr;.

int main()
char *str []={“AAAAA”,”BBBBB”,”CCCCC”,”DDDDD”};
char **sptr []={str+3,str+2,str+1,str};
char ***pp;

return 0;

Correct Answer
*str is a array pointer of string, **sptr is array pointer(double pointer) that is pointing to str strings in reverse order. ***pp also a pointer that is pointing sptr base address.
++pp will point to 1st index of sptr that contain str+2 (“CCCCC”).
in printf(“%s”,**++pp+2); ++pp will point to str+1, and **++pp, value stored @ str+1 (“BBBBB).
and (**++pp)+2 will point the 2nd index of “BBBBB”, hence BBB will print.

char* strFun(void)
char *str=”IncludeHelp”;
return str;
int main()
char *x;
printf(“str value = %s”,x);
return 0;

Correct Answer
str value= IncludeHelp

If the address of pointer ptr is 2000, then what will the output of following program ?
[On 32 bit compiler.]
int main()
void *ptr;
return 0;
Correct Answer – 4
ERROR: Size of the type is unknown or zero.
ptr is a void pointer, and the scale factor of void pointer is unknown or zero.

6) What will be the output of following program ?

int main()
char ch=10;
void *ptr=&ch;
return 0;

Correct Answer -
*(char*)ptr will return the value of ch, since we know printf evaluates right to left..
so, ++(*(char*)ptr) will increase the value to 11.

7) What will be the output of following program ?
int main()
int a=10,b=2;
int *pa=&a,*pb=&b;
printf(“value = %d”, *pa/*pb);
return 0;

Correct Answer
ERROR: unexpected end of file found in comment.
The compiler is treated the operator / and * as /*, that happens to be the starting of comment.
To fix the error, use either *pa/ *pb (space between operators) or *pa/(*pb).

What is meaning of following declaration?

(A) ptr is pointer to function.
(B) ptr is array of pointer to function.
(C) ptr is pointer to such function which return type is array.
(D) ptr is pointer to array of function.
(E) None of these Answer

Here ptr is array not pointer.

What is meaning of following pointer declaration?

(A) ptr is pointer to function.
(B) ptr is array of pointer to function.
(C) ptr is pointer to such function which return type is pointer to an array.
(D) ptr is pointer array of function.
(E) None of these Answer

What is size of generic pointer in c?

(A) 0
(B) 1
(C) 2
(D) Null
(E) Undefined Answer

Size of any type of pointer is 2 byte (In case of near pointer)
Note. By default all pointers are near pointer if default memory model is small.

What will be output of following c code?

int main(){
int *p1,**p2;
double *q1,**q2;
printf(“%d %d “,sizeof(p1),sizeof(p2));
printf(“%d %d”,sizeof(q1),sizeof(q2));
return 0;
(A) 1 2 4 8
(B) 2 4 4 8
(C) 2 4 2 4
(D) 2 2 2 2
(E) 2 2 4 4 Answer

Size of any type of pointer is 2 byte (In case of near pointer)

What will be output if you will compile and execute the following c code?

int main(){
char huge *p=(char *)0XC0563331;
char huge *q=(char *)0XC2551341;
else if(p>q)
printf(“Greater than”);
printf(“Less than”);
return 0;
(A) Equal
(B) Greater than
(C) Less than
(D) Compiler error
(E) None of above Answer

As we know huge pointers compare its physical address.
Physical address of huge pointer p
Huge address: 0XC0563331
Offset address: 0×3331
Segment address: 0XC056
Physical address= Segment address * 0X10 + Offset address
=0XC056 * 0X10 +0X3331
=0XC0560 + 0X3331
Physical address of huge pointer q
Huge address: 0XC2551341
Offset address: 0×1341
Segment address: 0XC255
Physical address= Segment address * 0X10 + Offset address
=0XC255 * 0X10 +0X1341
=0XC2550 + 0X1341
Since both huge pointers p and q are pointing same physical address so if condition will true.

What will be output if you will compile and execute the following c code?

int main(){
int a=5,b=10,c=15;
int *arr[]={&a,&b,&c};
return 0;


(A) 5
(B) 10
(C) 15
(D) Compiler error
(E) None of above Answer

Array element cannot be address of auto variable. It can be address of static or extern variables.

What will be output if you will compile and execute the following c code?

int main(){
int a[2][4]={3,6,9,12,15,18,21,24};
printf(“%d %d %d”,*(a[1]+2),*(*(a+1)+2),2[1[a]]);
return 0;

(A) 15 18 21
(B) 21 21 21
(C) 24 24 24
(D) Compiler error
(E) None of above Answer

In c,
a [1][2]=*(a [1] +2)=*(*(a+1) +2)=2[a [1]]=2[1[a]]
Now, a [1] [2] means 1*(4) +2=6th element of an array staring from zero i.e. 21.

What will be output if you will compile and execute the following c code?

int main(){
const int x=25;
int * const p=&x;
return 0;

(A) 25
(B) 50
(C) 0
(D) Compiler error
(E) None of above Answer

const keyword in c doesn’t make any variable as constant but it only makes the variable as read only. With the help of pointer we can modify the const variable. In this example pointer p is pointing to address of variable x. In the following line:
int * const p=&x;
p is constant pointer while content of p i.e. *p is not constant.
*p=2*x put the value 50 at the memory location of variable x.

What will be output if you will compile and execute the following c code?

int main(){
static char *s[3]={“math”,”phy”,”che”};
typedef char *( *ppp)[3];
static ppp p1=&s,p2=&s,p3=&s;
char * (*(*array[3]))[3]={&p1,&p2,&p3};
char * (*(*(*ptr)[3]))[3]=&array;
return 0;
(A) math
(B) phy
(C) che
(D) Compiler error
(E) None of these Answer

Here ptr is pointer to array of pointer to string. P1, p2, p3 are pointers to array of string. array[3] is array which contain pointer to array of string.
Note: In the above figure upper part of box represent content and lower part represent memory address. We have assumed arbitrary address.

As we know p[i]=*(p+i)
=(***(&array))[2] //ptr=&array
=(**array)[2] //From rule *&p=p
=(**(&p1))[2] //array=&p1
=(*&s)[2] //p1=&s

What will be output if you will compile and execute the following c code?

int display();
int main(){
return 0;

int display(){
int x=5;
return x++;

(A) 5
(B) 6
(C) 0
(D) Compiler error
(E) None of these Answer

In this example:
array []: It is array of pointer to such function which parameter is void and return type is int data type.
ptr: It is pointer to array which contents are pointer to such function which parameter is void and return type is int type data.

(**ptr)() = (** (&array)) () //ptr=&array
= (*array) () // from rule *&p=p
=array [0] () //from rule *(p+i)=p[i]
=display () //array[0]=display
(*(*ptr+1))() =(*(*&array+1))() //ptr=&array
=*(array+1) () // from rule *&p=p
=array [1] () //from rule *(p+i)=p[i]
=getch () //array[1]=getch

What will be output if you will compile and execute the following c code?

int main(){
int i;
char far *ptr=(char *)0XB8000000;
return 0;
It output will be A, B and C in blue, green and red color respectively.

What will be output if you will compile and execute the following c code?
int main(){
int j;
union REGS i,o;
char far *ptr=(char *)0XA0000000;
return 0;

What will be output if you will compile and execute the following c code?

int dynamic(int,…);
int main(){
int x,y;
printf(“%d %d “,x,y);
return 0;

int dynamic(int s,…){
void *ptr;
(int *)ptr+=2;
s=*(int *)ptr;
return s;

(A) 8 12
(B) 14 12
(C) 2 3
(D) Compiler error
(E) None of these Answer

In c three continuous dots is known as ellipsis which is variable number of arguments of function. In this example ptr is generic pointer which is pointing to first element of variable number of argument. After incrementing it will point third element.

Which of the following is not correct pointer declaration?

(i)int * const * ptr
(ii)int const * const * ptr;
(iii)const int ** const ptr;
(iv)const int const **ptr;
(v)int const ** const ptr;

(A) All are collect.
(B) Only (ii) is incorrect.
(C) Only (iv) is incorrect.
(D) Both (iii) and (v) are incorrect.
(E) All are incorrect

What will be output if you will compile and execute the following c code?

int main(){
char arr[]=”C Question Bank”;
float *fptr;
fptr=(float *)arr;
return 0;

(A) C Question Bank
(B) Question Bank
(C) Bank
(D) estion Bank
(E) Compilation error Answer


In the following declaration ptr is
far * near * huge * ptr;

(A) Near pointer.
(B) Far pointer.
(C) Huge pointer.
(D) Near and far pointer.
(E) Near,far and huge pointer. Answer


What will be output if you will compile and execute the following c code?

int main(){
char arr[]=”C Question Bank”;
char *p;
return 0;

(A) C question Bank
(B) C quesdion Bank
(C) C qdestion Bank
(D) C q100estion Bank
(E) Compilation error Answer

Which of the following ptr is not pointer?
(A) int(*ptr)()
(B) long **volatile*ptr
(C) int(*ptr[2])[3]
(D) float * (*ptr)[5]
(E) All are pointer Answer

Which of the following is incorrect c statement?

(A) We can increment array pointer
(B) We can increment function pointer
(C) We can increment structure pointer
(D) We can increment union pointer.
(E) We can increment generic pointer. Answer

Which of the following incorrect about far pointer?

(i)Size of far pointer is four byte.
(ii)Far pointer can points all segment of residence memory
(iii)If we will increment far pointer it can move from one segment to another segment.
Choose correct option:

(A) Only (i) is incorrect.
(B) Only (ii) is incorrect.
(C) Only (iii) is incorrect.
(D) Both (ii) and (iii) are incorrect.
(E) All three are incorrect.

Posted in Uncategorized | Leave a comment

2G, 3G, 4G, 4G LTE, 5G

2G, 3G, 4G, 4G LTE, 5G – What are They?
Quite simply, the “G” stands for Generation, as in the next generation of wireless technologies. Each generation is supposedly faster, more secure and more reliable. The reliability factor is the hardest obstacle to overcome. 1G was not used to identify wireless technology until 2G, or the second generation, was released. That was a major jump in the technology when the wireless networks went from analog to digital. It’s all uphill from there. 3G came along and offered faster data transfer speeds, at least 200 kilobits per second, for multi-media use and was a long time standard for wireless transmissions regardless of what you heard on all those commercials.
It is still a challenge to get a true 4G connection, which promises upwards of a 1Gps, Gigabit per second, transfer rate if you are standing still and in the perfect spot. 4G LTE comes very close to closing this gap. True 4G on a wide spread basis may not be available until the next generation arrives. 5G?
What are the Standards of the G’s
Each of the Generations has standards that must be met to officially use the G terminology. Those standards are set by, you know, those people that set standards. The standards themselves are quite confusing but the advertisers sure know how to manipulate them. I will try to simplify the terms a bit.
1G – A term never widely used until 2G was available. This was the first generation of cell phone technology. Simple phone calls were all it was able to do.
2G – The second generation of cell phone transmission. A few more features were added to the menu such as simple text messaging.
3G – This generation set the standards for most of the wireless technology we have come to know and love. Web browsing, email, video downloading, picture sharing and other Smartphone technology were introduced in the third generation. 3G should be capable of handling around 2 Megabits per second.

4G – The speed and standards of this technology of wireless needs to be at least 100 Megabits per second and up to 1 Gigabit per second to pass as 4G. It also needs to share the network resources to support more simultaneous connections on the cell. As it develops, 4G could surpass the speed of the average wireless broadband home Internet connection. Few devices were capable of the full throttle when the technology was first released. Coverage of true 4G was limited to large metropolitan areas. Outside of the covered areas, 4G phones regressed to the 3G standards. When 4G first became available, it was simply a little faster than 3G. 4G is not the same as 4G LTE which is very close to meeting the criteria of the standards.
The major wireless networks were not actually lying to anyone when 4G first rolled out, they simply stretched the truth a bit. A 4G phone had to comply with the standards but finding the network resources to fulfill the true standard was difficult. You were buying 4G capable devices before the networks were capable of delivering true 4G to the device. Your brain knows that 4G is faster than 3G so you pay the price for the extra speed. Marketing 101. The same will probably be true when 5G hits the markets.
4G LTE– Long Term Evolution – LTE sounds better. This buzzword is a version of 4G that is fast becoming the latest advertised technology and is getting very close to the speeds needed as the standards are set. When you start hearing about LTE Advanced, then we will be talking about true fourth generation wireless technologies because they are the only two formats realized by the International Telecommunications Union as True 4G at this time. But forget about that because 5G is coming soon to a phone near you. Then there is XLTE which is a bandwidth charger with a minimum of double the bandwidth of 4G LTE and is available anywhere the AWS spectrum is initiated.

Posted in Uncategorized | Leave a comment

A simple command line tool(TCL)

Tcl is a very simple programming language. If you have programmed before, you can learn enough to write interesting Tcl programs within a few hours. This page provides a quick overview of the main features of Tcl. After reading this you’ll probably be able to start writing simple Tcl scripts on your own; however, we recommend that you consult one of the many available Tcl books for more complete information.

Basic syntax
Tcl scripts are made up of commands separated by newlines or semicolons. Commands all have the same basic form illustrated by the following example:

expr 20 + 10
This command computes the sum of 20 and 10 and returns the result, 30. You can try out this example and all the others in this page by typing them to a Tcl application such as tclsh; after a command completes, tclsh prints its result.
Each Tcl command consists of one or more words separated by spaces. In this example there are four words: expr, 20, +, and 10. The first word is the name of a command and the other words are arguments to that command. All Tcl commands consist of words, but different commands treat their arguments differently. The expr command treats all of its arguments together as an arithmetic expression, computes the result of that expression, and returns the result as a string. In the expr command the division into words isn’t significant: you could just as easily have invoked the same command as

expr 20+10
However, for most commands the word structure is important, with each word used for a distinct purpose.
All Tcl commands return results. If a command has no meaningful result then it returns an empty string as its result.

Tcl allows you to store values in variables and use the values later in commands. The set command is used to write and read variables. For example, the following command modifies the variable x to hold the value 32:

set x 32
The command returns the new value of the variable. You can read the value of a variable by invoking set with only a single argument:
set x
You don’t need to declare variables in Tcl: a variable is created automatically the first time it is set. Tcl variables don’t have types: any variable can hold any value.
To use the value of a variable in a command, use variable substitution as in the following example:

expr $x*3
When a $ appears in a command, Tcl treats the letters and digits following it as a variable name, and substitutes the value of the variable in place of the name. In this example, the actual argument received by the expr command will be 32*3 (assuming that variable x was set as in the previous example). You can use variable substitution in any word of any command, or even multiple times within a word:
set cmd expr
set x 11
$cmd $x*$x
Command substitution
You can also use the result of one command in an argument to another command. This is called command substitution:

set a 44
set b [expr $a*4]
When a [ appears in a command, Tcl treats everything between it and the matching ] as a nested Tcl command. Tcl evaluates the nested command and substitutes its result into the enclosing command in place of the bracketed text. In the example above the second argument of the second set command will be 176.
Quotes and braces
Double-quotes allow you to specify words that contain spaces. For example, consider the following script:

set x 24
set y 18
set z “$x + $y is [expr $x + $y]”
After these three commands are evaluated variable z will have the value 24 + 18 is 42. Everything between the quotes is passed to the set command as a single word. Note that (a) command and variable substitutions are performed on the text between the quotes, and (b) the quotes themselves are not passed to the command. If the quotes were not present, the set command would have received 6 arguments, which would have caused an error.
Curly braces provide another way of grouping information into words. They are different from quotes in that no substitutions are performed on the text between the curly braces:

set z {$x + $y is [expr $x + $y]}
This command sets variable z to the value “$x + $y is [expr $x + $y]“.
Control structures
Tcl provides a complete set of control structures including commands for conditional execution, looping, and procedures. Tcl control structures are just commands that take Tcl scripts as arguments. The example below creates a Tcl procedure called power, which raises a base to an integer power:

proc power {base p} {
set result 1
while {$p > 0} {
set result [expr $result * $base]
set p [expr $p - 1]
return $result
This script consists of a single command, proc. The proc command takes three arguments: the name of a procedure, a list of argument names, and the body of the procedure, which is a Tcl script. Note that everything between the curly brace at the end of the first line and the curly brace on the last line is passed verbatim to proc as a single argument. The proc command creates a new Tcl command named power that takes two arguments. You can then invoke power with commands like the following:
power 2 6
power 1.15 5
When power is invoked, the procedure body is evaluated. While the body is executing it can access its arguments as variables: base will hold the first argument and p will hold the second.

The body of the power procedure contains three Tcl commands: set, while, and return. The while command does most of the work of the procedure. It takes two arguments, an expression ($p > 0) and a body, which is another Tcl script. The while command evaluates its expression argument using rules similar to those of the C programming language and if the result is true (nonzero) then it evaluates the body as a Tcl script. It repeats this process over and over until eventually the expression evaluates to false (zero). In this case the body of the while command multiplied the result value by base and then decrements p. When p reaches zero the result contains the desired power of base. The return command causes the procedure to exit with the value of variable result as the procedure’s result.

Where do commands come from?
As you have seen, all of the interesting features in Tcl are represented by commands. Statements are commands, expressions are evaluated by executing commands, control structures are commands, and procedures are commands.

Tcl commands are created in three ways. One group of commands is provided by the Tcl interpreter itself. These commands are called builtin commands. They include all of the commands you have seen so far and many more (see below). The builtin commands are present in all Tcl applications.

The second group of commands is created using the Tcl extension mechanism. Tcl provides APIs that allow you to create a new command by writing a command procedure in C or C++ that implements the command. You then register the command procedure with the Tcl interpreter by telling Tcl the name of the command that the procedure implements. In the future, whenever that particular name is used for a Tcl command, Tcl will call your command procedure to execute the command. The builtin commands are also implemented using this same extension mechanism; their command procedures are simply part of the Tcl library.

When Tcl is used inside an application, the application incorporates its key features into Tcl using the extension mechanism. Thus the set of available Tcl commands varies from application to application. There are also numerous extension packages that can be incorporated into any Tcl application. One of the best known extensions is Tk, which provides powerful facilities for building graphical user interfaces. Other extensions provide object-oriented programming, database access, more graphical capabilities, and a variety of other features. One of Tcl’s greatest advantages for building integration applications is the ease with which it can be extended to incorporate new features or communicate with other resources.

The third group of commands consists of procedures created with the proc command, such as the power command created above. Typically, extensions are used for lower-level functions where C programming is convenient, and procedures are used for higher-level functions where it is easier to write in Tcl.

Other features
Tcl contains many other commands besides the ones used in the preceding examples. Here is a sampler of some of the features provided by the builtin Tcl commands:

More control structures, such as if, for, foreach, and switch.
String manipulation, including a powerful regular expression matching facility. Arbitrary-length strings can be passed around and manipulated just as easily as numbers.
I/O, including files on disk, network sockets, and devices such as serial ports. Tcl provides particularly simple facilities for socket communication over the Internet.
File management: Tcl provides several commands for manipulating file names, reading and writing file attributes, copying files, deleting files, creating directories, and so on.
Subprocess invocation: you can run other applications with the exec command and communicate with them while they run.
Lists: Tcl makes it easy to create collections of values (lists) and manipulate them in a variety of ways.
Arrays: you can create structured values consisting of name-value pairs with arbitrary string values for the names and values.
Time and date manipulation.
Events: Tcl allows scripts to wait for certain events to occur, such as an elapsed time or the availability of input data on a network socket.
A simple command line tool
A simple network server

Posted in Uncategorized | Leave a comment

Embedded Wireless with Lora

Microchip’s Long-Range Low-Power End Node Solution

With the growing Internet of Things, Microchip has a LoRa® technology wireless solution to address increasing demands on end-devices for long range connectivity, low-power for battery operation, and low infrastructure cost for volume deployment.
Microchip’s LoRa technology solution is ready to run out-of-the box and with the complete LoRaWAN protocol and certifications in place, it reduces time to market and saves development costs.
LoRa Technology is ideal for battery-operated sensor and low-power applications such as:

Internet of Things
Smart agriculture
Smart city
Sensor networks
Industrial automation
Smart meters
Asset tracking
Smart home
LoRa Key Features

LoRa Technology:
Long range – greater than 15 km
High capacity of up to 1 million nodes
Long battery life – over 10 years
Reduced synchronization overhead and no hops in mesh network
Secured and efficient network
Interference immunity
Microchip LoRa Technology Module:
Embedded LoRaWAN Protocol Class A – easily connects to LoRa Technology gateway
LoRaWAN Protocol Stack ready in system
Simple ASCII command set
Full certification by region
LoRa Technology for Long Range Connectivity.
Real world example: Deployment of 7 LoRa technology gateways creates IoT network coverage for most of Munich!

Posted in Uncategorized | Leave a comment