Posts

Showing posts from March, 2012

POSIX thread programming

Introduction: Using thread has many benefits. They share the same resources of their calling process (parent process), like global variables, open files and so on. Also they have their own thread ID, stacks, and so on. For more information, please refer to the old article "Multitasking in Embedded Linux" and reference [1]. Here we focus on how to use it. The simplest thread programming: #include <stdio.h> #include <stdlib.h> #include <pthread.h> void *print_message(void *ptr) {     char *text;     text=(char *)ptr;     printf("%s \n", text); } main() {     pthread_t thread1, thread2;     char *str1="I am thread1";     char *str2="I am thread2";     int T1ret, T2ret;     /*Create two threads*/     T1ret=pthread_create(&thread1, NULL, print_message, (void*) str1);     T2ret=pthread_create(...

Multitasking in Embedded Linux

Multitasking in Embedded Linux In the computer field, "task" has the sense of a  real-time  application, as  distinguished from process , which  takes up   space (memory), and execution time.  A process, or task, can be seen as a set of allocated resources Process switching makes big memory consumption. Because, when we created a new process, we need to create a process descriptor and allocate another memory region as its work space. However, Thread allows you use the same memory in a process to work on, so you don't need to create an extra memory. So real-time linux use just one main process which includes threads to realize multitasking in embedded linux. But there's more. Threads also happen to be extremely   nimble . Compared to a standard fork(), they carry a lot less overhead. The kernel does not need to make a new independent copy of the process memory space, file descriptors, etc. That saves a lot of...

How to create process in Linux

 In Linux, we use  fork( )  to create a new process which is actually  a copy of the calling process . The new process is a copy ( the code after fork( ) function ) of its parent  process. So if we do nothing about control flow, the child process will actually do the same thing the parent does. Here we use the  return value of fork( )  to distinguish the child and parent. In fact, the function  fork( )  returns  two values  after it finishes.  For the calling process (parent process), it returns the PID of child process in order that the calling process can manage it . However in  child process, fork() will return 0 . So by this, we can just use a " if(chpid) " to distinguish the twos and make them execute the different sequences. Another very important thing is the fork only copy the code after the for( ) function. It does not care about the code above is except the definition part of variables. #include <stdio.h...

Anonymous pipe and Named pipe

Image
Introduction : Anonymous pipe and Named pipe are usually used for communication between two different tasks. Anonymous pipe : It does not have name, and can be applied in the shell by using ' | '. It is unidirectional. For example,  p1 | p2 Here anonymous pipe usually is used in case of standard output and standard input which are related to the shell. So here you can use anonymous pipe ' | ' directly to transfer data from p1 to p2. So here must remember that  the output and input are both for shell which means usually using functions printf() for output and scanf() for input or something like this. Named pipe: However, named pipe is related to a dev file which is more flexible. So in this case, you can transfer the data like writing/reading to/from file which is already familiar to you. We can create a pipe by using  mkfifo /dev/mypipe  where  mkfifo  is a new command, and in some old version of Linux you may use  mknod p /dev/myp...

Principle of Floating point

Image
Introduction: Compared to fixed point arithmetic, floating point allows us to use both larger scope of integer and fraction in a expression because of the floating exponent.  A floating point memory block is composed of  sign flag ,  exponent(2^e)  and  mantissa . The format is shown below. 64-bit floating point (double) 32-bit floating point (float) We need the exponent part to be signed, so the compiler will subtract the q with a bias. The calculations are shown below. e=q-bias The number the format above represents is: Here you must remember it is  1.M  which is we call "significant figure" (有效数字). So when you do the some arithmetics, you have to ensure you shif the number to keep there is a  "1"  in the left of  " . " . Precision of floating point: Because the significant digits(有效数字) only have sizeof(M) bits, so the  precision of floating point  is only 2^(-sizeof(M)-...

Magic of union

" union " is very useful C type which allows you to share  the same memory block  when using  different types of variables . Although, the types of variable is different, but the content of the memory they share is the same. So by this way you can "read" the content by using shift and " & " operator if the content is formated and assigned by compiler. Anyway, just remember " union " makes its members share the same memory block, and the size of memory block depends on the longest member. The following is an example to show how to use " union " to transfer floating point to binary. #include <stdio.h> union ufloat /*here we share the unsigned integer and float variable in the same location*/ {      float   f;      unsigned   int   i ; }; void print_float ( float a ) {      char   bin[ 32 ]={ 0 };   ...

Digital system design flow

Image
Specification : We need to define the requirements and implementation constraints of our system like we design a software architecture.  High-Level Design : We need to define the top-level architecture, which includes the modules needed in the design and how they communicate with each other. Low-Level Design : Each module in this stage should be implemented using simple design components like memories, regsisters, state machines, etc. HDL Coding : Here we need to use HDL to write code to implement the low-level design. Here HDL code must be synthesisable. Functional Simulation : Here we use the software simulator to test if the HDL design does the right things which are required by the specification. Synthesis : After the simulation verified the design complete the requirement by specification, then map the HDL design to the target technology primitives, initial timing info is obtained. Placement & Routing : Here all the primitives...