Monday, 28 April 2008

It's been a while...

I know it's been a while since I updated my blog. But I've been struggling with a couple of things, both personally as well as on my domotics.

On personal level, it's been a sad time for me. Two weeks back, my beloved Father passed away. Knowing my Mother passed away hardly 20 months before, one can imagine I've known happier times....

This is the site I created to commemorate my beloved Parents...

Anyway, life goes on and I will have to live with all the good memories I have of both my parents (and I can assure you there are many, many of them...).

Another issue I was struggling with, was the amount of threads in my system. I'm not even halfway my development, and I had already 20+ threads running.
This was too much and the reason was quite simple: every object that represented hardware that needed polling, was running in its own thread.

For instance, for my IO expanders, I had one thread per instance. This is of course very expensive and I was looking to a solution that would bring down the amount of threads to one per functionality.

So, one thread for all my IO tasks, one thread for my temperature measurements, etc...

I've been thinking hard on how to solve this and found a good solution in the usage of STL and polymorphism, using callback functions.

The only precondition was that the prototype of my callback functions all had to be the same. But that was not an issue: it perfectly fitted into one another.

The goal was to fill an array with pointers to callback functions and then scan that array at regular times (every 10ms, since I wanted to have a granularity of 10ms to poll my IO pins).

Registering the callback functions happens in the class that maintains a thread. That thread is running every 10ms and completely scans the array (I used a vector array for that). The callback function was called every 10ms and inside the callback function, a decision was taken if a certain pin of a certain IO expander had to be checked or not (depending on the polling time that was set for that particular pin).

So, I first started by creating a virtual class with only one function: class CSubThread().
#include "iostream"
using std::cout;
using std::endl;

class CSubThread
{
public:
     virtual void RunOnce( void )
     {
         cout << " I ran once... " << endl;
     };
};

Note: "iostream" should in fact be in between left and right triangle characters, but Blogger has problems printing those characters.  It thinks it's an HTML ta issue...

CSubThread() has one function, RunOnce(), that does not take any parameter and also doesn't return anything. You can't have something simpler, I guess...

The purpose is now that other classes will inherit the class CSubThread() and implement the function RunOnce().

The classes that need the polling mechanism, will implement RunOnce() as follows:
void C8575Io::RunOnce( void )
{
    Execute();
}   /* RunOnce */

Since RunOnce() is declared virtual in the base class, other classes can redefine the content of the function according their own needs.

In the above example, RunOnce()--which is a public member of the class C8575Io()-- simply calls a private class Execute() which will do the necessary things to poll the corresponding IO expander.

As you can see, very simple... The public function RunOnce() is simply calling a private function Execute(), which will see if one or more pins of a IO expander has to be polled or not.

How is the function RunOnce() connected to the callback array?

As said before, I wanted to have one thread per "activity", so, one thread for the IO polling, one thread for the temperature polling etc...

The first thing the class C8575Io() must do, is connecting to the IO thread. Now, there are two situations:
  1. The thread for the IO polling is already there
  2. The thread for the IO polling still has to be created.
This is not the concern of the class C8575IO(). This class simply does a call to the message queue class using the following command:
pMsgQueue = CMqMgr::QueueInstance();

Saturday, 9 February 2008

Need for debugging? Well, there is...

When writing programs, ideally spoken you should think hard enough and your code should be "first time right". But as I said, ideally spoken...

Reality is in (can I say) 100% of the cases different: one simply needs at some moment(s) in time a debugger.

For the FoxBoard, that's not so obvious. Ok, I know, there's GDB and you can activate gdbdebugger on the FoxBoard, but still, debugging on the GDB command line is only for the "happy few"...

I myself prefer to have something more graphical.

I've searched quite a bit to find what I was looking for. I've used Eclipse, NetBeans, KDevelop and other exotic applications, but none of them could convince me to used it together with the FoxBoard to debug.

I then found DDD, a graphical debugger that can be connected to the FoxBoard. This one is good, very good even. For those interested, I wrote an article on my Wiki website, which can be read here.

But I was still looking for something more "intuitive", something which looks more to the (sorry Linux guys) Windows debuggers, like there are Visual Studio/Visual Express (why always taking Micro$oft as a reference???). Am I spoiled? Yes, for sure, I am spoiled. At least regarding debug environments...

I finally found Insight, a debugger GUI made by RedHat. This looks very much to what I am used to see on Windows environments.

However, like DDD, Insight is not "right out of the box" useable. The reason is that this debugger is very "versatile": a lot of targets are supported, among them the CRIS one!

You have to download the sources and compile it yourself. But don't worry, I also wrote an article on how to do this on my Wiki pages.
As usual, for the ones interested, they can read the article here.

Overall, I'm quite satisfied about this debugger. Of course, this one too has its advantages and disadvantages, but on a scale of 10, I would give it a 7.

For sure, better than all the rest I've looked into.

Have fun reading the article, building the debugger and applying it on the FoxBoard!

Tuesday, 5 February 2008

Auto log-in? Sure!!!

Hi again,

For the lazy ones among us (I'm definitely adding myself to this group of people...), there's a nice way to log in to the FoxBoard without having to retype the user name (root) and password (pass) over and over again.

This so-called auto log-in can be done from Windows (using Putty), Linux and also CygWin (running under, yep, Windows)

To avoid writing twice the same article (I'm lazy, remember?), I already wrote a complete article on how to set up such construction using a private/public key exchange between the FoxBoard on the one hand and Linux/Windows/CygWin on the other hand.

If you're interested, pls. feel free to read this article on my Wiki.

In case of questions/problems, you can always contact me.

Enjoy!

Thursday, 24 January 2008

Dynamic or static?

A Linux driver is always assigned a major and minor device number. You can see this when you do a ls -als. Go to the /dev directory on your Linux system and execute the before mentioned command.

An example is given below:
[root@axis-00408c012351 /dev]192# ls -als
0 cr--r--r-- 1 root root 61, 0 Jan 20 2008 cam0
0 cr--r--r-- 1 root root 61, 1 Jan 20 2008 cam1
0 cr--r--r-- 1 root root 61, 2 Jan 20 2008 cam2
0 cr--r--r-- 1 root root 61, 3 Jan 20 2008 cam3
0 cr--r--r-- 1 root root 61, 32 Jan 20 2008 camquad
0 crw-rw-rw- 1 root root 91, 0 Jan 20 2008 can0
0 crw-rw-rw- 1 root root 91, 1 Jan 20 2008 can1
0 crw-rw-rw- 1 root root 91, 2 Jan 20 2008 can2
0 crw-r--r-- 1 root root 90, 0 Jan 20 2008 cflash0
0 crw-r--r-- 1 root root 90, 2 Jan 20 2008 cflash1
0 crw-r--r-- 1 root root 90, 4 Jan 20 2008 cflash2
0 crw-r--r-- 1 root root 90, 6 Jan 20 2008 cflash3
0 crw-r--r-- 1 root root 90, 8 Jan 20 2008 cflash4
0 crw-r--r-- 1 root root 90, 10 Jan 20 2008 cflash5
0 crw------- 1 root tty 5, 1 Jan 1 00:00 console
0 crw-r--r-- 1 root root 122, 0 Jan 20 2008 eeprom
0 crw-rw---- 1 root root 193, 0 Jan 20 2008 event

When you look to column 6 and 7 in the above given table, you will see that column 6 represents the major device number and column 7 represents the minor device number.

Since I'm working mainly on the I2C driver on the FoxBoard, I was interested in how this driver was set up.

At the same time, I was reading the (very interesting) book Linux Device Drivers and while reading it, I was especially interested in the chapter handling the devices major and minor numbers.

There was a very interesting statement done, which said to use dynamic device number allocation, in stead of doing it statically.

It was not only the direction to go, it also has the following benefits:
  • The system will take care of the major and minor number allocated at runtime
  • You will not "clash" with a driver which has the same major and minor number
  • You're safe for the future
For me, those were reasons enough to go and see if I could change the major and minor device number allocation of the I2C driver from static to dynamic.

I wrote a whole chapter on my Wiki pages, explaining what I have done to achieve this. Not only was it a challenge, it forced me to learn the mechanisms which were (and still are) used to build the flash images for the FoxBoard.

I don't want to fall into repetition, you can read the whole story here.

After you've done all necessary changes, you will see the effect when restarting the FoxBoard. At a certain moment, you will see that a dynamic major and minor number is requested to the Linux kernel for the device.

You will see that not the number 123 is given as major device number (as is the case with the static situation in the FoxBoard I2C code), but the number 254.

Here's the output when performing an ls -als in the directory /var/dev:
[root@axis-00408c012351 /var/dev]132# ls -als
0 drwxr-xr-x 2 root root 60 Jan 1 00:00 .
0 drwxr-xr-x 10 root root 200 Jan 1 00:00 ..
0 crw-r--r-- 1 root root 254, 0 Jan 1 00:00 i2c

This way, you are sure you won't "clash" with some other driver using the same major and minor numbers and you're sure you're following the advice of authorities in the Linux domain (writers of the Linux Device Driver book).

Sunday, 20 January 2008

What the... * Error -d is not a supported platform

Back again with some news.

As already mentioned in a previous blog, I had to re-install my Kubuntu on VmWare.

Once this was done, I also re-installed the FoxBoard SDK from scratch. However, when running the initial compilation, I quickly got the following error message on the screen, after which the installation ended:
install -p -d     /home/fb/devboard-R2_01/tools/build-R2_12_4/bin
* Error -d is not a supported platform

I couldn't get any further, also the command ./configure was facing the same problem.

After several tries and a lot of thinking (that hurts, you know!), I decided to analyse the whole installation script (install_svn_sdk.sh).

It took me a bit of time, but I got quite quickly an "eagle's view" on how the installation worked.

I executed the commands step by step on the command line and I saw the error I gave above, appeared when I executed the following command:
A=`yes n | \`make oldconfig 2&> install.log\``

The result I got, was the following:
make tools
make[1]: Entering directory `/home/foxboard/devboard-R2_01'
make -C tools/build install
make[2]: Entering directory `/home/foxboard/devboard-R2_01/tools/build-R2_12_4'
make -C ccdv install BINDIR="/home/foxboard/devboard-R2_01/tools/build-R2_12_4/bin" LIBDIR="/home/foxboard/devboard-R2_01/tools/build-R2_12_4/lib"
make[3]: Entering directory `/home/foxboard/devboard-R2_01/tools/build-R2_12_4/ccdv'
gcc -Wall -Wshadow -I/home/foxboard/devboard-R2_01/target/host/include -O0 -g -fno-omit-frame-pointer -L/home/foxboard/devboard-R2_01/target/host/lib -Wl,-rpath-link,/home/foxboard/devboard-R2_01/target/host/lib ccdv.c -o ccdv
install -p -d /home/foxboard/devboard-R2_01/tools/build-R2_12_4/bin
* Error -p is not a supported platform
make[3]: *** [install] Error 1
make[3]: Leaving directory `/home/foxboard/devboard-R2_01/tools/build-R2_12_4/ccdv'
make[2]: *** [ccdv] Error 2
make[2]: Leaving directory `/home/foxboard/devboard-R2_01/tools/build-R2_12_4'
make[1]: *** [tools] Error 2
make[1]: Leaving directory `/home/foxboard/devboard-R2_01'
make: *** [/home/foxboard/devboard-R2_01/tools/build/bin/aconf] Error 2

Then the search started to find out where the error could come from.

As a last exit, I tried to run the installation as root and to my surprise, I was able to install everything. Only later, it was clear to me as to why that was possible (see further).

Reverting back to a regular user, I tried over and over again, going bit by bit deeper into the problem.

I followed the call to make oldconfig (the one that failed) and when looking to the makefile in ./devboard-R2.01-1, I found out that the target oldconfig was defined as follows:
## oldconfig - Updates the product configuration.
##
.PHONY: oldconfig
oldconfig: $(AXIS_TOP_DIR)/tools/build/bin/aconf
@$(AXIS_TOP_DIR)/tools/build/bin/aconf -o configure-files/common/AC_common
@touch Makefile

So, first the target $(AXIS_TOP_DIR)/tools/build/bin/aconf in the same makefile was executed. This target was defined as follows:
$(AXIS_TOP_DIR)/tools/build/bin/aconf $(AXIS_TOP_DIR)/tools/build/bin/amconf:
$(MAKE) tools

Here I saw the same makefile was called again, with the target tools. The following was defined for that target:
## tools - Builds and installs all tools on this host.
##
.PHONY: tools
tools:
$(MAKE) -C tools/build install

So, I saw the makefile in /tools/build was called, with target install.

Going to that makefile, I saw the target install was defined as follows:
install:        $(ISUBDIRS) install_e100boot install_fsboot
@echo "Installation of build tools complete."

That means, I had to look for the content of variable $(ISUBDIRS). This was defined as follows:
ISUBDIRS :=
ccdv \
scripts \
aconfig \
filepp \
genromfs \
imgsum \
mkcramfs \
mkfs.jffs \
mkfs.jffs2
profile \
sermon \
sortdir \
tcptest \
Now I knew what command was filling ./devboard-R2.01-1/tools/build/bin!

When looking close into the makefile, I saw at the beginning the following definition:

INSTALL ?= install -p
export INSTALL

So, here the Linux command install -p was put under the variable INSTALL and then exported to the whole FoxBoard SDK.

That means, everywhere where there was a call to $(INSTALL), it was replaced by install -p.

Finally, I found where the install -p came from!!!

Now, when I executed the command "which install", I saw to my big surprise I was not getting the executable install, located in /usr/bin, but the script install instead, located in ./devboard-R2.01-1!!!

The picture was clear to me now. For one reason or another, the incorrect install was called!
I started digging into the paths and what I see was the following:

- I had extended the standard PATH variable with a couple of paths I'm frequently using, among others, the path ./devboard-R2.01-1.

- But more important: I'd added my personal paths in front of the system paths! So, when looking for the command install, the OS found one in the ./devboard-R2.01-1 directory, so there was no reason to go further along the path to look for another install!

It was clear now: in stead of calling the executable install, all FoxBoard SDK's were in fact calling the script install. Needless to say that a "target" -p indeed resulted in the error given at the top of that article.

Since I knew the real cause, I simply solved it by changing the order the PATH environment variable was build up: first the system directories/paths and only then adding my own paths!!!

This solved the issue, but still I think it's not wise to have a script having the same name as an executable. Therefore, I requested to AcmeSystems if they're willing to change the script install into installfoxsdk (or something like that).

Let's see what the outcome is!

What I've learned is, especially here, that it's very important to know the way the directory structure is traversed, if the OS is looking for an executable.

Also, having a script the same name as an executable isn't a wise choice, but that's my humble opinion.

And finally, why was I able to run the scripts as a root? Well, simply because for the user root, the paths were not "polluted" with the FoxBoard paths. That is, install was really the executable install, not the script install!!!

Learning all the time...

Wednesday, 9 January 2008

Small disaster happened

First off, a happy and prosperous new year for the people reading this blog!

The day before Christmas, I was working again (of course) on my domotics system. While doing an update of my Kubuntu 6.10 virtual machine, I was told I could upgrade to Kubuntu 7.10.

Since I'm always quite eager to do this (being up-to-date with my applications/OS), I took the risk to start the upgrade.

All went fine, until the moment I lost my internet connection on my virtual machine. Shortly after, I got the message that the system could not download any more the remaining parts of the upgrade.

And there I stood... A system which was half-half upgraded but that could not access the internet any more. Even worse, my samba connection was gone too, so I could not even reach my virtual machine from my Windows environment any more. Sad, sad, sad...

I've been looking on the internet, asked for some advice, but nobody that could help me get my internet connection back on my virtual machine.

Luckily, I'm taking a weekly backup of the software I've written for my domotics system, so I was quite confident I was not going to loose the most important thing.

In the end, the only thing I could do was buying a new harddisk and install Kubuntu 7.10 from scratch. I definitely didn't want to re-install what I still had, because one day or another there might be things I need on my new installation that are still only available on my, well, call it from now onwards "back-up".

The biggest problem now will be to have the state of the new virtual machine equal to the state of the old one.

Since I installed quite a bit of apps (going from FoxBoard stuff to debugging tools to editing tools to Kubuntu tools), it will take me still a lot of time to get on the same level again. This has been 14 days now, so I lost quite a bit of time.

In the mean time, I've re-installed the FoxBoard SDK on the new distro and bit by bit I will try to get to the level I had on my old distro.

Conclusion: be very careful with upgrades. If I want to do an upgrade in the (near) future, I will definitely start from scratch and as long as the new situation has not reached the level of the old situation, I won't change anything any more to the stable environment.

I've learned my lessons, I would say. So, be warned... ;-)