venerdì 21 marzo 2014

GDB and Geany IDE: Remote Cross Debugging

Embedded Linux System Debugging with Geany


Remote debugging is when GDB runs on one machine and the program being debugged runs on another. This is useful in embedded systems, and often in this case it's called remote cross-debugging because the target CPU is differerent from the host used for developing code.
gdbserver can be used to remotely debug the program without needing to change it in any way.

The Geany IDE debugger plugin does not support remote debugging natively. Some graphical debugger such as Insight or the Eclipse IDE support it, but not Geany. And I like Geany very much, while I don't like Eclipse: so I arranged a patch/workaround to do it (based on plugin version 0.21).


Compiling the patch

Download geany plugins sources [http://plugins.geany.org/downloads.html] and install geany and gtk devel packages for your distribution. You'll need also Geany devel package installed. Compiling debugger plugin needs also vte-devel package installed.
  # cd geany-plugins-0.21.1
  # ./configure --prefix=/usr --mandir=/usr/share/man/
  # cd debugger/src
  # make

Compiled plugin is in the debugger/src/.libs/ directory (debugger.so). You will need to copy it in /usr/lib/geany (or where your distribution places the geany plugins), or install it with:
  make install

Geany can use an addictional path for plugins search (see Geany options), and if you want to use it you will have to configure the sources with:
  # ./configure --prefix=/your/path/to/plugins --mandir=/usr/share/man/

Here below the patch for dbm_gdb.c file:

  --- geany-plugins-0.21.1/debugger/src/dbm_gdb.c.original
  +++ geany-plugins-0.21.1/debugger/src/dbm_gdb.c
  @@ -96,6 +96,9 @@
   
   /* flag, showing that on debugger stop we have to call a callback */
   gboolean requested_interrupt = FALSE;
  +
  +/* flag: remote debugging session*/
  +gboolean remote_session = FALSE;
   
   /* autos list */
   static GList *autos = NULL;
  @@ -598,6 +601,9 @@
    */
   gboolean load(char* file, char* commandline, GList* env, GList *witer)
   {
  +char *ip;
  +char *port;
  +
    /* loading file */
    GString *command = g_string_new("");
    g_string_printf(command, "-file-exec-and-symbols %s", file);
  @@ -610,11 +616,38 @@
     return FALSE;
    }
   
  - /* set arguments */
  - command = g_string_new("");
  - g_string_printf(command, "-exec-arguments %s", commandline);
  - exec_sync_command(command->str, TRUE, NULL);
  - g_string_free(command, TRUE);
  + /* is it a remote target? */
  + /* (remote sessions handle commandline on debugserver side) */
  + if (commandline[0] == '@') {
  +  ip = commandline + 1;
  +  port = strchr(ip, ':');
  +  if (port != NULL) {
  +   *port = '\0';
  +   port++;
  +  }
  +  else {
  +   port = (char *)"3278";
  +  }
  +  if (ip == '\0') {
  +   ip = (char *)"127.0.0.1";
  +  }
  +  if (port == '\0') {
  +   port = (char *)"3278";
  +  }
  +  command = g_string_new("");
  +  g_string_printf(command, "target remote %s:%s", ip, port);
  +  exec_sync_command(command->str, TRUE, NULL);
  +  g_string_free(command, TRUE);
  +  remote_session = TRUE;
  + }
  + /* set arguments in non-remote sessions */
  + else {
  +  remote_session = FALSE;
  +  command = g_string_new("");
  +  g_string_printf(command, "-exec-arguments %s", commandline);
  +  exec_sync_command(command->str, TRUE, NULL);
  +  g_string_free(command, TRUE);
  + }
    
    /* set locale */
    command = g_string_new("");
  @@ -678,7 +711,14 @@
    }
    free_start_messages();
   
  - exec_async_command("-exec-run &");
  + if (remote_session) {
  +  exec_async_command("break main");
  +  sleep(2);
  +  exec_async_command("continue");
  + }
  + else {
  +  exec_async_command("-exec-run &");
  + }
   }
   
   /*
  @@ -686,6 +726,9 @@
    */
   void restart(char* terminal_device)
   {
  + if (remote_session) {
  +  dbg_cbs->report_error(_("Restart command not available in remote sessions"));
  + }
    dbg_cbs->clear_messages();
    exec_async_command("-exec-run &");
   }


Remote debugging

After compiling and installing this patched plugin, enable Debugger plugin in Geany. Remote debugging can be used inserting in the debugger plugin tab "Command Line" field the following format string:
  @remoteipaddr:port

for example:
  @192.168.2.51:4567

If you don't specify remoteipaddr, the default used is 127.0.0.1; if you don't specify port, the default used is 3278.

On the remote side, you'll have to start gdbserver:
  # gdbserver localhost:4567 yourprogram [yourprogram options]

Command options must be specified on the gdbserver side, when debugging remotely.


Cross debugging

The remote device can be a target CPU different from the host. For example it could be an embedded ARM Linux board. In this case you have to use a shell script to start geany with the correct path for the right gdb executable (x86 gdb executable can not debug other target CPUs than x86); let's suppose your ARM gdb executable is gdb-arm-linux (you can download it from emdebian: gdb-arm-linux-gnueabi_7.2-1_i386.deb) and you installed it in your ~/bin/arm-linux-emdebian/usr/bin/ directory:
  • create a symlink gdb to gdb-arm-linux:
      # cd ~/bin/arm-linux-emdebian/usr/bin/
    
      # ln -s gdb-arm-linux gdb
    
  • then create a shell script like this and use it for starting Geany:
      #!/bin/sh
      PATH=/home/yourhome/bin/arm-linux-emdebian/usr/bin/:$PATH
      geany $1
    
    
    

Notes

A few notes on remote debugging use:
  • don't use "Restart" command in remote debugging session: it can't be used
  • a breakpoint is automatically placed at main start (break main) so program stops there after first run, but it's not shown in Geany
  • place manually yourself a breakpoint in the place where program stops initially: it will prevents other breakpoints garbage later
This does not want to be a definitive solution: it's a dirty patch/workaround for my needs.

venerdì 14 febbraio 2014

Eizo EV2316W: xrandr settings

Setting up Eizo Flexscan EV2316W LCD Monitor under Linux with xrandr


Using OpenSuse 11.4 and a DELL d820 laptop.

The monitor supports a max pixel clock of 148.50:

# xrandr --newmode "1920x1080"  148.50  1920 2008 2052 2200  1080 1084 1089 1125 +hsync +vsync
# xrandr --addmode VGA 1920x1080

# xrandr --output LVDS --off
# xrandr --output VGA --mode 1920x1080


If you are using KDE4 you may experiment a "mouse disappear" problem after changing screen resolution as shown; the only workaroud I found is the following (needs sudo):

# sudo /bin/chvt 1; sudo /bin/chvt 7

Here below a script for automating this:

Philips 226V4LAB: xrandr settings

Setting up Philips 226V4LAB LCD Monitor under Linux with xrandr



Using OpenSuse 11.4 and an old eeePC 701.

The monitor seems to support a max pixel clock of 138.50:

# xrandr --newmode "1920x1080R"  138.50  1920 1968 2000 2080  1080 1083 1088 1111 +hsync -vsync
# xrandr --addmode VGA1 1920x1080R

# xrandr --output VGA1 --rate 59.9* --mode 1920x1080R
# xrandr --output VGA1 --rate 59.9* --mode 1920x1080R --output LVDS1 --off



Here below a script for automating this:

mercoledì 12 febbraio 2014

Scelta del monitor


Parametri di selezione per un video LCD da programmatore
Recentemente mi sono trovato a voler acquistare un nuovo monitor da collegare al mio PC portatile quando e' in configurazione "dock", cioe' quando non lo uso come laptop ma in modo piu' simile ad un desktop. Ho fatto dunque delle ricerche e delle riflessioni sui parametri di scelta da usare che puo' essere utile ricordare.

L'utilizzo che faccio del monitor e' lavorativo, e nello specifico quello dello sviluppatore elettronico embedded: CAD elettronico, documentazione, navigazione internet, email, ma soprattutto programmazione software e firmware (quindi editor di testo, finestre terminale). Tutte le mie considerazioni sono da riferire a questo utilizzo.

Uso sempre solo Linux.


Dimensioni

Mi sono orientato intorno ai 20": penso che meno di 17" sia inutile rispetto al video del laptop, e piu' di 24 non adatto all'uso che ne faccio. 21" o 23" sono perfetti.


Tipologia pannello

TN o IPS? Opaco o lucido? Retroilluminazione?


TN o IPS?

TN e' la tecnologia piu' vecchia:
  • ha tempo di risposta leggermente piu' basso, quindi e' piu' veloce (positivo)
  • costa meno (positivo)
  • ha una resa colori meno realistica (negativo)
  • ha un angolo di visione verticale meno esteso (negativo)
Al contrario, IPS e' una tecnologia piu' recente, i cui unici aspetti negativi sono che costa di piu' ed ha un tempo di reazione leggermente piu' alto (typ. 6~10ms contro i 5ms dei TN). In considerazione dell'utilizzo che ne faccio, in cui la resa colori e la velocita' sono secondari, mi sono orientato su un TN.


Opaco o lucido?

Il video lucido attira l'attenzione e sembra piu' bello, ma e' solo un'impressione estetica: riflette di piu' la luce e stanca gli occhi, quindi e' meglio un video OPACO.


Retroilluminazione?

La possibilita' di regolare finemente luminosita', contrasto e temperatura di colore e' molto importante per la qualita' della visione e stanchezza dell'occhio.
Oggi tutti i video sono retroilluminati a LED, perche' costa meno, consuma meno, da' una luminosita' e contrasto maggiori, una resa dei colori migliore, dura di piu'.
Questo tipo di retroilluminazione pero' ha un grosso svantaggio: la regolazione della luminosita' e' fatta con una tecnica che si chiama "PWM" e consiste nell'accendere e spegnere ad una frequenza relativamente alta i LED; maggiore e' il tempo in cui stanno accesi rispetto a quello in cui stanno spenti, maggiore e' la luminosita' media prodotta.
Questo metodo funziona bene con le fonti luminose ad alta persistenza, cioe' che ci mettono un po' di tempo ad accendersi ed un altro po' a spegnersi: in tal caso infatti la luminosita' risultante e' veramente la media di ON e OFF della fonte luminosa; i LED purtroppo (per questa tecnica) hanno una velocita' di accensione e spegnimento elevatissima, quindi bassissima persistenza, quindi si accendono e spengono veramente durante i cicli di ON e OFF del PWM. Il risultato e' che chi ha occhi molto sensibili alla persistenza vede il video "vibrare" alle basse luminosita', soprattutto se la frequenza del PWM non e' elevatissima. Questo effetto e' chiamato "flickering", ed e' visibile da circa il 10% della popolazione (io sono tra questi). Anche chi non ricade in quel 10% che vede il fenomeno, inconsciamente si stanca di piu' lavorando su un video con flickering, e puo' essere anche soggetto a mal di testa verso fine giornata.
Per evitare del tutto il flickering i LED andrebbero controllati in corrente, ma cio' comporterebbe due problemi:
  • costo maggiore
  • cattiva resa dei colori
Al momento c'e' un solo produttore al mondo che si e' ingegnato per risolvere questo problema: EIZO ha rilasciato a Novembre 2013 una serie di video con tecnologia chiamata "EyeCare" che regola la luminosita' con un misto di PWM e corrente.
[http://www.tomshw.it/cont/news/eizo-eyecare-stop-ai-mal-di-testa-davanti-al-monitor/43828/1.html]


Consumo

Chissenefrega del consumo, un LCD a LED comunque non consuma niente. EnergyStar aveva senso con i video CRT.


Marca

Credo che tutti i pannelli LCD siano in realta' prodotti da una o due marche cinesi al mondo, probabilmente una delle quali e' LG. Questo potrebbe far pensare che non abbia senso prendere altre marche, ma non e' vero: il controllo delle regolazioni, gli optional, la retroilluminazione e il controllo di qualita' sono fatti dalla marca che li vende, e sono cose che contano. Sui monitor di fascia bassa inoltre non e' raro trovare dei pixel guasti, e normalmente il produttore accetta la sostituzione solo se sono piu' di 4 o 5; marche blasonate non hanno questo problema (di solito).


Scelte

Ho acquistato due monitor, uno per uso intensivo ed uno per uso occasionale.


Eizo Flexscan EV2316W LCD Monitor

23", TN, retroilluminazione LED EyeCare, 1920x1080. Molto soddisfacente, possibilita' di regolazioni finissime e numerose. Ottimo, anche se un po' costoso. Con il video all'altezza degli occhi si nota leggermente la differenza di colore tra la parte alta e la parte bassa (angolo di visualizzazione verticale), che probabilmente in un pannello IPS non si noterebbe (per 100 euro in piu').
Dotato anche di hub USB per collegare direttamente tastiera e mouse, altoparlanti, supporto girevole per la visione verticale, sensore luce ambiente per l'auto-adeguamento della luminosita'. Il manuale e' completissimo, con tutte le informazioni necessarie per impostarne l'uso anche su X11 Linux (xrandr).


Philips 226V4LAB LCD Monitor

21.5", TN, 1920x1080. Abbastanza scarso; appena sufficiente solo se usato alla massima definizione. Prezzo ottimo, pero' (un terzo del EIZO) e definizione massima buona. Possibilita' di regolazioni scarse e poco fini. Non sarebbe adatto se ne facessi un uso intensivo, e forse non mi soddisfa nemmeno per l'uso occasionale. Alle basse luminosita' si vede il flickering (o meglio: io lo vedo). Il manuale e' scarso (il pixel clock massimo, ad esempio, non l'ho trovato). Tutto sommato e' appena accettabile solo perche' costa poco e lo uso poco.

domenica 9 febbraio 2014

Del perche' la lampada a basso consumo sucks


Ho nostalgia della cara, vecchia illuminazione artificiale a incandescenza; le lampadine a basso consumo mi fanno schifo!

1) Costano 10 volte tanto le lampadine ad incancescenza: OTTO euro, dico otto euro minimo. Non se ne trovano a meno. Si, magari in un discount trovi lo scaffale con quelle a due euro, ma sono rottami che a malapena si accendono. Una lampadina standard quanto costava? Un euro? due? Zerocinquanta?

2) Durano UGUALE a quelle standard. Questa e' la mia percezione, non un dato oggettivo: mi sembra che si rompano con la stessa frequenza delle vecchie lampadine. Magari durano un po' di piu', ma poco. E non me ne accorgo.

3) Fanno una luce atroce. Alcune (quelle da DUE euro di cui sopra) secondo me fanno BUIO: attirano la luce ambiente come piccoli, malevoli buchi neri. Producono una luce vibrante, ci mettono un quarto d'ora ad accendersi e mezz'ora ad arrivare alla luce emessa massima; ho tre lampadine a basso consumo in bagno e rischio di tagliarmi quando mi faccio la barba se non mi alzo mezz'ora prima per accenderle!

4) COME CA**O PENSANO DI SMALTIRE QUELLE ROTTE? Una lampadina classica era un pezzo di vetro pieno di vuoto (o gas inerte) con un po' di latta: reciclabile al 100%, costo zero. Una lampadina a basso consumo e' fatta di: plastica, metallo, vetro, gas (non si sa bene quale e quanto dannoso sia), circuito stampato, stagno, rame, componenti elettronici vari. E forse ho dimenticato qualche pezzo.
NON E' RECICLABILE. Infatti non si sa mai dove buttarla.

5) Mi rompono le balle con la coscienza ecologica, e poi sul viale fuori casa c'e' accesa per tutta la notte un'alogena da centomilioni di kilowatt ogni cinque metri. Bah.

Spero solo nell'avvento dei LED, che pero' porteranno con se' il problema del flickering nella regolazione della luminosita' (problema gia' presente nei monitor LCD retroilluminati a LED).

venerdì 31 gennaio 2014

Install skype 4.2 on a linux system without GLIBCXX_3.4.15


Install Skype 4.2 on OpenSuSE 11.4

(a system without GLIBCXX_3.4.15)

OpenSuSE 11.4 lacks GLIBCXX_3.4.15 (has GLIBCXX_3.4.14 only), while Skype 4.2 needs it.
You can verify which GLIBCXX you have installed with:
strings /usr/lib/libstdc++.so.6 | grep GLIBC

It is possible to install it anyway:
  • Download Skype 4.2 for OpenSuSE 12.1 from [http://www.skype.com/it/download-skype/skype-for-linux/]
  • Install skype ignoring the failed dependency warning
  • Downlad libstdc++6-4.7.3_20130411-96.1.i586.rpm from [http://download.opensuse.org/repositories/devel:/gcc/openSUSE_12.2/i586/]
  • Copy libstdc++6-4.7.3_20130411-96.1.i586.rpm in your ~/bin directory or somewhere else in your home
  • cd ~/bin (or wherever you copied the rpm)
  • Extract locally the rpm file with the command: rpm2cpio libstdc++6-4.7.3_20130411-96.1.i586.rpm | cpio -idmv
  • Run skype from a terminal with the command: LD_LIBRARY_PATH=/home/yourname/bin/usr/lib/:/usr/lib/:/usr/local/lib/ skype
The method described here does not break any dependency nor install system libraries unsupported for your system.

domenica 29 dicembre 2013

Define TRUE and FALSE in C

What is FALSE and TRUE in C?


The C standard does not explicitly define TRUE and FALSE, you have to do it somewhere in your headers. Which is the best practice to define them?
It's not such a dumb question, because you may fall in this case:
  #define MASKBIT_0    0x01
  #define MASKBIT_1    0x02
  #define MASKBIT_2    0x04
  ...
  
  unsigned int bits;
  ...
  
  if (bits & MASKBIT_2) {
  ...
  }
  
The example above works correctly, but if you are somewhere absent and you accidentally write:
  #define FALSE         0
  #define TRUE          1
  
  if ((bits & MASKBIT_2) == TRUE) {
  ...
  }
The "if" test will fail, also if MASKBIT_2 is set. This is because ((bits & MASKBIT_2) == 4), that is not 1 (your defined TRUE).

To be honest, the problem is that writing if ((bits & MASKBIT_2) == TRUE) is not correct (you should use the if (bits & MASKBIT_2) semantics), but it's obvious what it means and I'd prefer there was a way to define TRUE and FALSE so that this kind of test would be supported.

Approach 1

  #define FALSE         0
  #define TRUE          1

As shown above, it's not a so good approach, although works in most cases.

Approach 2

Some experienced programmer ("The Linux Programming Interface", not exactly a johnny-come-lately...) suggest the following:
  typedef enum { FALSE, TRUE } Boolean;

The reasons for that are good: enum will add some static-assign-checking of the Boolean declared variables. Not so much checking indeed, enum is not a great checker in C: can't check dinamically assigned varibles, and enum variables are typically int.

Approach 3

Other experienced programmer (i.e. gnome glib) suggest that:
  #define FALSE         0
  #define TRUE          (!(FALSE))

This is another good approach: the FALSE condition in C/C++ is ALWAYS == 0; on the contrary, TRUE condition is not always 0, but usually is a "NOT 0" condition. On the other side, the if ((bits & MASKBIT_2) == TRUE) test will fail anyway: (!(FALSE)) is expanded as a constant (usually 1). There is no static-assign-checking.

Beside that, someone suggest:
  #define TRUE         (1==1)
  #define FALSE        (!TRUE)

Rather than this, I like more:
  #define FALSE        (1==0)
  #define TRUE         (!(FALSE))
  
In this way, you automatically assign the FALSE value also if (for a strange, rare case) your compiler DOES NOT use 0 as a FALSE value, and you assign a TRUE as the negation. This is "logically" good, but does not solve che if ((bits & MASKBIT_2) == TRUE) problem.

The MIX

So what I could do to mix-up the best practices?
Here it is:
  typedef enum { FALSE = (1==0), TRUE = (1==1) } boolean;

In order to avoid the if ((bits & MASKBIT_2) == TRUE) problem, I suggest the following solutions:
1) Use the following function or a similar macro:
  boolean test (int val)
  {
      return (val > 0);
  }
usage: if (test(bits & MASKBIT_2))

2) Do not use bitmask #defines such as MASKBIT_2, instead use the following function or a similar macro:
  boolean test (unsigned int bitpool, int bitnr)
  {
      return ((bitpool & (1 << bitnr)) != 0);
  }
usage: if (test(bits, 2))
I like the solution (2) more, because not defining any MASKBIT, you are forced to use the test() function. You can always define verbose bit names such as:
  #define MYBIT   2

Using the solution (2), you may want to use also the following small functions/MACRO to set and clear bits:
  unsigned int set (unsigned int bitpool, int bitnr)
  {
      return (bitpool | (1 << bitnr));
  }
  
  unsigned int clr (unsigned int bitpool, int bitnr)
  {
      return (bitpool & ~(1 << bitnr));
  }

(or you can pass a pointer to bitpool, if you prefer).

(!(FALSE)) or (1==1)?

It's better to use this?:
  #define TRUE     (!(FALSE))
or this?:
  #define TRUE     (1==1)

They are quite the same. The result is exactly the same. I think that it's slightly better #define TRUE (1==1) only because reading (!(FALSE)) may let you think that the result is anything else than FALSE, which is not correct.

Theoretically, you can't know how the compiler expand (!(FALSE)). Remember that FALSE is an int value you defined before: hypotetically, the compiler could expand (!(FALSE)) with a different value than (1==1); for example, it could expand #define FALSE (1==0) with 0, and (!(FALSE)) with -1 or 0xFFFFFFFF, and on the contrary expand (1==1) with 1. I don't think that any compiler do that, anyway.

Best Practices

I found the following "Best Practices" on a forum discussion:

Given the de facto rules that zero is interpreted as FALSE and any non-zero value is interpreted as TRUE, you should never compare boolean-looking expressions to TRUE or FALSE. Examples:
  if (thisValue == FALSE)  // Don't do this!
  if (thatValue == TRUE)   // Or this!
  if (otherValue != TRUE)  // Whatever you do, don't do this!
Why? Because many programmers use the shortcut of treating ints as bools. They aren't the same, but compilers generally allow it. So, for example, it's perfectly legal to write
  if (strcmp(yourString, myString) == TRUE)  // Wrong!!!
That looks legitimate, and the compiler will happily accept it, but it probably doesn't do what you'd want. That's because the return value of strcmp() is
   0 if yourString == myString
  <0 if yourString < myString
  >0 if yourString > myString
So the line above returns TRUE only when yourString > myString.
The right way to do this is either
  // Valid, but still treats int as bool.
  if (strcmp(yourString, myString))
or
  // Better: lingustically clear, compiler will optimize.
  if (strcmp(yourString, myString) != 0)
Similarly:
  if (someBoolValue == FALSE)     // Redundant.
  if (!someBoolValue)             // Better.
  return (x > 0) ? TRUE : FALSE;  // You're fired.
  return (x > 0);                 // Simpler, clearer, correct.
  if (ptr == NULL)                // Perfect: compares pointers.
  if (!ptr)                       // Sleazy, but short and valid.
  if (ptr == FALSE)               // Whatisthisidonteven.
You'll often find some of these "bad examples" in production code, and many experienced programmers swear by them: they work, some are shorter than their (pedantically?) correct alternatives, and the idioms are almost universally recognized. But consider: the "right" versions are no less efficient, they're guaranteed to be portable, they'll pass even the strictest linters, and even new programmers will understand them.
Isn't that worth it?

Conclusions

I'm not sure that my considerations are defintely good. I may ignore something that is important for this topic. Discussion is open.