At the last Embedded Linux Conference Europe I gave a presentation about my experience of porting Android (Ice Cream Sandwich) to a new custom board.
I hoped that people will find my presentation useful although there a several other good ressources as a presentation at the Android Builders Summit and good information at the elinux wiki.
You can find the slides here. Thanks to the guys from Free Electrons my speech, as well as all the others, were recorded and are available here.
In my presentation I tried to concentrate more the different system components of Android and how they are interacting. Please beware that, depending on your experience with Linux, some of the explanations might not be totally new to you, but they were for me.
I hope you find the presentation helpfull.
These days I tried to figure out, why my custom board didn’t generat the right video output for HDMI TV screens. Especially I wanted to add the 720p and 480p standard to my Linux kernel, to be able to show the desktop on any TV screen, which supports HDMI input with this standard.
My first problem was, that the CEA-861-x standard is not freely available and information on the web is quite sparse. But I was lucky and found this great post on the beagleboard mainlinglist.
I will try to sum up the hands-on part of it, so that it’s easier to calculate timings yourself. In my case, I afterwards added the values to the database in drivers/video/modedb.c with a special name (hd720 and hd480). So on boot-up I can tell the kernel which mode I want to use on my HDMI interface. Notice that I use a custom kernel based on version 2.6.37.
Ok let’s start.
First of all, the resolution you will see on your screen is not the real size of the framebuffer you need. To the framebuffer horizontal axis a horizontal blanking is added, and to the vertical axis a vertical blanking. This depends on the mode you want to display on your screen and varies (e.g. between 720p and 480p).
With this values you can calculate the real size, and therefore pixclock value, which is needed by the Linux kernel, to know how long it needs to update one pixel. The pixclock value is given in pico seconds, whereas the update frequency of your screen is given in Hz (1/seconds).
So to get the pixclock value, use the following formula:
real_horizontal_size x real_vertical_size x pixclock x 10^-12 = frequency
Let’s see how this works on a real example. I found a table with timing constrains for the standards, not sure if they are the original ones (they are protected by law), but I implemented the 480p standart and it works for me…
So let’s go. We can see the horizontal and vertical total number of pixel. This number is the sum of front porch, sync and back porch. This means, the sum of these three values equals the horizontal and vertical blanking. Let’s calculate the pixclock then:
880 x 525 x pixclock x 10^(-12) = 60 Hz
Some easy math brings us the the pixclock value of 36075 ps.
Great, let’s go on and find the horizontal sync (hsync) and vertical sync (vsync). We can read this values directly from the table. I found an implementation of 720p which uses the half of the hsync value, but I don’t know why. I tried to implement the standart with half of the hsync value, but found it difficult to calibrate in the end. Later more on that.
Alright, we take a hsync of 40 and a vsync of 3.
I don’t know the details of the 480p standart but the post mentioned above states that left margin and upper margin are fixed values in 720p.
So we assing the horizontal back porch to the left margin and the vertical front porch to the upper margin. To calculate the right margin and the lower margin use the following formulas:
right_margin = horizontal_blanking – hsync – left_margin
lower_margin = vertical_blanking – vsync – upper_margin
So you can see, that lower margin and upper margin (as well as right and left margin) are in a linear relationship. That means if you increment the upper margin by 5 (for scaling) you have to decrement the lower margin by 5 as well.
You see, as I’m talking about scaling by hand (!) it seems that the table I mentioned, isn’t totally correct. But at least for me it was a good strarting point to do the math and in the end get a picture on the screen. Afterwards I had to scale the left and right margin by hand, to get a good result on my Samsung SyncMaster B2030HD as well as on my OKI V32A-FH television.
That’s it, I hope you found this entry helpfull. As you can see, I’m not an expert in this stuff and there might be errors in the explanation, please don’t hesitate to correct me, to make this a usefull information for others.
Filed under: Noticias
It seems that ubuntu has changed the way you have to compile a kernel and install it. In older versions you used the make-kpkg tool to build debian pakages. In the version I use these days (11.10) I do it this way:
- get the linux source tree, unpack it.
- sudo make menuconfig
- sudo make
- sudo make modules_install install
After waiting quite a while, everything is done, even your grub menu was updated. So enjoy your machine…
… unless you have a Nvidia card. In this case you might have some trouble:
Your system might freeze with a black screen and you won’t be able to use any console with Ctrl+Alt+F1…
The solution is to start the kernel in recovery mode, log-in and execute the following command:
sudo jockey-text -e xorg:nvidia-current
This will update the Xorg config. Be sure that the nvidia-current kernel module is installed on your machine. You might need to reinstall your nvidia package first:
sudo apt-get install –reinstall nvidia-current
Have fun!
Filed under: hint
MADBench2 is a benchmarking tool to simulate high performance computing (HPC). I used it to evaluate some ideas for a project.
As it took me some time to get it compiled and running so I add a patch file here. Just patching the source code folder should do it.
diff -rupN madbenc2.orig//hostfile madbenc2//hostfile --- madbenc2.orig//hostfile 1970-01-01 01:00:00.000000000 +0100 +++ madbenc2//hostfile 2011-04-14 15:41:27.439836179 +0200 @@ -0,0 +1 @@ +localhost diff -rupN madbenc2.orig//MADbench2.c madbenc2//MADbench2.c --- madbenc2.orig//MADbench2.c 2006-10-12 23:16:40.000000000 +0200 +++ madbenc2//MADbench2.c 2011-04-14 15:22:26.678836179 +0200 @@ -6,12 +6,17 @@ /* jdborrill@lbl.gov */ /*****************************/ +#define _LARGEFILE64_SOURCE + #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/stat.h> #include <math.h> -#include "mpi.h" +#include <mpi.h> +#include <string.h> + + #include "MADbench2.h" #define PCOUNT 8 diff -rupN madbenc2.orig//Makefile madbenc2//Makefile --- madbenc2.orig//Makefile 2011-03-25 16:06:48.464573544 +0100 +++ madbenc2//Makefile 2011-04-14 15:38:42.805174338 +0200 @@ -0,0 +1,12 @@ +MPI_HEADER=/opt/mpich/ch-p4/include/ +MPI_LIBS=/opt/mpich/ch-p4/lib64 + +all: + mpicc -D SYSTEM -D IO MADbench2.c -isystem $(MPI_HEADER) -lmpich -L$(MPI_LIBS) -lm -o MADbench2 + +clean: + rm MADbench2 MADbench2.o + diff -rupN madbenc2.orig//run.sh madbenc2//run.sh --- madbenc2.orig//run.sh 2011-03-25 16:08:39.173698549 +0100 +++ madbenc2//run.sh 2011-04-14 16:07:36.359773210 +0200 @@ -0,0 +1,22 @@ +#!/bin/bash + +NO_PIX='1000' +NO_BIN='160' +NO_GANG='1' +SBLOCKSIZE='32K' +FBLOCKSIZE='32K' +RMOD='4' +WMOD='4' + +export IOMETHOD="POSIX" +export IOMODE="SYNC" +export FILETYPE="SHARED" +export REMAP="CUSTOM" +export BWEXP='1' + +export LD_LIBRARY_PATH=/usr/lib64/mpi/gcc/openmpi/lib64 +mpirun -np 4 -v -v ./MADbench2 $NO_PIX $NO_BIN $NO_GANG $SBLOCKSIZE $FBLOCKSIZE $RMOD $WMOD
I also added to the patch a script on how to run the program. Especially take care if you want to change the exported execution commands, be sure that they are added to the .bashrc file in every computation node.
Hope you find it useful.
Filed under: hint
The glibc exposes a function to get the time difference between two time_t structures (difftime). But what when you need some more accurate time? Normaly you use gettimeofday.
Libc lacks an implementation to compare two times achieved calling gettimeofday, so here comes my implementation.
Comments on this? The function gettimeofday gives you a really fine grained time in seconds and microseconds that happend since the Epoch (00:00:00 UTC, January 1, 1970). However remember that when you use my function, it will take some time to calculate the differences. Depending on your hardware, software and the real-time aspects of your application, the implementation might not fit your needs.
Anyway, here we go. As always comments are highly appreciated…
// This function stores the result in dtv of a older (otv) and newer (ntv) time.
#include <sys/time.h>
int time_diff(struct timeval otv, struct timeval ntv, struct timeval *dtv)
{
if(ntv.tv_sec < otv.tv_sec)
return -1;
else if(ntv.tv_sec == otv.tv_sec && ntv.tv_usec >= otv.tv_usec) {
dtv->tv_sec = 0;
dtv->tv_usec = ntv.tv_usec - otv.tv_usec;
} else { // ntv->tv_sec > otv.tv_sec
if(otv.tv_usec > ntv.tv_usec) {
dtv->tv_sec = ntv.tv_sec - 1 - otv.tv_sec;
dtv->tv_usec = ntv.tv_usec + 1000000 - otv.tv_usec;
} else {
dtv->tv_sec = ntv.tv_sec - otv.tv_sec;
dtv->tv_usec = ntv.tv_usec - otv.tv_usec;
}
}
return 0;
}
OpenSUSE dirstribution includes a modified kernel for using xen as dom0 host.
But it has some drawbacks.
1. yast doesn’t set the hypervisor parameter right. instead of “vga=mode-0×314″ it sets “vgamode=0×314″. You have to change this by hand in the bootloader menu.
2. nvidia graphic drivers does not support xen. Therefor you have to install it from hand. First of all you need kernel-source and xen-dev packages. Get the driver from the nvidia repository and save it somewhere like in /root.
Start your computer with the xen kernel.
Change to init 3 level.
Then type:
“export IGNORE_XEN_PRESENCE=1 SYSSRC= SYSOUT=” e. g.
export IGNORE_XEN_PRESENCE=1 SYSSRC=/usr/src/linux-2.6.34.7-0.3 SYSOUT=/usr/src/linux-2.6.34.7-0.3-obj/x86_64/xen
Afterwards install the nvidia driver: sh ./NVIDIA-Linux-x86_64-256.53.run
Changing to run level 5 (init 5) should show you the X-login screen.
Well done!
Filed under: hint
As a computer scientist, reading schematics for electronic devices was one of the things I had to learn at work. And I really appreciate it.
But I’m not an electronic engineer, that’s why I don’t have to understand every part of the design, but the big picture. Although I’m really keen on schematics, so I try to learn some new stuff every now and then. So lately I recognized a diode in some circuits, and I had no clue what it’s for:
This is a reset circuit. When the button S is pushed, the RESET of the CPU goes low, so that the CPU will be hold in reset until RESET goes high again. Resistor R2 acts as a voltage delimiter so that the capacitor C won’t get harmed. The capacitor will planish the current running, so that we won’t get any reset, because VDD (+5V) has minor inteferences. With resistor R1 you can regulate, how long you have to push the button to get a reset signal.
So now the clue, what’s the diode D for? Well imagine you take away VDD and put it quickly, something that happens often, especially in production stage. In this case, VDD will be ground, but the voltage won’t be able to flow there quickly, as it has to pass R1. So it may happen that the CPU was not set into a reset state, if you turn VDD off and on quickly. Therefore the diode exists. When VDD is disconnected, the diode will allow the current to flow quickly to ground but it won’t allow to pass through if VDD is 5V.
This is just trivial for an hardware engineer, and to me it show’s that physics at school is actually useful.
