Update posts

This commit is contained in:
Sanchayan Maity 2017-06-10 17:43:43 +05:30
parent 1ab28e7dce
commit f5abafef3f
28 changed files with 247 additions and 227 deletions

View File

@ -6,7 +6,7 @@ tags: CGI, SSI, lwip, Stellaris
<p style='text-align: justify;'>CGI stands for Common Gateway Interface and SSI stands for Server Side Include. The below post is going to be about, how to use them with lwip for employing web page interface in your embedded system.</p>
<p style='text-align: justify;'>First, i would like to give some clarification. My work on the above was build up over and above the enet_io example code provided by Texas Instruments with their Stellaris LM3S6965 boards. My main aim of this post is to help you in understanding the code flow and is very specific to the example provided. I have not done any work in porting lwip nor written this application from ground up.</p>
<p style='text-align: justify;'>First, I would like to give some clarification. My work on the above was build up over and above the enet_io example code provided by Texas Instruments with their Stellaris LM3S6965 boards. My main aim of this post is to help you in understanding the code flow and is very specific to the example provided. I have not done any work in porting lwip nor written this application from ground up.</p>
So let's get started.
@ -16,14 +16,28 @@ So let's get started.
1. SSI Server Side Includes (Displaying data on web page)
<p style='text-align: justify;'>When a web page request is sent from a browser to your embedded system, which has got lwip configured with CGI and SSI, if any SSI tag is present on the web page being served, the SSI handler is called. These handlers are registered with a call to the function http_set_ssi_handler(SSIHandler, g_pcConfigSSITags, NUM_CONFIG_SSI_TAGS), where SSIHandler is the function which gets called, when the web page is served containing SSI tags. g_pcConfigSSITags is an array containing the list of SSI tags. These names you will find in the html code of the web page and in the program code file  enet_io.c.  NUM_CONFIG_SSI_TAGS is the number of individual SSI tags, the http server can expect to find.</p>
<p style='text-align: justify;'>When a web page request is sent from a browser to your embedded system, which has got lwip configured with CGI and SSI, if any SSI tag is present on the web page being served, the SSI handler is called. These handlers are registered with a call to the function</p>
<p style='text-align: justify;'>To understand what i said, let me take you through the enet_io code. Open the folder fs in the code directory, and open the htm web page with a web brower.  In the web page, the SSI tag corresponding to this, can be found in I/O Control Demo2 link. Use view source, by right clicking on the web page. The SSI tag will be like <!--#PWMfreq-->. In the g_pcConfigSSITags array, you will see "PWMfreq". So, whenever the system is serving this web page, as there is an occurrence of an SSI tag, the SSI handler is called, and the value of PWMfreq is substituted by the actual value. In the SSI handler, you will find something like below,</p>
```c
http_set_ssi_handler(SSIHandler, g_pcConfigSSITags, NUM_CONFIG_SSI_TAGS)
```
<p style='text-align: justify;'>where SSIHandler is the function which gets called, when the web page is served containing SSI tags. g_pcConfigSSITags is an array containing the list of SSI tags. These names you will find in the html code of the web page and in the program code file  enet_io.c.  NUM_CONFIG_SSI_TAGS is the number of individual SSI tags, the http server can expect to find.</p>
<p style='text-align: justify;'>To understand what I said, let me take you through the enet_io code. Open the folder fs in the code directory, and open the htm web page with a web browser. In the web page, the SSI tag corresponding to this, can be found in I/O Control Demo2 link. Use view source, by right clicking on the web page. The SSI tag will be like</p>
```c
<!--#PWMfreq-->
```
In the g_pcConfigSSITags array, you will see "PWMfreq". So, whenever the system is serving this web page, as there is an occurrence of an SSI tag, the SSI handler is called, and the value of PWMfreq is substituted by the actual value. In the SSI handler, you will find something like below,</p>
```c
case SSI_INDEX_PWMFREQ:
ulVal = io_get_pwmfreq();
usnprintf(pcInsert, iInsertLen, "%d", ulVal);
break;
```
<p style='text-align: justify;'>When the user requests the web page, on seeing the occurence of the SSI tag, the SSI handler gets called, the case corresponding to PWMFreq, is selected and executed, the io_get_pwmfreq() returns the value of pwm frequency on the system, and this is inserted in the web page by usnprintf function. This gets done for each SSI tag in the web page. In case, you have defined a tag on the web page, but, not written a corresponding entry in the tags array and the handler, you will get an error on the web page, complaining no tag found.</p>
@ -31,8 +45,20 @@ break;
2. CGI Common Gateway Interface (Sending data to the system)
<p style='text-align: justify;'>Lets say you enter a new value of PWM frequency and click on Update Settings. On clicking, just check what url is displayed on the address bar of your browser. I entered a value of 50 for PWM frequency and the url changed to "file:///C:/StellarisWare/boards/ek-lm3s6965/enet_io/fs/iocontrol.cgi?LEDOn=1&PWMFrequency=50&PWMDutyCycle=100&Update=Update+Settings". ( N.B. I was not connected to the board while writing this and executed it from my local drive, so the file url). You can see, how the value of 50 was appended and send to the system. Also, notice the iocontrol.cgi in the url. This is defined along with the corresponding CGI handler in the g_psConfigCGIURIs array. When your board, receives this web page request, the lwip stack knows which function to call. The handlers are registered with a call to http_set_cgi_handlers(g_psConfigCGIURIs, NUM_CONFIG_CGI_URIS).  In the corresponding CGI handler, the parameters are extracted from the URL, by FindCGIParameter function and GetCGIParam function, and the functions are called for setting these values.</p>
<p style='text-align: justify;'>Lets say you enter a new value of PWM frequency and click on Update Settings. On clicking, just check what url is displayed on the address bar of your browser. I entered a value of 50 for PWM frequency and the url changed to</p>
```c
file:///C:/StellarisWare/boards/ek-lm3s6965/enet_io/fs/iocontrol.cgi?LEDOn=1&PWMFrequency=50&PWMDutyCycle=100&Update=Update+Settings"
```
<p style='text-align: justify;'>Note that I was not connected to the board while writing this and executed it from my local drive, so the file url). You can see, how the value of 50 was appended and send to the system. Also, notice the iocontrol.cgi in the url. This is defined along with the corresponding CGI handler in the g_psConfigCGIURIs array. When your board, receives this web page request, the lwip stack knows which function to call. The handlers are registered with a call to
```c
http_set_cgi_handlers(g_psConfigCGIURIs, NUM_CONFIG_CGI_URIS).
```
<p style='text-align: justify;'>In the corresponding CGI handler, the parameters are extracted from the URL, by FindCGIParameter function and GetCGIParam function, and the functions are called for setting these values.</p>
<p style='text-align: justify;'>This is how data gets passed to the system using CGI through web pages.</p>
<p style='text-align: justify;'>I hope, I was able to at least clear a little bit for you to start off on your own and make changes you want. In case, i missed something, do post a comment and I will try to help you out.</p>
<p style='text-align: justify;'>I hope, I was able to at least clear a little bit for you to start off on your own and make changes you want. In case, I missed something, do post a comment and I will try to help you out.</p>

View File

@ -4,9 +4,9 @@ title: Debugging a hard fault in ARM Cortex M3
tags: ARM Cortex M3, Hard Fault, Stellaris
---
<p style='text-align: justify;'>I have been working on the Stellaris LM3S6965 for quiet a while now. So i thought, may be i will put my learning's in one place, so others can use them and not get stuck, where i did.</p>
<p style='text-align: justify;'>I have been working on the Stellaris LM3S6965 for quiet a while now. So I thought, may be I will put my learning's in one place, so others can use them and not get stuck, where I did.</p>
<p style='text-align: justify;'>The Stellaris LM3S6965 is based on the ARM Cortex M3 architecture. What i am going to mention in my post, is how to track down the source of a hard fault. So let's get straight to the point.</p>
<p style='text-align: justify;'>The Stellaris LM3S6965 is based on the ARM Cortex M3 architecture. What I am going to mention in my post, is how to track down the source of a hard fault. So let's get straight to the point.</p>
<p style='text-align: justify;'>On getting a hard fault, check the value of MSP and PSP viz. the stack pointers. It's likely the MSP, if you are not using an RTOS.</p>
@ -14,7 +14,7 @@ tags: ARM Cortex M3, Hard Fault, Stellaris
Registers ro - r3, r12, lr, pc, xpsr.
<p style='text-align: justify;'>One thing i must mention is, if your fault handler does something other than spinning in a loop, a couple of other registers might be pushed on to the stack by the compiler. You need to take care of this. I am assuming here, that the default fault handler does nothing else besides spinning in a loop.</p>
<p style='text-align: justify;'>One thing I must mention is, if your fault handler does something other than spinning in a loop, a couple of other registers might be pushed on to the stack by the compiler. You need to take care of this. I am assuming here, that the default fault handler does nothing else besides spinning in a loop.</p>
<p style='text-align: justify;'>So take a look at the stack. The pushed PC should help you in debugging, as it usually points to the instruction that caused the fault.</p>

View File

@ -6,18 +6,19 @@ tags: lwip
<p style='text-align: justify;'>LWIP stands for Lightweight Internet Protocol stack and was developed by Adum Dunkels at the Swedish Institute Of Computer Science. It is open source TCP/IP stack designed mainly for embedded systems and written in C.</p>
<p style='text-align: justify;'>Today, i will give you guys a sample code for implementing TCP/IP echo server. The assumption is that, you have lwip already ported to your controller. So, here is the code.</p>
<p style='text-align: justify;'>Today, I will give you guys a sample code for implementing TCP/IP echo server. The assumption is that, you have lwip already ported to your controller. So, here is the code.</p>
{% highlight c %}
```c
char tcp_buffer[1024];
static void close_conn (struct tcp_pcb *pcb )
static void close_conn (struct tcp_pcb *pcb)
{
tcp_arg(pcb, NULL);
tcp_sent(pcb, NULL);
tcp_recv(pcb, NULL);
tcp_close(pcb);
}
static err_t echo_recv( void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err )
static err_t echo_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
int i;
int len;
@ -51,13 +52,14 @@ static err_t echo_recv( void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t er
}
if( err == ERR_OK && p == NULL )
  {
{
close_conn( pcb );
}
return ERR_OK;
}
static err_t echo_accept(void *arg, struct tcp_pcb *pcb, err_t err )
static err_t echo_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
LWIP_UNUSED_ARG( arg );
LWIP_UNUSED_ARG( err );
@ -67,7 +69,8 @@ static err_t echo_accept(void *arg, struct tcp_pcb *pcb, err_t err )
tcp_poll( pcb, NULL, 4 );
return ERR_OK;
}
void tcp_init( void )
void tcp_init(void)
{
struct tcp_pcb *tcp_pcb;
tcp_pcb = tcp_new();
@ -76,7 +79,7 @@ void tcp_init( void )
tcp_pcb = tcp_listen( tcp_pcb );
tcp_accept( tcp_pcb, echo_accept );
}
{% endhighlight %}
```
<p style='text-align: justify;'>Instructions for use:</p>

View File

@ -10,7 +10,7 @@ Before I start, let me mention a few things which I am assuming.
2. You are connected over a serial link to the BB - xM and are doing all operations from the terminal.
<p style='text-align: justify;'>Get the Angstrom Image from the below link and set up the SD card as per  the instructions given.</p>
<p style='text-align: justify;'>Get the Angstrom Image from the below link and set up the SD card as per the instructions given.</p>
[http://elinux.org/Getting_a_Workshop_SD_Image](http://elinux.org/Getting_a_Workshop_SD_Image)
@ -18,11 +18,11 @@ Before I start, let me mention a few things which I am assuming.
<p style='text-align: justify;'>After setting up the SD card, transfer an image in which you want faces to be detected. This image you can transfer to the /home/root directory in the root filesystem on the SD card.</p>
<p style='text-align: justify;'>Plug the SD card and boot up. The board will boot up and you will get the login prompt. Log in using root as the password, after which, you will be placed in the /home/root directory. This is the reason i told you to copy the image in this particular directory.</p>
<p style='text-align: justify;'>Plug the SD card and boot up. The board will boot up and you will get the login prompt. Log in using root as the password, after which, you will be placed in the /home/root directory. This is the reason I told you to copy the image in this particular directory.</p>
<p style='text-align: justify;'>Use vi and open up a file faces.c by typing "vi faces.c" on the command line. Write the below code in it.</p>
{% highlight c %}
```c
#include <opencv/cv.h>
#include <opencv/cxcore.h>
#include "stdio.h"
@ -67,19 +67,22 @@ int main(void)
return 0;
}{% endhighlight %}
}
```
After saving the above program, compile it using the command:
`arm-angstrom-linux-gnueabi-gcc   faces.c   /usr/lib/libopencv_*.so   -o   faces`
```bash
$ arm-angstrom-linux-gnueabi-gcc faces.c /usr/lib/libopencv_*.so -o faces
```
<p style='text-align: justify;'>I have mentioned /usr/lib/libopencv_*.so on the command line, as the compiler would then dynamically link all the OpenCV library files against this code.</p>
<p style='text-align: justify;'>This will create a executable called faces. Run it from the command line by typing "./faces". The code would run and print the number of faces detected in the image on the command line.</p>
<p style='text-align: justify;'>I didn't have a HDMI to DVI-D cable to connect my monitor to the board, so i printed the output on the command line. If you can connect a monitor, use the functions from the highgui library, and you can display your output on the monitor. You can draw rectangles around the faces detected.</p>
<p style='text-align: justify;'>I didn't have a HDMI to DVI-D cable to connect my monitor to the board, so I printed the output on the command line. If you can connect a monitor, use the functions from the highgui library, and you can display your output on the monitor. You can draw rectangles around the faces detected.</p>
<p style='text-align: justify;'>I am currently working on face detection in video and facing a few glitches, but, i will post it when i am successful.</p>
<p style='text-align: justify;'>I am currently working on face detection in video and facing a few glitches, but, I will post it when I am successful.</p>
<p style='text-align: justify;'>To learn what the functions actually do, refer to the OpenCV 2.2 C reference on the below link.</p>

View File

@ -4,13 +4,13 @@ title: Best books for Electronics Engineering
tags: books
---
<p style='text-align: justify;'>In this blog post, i am going to mention some of the best books, i have come across for learning the basic core subjects in Electronics. So, without wasting any more time, here is the list. A disclaimer first though.</p>
<p style='text-align: justify;'>In this blog post, I am going to mention some of the best books, I have come across for learning the basic core subjects in Electronics. So, without wasting any more time, here is the list. A disclaimer first though.</p>
**Disclaimer**:
<p style='text-align: justify;'>1. If you are looking to just pass the exams, then this post is not for you. Read your useless notes and local author books. The below books are for knowledge seekers, not for dumb future managers. The below post is not for you. It's for those, who want to learn for the sake of learning, for those who find it fun and like to know how things work.</p>
<p style='text-align: justify;'>2.I have not read all the books completely from start to end, but, i have tried to read most of it. During my college days, i simply could not manage to prepare for exams properly, while, also learning through those books. I have started though, to read the books, one by one and have kept myself an aim of reading each of them completely.</p>
<p style='text-align: justify;'>2. I have not read all the books completely from start to end, but, I have tried to read most of it. During my college days, I simply could not manage to prepare for exams properly, while, also learning through those books. I have started though, to read the books, one by one and have kept myself an aim of reading each of them completely.</p>
<p style='text-align: justify;'>If you live in India and can't find those books at your local bookshop, use flipkart for getting them.</p>
@ -52,13 +52,13 @@ The Art Of Electronics by Paul Horowitz
<p style='text-align: justify;'>If you really love analog, go for Analysis and Design of Analog Integrated Circuits by Paul Grey, Paul Hurst, Stephen Lewis and Robert Meyer.</p>
<p style='text-align: justify;'>I am going to express my rants again. I wish, i had never referred the local author J S Katre's book. His books are a piece of shit. During my first two years of engineering, i felt disappointed and lost. Got carried away by the senior's and peer talks of reference and foreign author books being difficult to read. It's the exact opposite. The books are so good and they explain things properly. I had this mental block in my head and found Neamen's book pretty tough to read, when i first read it. Never touched it again, till, after the end of fourth semester. I had failed in Digital Design during third semester, not having studied anything. As an experiment, i bought Digital Design by John Wakerley and read it. I did it just for the heck of it. I realized, that it was simple and easy to read from those books. So simple and precisely clear. The topic on logic families was handled so effortlessly in that. After the end of fourth semester, in vacations, i took up the book by Donald Neamen. At once, i realized my mistake. So, if you are reading this, and like to learn, refer good books. Don't listen to your seniors and peers, who will tell you otherwise. They are losers. Go get good books.</p>
<p style='text-align: justify;'>I am going to express my rants again. I wish, I had never referred the local author J S Katre's book. His books are a piece of shit. During my first two years of engineering, I felt disappointed and lost. Got carried away by the senior's and peer talks of reference and foreign author books being difficult to read. It's the exact opposite. The books are so good and they explain things properly. I had this mental block in my head and found Neamen's book pretty tough to read, when I first read it. Never touched it again, till, after the end of fourth semester. I had failed in Digital Design during third semester, not having studied anything. As an experiment, I bought Digital Design by John Wakerley and read it. I did it just for the heck of it. I realized, that it was simple and easy to read from those books. So simple and precisely clear. The topic on logic families was handled so effortlessly in that. After the end of fourth semester, in vacations, I took up the book by Donald Neamen. At once, I realized my mistake. So, if you are reading this, and like to learn, refer good books. Don't listen to your seniors and peers, who will tell you otherwise. They are losers. Go get good books.</p>
**6. Communications**
Modern Analog and Digital Communication by B. P. Lathi
<p style='text-align: justify;'>This has got to be one of the best books i have ever read. He explains concepts through mathematics as well as simple intuitive explanations. For the first time, this book made me realize, why having a good grasp of a language is essential. The English is plain and simple, yet, precise and clear. His full name is Bhagvandas Pannalal Lathi. Did his Bachelors from a Pune University and Master's from Oxford. I never expected such a good book from an Indian author. His book is an example of how all beginner to intermediate level texts should be written. The book covers Analog and Digital Communication thoroughly well. Also, this book makes it quiet clear of why Signals and Systems should be covered first, before teaching analog communication concepts and why Probability and Random Processes should be taught before teaching Digital Communication. Fucking Mumbai University teaches Analog communication first, before Signals and Systems and does not teach Probability and Random Processes before Digital Communication. Fucking idiots!!.</p>
<p style='text-align: justify;'>This has got to be one of the best books I have ever read. He explains concepts through mathematics as well as simple intuitive explanations. For the first time, this book made me realize, why having a good grasp of a language is essential. The English is plain and simple, yet, precise and clear. His full name is Bhagvandas Pannalal Lathi. Did his Bachelors from a Pune University and Master's from Oxford. I never expected such a good book from an Indian author. His book is an example of how all beginner to intermediate level texts should be written. The book covers Analog and Digital Communication thoroughly well. Also, this book makes it quiet clear of why Signals and Systems should be covered first, before teaching analog communication concepts and why Probability and Random Processes should be taught before teaching Digital Communication. Fucking Mumbai University teaches Analog communication first, before Signals and Systems and does not teach Probability and Random Processes before Digital Communication. Fucking idiots!!.</p>
**7. Signals and Systems**
@ -100,6 +100,6 @@ Digital Integrated Circuits A Design Perspective by Jan Rabaey
**12. Filter Design**
<p style='text-align: justify;'>Sorry, haven't come across a good book myself for this subject. Have been looking through various suggestions on the net. Will post when i get around to reading one.</p>
<p style='text-align: justify;'>Sorry, haven't come across a good book myself for this subject. Have been looking through various suggestions on the net. Will post when I get around to reading one.</p>
<p style='text-align: justify;'>hese are some of the best books for electronics, i have come across. The list is by no means exhaustive and there may be a lot of other good books for the subjects.</p>
<p style='text-align: justify;'>These are some of the best books for electronics, I have come across. The list is by no means exhaustive and there may be a lot of other good books for the subjects.</p>

View File

@ -4,9 +4,9 @@ title: Learning the importance of PCB Design - My experience
tags: hardware
---
<p style='text-align: justify;'>I don't know about the education system of other countries, but, in India, it's funny how most engineering colleges never bother to teach concepts and application of the concepts to practical real world problems. Though it very well may be the same in other countries as well, from what i have been reading about the state of education, even in countries like the US.</p>
<p style='text-align: justify;'>I don't know about the education system of other countries, but, in India, it's funny how most engineering colleges never bother to teach concepts and application of the concepts to practical real world problems. Though it very well may be the same in other countries as well, from what I have been reading about the state of education, even in countries like the US.</p>
<p style='text-align: justify;'>During my engineering college days, one of the most difficult subject for me to understand was Electromagnetics. I never thought that, one day, it would be the subject that would interest me the most and i would come across it's application in such a way, as i am soon going to tell you about.</p>
<p style='text-align: justify;'>During my engineering college days, one of the most difficult subject for me to understand was Electromagnetics. I never thought that, one day, it would be the subject that would interest me the most and I would come across it's application in such a way, as I am soon going to tell you about.</p>
<p style='text-align: justify;'>I was working on a system which used a 10/100 Mbps Ethernet connection for communication with the external world and for exchanging data. I designed the system, it was not a tough one, but, it had this one high speed interface. My understanding prior to first encountering failure on this project, was that on a Printed Circuit Board, a connection between Point A and Point B, is just a simple copper track laid out on the board. I made the schematics and send them to our local third party vendor. The vendor was just a regular run of the mill local guy, who didn't have any idea about such things, well neither did any of my seniors had any idea nor I. That vendor just tried to do the routing using the auto routing facility available in most PCB Design software these days like the PADS tool by Mentor Graphics. If that didn't work out properly, he would do the routing himself, trying to fit the tracks on the PCB properly.</p>
@ -40,7 +40,7 @@ Level III. PCB Design
<p style='text-align: justify;'>The first one is for beginners and doesn't require high level math or calculus. A must read for all embedded engineers. The second one is detailed and dives into PCB design from a mathematical and detailed theorotical point of view and requires knowledge of vectors and calculus.</p>
<p style='text-align: justify;'>An advanced book is available for the first one, but, no low price edition available in India. Another book by Eric Bogatin is also available, but, again no low price edition available in India. I mentioned the second book, because, i managed to get hold of a PDF for it. Now, i don't want to support piracy, but, since i couldn't lay my hands on any Signal Integrity book for under 5K, i had no other choice. That book is very good and a must read though. All specialised books happen to be so expensive or difficult to find in India. If any of the authors or book publishers come across this post, a sincere request to you, please make a low price edition available. Paying 5 grand for a book is a bit too much, though, i can afford it!</p>
<p style='text-align: justify;'>An advanced book is available for the first one, but, no low price edition available in India. Another book by Eric Bogatin is also available, but, again no low price edition available in India. I mentioned the second book, because, I managed to get hold of a PDF for it. Now, I don't want to support piracy, but, since I couldn't lay my hands on any Signal Integrity book for under 5K, I had no other choice. That book is very good and a must read though. All specialised books happen to be so expensive or difficult to find in India. If any of the authors or book publishers come across this post, a sincere request to you, please make a low price edition available. Paying 5 grand for a book is a bit too much, though, I can afford it!</p>
Blogs

View File

@ -4,7 +4,7 @@ title: A little something on Linux Device Drivers
tags: device drivers, linux
---
<p style='text-align: justify;'>I have been struggling for a while now, trying to learn device drivers and system programming in Linux. One of the many questions i had was, how does the CPU using the Linux kernel know, which devices are present and what are the drivers for them. The answer to this question is through "Platform Device and Platform Data". Though soon enough, you may find them obsolete as Linux very well might completely start using Device Trees. Below, are a few links from which you can learn about the Platform Device API and Device Tree.</p>
<p style='text-align: justify;'>I have been struggling for a while now, trying to learn device drivers and system programming in Linux. One of the many questions I had was, how does the CPU using the Linux kernel know, which devices are present and what are the drivers for them. The answer to this question is through "Platform Device and Platform Data". Though soon enough, you may find them obsolete as Linux very well might completely start using Device Trees. Below, are a few links from which you can learn about the Platform Device API and Device Tree.</p>
[http://lwn.net/Articles/448499/](http://lwn.net/Articles/448499/)

View File

@ -12,14 +12,14 @@ tags: audio, PWM
<p style='text-align: justify;'>Use the array generated from above in your code.</p>
<p style='text-align: justify;'>A few assumptions first, before we begin. The .wav file you have  uses 8Ksps and has 8 bits per sample.</p>
<p style='text-align: justify;'>A few assumptions first, before we begin. The .wav file you have uses 8Ksps and has 8 bits per sample.</p>
<p style='text-align: justify;'>For adequate filtering purposes, the PWM frequency has to be preferably ten times the highest voice frequency present in the sample. Although the audio frequency range is from 20 Hz to 20 KHz, the range of 20 Hz to 3400 Hz is enough for most purposes. So, let's set the PWM frequency at 40 KHz. Now, the playback rate has to match the sampling frequency rate. This implies that, before changing the duty cycle of the wave being generated, using the next value in the array, three samples have to be inserted in between the current sample and the next sample. These samples can be kept the same as the present sample or can be generated using interpolation. Using interpolation improves the sound quality and reduces distortion.  For the next part, let's assume you have managed to successfully generate the PWM wave.</p>
<p style='text-align: justify;'>For adequate filtering purposes, the PWM frequency has to be preferably ten times the highest voice frequency present in the sample. Although the audio frequency range is from 20 Hz to 20 KHz, the range of 20 Hz to 3400 Hz is enough for most purposes. So, let's set the PWM frequency at 40 KHz. Now, the playback rate has to match the sampling frequency rate. This implies that, before changing the duty cycle of the wave being generated, using the next value in the array, three samples have to be inserted in between the current sample and the next sample. These samples can be kept the same as the present sample or can be generated using interpolation. Using interpolation improves the sound quality and reduces distortion. For the next part, let's assume you have managed to successfully generate the PWM wave.</p>
<p style='text-align: justify;'>Next comes the filter. The filter becomes easy to design, due to the wide seperation between the PWM frequency and the frequency range of interest. One can design a filter using software tools like FilterPro provided by Texas Instruments. The higher the order of the filter, the better the audio output generated by the filter. For the filter, one can keep a passband frequency of 4 KHz and a stopband frequency of 5.6 KHz. Keeping the allowed ripple in the passband at 0.5 dB and a stopband attenuation at -45 dB would give a four stage, eigth order filter. Keeping an allowed ripple of 0.5 dB, allows us to use the Chebysev response, for achieving a sharper cut off. Using a Butterworth response, would not give a sharp enough cut off. If you are using FilterPro, try and see what happens if you change those parameters. For example, what happens, if i make the stopband frequency have a value of 5 KHz?</p>
<p style='text-align: justify;'>Next comes the filter. The filter becomes easy to design, due to the wide seperation between the PWM frequency and the frequency range of interest. One can design a filter using software tools like FilterPro provided by Texas Instruments. The higher the order of the filter, the better the audio output generated by the filter. For the filter, one can keep a passband frequency of 4 KHz and a stopband frequency of 5.6 KHz. Keeping the allowed ripple in the passband at 0.5 dB and a stopband attenuation at -45 dB would give a four stage, eigth order filter. Keeping an allowed ripple of 0.5 dB, allows us to use the Chebysev response, for achieving a sharper cut off. Using a Butterworth response, would not give a sharp enough cut off. If you are using FilterPro, try and see what happens if you change those parameters. For example, what happens, if I make the stopband frequency have a value of 5 KHz?</p>
<p style='text-align: justify;'>The filter seperates all the high frequency components and leaves us with a waveform which is a rough enough replica of the original signal of interest. You can record the output of the filter by connecting it to the microphone input of your PC and recording it with a player like Goldwave, using which you can also do some pretty cool analysis.</p>
<p style='text-align: justify;'>You might be wondering about the assumption i told you about, just in case you still didn't get it. The number of samples to be inserted in between will depend on the sampling rate. In my case, i used a PWM frequency of 40 KHz, so i inserted four samples in between. Refer the below figure. Depending upon the code you write and how you have to set up PWM for your processor, you might have to scale the values of the array and the bits per sample will be important for this scaling.</p>
<p style='text-align: justify;'>You might be wondering about the assumption I told you about, just in case you still didn't get it. The number of samples to be inserted in between will depend on the sampling rate. In my case, I used a PWM frequency of 40 KHz, so I inserted four samples in between. Refer the below figure. Depending upon the code you write and how you have to set up PWM for your processor, you might have to scale the values of the array and the bits per sample will be important for this scaling.</p>
[![](http://coherentmusings.files.wordpress.com/2012/10/playback2.jpg)](http://coherentmusings.files.wordpress.com/2012/10/playback2.jpg)

View File

@ -4,9 +4,9 @@ title: Beagleboard-xM GPIO Kernel Module Driver
tags: beagleboard, gpio driver
---
<p style='text-align: justify;'>Whenever i search for a particular implementation, of let's say GPIO, only user space implementation comes up in search results which use the sysfs interface. Being more interested in hardware and the kernel side of things, i thought i did start practicing writing some kernel module drivers. So, here is my first simple GPIO kernel module driver for the Beagleboard-xM.</p>
<p style='text-align: justify;'>Whenever i search for a particular implementation, of let's say GPIO, only user space implementation comes up in search results which use the sysfs interface. Being more interested in hardware and the kernel side of things, I thought I did start practicing writing some kernel module drivers. So, here is my first simple GPIO kernel module driver for the Beagleboard-xM.</p>
<p style='text-align: justify;'>I have set up my environment using Buildroot from the below link. I used this, because at some point i intend to use the camera module and Max Galemin has integrated those packages in his buildroot version. OpenCV 2.3.1 is supported in this buildroot, so that's a very good plus point. Set up your environment using the instructions given on the below link or i assume you can use the standard buildroot available as well.</p>
<p style='text-align: justify;'>I have set up my environment using Buildroot from the below link. I used this, because at some point I intend to use the camera module and Max Galemin has integrated those packages in his buildroot version. OpenCV 2.3.1 is supported in this buildroot, so that's a very good plus point. Set up your environment using the instructions given on the below link or I assume you can use the standard buildroot available as well.</p>
[http://blog.galemin.com/2012/03/buildroot-2012-02-for-beagleboard-xm-with-li-5m03-mt9p031-camera-support/](http://blog.galemin.com/2012/03/buildroot-2012-02-for-beagleboard-xm-with-li-5m03-mt9p031-camera-support/)
@ -14,9 +14,9 @@ tags: beagleboard, gpio driver
<p style='text-align: justify;'>Below I am posting the source code for the driver module, the user space application and the Makefile.</p>
The Driver Module:  gpio.ko
The Driver Module: gpio.ko
<pre><code>
```c
#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/init.h"
@ -26,7 +26,7 @@ The Driver Module:  gpio.ko
#include "linux/errno.h"
#include "asm/uaccess.h"
#define GPIO_NUMBER    149 //User LED 0. GPIO number 149. Page 71 of BB-xM Sys Ref Manual.
#define GPIO_NUMBER 149 //User LED 0. GPIO number 149. Page 71 of BB-xM Sys Ref Manual.
static int init_result;
@ -124,12 +124,12 @@ module_exit(cleanup_gpio);
MODULE_AUTHOR("Sanchayan");
MODULE_LICENSE("GPL");
</code></pre>
```
The User Space Application: gpio_app.c
<pre><code>
#include<stdio.h>
```c
#include <stdio.h>
#include <fcntl.h>
int main(void)
@ -163,11 +163,11 @@ int main(void)
return 0;
}
</code></pre>
```
Makefile
<pre><code>
```c
KERN_SRC=/home/vm/buildroot/output/build/linux-3.2.8
KERN_COMPILER=/opt/CodeSourcery/Sourcery_CodeBench_Lite_for_ARM_GNU_Linux/bin
@ -178,13 +178,15 @@ make -C $(KERN_SRC) ARCH=arm CROSS_COMPILE=$(KERN_COMPILER)/arm-none-linux-gnuea
clean:
make -C $(KERN_SRC) ARCH=arm CROSS_COMPILE=$(KERN_COMPILER)/arm-none-linux-gnueabi- M=`pwd` clean
</code></pre>
```
<p style='text-align: justify;'>The path for your kernel source and path for the CodeSourcery toolchain can and mostly will be different. So change them, as per your environment.</p>
<p style='text-align: justify;'>After this, compile your kernel driver module by typing "sudo make" at the command line prompt. After this, cross compile your user space application by typing</p>
`arm-none-linux-gnueabi-gcc   gpio_app.c   -o   gpio_app`
```bash
$ arm-none-linux-gnueabi-gcc gpio_app.c -o gpio_app
```
<p style='text-align: justify;'>I have assumed that the cross compiler path has been added to your path environment variable.</p>

View File

@ -4,15 +4,15 @@ title: Device node creation without using "mknod"
tags: beagleboard, gpio driver
---
<p style='text-align: justify;'>In my last post, where i showed how to write a character gpio driver, i had used mknod for device node creation. Without mknod the device files would not have been created under /dev. So, we had to manually create the device node under /dev using mknod. Now, cannot this manual work be done away with? Of course, it can be done!!.</p>
<p style='text-align: justify;'>In my last post, where I showed how to write a character gpio driver, I had used mknod for device node creation. Without mknod the device files would not have been created under /dev. So, we had to manually create the device node under /dev using mknod. Now, cannot this manual work be done away with? Of course, it can be done!!.</p>
<p style='text-align: justify;'>The automatic creation of device files can be handled with udev. One has to ensure that the major and minor numbers assigned to a device controlled by the driver are exported to user space through the sysfs interface. To know more about this, read "The Linux Device Module" chapter from the Linux Device Drivers book.</p>
<p style='text-align: justify;'>Below i am posting the source code for the driver module, the user space application and the Makefile. The user space application and Makefile remain the same. I have only changed the name of the device node under /dev from gpio to gpio_drv. So, the user space application code accordingly reflects this.</p>
<p style='text-align: justify;'>Below I am posting the source code for the driver module, the user space application and the Makefile. The user space application and Makefile remain the same. I have only changed the name of the device node under /dev from gpio to gpio_drv. So, the user space application code accordingly reflects this.</p>
**The Driver Module:**
<pre><code>
```c
#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/init.h"
@ -166,11 +166,11 @@ module_exit(cleanup_gpio);
MODULE_AUTHOR("Sanchayan");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Beagleboard-xM GPIO Driver");
</code></pre>
```
**The User Space Application:**
<pre><code>
```c
#include "stdio.h"
#include "fcntl.h"
@ -205,11 +205,11 @@ int main(void)
return 0;
}
</code></pre>
```
**Makefile:**
<pre><code>
```
# Cross compilation Makefile for ARM
KERN_SRC=/home/vm/buildroot/output/build/linux-3.2.8
@ -222,13 +222,15 @@ make -C $(KERN_SRC) ARCH=arm CROSS_COMPILE=$(KERN_COMPILER)/arm-none-linux-gnuea
clean:
make -C $(KERN_SRC) ARCH=arm CROSS_COMPILE=$(KERN_COMPILER)/arm-none-linux-gnueabi- M=`pwd` clean
</code></pre>
```
<p style='text-align: justify;'>The path for your kernel source and path for the CodeSourcery toolchain can and mostly will be different. So change them, as per your environment.</p>
<p style='text-align: justify;'>After this, compile your kernel driver module by typing “sudo make” at the command line prompt. After this, cross compile your user space application by typing</p>
`arm-none-linux-gnueabi-gcc   gpio_app.c   -o   gpio_app`
```bash
arm-none-linux-gnueabi-gcc gpio_app.c -o gpio_app
```
<p style='text-align: justify;'>I have assumed that the cross compiler path has been added to your path environment variable.</p>

View File

@ -10,7 +10,7 @@ tags: pcb design, impedance matching, hardware
<p style='text-align: justify;'>The concept of impedance mismatch will be known to anyone who has studied Transmission Lines in Electromagnetics or Microwave Engineering. Now, you might be wondering how does transmission lines come into the picture??!!.</p>
<p style='text-align: justify;'>At high frequencies, the interconnect lines do not function as simple interconnects, but, start acting as transmission lines at high frequencies. Also, if you remember control systems, at low frequencies a lumped parameter model is applicable, while at high frequencies, distributed parameter model becomes applicable. If i were to put it more simply, when the wavelength of the signal is less than the length of the interconnect on which it is propagating, you can treat them as simple interconnects and apply the lumped parameter model, meaning that you can model the behavior of the interconnect using a simple RC model. The response of a RC model is well-known to all in the field of electronics. At high frequencies, where the wavelength of the signal is less than the length of the interconnect on which it is propagating, you can no longer consider them as mere interconnects, but, the distributed parameter model becomes applicable and the transmission line concepts need to be applied now. A simple RC model will no longer suffice for modelling the behavior of interconnects.</p>
<p style='text-align: justify;'>At high frequencies, the interconnect lines do not function as simple interconnects, but, start acting as transmission lines at high frequencies. Also, if you remember control systems, at low frequencies a lumped parameter model is applicable, while at high frequencies, distributed parameter model becomes applicable. If I were to put it more simply, when the wavelength of the signal is less than the length of the interconnect on which it is propagating, you can treat them as simple interconnects and apply the lumped parameter model, meaning that you can model the behavior of the interconnect using a simple RC model. The response of a RC model is well-known to all in the field of electronics. At high frequencies, where the wavelength of the signal is less than the length of the interconnect on which it is propagating, you can no longer consider them as mere interconnects, but, the distributed parameter model becomes applicable and the transmission line concepts need to be applied now. A simple RC model will no longer suffice for modelling the behavior of interconnects.</p>
<p style='text-align: justify;'>In actual production environments and industry, PCB design and signal integrity issues like impedance mismatch are done and checked using software like PADS and Allegro. For a demonstration, I will show you how an impedance mismatch degrades signal integrity by using an example and lattice diagrams.</p>

View File

@ -6,25 +6,15 @@ tags: gtk, linux
<p style='text-align: justify;'>It's been a while since my last post in January. I shifted to Bangalore for work and took some time to get used to the new work environment and schedule. Anyways, let's get on with the topic at hand.</p>
<p style='text-align: justify;'>My current work involves a lot of GUI development on WinCE in C# and since i wanted to work on Linux, it left much to be desired. So, i thought why not do some GUI development on Linux. I could have opted for Qt and an Integrated Development Environment does speed up the work a lot and though developing GUI applications is a breeze in C#/QT with an IDE, i don't like GUI development and it becomes boring if things become too simple, like it happened with C#. So, i chose GTK+ for this task and Nano as the editor of my choice on my new Arch Linux installation to amuse myself and keep myself from getting bored.</p>
<p style='text-align: justify;'>My current work involves a lot of GUI development on WinCE in C# and since I wanted to work on Linux, it left much to be desired. So, I thought why not do some GUI development on Linux. I could have opted for Qt and an Integrated Development Environment does speed up the work a lot and though developing GUI applications is a breeze in C#/QT with an IDE, I don't like GUI development and it becomes boring if things become too simple, like it happened with C#. So, I chose GTK+ for this task and Nano as the editor of my choice on my new Arch Linux installation to amuse myself and keep myself from getting bored.</p>
<p style='text-align: justify;'>Also, on a different note, i recently tried my hands on Gentoo. For any package installation, having to download the source, compile the package and then install, turned me off it. Actually, i have wanted to contribute to the open source community for a while, and this [http://blog.dastergon.gr/get-involved-in-gentoo-linux/](http://blog.dastergon.gr/get-involved-in-gentoo-linux/) motivated me to go ahead with Gentoo, but, i was put off by the package management. I will stick with Arch.</p>
<p style='text-align: justify;'>Also, on a different note, I recently tried my hands on Gentoo. For any package installation, having to download the source, compile the package and then install, turned me off it. Actually, I have wanted to contribute to the open source community for a while, and this [http://blog.dastergon.gr/get-involved-in-gentoo-linux/](http://blog.dastergon.gr/get-involved-in-gentoo-linux/) motivated me to go ahead with Gentoo, but, I was put off by the package management. I will stick with Arch.</p>
I am using Xfce as my desktop environment in Arch Linux. At first, I was worried about having to take care of package installation and dependencies for starting with GTK programming, but, I think during the Xfce installation or something else this was taken care of.
First I just typed the below program in the Nano editor.
I am using Xfce as my desktop environment in Arch Linux. At first, i was worried about having to take care of package installation and dependencies for starting with GTK programming, but, i think during the Xfce installation or something else this was taken care of.
First i just typed the below program in the Nano editor.
{% highlight c %}
```c
#include <gtk/gtk.h>
static void hello( GtkWidget *widget, gpointer data )
@ -75,35 +65,18 @@ int main( int argc, char *argv[] )
return 0;
}
```
{% endhighlight %}
You can compile the above code by typing the following on command line.
 You can compile the above code by typing the following on command line.
{% highlight c %}
```c
gcc -o hello hello.c `pkg-config --libs --cflags gtk+-2.0`
{% endhighlight %}
After compilation, run the output file generated and see the output. I did not intend much with this tutorial, but, just wanted to share. This post is more sort of an incoherent musing and working on GUI's is boring and i can't make head or tails of how to make good user interfaces.
```
After compilation, run the output file generated and see the output. I did not intend much with this tutorial, but, just wanted to share. This post is more sort of an incoherent musing and working on GUI's is boring and I can't make head or tails of how to make good user interfaces.
You can find a detail tutorial and explanation of various functions, API's and callbacks on the GNOME development center below.
[https://developer.gnome.org/gtk-tutorial/2.24/book1.html](https://developer.gnome.org/gtk-tutorial/2.24/book1.html).
I hope to put up some articles soon on PCB design, which i have been putting off and some other stuff related to programming may be.
I hope to put up some articles soon on PCB design, which I have been putting off and some other stuff related to programming may be.

View File

@ -4,7 +4,7 @@ title: PCB Design Fundamentals - A Design Guide
tags: pcb design, hardware
---
<p style='text-align: justify;'>Recently I had the privilege to get some hands on training from one of the senior guys working at the Switzerland headquarters of our company. Till date, I had only learned about PCB design by reading books with a bit of experience coming from having dealt with PCB design vendors. It was very interesting to see the actual application of the principles i learned from someone very knowledgeable and experienced, first hand. The most interesting part of the training was the part where the concept of return paths was explained and how to take care of this while doing PCB design. It is something which i had not understood previously during my reading of books and application notes.</p>
<p style='text-align: justify;'>Recently I had the privilege to get some hands on training from one of the senior guys working at the Switzerland headquarters of our company. Till date, I had only learned about PCB design by reading books with a bit of experience coming from having dealt with PCB design vendors. It was very interesting to see the actual application of the principles I learned from someone very knowledgeable and experienced, first hand. The most interesting part of the training was the part where the concept of return paths was explained and how to take care of this while doing PCB design. It is something which I had not understood previously during my reading of books and application notes.</p>
<p style='text-align: justify;'>Rather than regurgitating what I learned and doing a shoddy job of it, I will just share the link to the design guide which my experienced colleagues have put out there for the benefit of customers of our company and others who might benefit from our products and work.</p>

View File

@ -8,6 +8,6 @@ tags: mysql, wince, amazon rds
[http://dev.mysql.com/doc/internals/en/client-server-protocol.html](http://dev.mysql.com/doc/internals/en/client-server-protocol.html)
<p style='text-align: justify;'>If I knew such a protocol document was available which gave details on how the MySQL Client and Server communicate with each other, i could have saved so much of my time and effort. Hope if anyone else out there needs a MySQL Client/Connector to communicate with the MySQL Server and if support is not available for his platform, this will be of help.</p>
<p style='text-align: justify;'>If I knew such a protocol document was available which gave details on how the MySQL Client and Server communicate with each other, I could have saved so much of my time and effort. Hope if anyone else out there needs a MySQL Client/Connector to communicate with the MySQL Server and if support is not available for his platform, this will be of help.</p>
<p style='text-align: justify;'>N.B. I hope it's implicit that you need a TCP/IP connection and need to use socket programming.</p>

View File

@ -4,13 +4,13 @@ title: Learning OpenEmbedded
tags: openembedded
---
<p style='text-align: justify;'>Recently, i was assigned a project for doing a Number Plate Recognition system on NVidia Tegra 2 based Toradex Colibri T20 module. Though the project was put on the sideline just a few days after being assigned due to another high priority task coming my way, i was able to learn how to use OpenEmbedded to some extent. In fact, most of my learning happened in my own spare time. As i was already aware that i would be working on this project, i had started playing around with OE at home and started building the image.</p>
<p style='text-align: justify;'>Recently, I was assigned a project for doing a Number Plate Recognition system on NVidia Tegra 2 based Toradex Colibri T20 module. Though the project was put on the sideline just a few days after being assigned due to another high priority task coming my way, I was able to learn how to use OpenEmbedded to some extent. In fact, most of my learning happened in my own spare time. As I was already aware that I would be working on this project, I had started playing around with OE at home and started building the image.</p>
<p style='text-align: justify;'>For building images for our modules, my company Toradex uses the oe-core build system. At first, i had no idea how to use it, how to add packages to my image and so on. I was using Arch Linux at first. Now, Arch Linux being a rolling release distribution everything stays up to date. This created it's own set of problems. Three days i just spend trying to get the initial build going as it was failing for some reason or other. For example, one of the problems i encountered was related to Perl documentation (some POD error) and later gcc4.7.2 just won't compile and kept segfaulting. On looking up, it turns out it was an Arch Linux issue and to get around this, i would have to upgrade to gcc4.7.8. At that point of time, i had no idea how to resolve this issue. It would have probably been resolved by getting the bitbake recipe for gcc4.7.8 and setting the preferred version in a bitbake recipe to 4.7.8. I didn't try this out, but, on reading the OE manual much later, i thought that it might have been the solution.</p>
<p style='text-align: justify;'>For building images for our modules, my company Toradex uses the oe-core build system. At first, I had no idea how to use it, how to add packages to my image and so on. I was using Arch Linux at first. Now, Arch Linux being a rolling release distribution everything stays up to date. This created it's own set of problems. Three days I just spend trying to get the initial build going as it was failing for some reason or other. For example, one of the problems I encountered was related to Perl documentation (some POD error) and later gcc4.7.2 just won't compile and kept segfaulting. On looking up, it turns out it was an Arch Linux issue and to get around this, I would have to upgrade to gcc4.7.8. At that point of time, I had no idea how to resolve this issue. It would have probably been resolved by getting the bitbake recipe for gcc4.7.8 and setting the preferred version in a bitbake recipe to 4.7.8. I didn't try this out, but, on reading the OE manual much later, I thought that it might have been the solution.</p>
<p style='text-align: justify;'>Though i was frustrated during this time, and i was also cursing Arch Linux a bit, these problems made me look at the bitbake recipes, at the source packages and the process of applying patches and trying to fix each issue which use to pop up started giving me an idea at what was going on. I started appreciating Arch Linux. But of course i couldn't do this everyday. I installed Linux Mint XFCE version and started the procedure again.</p>
<p style='text-align: justify;'>Though I was frustrated during this time, and I was also cursing Arch Linux a bit, these problems made me look at the bitbake recipes, at the source packages and the process of applying patches and trying to fix each issue which use to pop up started giving me an idea at what was going on. I started appreciating Arch Linux. But of course I couldn't do this everyday. I installed Linux Mint XFCE version and started the procedure again.</p>
<p style='text-align: justify;'>This time the process was going smoothly and when the errors did come, i was able to resolve them quickly as i knew what i had to change in the bitbake recipe to get the build going. For example a checksum error halted the build. All that had to be done, was change the checksum in the bitbake recipe to the one that was being computed.</p>
<p style='text-align: justify;'>This time the process was going smoothly and when the errors did come, I was able to resolve them quickly as I knew what I had to change in the bitbake recipe to get the build going. For example a checksum error halted the build. All that had to be done, was change the checksum in the bitbake recipe to the one that was being computed.</p>
<p style='text-align: justify;'>Anyways, this was my story of playing with OE and it's now time to share the links which will help you in learning OpenEmbedded. First step, have a look at a few of the bitbake recipes and try to understand as much as you can. After that, refer the below links.</p>
@ -18,7 +18,7 @@ tags: openembedded
2. **Layers FAQ**: [http://www.openembedded.org/wiki/Layers_FAQ](http://http://www.openembedded.org/wiki/Layers_FAQ)
<p style='text-align: justify;'>Read this without fail. I would have saved a lot of time had i understood the concept of layers. Wasted a day's time trying to find out how to add OpenCV package to my image. If i had understood the above, a lot of time would have been saved.</p>
<p style='text-align: justify;'>Read this without fail. I would have saved a lot of time had I understood the concept of layers. Wasted a day's time trying to find out how to add OpenCV package to my image. If I had understood the above, a lot of time would have been saved.</p>
3. **Adding a Package**: [http://www.openembedded.org/wiki/I_want_an_image_with_package_XYZ_installed](http://www.openembedded.org/wiki/I_want_an_image_with_package_XYZ_installed)
@ -48,9 +48,9 @@ a. [http://www.multitech.net/developer/products/multiconnect-ocg/development/wri
b. [http://www.openembedded.org/wiki/How_to_create_a_bitbake_recipe_for_dummies](http://www.openembedded.org/wiki/How_to_create_a_bitbake_recipe_for_dummies)
<p style='text-align: justify;'>Well this is the last now for sure. I have put this in the last as most probably you won't have to write a recipe. There are already recipes available for thousands of various software packages which you can use. You can search for them in the layer index link i gave earlier. You can then use those recipes. If they are not already included in the layers you have, you will figure out how to add them by following the documentation above.</p>
<p style='text-align: justify;'>Well this is the last now for sure. I have put this in the last as most probably you won't have to write a recipe. There are already recipes available for thousands of various software packages which you can use. You can search for them in the layer index link I gave earlier. You can then use those recipes. If they are not already included in the layers you have, you will figure out how to add them by following the documentation above.</p>
<p style='text-align: justify;'>Hope these incoherent musings of mine will be of use to you. The post turned out to be longer than i expected, but anyways, have a good time playing with OE and Linux. May the source be with you!</p>
<p style='text-align: justify;'>Hope these incoherent musings of mine will be of use to you. The post turned out to be longer than I expected, but anyways, have a good time playing with OE and Linux. May the source be with you!</p>

View File

@ -4,15 +4,15 @@ title: How to write a Platform Device/Driver - ADC Driver using wm97xx codec
tags: device driver
---
<p style='text-align: justify;'>Somewhat more than two years back, while i was working in Godrej, a senior colleague from my development team gave us a lecture on how to write character drivers for Linux. Didn't understand one single thing, but since that time i have been trying to learn Linux kernel related stuff, with device drivers being the main area of focus. Of course, in between there have lot of lulls where i have hit a road block and then gone into a depression mode and then started again from where i left off, with renewed zeal and vigor.</p>
<p style='text-align: justify;'>Somewhat more than two years back, while I was working in Godrej, a senior colleague from my development team gave us a lecture on how to write character drivers for Linux. Didn't understand one single thing, but since that time I have been trying to learn Linux kernel related stuff, with device drivers being the main area of focus. Of course, in between there have lot of lulls where I have hit a road block and then gone into a depression mode and then started again from where I left off, with renewed zeal and vigor.</p>
<p style='text-align: justify;'>One of the road blocks till date has been the inability to understand or picture the driver framework. Recently, after quiet a lot of effort the platform device/driver framework (may be framework isn't the correct technical term, but, anyways) became clear to me.</p>
<p style='text-align: justify;'>Let me give you a background on what i was trying to write and achieve. My company Toradex manufactures and sells embedded computer on modules. One of them is the Colibri T20 which has the NVidia Tegra 2 processor on it. There is WM9715 codec from Wolfson Microelectronics, which is an audio codec with a touch panel controller. This codec has four auxilary ADC's and the device is connected on an AC97 bus. These four ADC's can be used as general purpose ADC's, while also being used for audio and touchscreen functionality.</p>
<p style='text-align: justify;'>Let me give you a background on what I was trying to write and achieve. My company Toradex manufactures and sells embedded computer on modules. One of them is the Colibri T20 which has the NVidia Tegra 2 processor on it. There is WM9715 codec from Wolfson Microelectronics, which is an audio codec with a touch panel controller. This codec has four auxilary ADC's and the device is connected on an AC97 bus. These four ADC's can be used as general purpose ADC's, while also being used for audio and touchscreen functionality.</p>
<p style='text-align: justify;'>Now, my company provides WinCE and Linux for the modules, but, the Linux is hardly as well supported as WinCE. With the default Linux image which is provided, there is no support for being able to use all the four ADC's. Only two ADC's can be used which are made available through the power driver framework. Now what i mean by power driver framework is difficult to explain, and doing so would result in digressing from the main topic. Don't worry though, this will not affect the purpose of this tutorial. For wm9715, there is already a driver available which provides the touch screen functionality along with providing access to auxiliary ADC's. But, you need to expose the interface through some other driver or framework, for it to be usable as a general purpose ADC.</p>
<p style='text-align: justify;'>Now, my company provides WinCE and Linux for the modules, but, the Linux is hardly as well supported as WinCE. With the default Linux image which is provided, there is no support for being able to use all the four ADC's. Only two ADC's can be used which are made available through the power driver framework. Now what I mean by power driver framework is difficult to explain, and doing so would result in digressing from the main topic. Don't worry though, this will not affect the purpose of this tutorial. For wm9715, there is already a driver available which provides the touch screen functionality along with providing access to auxiliary ADC's. But, you need to expose the interface through some other driver or framework, for it to be usable as a general purpose ADC.</p>
<p style='text-align: justify;'>I am giving three links below and i will be using these through out the rest of the tutorial, by referring to their names instead of the URL's.</p>
<p style='text-align: justify;'>I am giving three links below and I will be using these through out the rest of the tutorial, by referring to their names instead of the URL's.</p>
1. **Header file**: [http://git.toradex.com/cgit/linux-toradex.git/tree/include/linux/wm97xx.h?h=tegra](http://git.toradex.com/cgit/linux-toradex.git/tree/include/linux/wm97xx.h?h=tegra)
@ -28,15 +28,15 @@ tags: device driver
<p style='text-align: justify;'>The first question most people will ask is, what's the use of a platform device/driver framework. For x86 based PC's, it is possible for the OS to know what all devices are present, as ACPI or USB devices make it possible for the OS to query and find out which devices are present on the system, on which it is booting. For example, a device which is attached to a PCI or USB bus, the OS can query and find out what the device does or what are it's capabilities, is it a graphics card or removable USB mass storage device.</p>
<p style='text-align: justify;'>For embedded systems, you have buses like I2c or SPI. Devices attached to these buses are not discoverable in the above sense as i tried to explain. The OS has to be explicitly told that, for example, a RTC is connected on the I2C bus at an address of 0x68. This is where the platform device/driver comes in the picture.</p>
<p style='text-align: justify;'>For embedded systems, you have buses like I2c or SPI. Devices attached to these buses are not discoverable in the above sense as I tried to explain. The OS has to be explicitly told that, for example, a RTC is connected on the I2C bus at an address of 0x68. This is where the platform device/driver comes in the picture.</p>
<p style='text-align: justify;'>A board file is created for each board, which specifies the devices present on buses such as SPI and I2c. Have a look at the board file. You will find various platform devices and platform data structures which are used to register devices and relevant data with the OS. Platform data is used at later point when the OS is booting to know some specific details about the device. I will explain how the platform device and it's driver are bound to each other in a while.</p>
<p style='text-align: justify;'>Have a look at the core driver file. The first two functions to look out for are the wm97xx_probe and wm97xx_remove. These are the two common operations (probe and remove) for any platform device and driver. You can see there is a device_driver structure at the bottom of the file. Whenever a module is loaded, the first function to be called is the _init() function. In this function, the driver is registered with a call to driver_register and passing it the device_driver structure. On a call to device_register() the probe function will be called. It will do all the necessary set up required. For this example, it is allocating memory, setting up handlers, allocating devices which will be using this core driver and registering it with the input subsystem, which is used for providing the touch screen functionality. Now, this basically remains the same, but might vary slightly, for example, a true ADC driver will register itself with the Industrial IO framework (IIO).</p>
<p style='text-align: justify;'>Now, here comes the main part. For me to use the ADC's through a platform driver, i also need a platform device. So, i added a few function calls inside the probe() function for allocating platform device. This device i will be using later, how, we will come to that in a moment.</p>
<p style='text-align: justify;'>Now, here comes the main part. For me to use the ADC's through a platform driver, I also need a platform device. So, I added a few function calls inside the probe() function for allocating platform device. This device I will be using later, how, we will come to that in a moment.</p>
<pre><code>
```c
wm->colibriadc_dev = platform_device_alloc("colibri_adc", -1);
if (!wm->colibriadc_dev) {
ret = -ENOMEM;
@ -47,26 +47,26 @@ wm->colibriadc_dev->dev.parent = dev;
ret = platform_device_add(wm->colibriadc_dev);
if (ret < 0)
goto adc_reg_err;
</code></pre>
```
<p style='text-align: justify;'>For error handling,</p>
<pre><code>
```c
adc_reg_err:
platform_device_put(wm->colibriadc_dev);
adc_err:
platform_device_del(wm->colibriadc_dev);
</code></pre>
```
<p style='text-align: justify;'>Now, when the OS boots and registers and makes provision for this core driver, it will also allocate and make provision for my platform device which I created, to use this core driver. I added a platform_device pointer to the struct wm97xx which is in the header file.</p>
<pre><code>
```c
struct platform_device *colibriadc_dev;
</code></pre>
```
<p style='text-align: justify;'>This pointer holds the return value of platform_device_alloc(). After the above changes, we are ready for the platform driver which we will use in conjunction with a character driver for accessing the ADC's.</p>
<pre><code>
```c
#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/init.h"
@ -278,9 +278,9 @@ module_exit(sample_wm97xx_exit);
MODULE_AUTHOR("Sanchayan Maity");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Colibri T20 ADC Driver");
</code></pre>
```
<pre><code>
```c
CROSS_COMPILE ?= /home/sanchayan/Toradex/gcc-linaro/bin/arm-linux-gnueabihf-
ARCH          ?= arm
SOURCE_DIR    ?= /home/sanchayan/Toradex/T20V2.0/linux-toradex
@ -303,17 +303,17 @@ all:
clean:
rm *.o *.ko *.symvers *.order
</code></pre>
```
<p style='text-align: justify;'>The driver file and makefile source are shown above. On loading the module, the _init() will be called, which will in turn call platform_driver_register(). This will call the probe() function. If you really noticed carefully, then you can see **the driver has the same name viz. "colibri_adc" which is also the name i passed for device allocation** inside the probe() call of core driver. This is how the platform device will bind to a platform driver. They will have the same names and if you try to do a platform driver for which a platform device was not allocated, you will get a no device exists error.</p>
<p style='text-align: justify;'>The driver file and makefile source are shown above. On loading the module, the _init() will be called, which will in turn call platform_driver_register(). This will call the probe() function. If you really noticed carefully, then you can see **the driver has the same name viz. "colibri_adc" which is also the name I passed for device allocation** inside the probe() call of core driver. This is how the platform device will bind to a platform driver. They will have the same names and if you try to do a platform driver for which a platform device was not allocated, you will get a no device exists error.</p>
<p style='text-align: justify;'>One of the important things to note, is the call to **platform_set_drvdata()** in the probe call of core driver. It's not like i have traced all functions, but, from what i understand this establishes a linking between the device allocated by the core driver and your driver, which will later allow you access to the device pointer, which you need to pass to the functions in the core driver, to use them.</p>
<p style='text-align: justify;'>One of the important things to note, is the call to **platform_set_drvdata()** in the probe call of core driver. It's not like I have traced all functions, but, from what I understand this establishes a linking between the device allocated by the core driver and your driver, which will later allow you access to the device pointer, which you need to pass to the functions in the core driver, to use them.</p>
<p style='text-align: justify;'>You can see that the functions in core driver take a pointer to struct wm97xx. From where are you suppose to get this pointer? This you will get in the probe call of the driver which we wrote, by calling **platform_get_drvdata(). **You can see that this is so, in the driver code, where it is assigned to a static global pointer. The reason for using a static global pointer is i want this pointer to be accessible in the ioctl() calls, which will be the final interface for the user, which ultimately calls the core driver functions, by passing the required wm97xx pointer. On module unloading, _exit() will be called, which in turn calls platform_driver_unregister() which will result in a call to remove() function of the driver. Now, here there is not really anything to do in remove, as we do not require any kind of memory deallocation or clean up work for the platform part of the driver. You can have a nice look at the probe and remove functions of the core driver for getting an idea of what is really done in real world driver.</p>
<p style='text-align: justify;'>You can see that the functions in core driver take a pointer to struct wm97xx. From where are you suppose to get this pointer? This you will get in the probe call of the driver which we wrote, by calling **platform_get_drvdata(). **You can see that this is so, in the driver code, where it is assigned to a static global pointer. The reason for using a static global pointer is I want this pointer to be accessible in the ioctl() calls, which will be the final interface for the user, which ultimately calls the core driver functions, by passing the required wm97xx pointer. On module unloading, _exit() will be called, which in turn calls platform_driver_unregister() which will result in a call to remove() function of the driver. Now, here there is not really anything to do in remove, as we do not require any kind of memory deallocation or clean up work for the platform part of the driver. You can have a nice look at the probe and remove functions of the core driver for getting an idea of what is really done in real world driver.</p>
<p style='text-align: justify;'>So, now we finally have access to the auxiliary ADC's!!!. Hurray! And we also have our first (at least my first) platform device/driver. The user space application is below and is pretty simple.</p>
<pre><code>
```c
#include "stdio.h"
#include "fcntl.h"
#include "linux/ioctl.h"
@ -393,8 +393,8 @@ int main(void)
return 0;
}
</code></pre>
```
<p style='text-align: justify;'>Do note that this is only an example, and what you might need to do will depend on what is available and what is not. Also, the code is not exactly up to the mark as per coding standards, but, i was too excited while working and rolling this out, so. I hope this clears the idea of how to use platform device/driver. Also, just in case it is not clear to people who are starting out, the core driver and header files are being changed. This will require a kernel recompilation and updating the uImage on the module, for our driver to work.</p>
<p style='text-align: justify;'>Do note that this is only an example, and what you might need to do will depend on what is available and what is not. Also, the code is not exactly up to the mark as per coding standards, but, I was too excited while working and rolling this out, so. I hope this clears the idea of how to use platform device/driver. Also, just in case it is not clear to people who are starting out, the core driver and header files are being changed. This will require a kernel recompilation and updating the uImage on the module, for our driver to work.</p>
<p style='text-align: justify;'>I will be putting another example of a PWM driver, which will be slightly bit more involved and should serve as another example.</p>

View File

@ -6,7 +6,7 @@ tags: device driver
<p style='text-align: justify;'>I will get straight to the point in this tutorial and give the codes here. The explanation given in the earlier post for ADC should suffice.</p>
<p style='text-align: justify;'>Do note that this is only an example, and what you might need to do will depend on what is available and what is not. Also, the code is not exactly up to the mark as per coding standards, but, i was too excited while working and rolling this out, so. I hope this clears the idea of how to use platform device/driver. Also, just in case it is not clear to people who are starting out, the core driver and header files are being changed. This will require a kernel recompilation and updating the uImage on the module, for our driver to work.</p>
<p style='text-align: justify;'>Do note that this is only an example, and what you might need to do will depend on what is available and what is not. Also, the code is not exactly up to the mark as per coding standards, but, I was too excited while working and rolling this out, so. I hope this clears the idea of how to use platform device/driver. Also, just in case it is not clear to people who are starting out, the core driver and header files are being changed. This will require a kernel recompilation and updating the uImage on the module, for our driver to work.</p>
**1. Header File:**
[http://git.toradex.com/cgit/linux-toradex.git/tree/include/linux/pwm.h?h=tegra](http://git.toradex.com/cgit/linux-toradex.git/tree/include/linux/pwm.h?h=tegra)
@ -38,13 +38,13 @@ if (ret < 0) {
mutex_lock(&pwm_lock);
</code></pre>
<p style='text-align: justify;'>In the **tegra_pwm_remove** function, i added the below line just before **return**.</p>
<p style='text-align: justify;'>In the **tegra_pwm_remove** function, I added the below line just before **return**.</p>
<pre><code>
platform_device_unregister(pwm->colibripwm_dev);
</code></pre>
<p style='text-align: justify;'>In the board file i commented out lines 737 to 830. This was done as these lines exported the PWM to led driver framework. The led driver framework only allowed controlling the PWM's duty cycle and period was fixed at 19600, as you can see in those lines. Hence, this driver to allow period or frequency to be controlled as well. Also, line 1479 was commented to prevent registration of these PWM's with the led framework.</p>
<p style='text-align: justify;'>In the board file I commented out lines 737 to 830. This was done as these lines exported the PWM to led driver framework. The led driver framework only allowed controlling the PWM's duty cycle and period was fixed at 19600, as you can see in those lines. Hence, this driver to allow period or frequency to be controlled as well. Also, line 1479 was commented to prevent registration of these PWM's with the led framework.</p>
<p style='text-align: justify;'>The driver code is as follows:</p>
@ -180,7 +180,7 @@ static int pwm_device_probe(struct platform_device *pdev)
return -ENOMEM;
}
for (i = 1; i < PWM_CHANNELS; i++)
for (i = 1; I < PWM_CHANNELS; i++)
{
switch (i)
{

View File

@ -24,7 +24,7 @@ tags: device driver, sysfs
<p style='text-align: justify;'>The below change was made to the **probe** function of the core driver file</p>
<pre><code>
```c
if ( device_create_file(wm->dev, &dev_attr_adc_channel1) != 0 )
{
printk(KERN_ALERT "Sysfs Attribute Creation failed for ADC Channel1\n");
@ -44,11 +44,11 @@ if ( device_create_file(wm->dev, &dev_attr_adc_channel4) != 0 )
{
printk(KERN_ALERT "Sysfs Attribute Creation failed for ADC Channel4\n");
}
</code></pre>
```
<p style='text-align: justify;'>The following was added to the core driver file to access the ADC data via sysfs attributes.</p>
<pre><code>
```c
static ssize_t adc_channel1_show(struct device *child, struct device_attribute *attr, char *buf)
{
struct wm97xx *wm = dev_get_drvdata(child);
@ -81,16 +81,16 @@ static DEVICE_ATTR(adc_channel1, 0644, adc_channel1_show, NULL);
static DEVICE_ATTR(adc_channel2, 0644, adc_channel2_show, NULL);
static DEVICE_ATTR(adc_channel3, 0644, adc_channel3_show, NULL);
static DEVICE_ATTR(adc_channel4, 0644, adc_channel4_show, NULL);
</code></pre>
```
<p style='text-align: justify;'>For cleanup, the attribute removal was done in the **remove** function as below.</p>
<pre><code>
```c
device_remove_file(wm->dev, &dev_attr_adc_channel1);
device_remove_file(wm->dev, &dev_attr_adc_channel2);
device_remove_file(wm->dev, &dev_attr_adc_channel3);
device_remove_file(wm->dev, &dev_attr_adc_channel4);
</code></pre>
```
<p style='text-align: justify;'>After doing the above changes, the device attributes which we added show up in the sysfs tree, which can be used to get the ADC values, as shown in the below picture.</p>

View File

@ -4,13 +4,13 @@ title: Implementing mmap for transferring data from user space to kernel space
tags: device driver
---
<p style='text-align: justify;'>I was recently working on an application where streams from four multiplexed analog video channels had to be displayed in four windows. I was trying to do this using OpenCV while the analog video decoder/multiplexer in question was the ADV7180. For switching the channels, i was using an ioctl() call to switch the channels in a while loop with a certain time interval, while capturing the frames and putting them in a separate queues as per the channel selected. This was done in the main thread, while separate threads pulled the frames from the queue and rendered them. The capturing and rendering part was being done with OpenCV. I was not able to achieve a decent enough frame rate with this. I had put delays in certain places to avoid frame glitches in the multiple windows displaying the frames.</p>
<p style='text-align: justify;'>I was recently working on an application where streams from four multiplexed analog video channels had to be displayed in four windows. I was trying to do this using OpenCV while the analog video decoder/multiplexer in question was the ADV7180. For switching the channels, I was using an ioctl() call to switch the channels in a while loop with a certain time interval, while capturing the frames and putting them in a separate queues as per the channel selected. This was done in the main thread, while separate threads pulled the frames from the queue and rendered them. The capturing and rendering part was being done with OpenCV. I was not able to achieve a decent enough frame rate with this. I had put delays in certain places to avoid frame glitches in the multiple windows displaying the frames.</p>
<p style='text-align: justify;'>Thinking that may be the ioctl() call and the context switch is the reason i have to use delays and this is going slow, i decided to look into ways of transferring data faster between the user and kernel space, instead of using an ioctl() call. An mmap() implementation in a driver or a memory mapping between user and kernel space is the fastest way to transfer data. This approach doesn't incur a context switch nor a memory buffer copying. Below is a sample code showing how a mmap() implementation for a driver is done.</p>
<p style='text-align: justify;'>Thinking that may be the ioctl() call and the context switch is the reason I have to use delays and this is going slow, I decided to look into ways of transferring data faster between the user and kernel space, instead of using an ioctl() call. An mmap() implementation in a driver or a memory mapping between user and kernel space is the fastest way to transfer data. This approach doesn't incur a context switch nor a memory buffer copying. Below is a sample code showing how a mmap() implementation for a driver is done.</p>
<p style='text-align: justify;'>Below is the driver code.</p>
<pre><code>
```c
#include "linux/module.h"
#include "linux/kernel.h"
#include "linux/init.h"
@ -120,11 +120,11 @@ static void __exit mmapexample_module_exit(void)
module_init(mmapexample_module_init);
module_exit(mmapexample_module_exit);
MODULE_LICENSE("GPL");
</code></pre>
```
Below is the user space application showing it's use in an application.
<pre><code>
```c
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
@ -157,7 +157,7 @@ int main ( int argc, char **argv )
    close(configfd);    
    return 0;
}
</code></pre>
```
<p style='text-align: justify;'>The above code should run well for both desktop or embedded Linux. For learning more, refer to Chapter 15 of the Linux Device Drivers book.</p>

View File

@ -14,11 +14,12 @@ tags: opencv, gstreamer
<p style='text-align: justify;'>The first one is active in the code below and the second one commented out. To enable the first mechanism, uncomment the mutex locking and signal connect mechanism and comment out the pull buffer call related stuff in the while loop.</p>
<p style='text-align: justify;'>Learn more about gstreamer from [http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/index.html](http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/index.html) and especially refer section 19.</p>
<p style='text-align: justify;'>Learn more about gstreamer from [Gstreamer manual](http://gstreamer.freedesktop.org/data/doc/gstreamer/head/manual/html/index.html) and especially refer section 19.</p>
<p style='text-align: justify;'>For some reason, I am experiencing a memory leak issue with the below code (more so with the fist approach) and haven't got around and being able to fix it. Also, for your platform the gstreamer pipeline elements will be different. Another problem was, I get x-raw-yuv data from my gstreamer source element and I am only able to display the black and white image with OpenCV. Nonetheless, I thought this might be useful and may be someone can also point out the error to me. Not a gstreamer expert by any means.</p>
<pre><code>
```c
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
@ -401,4 +402,6 @@ int main(int argc, char *argv[])
    delete_pipeline(&gstreamerData);
    
       return 0;
}</code></pre>
}
```

View File

@ -4,13 +4,13 @@ title: Multithreaded Facial Recognition with OpenCV
tags: opencv
---
<p style='text-align: justify;'>It has been quiet a while since i have been maintaining this blog and giving some information and codes to work with. Lately i started noticing that this can become tedious. So from now on i will try to give access to the projects or work i do using git. I had a git account since September of 2013, but, never got around to using it.</p>
<p style='text-align: justify;'>It has been quiet a while since I have been maintaining this blog and giving some information and codes to work with. Lately I started noticing that this can become tedious. So from now on I will try to give access to the projects or work I do using git. I had a git account since September of 2013, but, never got around to using it.</p>
<p style='text-align: justify;'>This project is a modification of the facial recognition project which is given with Mastering OpenCV with Practical Computer Vision. The book is available with Packtpub and Amazon. The code base is here [https://github.com/MasteringOpenCV](https://github.com/MasteringOpenCV) and is maintained by Shervin Emami.</p>
<p style='text-align: justify;'>I was trying to do the same on a Toradex NVidia Tegra3 based Colibri T30 module which has four CPU cores. The code is single threaded and as such doesn't detect faces if the training process is going on. I made changes to this, so that even while the training process is on going, it can still detect faces. And mind you, the training process can go on for quiet a while if there are more than 3-4 faces. So, this is basically a two threaded version of the main code along with a few more changes as per my personal requirement. You can actually go one step further to utilize three cores, though right now i can't recall what was suppose to be the job of the third core.</p>
<p style='text-align: justify;'>I was trying to do the same on a Toradex NVidia Tegra3 based Colibri T30 module which has four CPU cores. The code is single threaded and as such doesn't detect faces if the training process is going on. I made changes to this, so that even while the training process is on going, it can still detect faces. And mind you, the training process can go on for quiet a while if there are more than 3-4 faces. So, this is basically a two threaded version of the main code along with a few more changes as per my personal requirement. You can actually go one step further to utilize three cores, though right now I can't recall what was suppose to be the job of the third core.</p>
<p style='text-align: justify;'>I do apologize for the code not being very clean. At first i was trying to use the threading facility available with C++, but since i am no C++ expert i ran into problems which i wasn't able to fix quickly. Decided to use pthreads, which i am much more familiar and comfortable with. You will find the C++ threading part which i was trying to do, commented out. Once i get some C++ mastery using Bruce Eckel's Thinking in C++, i will try to do it cleanly in just C++ and clean it or clean it anyways when i get time.</p>
<p style='text-align: justify;'>I do apologize for the code not being very clean. At first I was trying to use the threading facility available with C++, but since I am no C++ expert I ran into problems which I wasn't able to fix quickly. Decided to use pthreads, which I am much more familiar and comfortable with. You will find the C++ threading part which I was trying to do, commented out. Once I get some C++ mastery using Bruce Eckel's Thinking in C++, I will try to do it cleanly in just C++ and clean it or clean it anyways when I get time.</p>
<p style='text-align: justify;'>You can clone the project with:</p>

View File

@ -6,13 +6,13 @@ tags: gstreamer
<p style='text-align: justify;'>You can also clone this with</p>
<pre><code>
git clone https://github.com/SanchayanMaity/gstreamer-audio-playback.git
</pre></code>
```bash
$ git clone https://github.com/SanchayanMaity/gstreamer-audio-playback.git
```
<p style='text-align: justify;'>Though I used this on a Toradex Colibri Vybrid module, you can use the same on a Beagleboard or desktop with the correct setup.</p>
<pre><code>
```c
/*
Notes for compilation:
1. For compiling the code along with the Makefile given, a OE setup is mandatory.
@ -344,11 +344,10 @@ err:    
    
    return TRUE;
}
</code></pre>
```
<p style='text-align: justify;'>A simple Makefile for compiling the code. You need to change the path as per your OE setup.</p>
<pre><code>
```
#Notes for compilation:
#1. For compiling the code with this Makefile, a OE setup is mandatory.
#2. Before compiling, change the paths as per the setup of your environment.
@ -364,4 +363,4 @@ all:
clean:
    rm -rf audiovf
</code></pre>
```

View File

@ -4,33 +4,33 @@ title: Setting up Yocto/Poky for Beagleboard-xM/Beagleboard/Beaglebone
tags: yocto, poky, beagleboard, qt5
---
<p style='text-align: justify;'>I have used Buildroot before for setting up environment for Beagleboard, but OpenEmbedded or Yocto gives much more power with regard to the number of packages you can build or do your own customizations. From here on i am assuming that you have a separate beagle directory in which you are doing this. A knowledge of git and your smartness ;-) is assumed.</p>
<p style='text-align: justify;'>I have used Buildroot before for setting up environment for Beagleboard, but OpenEmbedded or Yocto gives much more power with regard to the number of packages you can build or do your own customizations. From here on I am assuming that you have a separate beagle directory in which you are doing this. A knowledge of git and your smartness ;-) is assumed.</p>
Clone the poky repository with git
<pre><code>
git clone git://git.yoctoproject.org/poky
</code></pre>
```bash
$ git clone git://git.yoctoproject.org/poky
```
<p style='text-align: justify;'>Enter the poky directory and clone the "meta-ti" layer. This layer will be required for Beagle specific builds.</p>
<pre><code>
git clone git://git.yoctoproject.org/meta-ti meta-ti
</code></pre>
```bash
$ git clone git://git.yoctoproject.org/meta-ti meta-ti
```
<p style='text-align: justify;'>Clone the meta-openembedded, openembedded-core and meta-qt5 layers, while in the poky directory</p>
<pre><code>
git clone git://git.openembedded.org/openembedded-core openembedded-core
</code></pre>
```bash
$ git clone git://git.openembedded.org/openembedded-core openembedded-core
```
<pre><code>
git clone git://git.openembedded.org/meta-openembedded meta-openembedded
</code></pre>
```bash
$ git clone git://git.openembedded.org/meta-openembedded meta-openembedded
```
<pre><code>
git clone git://github.com/meta-qt5/meta-qt5 meta-qt5
</code></pre>
```bash
$ git clone git://github.com/meta-qt5/meta-qt5 meta-qt5
```
<p style='text-align: justify;'>In each of the git cloned repositories, select the branch you want to work with. If you do not select a branch, all of them will be with the default **master** branch. For example, you can select the **dora** or **daisy** branch.</p>
@ -42,7 +42,7 @@ git clone git://github.com/meta-qt5/meta-qt5 meta-qt5
<p style='text-align: justify;'>Open the **conf/bblayers.conf** file with an editor like nano or gedit. Add the required entries to have this file exactly as below.</p>
<pre><code>
```c
# LAYER_CONF_VERSION is increased each time build/conf/bblayers.conf
# changes incompatibly
LCONF_VERSION = "6"
@ -63,11 +63,11 @@ BBLAYERS ?= " \
BBLAYERS_NON_REMOVABLE ?= " \
  /home/sanchayan/beagle/poky/meta \
  /home/sanchayan/beagle/poky/meta-yocto \
  "</code></pre>
```
<p style='text-align: justify;'>Open a different terminal and go to the **openembedded-core** in **poky** directory.  Make a **conf **directory and add a **layer.conf** file as below.</p>
<pre><code>
```c
# We have a conf and classes directory, append to BBPATH
BBPATH .= ":${LAYERDIR}"
@ -76,11 +76,12 @@ BBFILES += "${LAYERDIR}/recipes*/*/*.bb ${LAYERDIR}/recipes*/*/*.bbappend"
BBFILE_COLLECTIONS += "openembedded-core"
BBFILE_PATTERN_openembedded-core := "^${LAYERDIR}/"
BBFILE_PRIORITY_openembedded-core = "4"</code></pre>
BBFILE_PRIORITY_openembedded-core = "4"
```
<p style='text-align: justify;'>Now go to the **meta-openembedded** directory in **poky**. Make a **conf** directory and add a **layer.conf** file as below.</p>
<pre><code>
```c
# We have a conf and classes directory, append to BBPATH
BBPATH .= ":${LAYERDIR}"
@ -90,11 +91,11 @@ BBFILES += "${LAYERDIR}/recipes*/*/*.bb ${LAYERDIR}/recipes*/*/*.bbappend"
BBFILE_COLLECTIONS += "meta-openembedded"
BBFILE_PATTERN_meta-openembedded := "^${LAYERDIR}/"
BBFILE_PRIORITY_meta-openembedded = "5"
</code></pre>
```
<p style='text-align: justify;'>Go to the terminal in which you got into the **poky-build** directory after running **source/oe-init-build-env**. Add the following to the **conf/local.conf**.</p>
<pre><code>
```c
BB_NUMBER_THREADS = "4"
PARALLEL_MAKE = "-j 4"
INHERIT += "rm_work"
@ -109,29 +110,32 @@ IMAGE_INSTALL_append = " \
            qtwebsockets \
            qtsvg \
            qtx11extras \
              "</code></pre>
              "
```
<p style='text-align: justify;'>The BB_NUMBER_THREADS and PARALLEL_MAKE in my **local.conf** is as per the fact that i have a quad core machine. Set it as per your machine configuration. Also, set the **MACHINE** variable in the file. I set it to **MACHINE ?= "beagleboard"**. Just add this line below the default. The IMAGE_INSTALL_append will add the packages specified to any image we build and we are going to do a minimal build. You can add the packages you like.</p>
<p style='text-align: justify;'>The BB_NUMBER_THREADS and PARALLEL_MAKE in my **local.conf** is as per the fact that I have a quad core machine. Set it as per your machine configuration. Also, set the **MACHINE** variable in the file. I set it to **MACHINE ?= "beagleboard"**. Just add this line below the default. The IMAGE_INSTALL_append will add the packages specified to any image we build and we are going to do a minimal build. You can add the packages you like.</p>
<p style='text-align: justify;'>First look for a specific package you like at the below link. Do select the relevant branch as per your branch selection in the start of the tutorial.</p>
[http://layers.openembedded.org/layerindex/branch/master/recipes/](http://layers.openembedded.org/layerindex/branch/master/recipes/)
<p style='text-align: justify;'>After this, check the layer in which that package recipe resides. Clone the layer in the same way we added the **meta-ti** or **meta-qt5** layers and add them to the **bblayers.conf** file. If the layer has a dependency you need to clone and add the relevant dependency layer too. I wanted to build qt5, so i added the meta-qt5 layer. If you want to build cherokee, you need to add the meta-webserver layer in which the cherokee recipe resides.</p>
<p style='text-align: justify;'>After this, check the layer in which that package recipe resides. Clone the layer in the same way we added the **meta-ti** or **meta-qt5** layers and add them to the **bblayers.conf** file. If the layer has a dependency you need to clone and add the relevant dependency layer too. I wanted to build qt5, so I added the meta-qt5 layer. If you want to build cherokee, you need to add the meta-webserver layer in which the cherokee recipe resides.</p>
<p style='text-align: justify;'>Some packages fail due to a fetch failure. This is because a particular define for a url is not there in Yocto which Openembedded uses.</p>
<p style='text-align: justify;'>Add the following to **meta/classes/mirrors.bbclass** and **meta/conf/bitbake.conf** in the **poky** source tree respectively. Make sure you add it at the right place.</p>
${SAVANNAH_GNU_MIRROR} http://download-mirror.savannah.gnu.org/releases \n \
${SAVANNAH_NONGNU_MIRROR} http://download-mirror.savannah.nongnu.org/releases \n \
```c
${SAVANNAH_GNU_MIRROR} http://download-mirror.savannah.gnu.org/releases
${SAVANNAH_NONGNU_MIRROR} http://download-mirror.savannah.nongnu.org/releases
SAVANNAH_GNU_MIRROR = "http://download-mirror.savannah.gnu.org/releases"
SAVANNAH_NONGNU_MIRROR = "http://download-mirror.savannah.nongnu.org/releases"
```
<p style='text-align: justify;'>A patch for the **poky** tree to do the above is below, which you can apply with **git**.</p>
<pre><code>
```c
diff --git a/meta/classes/mirrors.bbclass b/meta/classes/mirrors.bbclass
index 1fd7cd8..1dd6cd6 100644
--- a/meta/classes/mirrors.bbclass
@ -171,7 +175,7 @@ index 9716274..13f9127 100644
 
-IMAGE_ROOTFS_SIZE ?= "8192"
+#IMAGE_ROOTFS_SIZE ?= "8192"
</code></pre>
```
<p style='text-align: justify;'>Now, you can build an image for your board by doing **bitbake core-image-minimal**. The generated files and images will be in **poky-build/****tmp/deploy/images/beagleboard**.</p>
@ -179,7 +183,7 @@ index 9716274..13f9127 100644
[https://www.yoctoproject.org/downloads/bsps/dora15/beagleboard](https://www.yoctoproject.org/downloads/bsps/dora15/beagleboard)
<p style='text-align: justify;'>Now, plug in the SD card and boot. It boots very quickly. You are supposed to be connected to the debug serial port. For some reason Ethernet and all USB ports don't work. I am trying to figure out why, will update as soon as i do. X also doesn't seem to work on running startx.</p>
<p style='text-align: justify;'>Now, plug in the SD card and boot. It boots very quickly. You are supposed to be connected to the debug serial port. For some reason Ethernet and all USB ports don't work. I am trying to figure out why, will update as soon as I do. X also doesn't seem to work on running startx.</p>
<p style='text-align: justify;'>If you would like to setup qtcreator and use qt5, build **meta-toolchain-qt5** and follow the below link. The link is not exactly for qt5, but, can be used for qt5 setup for beagle. No need to follow the relocation related stuff on the link.</p>

View File

@ -8,7 +8,7 @@ tags: device driver
So let me show how this is done for both.
<pre><code>
```c
static struct resource foo_resource[] = {
[0] = {
.start = foo_BASE_TEG, /* address */
@ -34,7 +34,7 @@ static struct platform_device foo_device = {
.platform_data = &foo_platdata,
}
};
</code></pre>
```
<p style='text-align: justify;'>Something like above will be specified in a board file for the hardware. The resource structure specifies the memory address with .start and .end specifier. This in turn is passed in the platform_device structure. When your driver loads at kernel boot up, in init() the platform driver register function matches the name specified in the driver structure and uses the data passed from platform device above. Or if a probe() is directly called by the kernel on boot up, the platform_device pointer passed to the probe call, can be used to retrieve the platform data. The oscillator frequency was specified in the platform data above, but, any such data can be specified and then accessed in the driver. If pdev is the pointer in the probe call, the platform data will be accessible with pdev->dev.platform_data.The pointer to the resource structure can be had with a call to platform_get_resource. Once the resouce structure pointer is available, an ioremap call will return the address to be used from that point onwards, which will be assigned to an iomem variable. Any writes or read you from here on will be based off the memory address you got in the iomem variable above. The readl and writel functions are used for the ARM architecture to read or write to registers. Now you may not note this functions directly in a driver, as a lot many times the drivers are build around functionality provided by a subsystem, but, ultimately in the back end these functions will be used.</p>
@ -48,7 +48,7 @@ static struct platform_device foo_device = {
<p style='text-align: justify;'>In recent kernels, device trees are used. For example, an ADC peripheral have a device tree node specification as below</p>
<pre><code>
```c
adc0: adc@4003b000
{
compatible = "fsl,vf610-adc";
@ -59,6 +59,6 @@ adc0: adc@4003b000
status = "disabled";
#io-channel-cells = <1>;
};
</code></pre>
```
<p style='text-align: justify;'>So, 0x4003b000 is the starting address of the peripheral. Have a look here [http://lxr.free-electrons.com/source/drivers/iio/adc/vf610_adc.c](http://lxr.free-electrons.com/source/drivers/iio/adc/vf610_adc.c). The of_device_id matches against the name specified in the node and uses the information from the node. Have a look at the driver, probe() function especially and this is pretty simple. Shows how the memory information is read in from the node and used further. Also, one can clearly see the readl() and writel() calls. Do note that however not all drivers will use readl and writely directly, but, have several cascaded pointer calls which will ultimately result in a call to readl or writel. The data in a device tree node can be retrieved with device tree node helper functions.</p>

View File

@ -10,7 +10,8 @@ tags: emacs
[http://scottfrazersblog.blogspot.in/2009/12/emacs-named-desktop-sessions.html](http://scottfrazersblog.blogspot.in/2009/12/emacs-named-desktop-sessions.html)
<pre><code>(custom-set-variables
```
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
@ -161,4 +162,4 @@ tags: emacs
(my-desktop-save "last-session"))
(add-hook 'kill-emacs-hook 'my-desktop-kill-emacs-hook)
</code></pre>
```

View File

@ -8,7 +8,7 @@ tags: emacs
<p style='text-align: justify;'>When editing from the command line, I use to resort to using nano or more recently vim. I was using nano as the text editor for editing my git logs, patches and as an editor for mutt too. Why not use emacs for all of them? Well if you open single emacs instances all the time, it takes time to load the .emacs or init.el file and even if you invoke it as emacs -Q -nw it is not really worthwhile. What is required is to run emacs in daemon mode. I created a systemd service file to start emacs in daemon mode at startup with this script taken from the Arch wiki.</p>
<pre><code>
```c
[Unit]
Description=Emacs: the extensible, self documenting text editor
@ -20,23 +20,23 @@ Restart=always
[Install]
WantedBy=default.target
</pre></code>
```
<p style='text-align: justify;'>This results in emacs automatically being started in daemon/server mode. Added a few aliases to my .zshrc file as below.</p>
<pre><code>
```c
alias e="emacsclient -t"
alias ec="emacsclient -c"
</pre></code>
```
<p style='text-align: justify;'>Now I can open emacs from command line as "e filename". And it will open quickly now. So all good? No, still one problem remained. I use solarized theme for my terminal and mutt while I use zenburn for emacs. On opening a file as above, the color themes I guess superimpose or mix and result in a very bad display of text. If I run emacs -Q -nw to open a file it would be alright, as the -Q option does not lead emacs to load it's init.el file. I now needed a way to tell emacsclient to not apply any theme while being opened on a terminal. After some searching, adding the below snippet to init.el resulted in what I wanted. So if I run a GUI emacs, zenburn theme is used, if I use emacs in terminal, no background theme gets applied.</p>
<pre><code>
```c
(defun on-frame-open (frame)
(if (not (display-graphic-p frame))
(set-face-background 'default "unspecified-bg" frame)))
(on-frame-open (selected-frame))
(add-hook 'after-make-frame-functions 'on-frame-open)
</pre></code>
```
And viola......

View File

@ -8,43 +8,45 @@ tags: openembedded, containers
<p style='text-align: justify;'>Now I am certainly not going to stop using Arch Linux, I like it quite a bit with the setup I have. The solution is to use a chroot jail or having systemd as my init, that would be resorting to the use of systemd-nspawn. So lets get on how to set up an environment which we can use for openembedded builds. I assume you have yaourt installed. yaourt is pretty cool as I do not have to bother with downloading pkgbuilds anymore.</p>
<pre><code>
```bash
yaourt -S debootstrap
mkdir ~/debian-root
sudo debootstrap --arch=amd64 --variant=minbase jessie ~/debian-root
sudo systemd-nspawn -D debian-root
</code></pre>
```
<p style='text-align: justify;'>The third command is gonna take a while. After you run the last command you would be inside the chroot jail as a root user. After that run the following.</p>
<pre><code>
```bash
apt-get install update
apt-get install sudo
adduser -uid 1000 -gid 100 username
visudo
su username
</code></pre>
```
<p style='text-align: justify;'>I assume you know what to add after running visudo. Basically add yourself to the sudoers file. In case you are wondering how I got the user id and group id for the adduser command, that would be by running "id" on my host. The last command will drop you in the home directory for the newly created user. Whenever you want to work on openembedded, just use systemd-nspawn to log in to the debian environment. You can keep this environment for as long you like to maintain your build setup while your normal userspace can be updated without fear of breaking the build. You can replicate the exact debian environment by just copying the complete debian root directory using something like rsync to any number of your machines.</p>
<p style='text-align: justify;'>Nice ain't it? Now I don't have to bother that something will break when I update. I am writing this while my openembedded build is going on. I mean to look into how vagrant, docker and CoreOS are exactly used. May be it will be something which can be used to help our customers replicate the setup which we know to be working at our end. Do not know if it is actually possible, but I read somewhere something like this atleast in the context of vagrant while messing around a bit with vim related stuff. Also do note that debian is not the only one you can use. You can do this for Fedora, Arch and probably other distros too, however I have not tried that. This is my first time using this. I do remember using a chroot jail while setting up Arch Linux, but, it's not something I looked closely into which I mean to rectify soon.</p>
<p style='text-align: justify;'>Output from my debian root environment.</p>
<pre><code>
```bash
sanchayan@debian-root:~/oe-core/build$ uname -a
Linux debian-root 4.0.0-ck1-bfs-ck+ #8 SMP PREEMPT Wed Apr 29 11:35:34 IST 2015 x86_64 GNU/Linux
sanchayan@debian-root:~/oe-core/build$ pwd
/home/sanchayan/oe-core/build
</code></pre>
```
<p style='text-align: justify;'>Output of machinectl from my host.</p>
<pre><code>
```bash
machinectl
MACHINE CLASS SERVICE
debian-root container nspawn
1 machines listed.
</code></pre>
```
[systemd for Administrators](http://0pointer.net/blog/archives.html) series should be interesting to you.

View File

@ -7,20 +7,21 @@ tags: epoll
<p style='text-align: justify;'>Finally I have some time to relax a bit and write about a few things now that my fall semester course ended. I had taken a Distributed Systems class where we were taught the basics of distributed systems, had some assignments, with the final assignment being evaluation of some of the distributed key-value stores. The most interesting thing I learned on my own was how to use epoll in a multithreaded design. Was actually trying to use the libevent library during my second assignment, however, due to my lack of understanding I could not get it to work the way I wanted. During my third assignment I tried using epoll directly, but, I wanted to do a multithreaded design. Searching on the internet did not get me any examples, only notes on how one might implement it. So I tried and finally got it working. This will probably be the first write up on the net to be talking about this. However I am no expert in such things, so if anyone has any suggestions or improvements to what I did, please do share in the comments or mail me directly.</p>
<p style='text-align: justify;'>One can clone the concerned repository with</p>
<pre><code>
git clone https://github.com/SanchayanMaity/Multithreaded_Epoll.git
</code></pre>
<p style='text-align: justify;'>The first requirement is a workqueue implementation. During my work with libevent and looking for usable examples, I came across one which was being used with libevent by the code's author Ron Cemer [1]. The second requirement was to have a good usable epoll example I could use which I found here [2].</p>
```bash
$ git clone https://github.com/SanchayanMaity/Multithreaded_Epoll.git
```
<pre><code>
The first requirement is a workqueue implementation. During my work with libevent and looking for usable examples, I came across one which was being used with libevent by the code's author Ron Cemer [1]. The second requirement was to have a good usable epoll example I could use which I found here [2].
```c
[1]. http://roncemer.com/software-development/multi-threaded-libevent-server-example/
[2]. https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/
</code></pre>
```
<p style='text-align: justify;'>With the above I had a workqueue implementation and a usable epoll example, on which I could base my work upon. So let us jump to the thread which uses epoll and acts as the main event loop queueing up work for the workqueues to process.</p>
<pre><code>
```c
efd = epoll_create1(0);
if (efd == -1)
err_sys("Error with epoll_create1");
@ -43,11 +44,12 @@ for ( ; ; ) {
for (i = 0; i < n; i++) {
......
}
</code></pre>
}
```
<p style='text-align: justify;'>The listen descriptor is created when the main loop starts. The listen descriptor is added to the list of descriptors epoll should wait on. After that we start our infinite loop, in which we block with epoll waiting for events on this listen descriptor. Once any event occurs on the listen descriptor, which in this case are the incoming connection requests, we iterate over the event list. There are three possibilites from here on. First is of course some error occured, so we check for errors, we also check if connections were closed with the EPOLLHUP and if it is not the event we registered for.</p>
<pre><code>
```c
if ((events[i].events & EPOLLERR) ||
(events[i].events & EPOLLHUP) ||
(!(events[i].events & EPOLLIN))) {
@ -64,11 +66,11 @@ if ((events[i].events & EPOLLERR) ||
}
continue;
}
</code></pre>
```
<p style='text-align: justify;'>Second is an incoming connection request. In this case we accept the incoming connection, and then add the descriptor returned by accept to the descriptor list of events epoll should let us know about. This descriptor would be the one on which incoming and outgoing messages will be processed and send respectively.</p>
<pre><code>
```c
if (listenfd == events[i].data.fd) {
/*
* We have a notification on the listening socket, which means
@ -111,11 +113,11 @@ if (listenfd == events[i].data.fd) {
}
continue;
}
</code></pre>
```
<p style='text-align: justify;'>Third case is an incoming request on one of the connections that was accepted in second step. In this case, we dynamically allocate a job and add it to the workqueue along with the respective data required. However before adding the job to the workqueue, we make sure to remove the descriptor which we will process, from the list of event descriptors epoll will monitor. See the comment in code.</p>
<pre><code>
```c
else {
if ((job = malloc(sizeof(* job))) == NULL) {
@ -150,22 +152,22 @@ else {
/* Add the job for processing by workqueue */
workqueue_add_job(&workqueue, job);
}
</code></pre>
```
<p style='text-align: justify;'>The above code snippets are from the dht.c file which is the primary file. The workqueue implementation can be seen and understood by going through the workqueue.c and workqueue.h files. Note that the function called by the workqueue will basically do the job of processing the incoming client request as per one's protocol requirements. Workqueue initialisation is simple enough as below</p>
<pre><code>
```c
/* Initialize work queue */
if (workqueue_init(&workqueue, NUMBER_OF_WQS)) {
workqueue_shutdown(&workqueue);
perror("Failed to create workqueue");
goto free_tokens;
}
</code></pre>
```
<p style='text-align: justify;'>At the end of the request processing function, the descriptor which was passed to the function for processing needs to be added back to the list of descriptors epoll should monitor.</p>
<pre><code>
```c
event.data.fd = connfd;
event.events = EPOLLIN;
ret = epoll_ctl(efd, EPOLL_CTL_ADD, connfd, &event);
@ -173,6 +175,6 @@ if (ret == -1)
perror("Error with epoll_ctl ADD");
free(job_wq_data);
free(job);
</code></pre>
```
<p style='text-align: justify;'>The server thread with the epoll event loop will only be one and depending on the number of cores one would initialise the number of workqueues. So since I had a four core system, I had three workqueues and one thread with epoll event loop. This kind of a system can scale well instead of naive approaches like one thread or one process per client connection. Further work to be done are to get the EPOLLONESHOT flag to work as I am sure I was definitely doing something wrong while trying to use it and second would be using non blocking sockets instead of blocking one, however that will be quite a bit of work. Non blocking sockets are not so easy to handle.</p>