Sunday 24 January 2016

Raspberry Pi real time kernel

I have recently worked on a realtime application for Raspberry Pi 2.

One of the steps to achieve the goal was to enable the realtime scheduler policies in the Linux kernel.
In this case I have selected the SCHED_FIFO policy.
The behaviour of a process scheduled with this policy is that when it becomes runnable it will be inserted in the list of SCHED_FIFO processes. It will stay running until another process in the SCHED_FIFO policy with a higher priority becomes runnable. 
For more information refer to the sched_setscheduler function documentation.

In this post I am going to show you how to build a kernel with the PREEMPT-RT profile enabled.
Cause the limited Raspberry Pi resources, I decided to cross-compile the kernel on an Ubuntu system. Thus i have setup the compiling environment on a VirtualBox virtual machine on my Intel Core i7.
The VM is configured with 2 cores and 4 GB of RAM. Make sure to define the Virtual Hard Drive maximum size to at least 20 GB.

From this point I will assume that you have a running and updated Ubuntu 15.10 desktop.

Let's start


Download the kernel sources from the raspberry git repository (~ 160 MB).
Before continuing please bear in mind that the RT-Kernel project provides a specific version of the patch for a specific version of the Linux kernel. So, before downloading a version of the kernel, check if the RT patch is available. In my case I have patched the linux-rpi-4.1.y (Linux 4.1.15) branch sources with the patch-4.1.15-rt17.patch.


~ $ git clone -b rpi-4.1.y https://github.com/raspberrypi/linux.git

Or downloading the archive:
~ $ wget https://github.com/raspberrypi/linux/archive/rpi-4.1.y.zip
~ $ unzip rpi-4.1.y.zip
~ $ mv linux-rpi-4.1.y linux


Download the raspberry tools from the raspberry git repository (~ 300 MB):
~ $ git clone https://github.com/raspberrypi/tools

Or downloading the archive:
~ $ wget https://github.com/raspberrypi/tools/archive/master.zip
~ $ unzip master.zip
~ $ mv tools-master tools


Download the version of RT-patches relative to the kernel version:
~ $ wget https://www.kernel.org/pub/linux/kernel/projects/rt/4.1/patch-4.1.15-rt17.patch.xz


Setup the GCC environment:
~ $ export CCPREFIX=~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-


Test GCC:
~ $ ${CCPREFIX}gcc -v

This should output the version of GCC .


Apply the RT patch:
~ $ cd linux
~/linux $ xzcat ../patch-4.1.15-rt17.patch.xz | patch -p1


Compile the kernel:
It is a good idea to start from an existent configuration. Connect to your Raspberry Pi and download the current configuration:
~/linux $ scp pi@raspberrypi:/proc/config.gz .

Extract the config file:
~/linux $ gunzip -c ../config.gz > .config

Bootstrap the kernel configuration using the provided .config file:
~/linux $ ARCH=arm CROSS_COMPILE=${CCPREFIX} make oldconfig

Start the kernel configuration utility and enable the Full real-time profile:
~/linux $ sudo apt-get install libncurses5-dev
~/linux $ make menuconfig

Build the kernel (~35 minutes):
~/linux $ ARCH=arm CROSS_COMPILE=${CCPREFIX} make

Consider adding the -j n option to the command line to compile more than one file at time.

Generate kernel modules:
~/linux $ ARCH=arm CROSS_COMPILE=${CCPREFIX} INSTALL_MOD_PATH=../modules make modules_install 


Create a new uncompressed kernel image:
~/linux $ cd ../tools/mkimage
~/tools/mkimage $ ./imagetool-uncompressed.py ../../linux/arch/arm/boot/zImage
~/tools/mkimage $ mv kernel.img ../..

Create an archive for all modules:
~ $ cd modules
~/modules $ tar czf modules.tgz *
~/modules $ mv modules.tgz ..

Deploy the new kernel on the Raspberry Pi:
~ $ scp ./kernel.img pi@raspberrypi:/tmp/kernel.img
~ $ scp ./modules.tgz pi@raspberrypi:/tmp/modules.tgz

Complete the deployment in a terminal on the Raspberry PI.
~ $ cd /
/ $ sudo mv /tmp/kernel-test.img /boot
/ $ sudo tar xzf /tmp/modules.tgz


Pwew! Hope you will find this guide useful for your next Raspberry real-time project.


Thursday 21 January 2016

The Good Dinosaur

Last weekend my family and I finally watched the last Disney Pixar movie.
This was our first time in a cinema with Stefano, so it was a great experience, regardless of the movie.
We watched the 2D version of the movie, and frankly, I have been in more comfortable and technically-equipped cinemas, but this did not make the visual experience less pleasant.
I think Pixar wanted to show the maximum photorealism they could achieve.
The representation of nature is perfect in every detail: the mountains, the grass, the water, everything in the environment seems more real than real.
The character design, with the exaggerated animations and those big eyes, is that toon-ish style that makes the movie more suitable for kids.
Because, after all, this should be a movie for kids.
The problem is that, even with that PG rate that it took, it is not remarked enough that this is not exactly a movie for kids.
In hindsight, I wish I had read the reviews on imdb.com before going to the cinema.
Some scenes are, to say the less, not appropriate for a young public. Stefano is not scared easily, but some scenes made him silent (I know what this means), and I did my best to mitigate the tension in such moments.
The story has great potential: imagine the world if the dinosaurs would not be extinct after the meteor. It could be intended for families, but I think they put too much unnecessary tension in different parts of the movie.

I cannot really understand the reason of some scenes:

Why graphically represent a decapitation? Why visualize a small animal eaten alive? Why repeat the scene of the death of Arlo's father? Why put so much tension in the storm representation?



Even the short that precedes the movie is somewhat not appropriate: the graphic style of the monster could be a little less scary considering the average age of the public.

As an adult, I somewhat enjoyed The Good Dinosaur, even with its over-simplistic story, but I would not recommend other parents watch it with their children.

Stefano was very bored, and for the last 20 minutes, he barely resisted leaving and did not watch the movie.

We spent the rest of the day at his favourite playground to reward his patience. 

This was the first time I did not bother watching the credits at the end of the movie.
I promised myself to read the reviews before watching a movie in future.

Saturday 16 January 2016

Playing with... MonkeyRunner

A few days ago, Stefano was playing with our Samsung Galaxy Tab 2.

He usually enjoys playing a plethora of MineCraft clones on it, and he was playing with a game with the well-known blocky graphic style (I have already purchased the XBox360 version, and I don't want to spend other money for the same game on a different platform... this actually already happened some months ago, but this is another story  ).
I enjoy watching him play video games because, in general, children have different and way-more-creative ways to play than adults.
I think this is one of the reasons for Minecraft's global success.
Apart from the graphic style, the game was not a sandbox this time.

PickCrafter is a very simple arcade where your only aim is to collect as many blocks and "picks" as possible.

All you have to do is shake your device, mimicking mining with a pickaxe (the only tool of the game) or tapping as fast as you can on the screen. Moving your device allows you to collect "picks" faster than tapping.
You can buy enhancements by spending your "picks" in the game shop. Enhancements allow you to collect picks faster.

While helping Stefano tap furiously on the poor tablet screen, I thought the game was an excellent target for the Android SDK MonkeyRunner utility  .

MonkeyRunner is a tool that helps the developer to simulate some user events by writing a Python program using the MonkeyRunner API.

For me, it was also an occasion to work with Python.


Ok, let's start then from the Python program.
from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
import time
# Connects to the current device, returning a MonkeyDevice object
device = MonkeyRunner.waitForConnection()

points = [{"x":300, "y":900},
          {"x":500, "y":300},
          {"x":400, "y":700},
          {"x":600, "y":600}]

while True:
  for p in points:
    device.touch(p["x"], p["y"], MonkeyDevice.DOWN_AND_UP)

    time.sleep(.05)


This program defines a list of points (technically a list of dictionaries) and then sends them indefinitely to the device.

After a few attempts, I found the screen coordinates to get the best from the game.
I also found that a small sleep is necessary after each touch event; otherwise, the game will hang.

To find the exact screen coordinates, I enabled the option "Show touches" and "Show pointer location" in the developer options menu of the device settings.

Remember to disable both settings afterwards because they will slightly slow the device considering that we send a touch event every 50 ms.



It is time to run MonkeyRunner: save the code in a file (e.g. send_touch_events.py) and open the Console link you can find in the root folder of the Android SDK installation.
As MonketRunner sends the touch events to the foreground activity, you should open the game on your device before starting the script. 

On the Command Prompt type
monkeyrunner SendTouchEvents.py

and hit return.

If the device is connected correctly and you have authorized the USB debug connection in the device settings, the game now should receive the touch events.
You will then quickly collect a large amount of "picks" and blocks without risking damaging your device.


 
PickCrafter during a MonkeyRunner session

Issues

- During the first few seconds of the "fire time", you will still need to tap on the screen. I don't know exactly why, and I don't want to spend more time finding it.- The script cannot catch the "creep" that randomly appears on the screen. Without knowing the game code, we will need a complete AI and a more sophisticated system.

 
Enjoy! :)


Sunday 10 January 2016

Windows 10 is here

I have finally decided to accept the insistent Microsoft invitation to the upgrade. I was happy with Windows 7 on both my laptop and home desktop, but I thought to try it anyway.

First, I upgraded my Asus K53SJ laptop after a quick check on the support website for known issues: the upgrade was successful and faster than expected.
I tried it for two days before applying the upgrade to the desktop. This is a custom-made one with an AMD AM3 Socket based motherboard. The upgrade process was flawless also in this case.

Issues

Unfortunately, I have noticed some minor issues on both PC.

Laptop

The integrated webcam was not recognised anymore. To fix this issue, I uninstalled the driver, downloaded the latest version from the Asus website and installed it again, taking care to reboot after each setup execution.
Another issue that I have not fixed yet, the user switch sometimes gets the laptop stuck: the only solution is to hard reset and reboot.

Desktop

Even in this case, the webcam - an external Logitech C525 - was not recognised anymore. I fixed the issue with the same solution for the laptop webcam (uninstall, reboot, install the latest driver, reboot).
After the upgrade, the additional PCIEx-to-USB was not recognised anymore. Fortunately enough, in this case, a simple reboot fixed it.
Last, sometimes during the boot animation, the PC hangs.
I have yet to find a solution better than a hard reset.


Privacy Settings

Windows 10 is well known to send user information to Microsoft without asking for permission.
After an upgrade, I would recommend disabling all the privacy-related settings.
I have found this helpful guide, but you can find many similar ones on the internet. Somebody also created utilities that automate these tasks.

Conclusions

Apart from those minor annoyances, I feel the new OS is worth the upgrade.
The best improvements on the early versions are in the Command Prompt (that finally supports the windows resizing!) and the integrated Modern UI windows in the desktop environment.