Tuesday, March 1, 2016

Porting a VB.NET app to linux with Mono

I recently faced an interesting challenge : porting an existing VB.NET industrial application to linux. The code was running on Windows CE 5.0 until then with the compact framework 3.5.
This work was motivated by the desire of the company to reduce the costs of our future equipments. Knowing that my company sells no more than a hundreds of products per year, I came up with the raspberry pi solution.

Why the raspberry pi ?

Even though there are a lot of competitors now (banana pi, lemon pi, solidrun products...), the raspberry pi is still the most attractive:

  •  35 $/ unit
  •  Free to use for commercial purpose
  •  Huge community
  •  Lots of additional modules

What about the performances ?

The board that I try to replace is based on an ARM Cortex A5 (500 Mhz) with 256 Mb of RAM. It provides I²C, SPI, UART lines, a LAN interface, and comes with a 6" LCD touchscreen.

The raspberry pi 2 offers the same interfaces with a similar CPU clocked at a higher frequency (900 MHz). Recently, the raspberry pi has been offered an officiel 7" LCD touchscreen for only 80 $. Plus, the raspberry pi 2 has 1 Gb of RAM making it more than suitable for the repacement of the other board.

VB.NET

I am a big fan of C# .NET. I think it is an elegant and powerful language, very easy to learn, with a great documentation. Never used VB though. Fortunately, I found this:

http://www.harding.edu/fmccown/vbnet_csharp_comparison.html

and it is quite helpful for those coming from the C# syntax.

NET on linux

I've heard about Mono for many years but never experienced it. This was going to be the first time.
Recently, Microsoft started the .NET Foundation : an organization around an open-source, collaborative project for .NET technologies to make them portable.
One can now checkout the .NET source code and compile it on its machine. Does it mean that we can run .NET Core on the raspberry ? Not exactly. At this day, the .NET Core is only available with Windows 10 IoT Core. With linux, you only have one option: Mono.

For my porting work, I only used Mono.
The linux distribution I worked with is the now famous raspbian (Debian).

Install Mono

Installing Mono is straightforward as everything is explained on:

http://www.mono-project.com/docs/getting-started/install/linux/

Additionally,  I had to install the Mono VB compiler:

sudo apt-get install mono-basic

Note: I also tried to install Mono on my old raspberry pi 1, but the install failed (script error). After looking on the internet, it seems that the first version of raspberry pi is not compatible (or so they say...).

Porting : Step 1

Before checking out the project's repository on the rpi and trying to compile it, we need to ensure that it is portable. So I installed Xamarin Studio on my Windows desktop and I tried to compile the VB project for windows. I think everybody knows what happened : it failed... miserably.

The vs2008 vbproj file was not compatible with Xamarin studio so I had to create a new one from the IDE and inserted the existing code.
I added the same options (starting class, splash screen, ...).
I added the required references : fortunately, all of the assemblies were available for Windows but one (a third party assembly compiled for Windows CE used to display a fancy keyboard. Not critical).
I compiled .... about 1000 errors were signaled.

For most of them, they were due to missing Imports or non-declared variables (used in loops for example). The last ones were more annoying : OpenNetCF-dependent code, differences between Windows Forms and WinCE Forms, P/Invokes, .... It took me 2 days to correct them all. Once done, I found out that you can set some compiler options for VB : Explicit, Strict... Maybe turning them OFF immediately would have helped me. Anyway, it was too late and at least, the code gained in clarity.

At the end of this step, my code compiled successfully.

Porting : Step 2

The second step was to execute the code on my desktop computer. Once again.... failure ! Exceptions here and there.
Again, I found some parts of code where file paths were hard-coded (WinCE "/Hard Disk" root).
Following Mono advices, I used IO.Path.Combine wherever possible as well as IO.Path.DirectorySeparatorChar.
Other minor errors appeared but I corrected them easily and the application finally booted on my desktop. (Happy Face)

Note: Facing some unexplained NullExceptions, I had to debug my application with Visual Studio instead of Xamarin. VS gives you more details about the exception and stops right where they happened while Mono sometimes signals the exception from the main thread (this is particularly true when an exception occurs in a control handler or within invoked methods).

Porting : Step 3

This step is just an experiment really. Naively, I deployed the application on my raspberry pi with all the dependencies (I personnaly used scp for this) and ran:

mono myApp.exe

Well, the result was not disastrous as the splash screen appeared on the screen for a while. Unfortunately, the app stopped with a crash. The stack strace was not very explicit, indicating that a disposed object can not be used (somewhere in the internals, following Application.Run).


Porting : Step 4

The idea now, is to checkout the code on the raspberry pi and to compile it with Mono. For convenience, I used MonoDevelop:

sudo apt-get install monodevelop

Once checked out, open your vbproj project file with MonoDevelop. Normally, you should not see any error as we already clean them up in Step 1.
Make sure that you made a local copy of the third-party assemblies that the application needs. Reference them from MonoDevelop.

Ok, let's compile ! .... Failure again. But this time, the error is way too ambiguous to be interpreted :

Compiler crashed with code : 255



-_- ... I disabled Explicit, Stric, Infer options and tried again : same result. In MonoDevelop option, you can uncheck MSBuild option to force the compilation with vbnc instead of using xbuild, a clone of MSBuild. The build failed due to a bad syntax of the command, so I wrote my own vbnc command with all sources, references, resources specified and I experimented the same crash. The stacktrace was not referencing any file or part of code. And that was it, I could not get further due to a compiler limitation. I checked the vbnc compiler project and the last commit was 1-year old. Finally, with some basic console logtraces, I managed to find out that the crash was being caused by the database loading.

Porting : Step 5

The database, of course ! I did not think about it but working with SQL Server Compact database on linux is not possible. So I had to find a solution to convert the existing database (sdf file) to a more common and portable one. Check this post for a full tutorial.

After doing that, with a fresh and working SQlite3 database file, my application finally booted properly. However, another bug came out: the application was not responding to clicks (no event fired)...
I did not go through this one as I spent too much time already on what was supposed to be a demo project. If anyone has a solution for this bug, please comment.

Conclusion

Porting an existing VB.NET code to linux was a long journey that ended with a failure. The VB compiler provided by Mono is not rock-solid and can give you a bad time. C# seems to be better implemented and it is a shame that the existing code was not written with it.
Despite of the result, I consider Mono as an unbelievably complete solution. I think that the developers did a great job.
Now that the .NET Core is public and that a synergy exists with Mono/Xamarin, I am sure that someday, porting my code will be easier.

Porting the code to a linux environment was just a challenge really. I will now try to do the same with Windows IoT Core instead, the real successor of Windows CE. According to Microsoft, the Iot Core can run Win32 apps and knowing that my app was running on my desktop computer, I have good chances to see the app running on my rasperry pi.

EDIT: A few words on my quick test with Windows IoT Core. I overlooked a very important detail with .NET Core: the existing .NET Framework assemblies are incompatible with .NET Core which means that the third party assemblies that I was using in my application can not run on Windows IoT Core. As I don't have the sources of these assemblies, the porting of the application to Windows IoT Core is a dead-end.

Friday, February 26, 2016

Upgrade from Redmine 2.x to Redmine 3.x on a Windows server

Today I want to give a summary of the painful steps I came through to install Redmine on a windows server (sometimes, you can't chose).
I assume that you have a backup of your database.

Install Rails

Pick the last installer on http://railsinstaller.org/fr-FR

(take a look at the requirements here)

Extract Redmine

Download the package 3.x from here.
Extract it to server's hardrive (in C:\ for example).

Optional : Recover the password of the database

Get into the previsous redmine installation directory.
Open config/database.yml and note the password.

production:
  adapter: mysql
  database: redmine
  host: localhost
  username: redmine
  password: my_password

Copy your old confiuration files

Go to your old redmine install directory and copy :
  • config/configuration.yml 
  • config/database.yml
to the same location in your new redmine install directory.

Install Dependencies

Open a cmd and type :

gem install bundler
gem install thin
gem install thin_service

Open GemFile at the root of your new redmine install directory and add the following lines;

gem "thin"gem "i18n"

Proceed to Redmine installation

Still from cmd, go to your new redmine install directory (say C:\redmine3.2.0) and type:
bundle install --without development test rmagick

Session store secret generation

Still in the redmine install directory, run:
bundle exec rake generate_secrete_store

Database object creation/migration

Still in the redmine install directory, run:

set RAILS_ENV=production# For french peopleset REDMINE_LANG=fr# Use your own language code otherwisebundle exec rake db:createbundle exec rake db:migratebundle exec rake redmine:load_default_data

Test the installation

Simply run 

rail s

from the install directory. A few seconds later, you should be able to access your redmine at http://localhost:3000

Install redmine as a service

If you already have a Redmine service, delete it first:

sc delete RedmineThin

Optional : Add the following line at the end of your config/environment.rb file if you want to access redmine with a prefix (http://localhost:3000/redmine instead of http://localhost:3000):

Redmine::Utils::relative_url_root = "/redmine"

Finally, run

thin_service install -N RedmineThin -e production -p 3000 --chdir C:\redmine3.2.0 --prefix /redmine

Redmine is now installed as a service. Go in your service configuration panel, and configure it to run automatically on windows start.

Reboot your server.


Friday, February 19, 2016

C++ : auto_ptr

NOTE: auto_ptr is deprecated. Use std::unique_ptr instead !

auto_ptr is a smart pointer facility.
Usually, this is what we do when we manipulate pointers :

void f()
{
   T* pt( new T );
   /*...more code...*/
   delete pt;
}

With auto_ptr, no need to delete the object anymore, it is all  taken care of !

    void f()
    {
      auto_ptr<T> pt( new T );
      /*...more code...*/
    } // cool: pt's destructor is called as it goes out
      // of scope, and the object is deleted automatically

It ensures more robust code as we avoid potential memory leaks.

Ownership


Passing


T* pt1 = new T;
// right now, we own the allocated object
// pass ownership to an auto_ptr
auto_ptr<T> pt2( pt1 );
// use the auto_ptr the same way
// we'd use a simple pointer

*pt2 = 12;       // same as "*pt1 = 12;"

Releasing


...
// use release() to take back ownership
T* pt3 = pt2.release(); // pt3 = pt1 --> points to T object
// delete the object ourselves, since now
// no auto_ptr owns it any more

delete pt3;

Reset


To substitute the pointer owned by auto_ptr with another one, one would use auto_ptr's reset() method:

auto_ptr<T> pt( new T(1) );
pt.reset( new T(2) );
// deletes the first T that was
// allocated with "new T(1)"
 It internally calls delete on T(1) and create a new auto_ptr on T(2).

Notes


  • Never put auto_ptr into standard containers

vector< auto_ptr<T> > v; // No !!!

The problem is that auto_ptr does not quite meet the requirements of a type you can put into containers, because copies of auto_ptrs are not equivalent

C++ : const at the end of function declaration

class User
{
    public:
        User();
        User(std::string name);
        void doSomething() const;

    protected:
        std::string m_name;
};


In .cpp:

void User::doSomething() const
{
    // code
}

The const keyword indicates that *this (the object) is const on the method call. This declaration tells you that the object will not be modified within this function (in the example above, doSomething() cannot modify m_name).

Note : In practice, this notation is just a promise that can be violated by the function (not advised though).

C++ : constructor initialization list

In the implementation of the constructor, it is possible to initialize internal members with an initialization list. It is basically a list of parameters following a semicolon (:) with their initialization values :

Basic initialization


class Something
{
private:
    int m_nValue;
    double m_dValue;
    int *m_pnValue;

public:
    Something()
    {
        m_nValue = 0;
        m_dValue = 0.0;
        m_pnValue = 0;
    }
};


With an initialization list


class Something
{
private:
    int m_nValue;
    double m_dValue;
    int *m_pnValue;

public:
    Something() : m_nValue(0), m_dValue(0.0), m_pnValue(0)
    {
    }
};


Note : This syntax can be used with const member as well. For instance, if m_nValue was a const, it would had the same effect.

Hands on GPIOs

Now that we know what a GPIO is, let's try to write a driver that we will use further to play with our Pi.

The reference document for this work is the BCM2835-ARM-Peripherals.pdf that you can easily find on the web.

GPIO Registers

GPFSELx : GPIO Function Select with x in [0;5]
Everyone of these registers configures up to 10 pins (except for GPFSEL5 which configures only 3).
Each pin can be configured as an input, output or alternate.
Here is the table with the definition of every alternate configuration for every pi.

GPSETx : GPIO Set function with x in [0;1]
Every pin is represented by a bit in these registers. If the pin is configured as an output, setting its bit in  GPSET will drive it to HIGH level.
GPCLRx : GPIO Clear function with x in [0;1]
Every pin is represented by a bit in these registers. If the pin is configured as an output, setting its bit in  GPSET will drive it to LOW level.
GPLEVx : GPIO Level wih x in [0;1]
Every pin is represented by a bit in these registers. You can get the current level of a pin by reading its pin in these registers.
GPEDSx : GPIO pin event status with x in [0;1]
Every pin is represented by a bit in these registers. A bit is set by the micro-controller whenever an event occurs on a pin and matches the event we are waiting for (configurable edge or level).
You can also configure the interrupt controller to be alerted with an interrupt for any pin.

GPIO pin configuration registers

GPRENx : GPIO Rising edge detect enable with x in [0;1]
GPFENx : GPIO  Falling edge detect enable with x in [0;1]
GPHENx: GPIO High detect enable with x in [0;1]
GPLENx : GPIO Low detect enable with x in [0;1]
GPARENx : GPIO Asynchronous rising edge  detect enable with x in [0;1]
GPAFENx: GPIO Asynchronous falling edge  detect enable with x in [0;1]

Asynchronous means the incoming signal is not sampled by the system clock. As such
rising edges of very short duration can be detected.
GPPUD : GPIO Pull up/down register
GPPUDCLKx : GPIO Pull up/down clock register with x in [0;1]
Use GPPUD to configure a pull up, pull down or unused mode. Then, use GPPUDCLKx to apply this mode to the desired pins.

Writing the driver step by step

Now that we know the registers to modify to handle raspberry GPIOs, we can go further and define our design. Here is a list of what we need :

A. GPIO registers memory mapping : Every register is located at a specific address in the microcontroller.  The first step would be to define them.
B. GPIO registers accessors: typically macros to avoid using masks in our code.
C. a GPIO static configuration : we will define the pins default configuration at build time. This is usually done to limit the number of function calls at boot to configure the device.
D. an interface : how will we use this driver ? We won't discuss about the integration of this driver into linux here.

And of course, everything we need to test our work !

A. GPIO Registers memory mapping

Given the BCM2835 document, the addresses start from 0x7E200000 and go to 0x7E2000B0, with 4 bytes per register (32 bits platform). My choice here is to create a structure where all of the registers are listed in the same order as the reference manual rather than defining every one of the registers with a #define statement. It is more elegant and a lot more handy when it comes to use them in the code. The final step will be to define the structure as volatile and to assign to it the GPIO base address (0x7E200000).

typedef struct
{
      uint32_t GPFSEL[6];
      uint32_t Reserved0; // Reserved byte
     
uint32_t GPSET[2]
      uint32_t Reserved1;
     
uint32_t GPCLR[2];
      uint32_t Reserved2;
     
uint32_t GPLEV[2];
      uint32_t Reserved3;
     
uint32_t GPEDS[2];
      uint32_t Reserved4;
     
uint32_t GPREN[2];
      uint32_t Reserved5;
     
uint32_t GPFEN[2];
      uint32_t Reserved6;
     
uint32_t GPHEN[2];
      uint32_t Reserved7;
     
uint32_t GPLEN[2];
      uint32_t Reserved8;
     
uint32_t GPAREN[2];
      uint32_t Reserved9;
     
uint32_t GPAFEN[2];
      uint32_t Reserved10;
     
uint32_t GPPUD;
     
uint32_t GPPUDCLK[2];
      uint32_t Reserved11[4];
      uint8 Test;
}volatile* GPIO_MemMap_ts;


The structures declared in GPIO_MemMap_ts should be defined too.
 When you are done, all you need is to declare a global variable for the GPIO_MemMap_ts:

const GPIO_MemMap_ts GPIO_BASE = 0x7E200000;

B. GPIO Registers Accessors

What we need here is to have an access to the bit of our choice in one of the GPIO registers. There is of course many ways to do that, here is a possible solution:

/* GPFSEL accessing macros */
#define GPFSEL_MODE_INPUT   ((uint32_t)0x000)
#define GPFSEL_MODE_OUTPUT  ((uint32_t)0x001)
#define GPFSEL_MODE_ALT0    ((uint32_t)0x100)
#define GPFSEL_MODE_ALT1    ((uint32_t)0x101)
#define GPFSEL_MODE_ALT2    ((uint32_t)0x110)
#define GPFSEL_MODE_ALT3    ((uint32_t)0x111)
#define GPFSEL_MODE_ALT4    ((uint32_t)0x011)
#define GPFSEL_MODE_ALT5    ((uint32_t)0x010)

#define GPFSEL_SET_FSELy(base, y, mode) (((volatile* GPIO_MemMap_ts)base).GPFSEL[y/10]) |= (mode << (3* (y%10)))

C. GPIO Static configuration

Work in progress...

Emulate raspberrypi on Windows

QEmu

QEmu is a powerfuln and open-source machine emulator. It allows you to run OSes and programs made for specific target machines on your desktop computer.
It can be compared to the popular VirtualBox and VMWare emulators but has a significant advantage in the fact that it can emulate ARM platforms. This is specifically why we are going to use it here.

How to proceed ?

Luckily, a full-packaged solution exists for Windows ! 

  • Follow this link:

and download the zip file.
  •  Unzip the file to your local hard drive 
  • Get into the unzipped qemu folder and double-click on run.bat.
There, you will see QEmu starting and initiating the boot of your virutal raspberry pi. Simply wait until the end of this process.
This is the screen you will normally see on first boot:


Ignore it for now, click on Finish.

  • Start raspbian
Run the following command at prompt:
startx
and there you are ! In your virtual raspberry environment !

Default credentials

Login: pi
Password: raspberry

Enjoy !

 
biz.