nanosleep : High Resolution Sleeping

A process that voluntarily suspends the execution for a specified time is said to sleep. Whenever a thread or process sleeps, it will allow other thread or process to utilize CPU time and do useful operation.

Unix/Linux system provides mechanisms where a process or a thread can suspend the execution for the specified time and resumes executions after the time has expired.


The sleep function causes the calling thread to be suspended either until the specified number of seconds has elapsed or until the calling thread catches the signal.

#include <unistd.h>

int sleep(unsigned seconds)

The sleep function returns 0 if the requested time has elapsed or the amount of unslept time if interrupted by signal or a high priority interrupt. The disadvantage of sleep function is, it expects arguments only in seconds. Since the most of the embedded systems requires timing in terms of microseconds or nanoseconds.


The usleep function causes the calling thread to be suspended either the specified number of microsecond has elapsed or until the calling thread catches the signal. The sleep may be lengthened slightly by any system activity or by the time spent processing the call or by the granularity of system timers.

#include <unistd.h>

int usleep (useconds_t usec)

the usleep function returns 0 on sucess and -1 on error.



Interrupted by a signal;


usec is not smaller than 1000000. (On systems where that is considered an error.)

The disadvantage of usleep() function is, if  the function is interrupted by a signal, it will not return for how much time this function has slept and how much time is remaining.


nanosleep() suspends the execution of the calling thread until either at least the time specified in *req has elapsed, or the delivery of a signal that triggers the invocation of a handler in the calling thread or that terminates the process.

If the call is interrupted by a signal handler, nanosleep() returns -1, sets errno to EINTR, and writes the remaining time into the structure pointed to by rem unless rem is NULL. The value of *rem can then be used to call nanosleep() again and complete the specified
pause (but see NOTES).

#include <time.h>

int nanosleep(const struct timespec *req, struct timespec *rem);

The structure time-spec is used to specify intervals of time with nanosecond precision. It is defined as follows:

struct timespec {
          time_t tv_sec; /* seconds */
          long tv_nsec; /* nanoseconds */

The value of the nanoseconds field must be in the range 0 to 999999999.

Compared to sleep() and usleep(), nanosleep() has the following advantages: it provides a higher resolution for specifying the sleep interval; POSIX.1 explicitly specifies that it does not interact with signals; and it makes the task of resuming a sleep that has been interrupted by a signal handler easier.

On successfully sleeping for the requested interval, nanosleep() returns 0. If the call is interrupted by a signal handler or encounters an error, then it returns -1, with errno set to indicate the error.

EFAULT Problem with copying information from user space.

EINTR The pause has been interrupted by a signal that was delivered to the thread (see signal(7)). The remaining sleep time has been written into *rem so that the thread can easily call nanosleep() again and continue with the pause.

EINVAL The value in the tv_nsec field was not in the range 0 to 999999999 or tv_sec was negative.

In embedded system application, a wrapper function can be implemented which will take the argument in terms of second, microsecond or nanosecond, and nanosleep() and it’s functionality will be wrapped inside the function. 

#include <stdio.h>

#include <time.h>

enum SleepType = {Second = 0, miliSecond, microSecond, nanoSeconds}

void MyWrappedSleepFunction(SleepType  sleepType, long sleepTime)


     struct timespec tv;



           case Second :


  tv.tv_sec = sleepTime ;

                tv.tv_nsec  = 0;



           case miliSecond:


  tv.tv_sec = 0;

                tv.tv_nsec  = sleepTime * 1000 * 1000;



           case microSecond:


  tv.tv_sec = 0;

                tv.tv_nsec  = sleepTime * 1000;



           case nanoSeconds:


  tv.tv_sec = 0;

                tv.tv_nsec  = sleepTime;




   while ((nanosleep(&tv, &tv) == -1) && (errno == EINTR))


         /* wait here till the specified time gets over */



int main()


MyWrappedSleepFunction(Second , 2);

MyWrappedSleepFunction(miliSecond , 30);

MyWrappedSleepFunction(microSecond , 10);

MyWrappedSleepFunction(nanoSeconds , 5);

return 0;


I hope, you would find this post useful and hope you will try to implement this wrapper function in your application.

Please share your thoughts and suggestions in the comments and stay tuned for the next post. Till then enjoy clicking embedded.


Update U-Boot Environment Variables stored in Flash from Linux

Hi folks,

How are you all?

Many of us wondering that, Is it possible to get U-boot environment variables in user space? Is it possible to set U-boot environment variable from user space? Answer to these questions is YES. It is possible to set and retrieve U-boot environment variables from user space through command-line or any application.

In this article I will demonstrate how to set and get U-boot environment from Linux user space through an application or shell command. To explain this I will take a reference of AM335x EVM.

In Linux source code, there is a board file specific to board or processor (in my case it is board-am335xevm.c) which contains a structure of memory partitions, In that memory partions will be a separate memory partition of Uboot environment variables where these variables will be stored. refer the below image.


Build fw_printenv / fw_setenv tool

  • first of all cd to top of the u-boot source directory
  • Issue a command
    host# make HOSTCC=arm-arago-linux-gnueabi-gcc env

    This must create a fw_printenv and fw_setenv cross compiled binaries in <uboot-src>/tools/env directory. You must see these binaries along with fw_env.config file. You must copy these two binaries to /bin folder and fw_env.config file to /etc directory of the target system.

Test fw_printenv / fw_setenv tool

The executable fw_printenv will dump the entire environment space, individual variables can be read by:

target# ./fw_printenv autoload

To set an environment variable use fw_setenv. This example will set the variable autoload to no, use fw_printenv to read back the change.

target# ./fw_setenv autoload no

Top and Bottom Halves in Linux

Top and Bottom Halves

One of the main problems with interrupt handling is how to perform lengthy tasks within a handler. Often a substantial amount of work must be done in response to a device interrupt, but interrupt handlers need to finish up quickly and not keep interrupts blocked for long. These two needs (work and speed) conflict with each other, leaving the driver writer in a bit of a bind.

Linux (along with many other systems) resolves this problem by splitting the interrupt handler into two halves. The so-called top half is the routine that actually responds to the interrupt—the one you register with request_irq. The bottom half is a routine that is scheduled by the top half to be executed later, at a safer time.

The big difference between the top-half handler and the bottom half is that all interrupts are enabled during execution of the bottom half—that’s why it runs at a safer time. In the typical scenario, the top half saves device data to a device-specific buffer, schedules its bottom half, and exits: this operation is very fast.

The bottom half then performs whatever other work is required, such as awakening processes, starting up another I/O operation, and so on. This setup permits the top half to service a new interrupt while the bottom half is still working.

Almost every serious interrupt handler is split this way. For instance, when a network interface reports the arrival of a new packet, the handler just retrieves the data and pushes it up to the protocol layer; actual processing of the packet is performed in a bottom half.

The Linux kernel has two different mechanisms that may be used to implement bottom-half processing, Tasklets are often the preferred mechanism for bottom-half processing; they are very fast, but all tasklet code must be atomic. The alternative to tasklets is workqueues, which may have a higher latency but that are allowed to sleep.


Remember that tasklets are a special function that may be scheduled to run, in software interrupt context, at a system-determined safe time. They may be scheduled to run multiple times, but tasklet scheduling is not cumulative; the tasklet runs only once, even if it is requested repeatedly before it is launched. No tasklet ever runs in parallel with itself, since they run only once, but tasklets can run in parallel with other tasklets on SMP systems. Thus, if your driver has multiple tasklets, they must employ some sort of locking to avoid conflicting with each other.

Tasklets are also guaranteed to run on the same CPU as the function that first schedules them. Therefore, an interrupt handler can be secure that a tasklet does not begin executing before the handler has completed. However, another interrupt can certainly be delivered while the tasklet is running, so locking between the tasklet and the interrupt handler may still be required.

Tasklets must be declared with the DECLARE_TASKLET macro:

DECLARE_TASKLET(name, function, data);

name is the name to be given to the tasklet, function is the function that is called to execute the tasklet (it takes one unsigned long argument and returns void), and data is an unsigned long value to be passed to the tasklet function.

The short driver declares its tasklet as follows:

void short_do_tasklet(unsigned long);
DECLARE_TASKLET(short_tasklet, short_do_tasklet, 0);

The function tasklet_schedule is used to schedule a tasklet for running. If short is loaded with tasklet=1, it installs a different interrupt handler that saves data and schedules the tasklet as follows:

irqreturn_t short_tl_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    do_gettimeofday((struct timeval *) tv_head); /* cast to stop 'volatile' warning */
    short_wq_count++; /* record that an interrupt arrived */
    return IRQ_HANDLED;

The actual tasklet routine, short_do_tasklet, will be executed shortly (so to speak) at the system’s convenience. As mentioned earlier, this routine performs the bulk of the work of handling the interrupt; it looks like this:

void short_do_tasklet (unsigned long unused)
    int savecount = short_wq_count, written;
    short_wq_count = 0; /* we have already been removed from the queue */
     * The bottom half reads the tv array, filled by the top half,
     * and prints it to the circular text buffer, which is then consumed
     * by reading processes

    /* First write the number of interrupts that occurred before this bh */
    written = sprintf((char *)short_head,"bh after %6i\n",savecount);
    short_incr_bp(&short_head, written);

     * Then, write the time values. Write exactly 16 bytes at a time,
     * so it aligns with PAGE_SIZE

    do {
        written = sprintf((char *)short_head,"%08u.%06u\n",
                (int)(tv_tail->tv_sec % 100000000),
        short_incr_bp(&short_head, written);
    } while (tv_tail != tv_head);

    wake_up_interruptible(&short_queue); /* awake any reading process */

Among other things, this tasklet makes a note of how many interrupts have arrived since it was last called. A device such as short can generate a great many interrupts in a brief period, so it is not uncommon for several to arrive before the bottom half is executed. Drivers must always be prepared for this possibility and must be able to determine how much work there is to perform from the information left by the top half.


Recall that workqueues invoke a function at some future time in the context of a special worker process. Since the workqueue function runs in process context, it can sleep if need be. You cannot, however, copy data into user space from a workqueue, the worker process does not have access to any other process’s address space.

The short driver, if loaded with the wq option set to a nonzero value, uses a workqueue for its bottom-half processing. It uses the system default workqueue, so there is no special setup code required; if your driver has special latency requirements (or might sleep for a long time in the workqueue function), you may want to create your own, dedicated workqueue. We do need a work_struct structure, which is declared and initialized with the following:

static struct work_struct short_wq;

    /* this line is in short_init(  ) */
    INIT_WORK(&short_wq, (void (*)(void *)) short_do_tasklet, NULL);


Our worker function is short_do_tasklet, which we have already seen in the previous section.

When working with a workqueue, short establishes yet another interrupt handler that looks like this:

irqreturn_t short_wq_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    /* Grab the current time information. */
    do_gettimeofday((struct timeval *) tv_head);

    /* Queue the bh. Don't worry about multiple enqueueing */

    short_wq_count++; /* record that an interrupt arrived */
    return IRQ_HANDLED;