Embedded Systems Software, Computer Networking and Geeky Fun

nerd1951.com

January 28, 2009

Using the Linux select() function for embedded systems

Filed under: Projects, Programming — Harvey @ 12:40 am

A couple of years ago I gave a presentation at the Embedded Systems Conference about implementing communications protocols in C++. One of the main themes in my talk was avoiding context switch because of its high cost. This is especially important in embedded Linux. The computational costs for context switching are high whether you are using processes or pthreads.

The primary reason for using embedded Linux is for network centric applications. One of the Linux Kernel’s biggest advantages is its reliable and efficient TCP/IP network stack. If you’re using Linux in an embedded system and networking isn’t a big part of your application you need to make sure you have another compelling reason for incurring the costs of a Linux kernel.

Linux provides an elegant mechanism for simulating multitasking for network applications. This is the select() function. For those who are not familiar with the select() function, it allows you to wait on events on multiple file descriptors. This might not seem too interesting unless you realize that network sockets are file descriptors. You can also write drivers for your specialized hardware that emulate file I/O so that you can create file descriptors for your application specific hardware devices.

The select() function works on three sets of file descriptors: read, write, and exception. You can also pass a timeout value to select allowing execution of periodic tasks. The main loop for an application that uses select() looks something like this:

Do forever:

Initialize the timeout
Initialize the File Descriptor Lists

Call select

Check for file descriptors in each list that are ready for servicing.
Determine if the time interval for periodic tasks has elapsed.

End do

In addition to the select() function, Linux provides macros for clearing, building file descriptor lists. There is also a macro to check which of the file descriptors are ready after select() returns.

The select() function is commonly used in implementing all kinds of network servers from Web servers to SNMP. The Linux man pages select(2) and select_tut(2) are very complete if a little overwhelming. On the Web, the world of select is a good starting point. If you want to look at a real world example that’s not too complicated, the boa web server is a good example.

• • •
 

January 20, 2009

Processor price vs. cost

Filed under: Rants — harvey.sugar @ 1:45 pm

There can be a big difference between the cost of choosing a processor or micro-controller and its price. That might sound counterintuitive but the total cost of using a particular processor includes much more than its piece-price. These additional costs include the cost of development tools, the RTOS if you are using one, and software especially development time. The software development time can also have a significant impact on a product’s time-to-market. I’ve work on many products where the cost of time-to-market in terms of lost sales far out-weighed component costs. The product quantities, tool costs, time-to-market, and software complexity must all be considered in determining the most cost effective processor.

The software team needs to be involved in processor selection as much as the hardware engineers. Some hardware engineers have a narrow view of processor costs; limited to the component cost for the processor and support components. I have seen projects where choosing the wrong micro-controller cost man-months of development time because the processor had a small address space and the memory had to be bank-switched, or the internal RAM was too small and variables had to be copied in and out of the internal RAM as needed.

Sometimes the hidden costs are in the development tools. Some processors are only supported by expensive proprietary tool sets. In others cases the only tools available provided a nonstandard subset of the C language. One well known micro-controller family is supported by a C compiler that can’t even link multiple object files. If you want to write modular code you have to divide your code into several include files that are basically compiled and linked as one single source file.

Another risk is thinking too small. You should be very careful about using small eight bit micro-controllers unless you are developing a product that will be produced in quantities of thousands per year and every penny of component costs is critical. There are so many low cost low power 16 bit and 32 bit processors out there that there’s no excuse for using under-powered processors for short-run or one-off embedded systems. Some examples are the ARM families, TI’s 403, Atmel’s 32 bit AVR, Frescale’s ColdFire, and Analog Devices’ Blackfin. Most of these processors have wide support from a number of software tool vendors as well as GNU open source tool support.

The tradeoffs in choosing the best processor for a product are more complex than the component costs. Engineering is often the art of compromise and choosing the most cost effecting processor is a compromise between component prices and development costs.

• • •