Archive for the ‘Techy’ Category

Debian on Flexiview FV-1

Sunday, February 26th, 2012

This post is about running Debian GNU/Linux on the Mesada/Flexiview FV-1 “AndroidTV” unit. This post has been a bit delayed, I got very sidetracked with other things this month!

By following these steps, you should be able to use the FV-1 a bit like a normal desktop Linux computer. However, it’s still a long way from my dream goal of running XBMC for Linux.

(Edit 11 March – added a couple more notes about exactly how poor the UI graphics performance is.)

What This Is

A lightly customised installation of Debian Wheezy, set up initially with a minimal “LXDE core.” Kernel is 3.3rc from linux-samsung-soc, plus some minor patches for FV-1 hardware support.

Debian Installation

This configuration has the kernel loaded into the internal flash of the FV-1. However, the root filesystem with Debian is external – on either a USB device or an SD card.

If you want to reverse back to Android after testing Debian, you should be able to perform a normal FV-1 firmware upgrade using their “SDtool” to prepare an SD card.

In theory, it should also be possible to install Debian into the internal flash. However, the m-boot bootloader is quite peculiar so I haven’t tried.

How to install

1) Download an SD card image to flash the kernel – use this one if you to boot Debian from an SD card, and this one to boot Debian from a USB device. The only difference between the two is the kernel commandline in the config, you can see the configs here.

2) Work out what device name your SD card reader in your computer has. It will probably look like /dev/sdX (for USB card readers) or /dev/mmcblkX (for built-in card readers). I’ll be using /dev/sdX for the sample commands here. You can probably work this out by inserting an SD card, waiting for it to mount on the desktop, and then typing “mount” to see what is mounted.

3) Flash your SD card with the kernel upgrade. This will erase any content already on the card.
umount /dev/sdX1
dd if=kernel-boot-usb.img of=/dev/sdX
sync

4) Remove the SD card and insert it into the FV-1. Power on the FV-1. The red light will come on, followed by the green light. After 1 minute or so the green light will start blinking. This means the new kernel has finished flashing. Power off the FV-1 and remove the SD card.

5) Download the rootfs tarball. This is the filesystem that the kernel will boot into.

6) You then unpack the rootfs, to your SD card or USB device. If you only have one SD card, you can reuse the one which you just used for the kernel (although you’ll need to repartition and reformat it.) I suggest formatting as ext3.

7) Once your SD card is ready, unpack the rootfs:

cd /media/[path-to-my-SD-card-mountpoint]
sudo tar zxvf ~/path/to/rootfs.tgz
sync
cd ..
eject [path-to-my-SD-card-mountpoint]

8) Insert the card back to the FV-1, and power on.

9) The FV-1 will boot to a login screen, using the lightdm login manager. Alternatively, if you don’t have a screen then you can connect an ethernet cable – the FV-1 will establish a connection using DHCP and you will be able to ssh into it.

10) The default username is ‘user’ and the password is ‘android’

11) The stock image only has a very basic LXDE GUI desktop (lxde-core.) When you first log in, go to the LXDE menu (bottom-left) and choose Accessories -> LXTerminal.

12) Use “passwd” to change the default password.

13) Optionally, use “sudo adduser (username)” to add a new user then “sudo usermod -aG sudo (username)” to give them sudo. Then reboot and login as your new user, and “sudo deluser user” to remove the initial user.

14) If you’re not in the US, edit /etc/apt/sources.list and change to a local mirror for packages.

15) To install a full GUI LXDE environment, run “sudo apt-get update” then “sudo apt-get install lxde”. It may also be possible to remove lxde-core and install other desktop environments like Xfce4, GNOME, KDE – as described in the Debian documentation.

16) When installing LXDE (or any other environment), the gdm3 package may prompt you to choose a default login manager. Keep the current “lightdm”. Any new manager will need to be preconfigured to use Xwrapper.sh to launch X (see below.)

17) Happy computing! From now on, everything should behave like a standard Debian Wheezy system.

Keep reading for the status of the hardware support.

Things That Work

X11 graphics

Up to 1920×1080 over HDMI, 16-bit colour.

USB, ethernet, SD card slot.

Things That Might Work

HDMI audio output

I’m using an HDMI->DVI cable and a computer monitor, so I haven’t been able to test audio output.

Things That Don’t Work

Wifi & Bluetooth

This is another case where having the actual GPL source release would be very helpful. The wl12xx_sdio driver detects the chip correctly, sometimes successfully uploads firmware, and very occasionally I’ve managed to get it to associate and send/receive packets. More commonly it just crashes with MMC read/write errors.

My vague theories for why it is not working include:

  • An incorrectly set clock frequency (if I force lower the SDIO frequency it becomes more reliable but not 100% reliable.)
  • Samsung HSMMC driver bug of some kind.
  • A floating GPIO line that I don’t know about.
  • Unpublished differences between Samsung’s SWB-T37 chip and the original TI WL1271.

Changing screen resolution normally

The X server is launched via a custom wrapper script, /usr/local/bin/Xwrapper.sh, that sets the screen resolution for the HDMI output before X starts. Out of the box it is set for 720p (1280×720), but you can edit that file to get 1080p (1920×1080) or 480p (720×480.)

Detecting available screen resolutions

The mainline kernel has no support for DDC/EDID (receiving monitor identification data) over HDMI on the Samsung S5PV210 SoC.

Blanking/unblanking the screen

This includes restarting the X server – any time HDMI output is disabled and then reenabled it hard locks the system. I’ve committed a note on the fv1_hacks branch showing where the system locks the second time around, but I haven’t worked anything else out yet.

To work around the issue there’s also a custom xorg.conf installed, disabling all screen blanking functions.

I think the lockup may be related to the fact that (unlike fancier hardware) the FV-1 has no system-controlled voltage regulators. This means some HDMI subsystems that would otherwise be disabled when HDMI output stops stay running, and cause problems. This is only a theory, though.

Video acceleration

This is the big one. Currently single buffered, software acceleration only – means any graphics-intensive or interactive operations tend to use a lot of CPU time and can be very jerky.

The videobuf2-fb driver that the XServer runs on (ie a framebuffer driver that maps to a V4L2 output device) is only a proof of concept, made by Samsung. It would be possible to add some more features, at least in principle. Or alternatively to write an Xorg driver that outputs directly to v4l2 (this is how Android does it.)

3D acceleration

I’ve been messing with the PowerVR drivers for the SGX540 core, but it’s all a closed-source restricted mess and very unlikely it can be made to work. Hopefully the FSF will get some traction behind their goal of open source PowerVR SGX drivers.

SD card plugging & unplugging

For some reason the Card Detect interrupt doesn’t work on the SD card slot. An SD card will work fine if its inserted at boot time, but not if it’s plugged/unplugged later on. I’ve committed what I think should work to a branch (can even see the CD line changing state and attach the interrupt to it), but I can’t make it actually work.

RF remote control

I spotted data from this coming in over the i2c bus but I haven’t tried to decode it, or work out functions like pairing, or discover if it has its own GPIO interrupt line. There’s a kernel driver for the remote in the vendor’s kernel, but due to GPL violation that’s not of any help.

Restarting

The system won’t reboot, you have to shutdown and then cycle the power by plugging/unplugging the cord!

That’s All

I hope this is of some use. Patches are very welcome if anyone works any of the issues out. :)

Mesada Flexiview FV-1 “AndroidTV” Technical Review

Monday, January 9th, 2012

I’m calling this a “technical review” because I’m not going to spend much time talking about using Android on this device. The reason for that will become apparent.

I recently purchased two “Android TV” boxes from aliexpress, for investigation and general hackery.

Android TV front
Android TV back
Android TV remote

You can buy these from various online vendors (dealextreme, aliexpress, etc.) Also under other names – for instance it’s sold here in Australia as the Kogan Agora TV.

The “original” product is the Flexiview FV-1, made by Mesada Technology, Shenzhen.

High-Level Specifications

  • Cortex-A8 1Ghz CPU (Samsung S5PV210 SoC)
  • 512Mb RAM
  • Hardware supports 1080p video decoding, 2d/3d acceleration
  • HDMI output
  • Wifi, bluetooth, ethernet connectivity
  • 3 USB 2.0 ports
  • RF remote with wiimote-like infared pointing feature

Price varies between $130 & $150 online.

Bear in mind that like most of these “shanzhai-esque” products, what’s advertised on the web page may be different to what you get. There are a few similar-looking products out there – I’ve seen ones with SoCs from Rockchip and Amlogic. Also, specs and build quality can vary widely depending on vendor.

First Impressions

The hardware is cheap & cheerful. The marks and scratches visible in the photos weren’t me, it was like that out of the box. Nevertheless, things mostly work and the build quality seems OK. One thing I did notice is that the video output can be a bit picky on the stock firmware – only some of my monitors worked, and I saw reports of some TVs not working. I think the requirement may possibly be supporting a 720p YPbPr video mode.

The other cheap and nasty bit is the little plastic “door” on the front covering 2 USB ports. It’s hard to open and close, and I doubt any serious user would leave it there for long.

Android TV?

Three word review of the “Android TV” experience: “really, don’t bother.”

If you’ve never heard of “Android TV”, that’s because it doesn’t really exist. There is a thing called “Google TV”, but those products are relatively rare and closed-source and not available for $130.

“Android TV” really means “the plain vanilla phone operating system, with a remote control that emulates a mouse & keyboard which you then use to control an interface designed for touch-screens.”

Sound nearly unusable? It is. A touchscreen interface is not a PC, which is in turn not a remote control interface. It’s horrid.

The device works pretty well with a wireless keyboard and/or mouse. Which is fine, but you’d be just as well off buying a tablet with an HDMI port (for less money) or even just hooking up an old PC.

I didn’t use Android much – I can confirm the browser works quite nicely. However, looking around the internet I saw a lot of reports of patchy video playback. Which is disappointing.

Firmware Updates

As usual for these devices, the vendor offers no after-sales support. Firmware updates are scattered around the net in strange places (others are hidden in various giant forum threads!)

So why did you buy two?

I bought these because I have a weakness for cheap low-power ARM hardware. I wanted to see how easy it was to port GNU/Linux, and maybe have a stab at porting XBMC. I’ll put details about running GNU/Linux in a follow-up blog post.

Of course, to get hacking, you need to open the cover:

Top of FV-1 board

Here’s the board. The sloppily attached cable is the serial console. Thanks to eDIY NZ for posting the serial cable pinout online – it’s a 3.3v lvTTL port, 115200bps. Looking top-to-bottom in this photo the pinout is 3.3v/TX/RX/GND. The hot glue was originally for strain relief!

For a serial link, I used my favourite source – a mobile phone USB<->Serial cable that I got for $2 at an op shop1.

Also note the unpopulated USB port, some unpopulated front & rear connectors, and the button cell battery. The battery surprised me, I wonder why they didn’t drop it to save on BoM (bill-of-materials) cost.

The large clear LEDs at the front are the IR LED beacon for the “wiimote-style” remote. The red LED is for power (amusingly, HDMI standby power can come from the monitor and light it even when the unit is off!) The green LED is connected to a GPIO.

Under the covers

Pry off the RF shielding and things are a bit more interesting. “Open in New Tab” on the images if you want to be able to read chip names.

Naked top of FV-1 board

Left hand area contains:
* Power regulation.

Middle area contains:
* Asix AX88772A USB to 10/100 Ethernet adapter
* RAM
* System-On-A-Chip (Samsung S5PV210)
* Sandisk flash memory. I believe this is an “embedded MMC” interface – it shows up as an SD card to the kernel.

Right area contains:
* TI WL1271 combined Wifi & Bluetooth adapter, packaged by Samsung as the SWB-T37 and connected via SDIO.

Naked base of FV-1 board

On the underside, the most interesting thing is the Nordic Semiconductor nRF24LE1 2.4Ghz digital transceiver under the left-hand shield. This is connected via SPI and talks to a similar model IC in the remote control. I haven’t looked at the protocol yet.

Under the main cover, it looks like there is an unpopulated LCD interface. Plus something else totally unpopulated on the bottom left. Given that Mesada also make many GPS devices, maybe there is a car GPS that uses this board?

PCB identifier for this batch is 9000J-MSD-SACC-PCB-110107. Which I guess makes it just over one year old!

GPL? What’s a GPL?

As I’ve written before, GPL compliance for these kinds of products is generally poor. The FV-1 is no exception, as far as I know it is impossible to get source for the exact Linux kernel running on the device.

It is possible that distributors outside China, like Kogan here in Australia or “Flexiview NZ”, are able to supply GPL source code – they have more reasons to act ethically and not break the license, and potentially severe consequences if they are distributing a violating product. I don’t have any more information either way.

In the meantime, I bought this device anyhow because Samsung are generally proactive with open source development, and S5PV210 SoC support is part of the mainline Linux kernel. In practice, it was much more work than I anticipated to get a kernel building from source that runs on the device.

This is partially because of differences between the FV-1 and any available reference board. Partially because not all S5PV210 support has made it to the official linux-samsung-soc kernel. Partially because embedded development is always a bit of a pain…

Vendor Kernel on Device

The device comes with a 2.6.32 Android kernel loaded. Here’s a dump of the boot messages and dmesg, plus some interactions from the Android side – /proc entries, mount points, etc.

Among the custom additions in this kernel are:
* The TI vendor WL1271 driver (open source, but different to the Linux kernel one)
* The PowerVR SGX540 3D accelerator drivers
* In-kernel driver (it seems) for the RF remote, via SPI.

Also of note is that Android isn’t using a Framebuffer device for the HDMI output (the framebuffer in that kernel is for the LCD only.) Android must be using an earlier revision of the v4l2-based s5p-tv interface.

3.2 Kernel

As I said, it seems like no source exists for the 2.6.32 “vendorkernel” that ships on the device.

I now have a 3.2rc kernel that boots and can run a normal GNU/Linux, with xorg over framebuffer, available here on github. Not everything works yet, though. Some of the fixes are a bit hacky and need to be cleaned up. Hopefully, soon some of the support can go upstream to the mainline kernel. More on this kernel in a follow-up post.

Other Reference Kernels

After much searching, I found two other helpful S5PV210/S5PC110 kernel sources (not that I ever successfully booted them on the FV-1.)

The Samsung Galaxy GT-I9000 source code, available from opensource.samsung.com, is for very similar hardware.

A Chinese development board called the RealARM Realv210. This looks to be very similar to Samsung’s SMDKV210 development board. I think the FV-1′s reference board was either the Realv210 or the SMDKV210.

RealARM are distributing a number of useful resources, including a Linux 2.6.32 kernel for the Realv210 board. This reference has been very helpful in getting 3.2 up and running.

Mesada mboot

The last vendor surprise is the bootloader. “Mesada mboot” is the strangest embedded bootloader I’ve ever seen – among its features it appears to be able to both read and format EXT3 filesystems! Unfortunately, mboot is also closed source and no documentation is available.

Here’s a dump of mboot performing a full system update for an Android firmware

The good news is I’ve managed to reverse engineer enough of the format to “unpack” and “repack” mesada’s .osk firmware update files. This allows the flashing of a new kernel, or new system partitions, or even a new bootloader. The project is called mboot-tools and is up on github. There are some usage instructions in the README there, and lots of comments in the header file.

It should also be possible to use mboot_unpack & mboot_pack to make “custom Android ROMs” or possibly even as a first step to porting a newer version of Android (after all the hardware is very similar to Galaxy/Nexus S, which can run ICS.)

What’s Next

I’ll put a post up soon explaining how to boot Debian on the FV-1, explaining what currently works and what doesn’t.

  1. “thrift store” []

Notes using scratchbox2 with debian multiarch

Tuesday, December 6th, 2011

First Steps

I’m a very recent (3 days) user of scratchbox2 for cross-compiling. My initial response was “this is crazy magic” awe, followed shortly by “this is a crazy mountain of hacks” skepticism. However, after some use & success now, it seems to be a really neat tool.

The best introductions to scratchbox2 that I’ve found are this wiki page from the plugcomputing people, and this nice succinct set of presentation slides from Riku Voipi.

One of the big annoyances has been seeking information, Google likes to replace sb2 (the main scratchbox2 command) with db2 and scratchbox2 with scratchbox.

Multiarch

I have found that scratchbox2 (as of 2.3.3) is a bit fiddly when targeting Debian wheezy or sid (testing or unstable.) This is due to the new Debian Multiarch support.

In a nutshell, multiarch means libraries and tools are moving from locations like /usr/lib to arch-specific locations like /usr/lib/[triplet] where triplet identifies the architecture, ie arm-linux-gnueabi for ARM systems.

The symptoms I saw were linking errors (or configuration failures) due to missing libraries, when you know they are installed on the target. The crucial test is whether “sb2 [some-simple-command]” fails while “sb2 -e [same-simple-command]” passes – this implies that the problem is in the host translation, not in the target (otherwise it would fail in the -e qemu’d environment, as well.)

Here’s what worked for me. In the file ~/.scratchbox2/[TARGETNAME]/gcc.config.lua, I sought out and changed the following two config items as follows, to add linker search paths:

extra_cross_compiler_args="   -L@SBOX_TARGET_ROOT@/usr/lib -L@SBOX_TARGET_ROOT@/usr/lib/arm-linux-gnueabi -L@SBOX_TARGET_ROOT@/lib  -L@SBOX_TARGET_ROOT@/lib/arm-linux-gnueabi",

extra_cross_ld_args="-rpath-link @SBOX_TARGET_ROOT@/usr/lib/arm-linux-gnueabi:@SBOX_TARGET_ROOT@/usr/lib:@SBOX_TARGET_ROOT@/lib:@SBOX_TARGET_ROOT@/lib/arm-linux-gnueabi",

I also ran the command

sb2-config setenv PKG_CONFIG_PATH /usr/lib/pkgconfig/:/usr/lib/arm-linux-gnueabi/pkgconfig/

(In all the above, replace arm-linux-gnueabi with your target architecture’s “triplet” of choice.)

As always, the solutions are simple and easy to follow once you know what they are. :) Please bear in mind also that this may not be the best solution, I’m still a scratchbox2 newbie.

Distro Versions

The other major gotcha, hinted at in the presentation I linked to, is that the host and the target distros must match exactly. If you have different library versions on each then you are headed for problems.

This can be tricky even when the distros match. At time of writing debian wheezy uses libc6-dev 2.13 on amd64 but emdebian wheezy uses libc6-dev-armel-cross 2.11 for the cross-compiler. The header files are different enough to cause builds to fail. To get matching headers I had to change to emdebian sid, which currently has libc6-dev-armel-cross 2.13.

An alternative, also hinted at in the presentation, is to set up a “tools” distro. This is a directory with a complete host-arch distribution, matching perfectly the target’s distro except for the architecture. It seems the idea there is to create a controlled single-purpose environment, instead of just sharing the host’s tools. Maybe that’s a cleaner path, especially if it lets you sandbox a stable distro release with predictable versions.

(Extended Rant, Feel Free to Ignore)

The header-mismatch problem seems to be caused because programs compiled under sb2 can search for headers in both the host directory /usr/include/, and also in the cross-compiler directory (ie /usr/arm-linux-gnueabi/include/), -and- in the target rootfs directory.

Exactly which header file gets chosen for which purpose seems to be somewhat haphazard – in the example I saw, a #include <fcntl.h> was pulling in /usr/include/fcntl.h which was then pulling /usr/arm-linux-gnueabi/include/bits/stat.h.

I haven’t dug deep enough into sb2 to see what’s really going on here with gcc include paths, but it seems like it should be possible to workaround this and ignore the host’s headers entirely – in favour of the cross-compiler headers & those installed in the target rootfs.

However, passing these paths explicitly is exactly the kind of drudgery that sb2 tries to avoid with its “magic”, so at this stage I’m leaving it – my program compiles & links, so that’s good enough for now. If I end up having to explicitly set everything then I may as well create a conventional cross-compiler environment.

Notes on FTDI latency with Arduino

Sunday, October 16th, 2011

Today I Learned how to minimise latency when sending data to a computer from an Arduino (or any other FTDI-based device.) I learned it specifically for Windows, Linux and OS X.

Well, actually I learned this a few weeks ago while developing the Hairless MIDI<->Serial Bridge. But the blog post had to wait until today.

The Problems

  • By default, serial latency with FTDI chips (including Arduino Duemilanove/Mega) on Windows & Linux can be quite high (>16ms) and unpredictable.
  • In audio applications (like sending MIDI data), this can add enough latency to create audible artifacts.
  • In Java-based applications that use it, librxtx introduces an additional 20ms of latency. I wasn’t using Java or librxtx, but you’ll want to read that if you are.

The good news is that you can reduce FTDI latency substantially with a simple tweak.

What’s Latency?

In this case, latency is the amount of time between when some data gets sent from one side (the Arduino), and received on the other side (the computer.)

In lots of cases latency doesn’t matter, or you accept higher latency in exchange for higher throughput. However, for real-time applications like MIDI controllers, you don’t want a noticeable delay between pressing a button and hearing the sound that it makes.

The consensus seems to be that for acceptable MIDI audio responses, you need to keep MIDI message latency under about 20ms.

FTDI Latency Timer

The problem stems from the Arduino’s “Serial to USB converter” chip, the FTDI FT232R. The FTDI can’t send a USB packet to the computer for every byte that comes from the Arduino’s microcontroller. Instead, it stores the serial data in an internal buffer and only sends a USB packet when the buffer is full, or after a period of time has elapsed. This period of time is determined by the FTDI Latency Timer, which is the reason why FTDI chips can give bad latency characteristics.

On Linux & Windows, the default latency timer setting is 16ms. For example, say you send a 3 byte MIDI message from your Arduino at 115200bps. As serial data, it takes 0.3ms for the MIDI message to go from the Arduino’s microcontroller to the FTDI chip. However, the FTDI holds the message in its buffer for a further 15.8ms (16ms after the first byte arrived), before the latency timer expires and it sends a USB packet to the computer.

Thankfully, the latency timer can be tweaked. The tweaking method varies between operating systems.

Linux

In proper Linux style, the kernel’s FTDI driver exposes a nice sysfs interface that lets you get and set the latency timer. For example, if your serial port is ttyUSB0:

# cat /sys/bus/usb-serial/devices/ttyUSB0/latency_timer
16
# echo 1 > /sys/bus/usb-serial/devices/ttyUSB0/latency_timer
# cat /sys/bus/usb-serial/devices/ttyUSB0/latency_timer
1

… that will lower the timer from 16ms to 1ms (the minimum), to reduce latency.

In my experience, the timer value won’t change immediately on an open serial port. If an application is using it then you’ll need to close and reopen it before the new value takes effect.

If you’re writing code, there is also a Linux-specific serial flag ASYNC_LOW_LATENCY that programmatically sets the latency timer down to 1ms. This is how Hairless MIDI<->Serial Bridge does it. You can see a succinct C code example in this patch I submitted to the ttyMIDI project.

In testing, I found that ASYNC_LOW_LATENCY also only works if you subsequently close the serial port and then reopen it (annoying, because setting the flag requires you have open()ed it already.)

Windows

FTDI’s own driver for Windows has a combo box in the Port Settings dialog that lets you choose the latency timer value. This Instructable has some screen shots showing how to find the setting in the Windows Device Manager control panel.

Programmatically, setting the timer is a bit hackier on Windows but not impossible. The FTDI driver saves the current latency setting for each device in the registry, so you can use Microsoft’s Registry API to write a new value, then reopen the serial port. The registry key is

SYSTEM\CurrentControlSet\Enum\FTDIBUS\-device id-\0000\Device Parameters

There is a code example for this hack in the Hairless MIDI<->Serial source code.

OS X

OS X does things differently. The driver bundle contains a file, /System/Library/Extensions/FTDIUSBSerialDriver.kext/Contents/Info.plist. This XML plist file describes different profiles for the serial port, including different LatencyTimer values, depending on how the FTDI identifies itself on the USB bus. FTDI’s own Technical Note on the subject [PDF] explains how to edit that value to change the latency.

The good news is that on OS X the latency timer defaults to 2ms for any FTDI FT232 that uses the default vendor & device USB IDs (0403:6001). This includes Arduino & clone FTDIs, so there is no real need to change anything.

How Fast?

I ran a test of the tweaked latency timers. The test sketch sends a MIDI note (3 bytes), then waits to see that same note echoed back. It does this many times and calculates the average delay.

With the latency timer set to 1-2ms, the entire round trip averages 18-19ms. This includes at least 1ms spent in the MIDI framework on the computer. So, based on those results, I estimate the one-way latency to be under 10ms. Excellent!

With a 16ms latency timer, the one-way latency would have been 25ms or more.

I don’t know how much of the 10ms latency is now coming from FTDI/USB layer, or from higher layers in the host operating system. It’s good enough for MIDI use, so I stopped investigating!

Which Arduinos?

Arduinos with FTDI chips include the Arduino Duemilanove & Mega, and some clones like the Seeeduino.

The newer Arduino Uno & Mega 2560 have a different AtMegaU8 chip, programmed to behave as a USB/Serial converter. According to tests I’ve seen, these have good latency characteristics.

Developing & static linking Qt apps for Windows, using Linux & wine

Sunday, September 4th, 2011

I just started working on a simple cross-platform desktop application. I’m developing from Linux and hoping to build binaries for Linux, Windows and OS X.

This quick blog post are some notes I took about:

* Developing & building a Qt app for Windows, on Linux with wine.

* Building static Qt libraries for Windows, on Linux with wine, using mingw32.

* Building a standalone static linked Qt executable for Windows, using mingw32.

This information is mostly out there somewhere on the web, but spread among lots of sources (many out of date.) I thought it would help to rewrite my experiences start-to-finish here.

Building Qt apps under wine

This is almost insanely easy. In my case I downloaded Qt Creator 2.21 for Windows & Qt 4.7.3 for mingw32, both directly from nokia. Ran the installers with


wine qt-creator-win-opensource-2.2.1.exe
wine qt-win-opensource-4.7.3-mingw.exe

The Qt installer needs to be pointed at a mingw32 installation. One comes bundled with Qt Creator, so if you’ve used the default install path it will be C:\Qt\qtcreator-2.2.1\mingw\bin\

Kudos to both the Wine team and the Qt developers.

Developing with Qt Creator

If you’re using Qt Creator as an IDE, and happy with dynamic linking (ie distributing DLLs with your application), then you’re pretty much finished. I found I was able to keep the same project open in both Linux & Wine versions of Creator simultaneously (one would prompt to reload when I’d made changes in the other.)

Mostly everything just worked!

EDIT: OK, not quite. Autocomplete seems to lock up Creator in wine for ~20 seconds each time, so it’s not so good for on-the-fly coding.

Only one oddity, on the Wine side I seem to need to “Rebuild” more often that I probably should. Don’t know if that’s a Windows thing, a Qt thing, or a Wine thing.

Command Line Building

The Qt installer for Windows installs a “Qt Command Prompt” program shortcut for Qt command line stuff. This doesn’t work under Wine. All you need to do, however, is to set some environment variables.

Wine inherits environment variables from its parent shell, so in theory you can just set variables (except for PATH) in your Linux shell and it’ll all work just fine. However, you then run the risk of confusing your Linux build environment.

My preferred approach is to use wine’s regedit to set the variables in the registry:

cat > /tmp/qttemp.reg << EOF
[HKEY_CURRENT_USER\Environment]
"PATH"="%PATH%;c:\\windows\\system32;c:\\qt\\qtcreator-2.2.1\\mingw\\bin;C:\\Qt\\4.7.3\\bin"
"QTDIR"="C:\\Qt\\4.7.3"
"QMAKESPEC"="win32-g++"
EOF
regedit /tmp/qttemp.reg
rm /tmp/qttemp.reg

Now commands like "wine qmake myproject.pro" and "wine mingw32-make" should work.

Static Linking

You may want to static link your Windows Qt app for deployment. This, essentially, means you no longer have to distribute ~12Mb of release DLLs (QtCore4.dll, QtGui4.dll, libgcc) with your application (~6Mb if zipped.)

Instead, if static linked, a 600kb application will grow out to around 11Mb itself (4.5Mb zipped), but will run standalone. However, you'd be able to use an Executable Packer like UPX if you wanted to, to get it down under 4Mb.

Think hard if this is all really worth the effort compared to shipping DLLs. The Qt documentation has a good discussion of the pros & cons of static linking, and explains the basic steps to rebuild Qt on Windows to allow static linking.

Note that if static linking the open source edition of Qt, you'll have to make sure you can comply with the terms of the license - either LGPL 2 or GPL 3.

Here are the steps I took under wine, they are a variation of the steps outlined for Windows in the Qt docs.

Environment

First I needed to set the command line build environment variables, as described above.

Separate Tree

I copied my existing Qt Windows tree to a new directory, so I could have side-by-side dynamic & static options (AFAIK this is the only way to have them side-by-side.)

cd ~/.wine/drive_c/Qt
cp -al 4.7.3 4.7.3-static
cd 4.7.3-static

After this, run 'wine regedit' and change the paths to Qt which are set under HKEY_CURRENT_USER\Environment.

If using Qt Creator, you may also need to update the Qt installation listed under Tools -> Options -> Qt4 (if it isn't autodetected from PATH.)

Newer mingw32 version

When built with older versions of mingw32, applications would depend on mingw32.dll. This is a ~10k DLL that contains some functions for thread exception support. It has to be a DLL, cannot be built statically. To deploy your application you would have had these choices:

  • Bundle mingw32.dll (a public domain DLL so no licensing issues.)
  • Don't use exceptions, and configure/compile everything with -no-exceptions.
  • Don't use threads, ie no -mthreads.

However, in the most recent version of mingw32 (gcc 4.5.2) this restriction has been lifted. QT Creator is bundled with the older mingw32, using gcc 4.4.0. So, if you want a fourth option, you can:

  1. Download the latest mingw32 installer and run it under wine.
  2. Select "C++ compiler" and "MSYS Basic System" when prompted by the installer.
  3. Run 'wine regedit' and edit PATH under HKEY_CURRENT_USER\Environment to point to the new mingw\bin directory.
  4. If using QT Creator, go to Tools->Options->Toolchains and add a new MinGW entry for that compiler. Then go to Projects -> Build Settings in your project and switch to the new compiler entry.

(NB: for reasons I don't actually comprehend, you may still need mingw32.dll for debug builds. Although this may just be a sign I need to rebuilt my entire Qt oncem ore.)

Configuring Qt for static libraries

Configure as per the documentation. You'll be prompted for license choice, etc.

wine configure.exe -static

Make in parallel

Building Qt with mingw32 is excruciatingly slow. To make things faster, you can force make to use multiple parallel jobs:

MAKE="mingw32-make -j4" wine mingw32-make sub-src

Replace "4" with the number of parallel compilations you'd like to see.

The full build with -j4 on my quad core i5 2.7Ghz machine takes about 75 minutes, including restarting after the errors (see below.)

Cope with errors

Unfortunately, building Qt 4.7.3 in parallel will lead to false errors towards the end - some codec-related plugins do not have their dependencies set quite right. The easiest thing to do is to just restart from here without -j set, the build only has about 10 minutes to run at this point anyhow.

Also, YMMV but one time I had Qt fail to link libbootstrap - claiming missing functions from QLocale. I don't know what this was caused by, seemingly nothing to do with parallel make, but I deleted tools/bootstrap/tmp/obj/release_static/qlocale.o , ran mingw32-make again, and it was fine.

Add static options to project

Finally, once you're done building Qt, you still need to add

QMAKE_LFLAGS += -static -static-libgcc

to your .pro file(s), in order to statically link in libgcc & libstdc++.

Yay Static!

... and Static linking is set up for Windows! Hope it was worth it. ;)

Disadvantages To using Qt with Mingw32 under Wine

Compilation is slow

Apparently this is mostly mingw32's slowness, although building under wine can't be helping. Regardless, it is many times slower than native building on Linux.

Parallel building makes a massive improvement though, with modern multicore CPUs. If you're running with Qt Creator, you can force your whole project to build in parallel by going to Projects -> Build Settings -> expanding the 'Make:' build step and setting Make arguments to -j3 MAKE="mingw32-make -j3" (where 3 is your number of parallel steps.) YMMV on that, though. You may need to better specify dependencies, as described here.

Real Machine

Even with this setup, you still need a "real" Windows machine (or VM) to do final testing. Although this way you can avoid contact with as many Windows subsystems as theoretically possible, and just copy across your built app to test. :)

Possible Alternatives

It looks like it may be possible to install the Microsoft Platform SDK tools under wine and use Qt with the Visual Studio platform, but I haven't tried.

Or, apparently it is possible to install mingw32 as a cross-compilation toolchain. This way the the compiler runs directly on Linux instead of under Wine. I haven't tried this, not sure how it would compare. You certainly wouldn't be able to use that toolchain with QT Creator, I don't think.

Finally, you could use a VM or a real Windows box. I prefer working with wine, though (ideally I'll touch the bare minimum amount of Windows internals that are necessary. ;))

Next up

Cross-compiling Qt apps for OS X (Ref A, ref B.) Just kidding, not that masochistic. I think I'll go and find a real Mac to borrow. ;)

Froyo (Android 2.2) alpha for Eken M001 & M003

Wednesday, November 24th, 2010

Update 25/11: Now supports M003 as well, and it appears the M002 may be able to boot from the M001 build.

Update 27/11: New build posted, now with better functioning Wifi!

Android 2.2 on dirt cheap WM8505 tablets. I said it may not be possible. Since then, I’ve spent hours and hours trying to reverse-engineer the custom calls that the WM8505 Android port uses to set up the correct graphics modes. I still can’t replicate their process successfully.

However, on Sunday I had what my friend Adam has called “an a-ha moment1. Android’s own porting guide says the graphics mode has to be RGB565 with double-buffering (aka page-flipping), but apparently this is not strictly true.

Within a couple of hours, I had a Froyo home screen up on my M001:

Now, a few busy evenings later, I can offer a hacky alpha for people to check out, and hopefully build upon. However, this is not the same as “the Eken M001 now supports Android 2.2“.

Get to the Android already!

OK, here it is. This build is configured to boot entirely from the SD card, to minimise the chances of bricking a tablet and to make it easy for people to check it out. You should be able to run this without any impact on the OS installed in the tablet.

This image is a dodgy hack, pre-release quality, and totally unsupported, btw. Do not expect very much.

Installing from Linux/OS X

If you have a 2Gb+ SD card, you can download the image (M001 or M003) and use ‘dd’ to copy it over the top of your SD card:

zcat image-m001.gz | dd of=/dev/sdX

(where sdX is your SD card device. You’ll need to unmount the SD card, first.)

Installing from Windows

If you’re unfortunate enough to be stuck on Windows, you can download a zip file with the image (M001 or M003). First, unzip the image. Then, the Slatedroid forums have instructions on how to flash the Debian SD card image from Windows. If that doesn’t work, you can try these instructions. The Debian image is the same format as the Froyo image, so the same steps should apply.

Installing the SD Card manually

If you have a smaller SD card, or you just want to make your own, then I also uploaded tarballs containing the FAT and ext2 partitions for each tablet. You can unpack these onto any SD card, with the following partition & formatting scheme:

  1. FAT16 (for script/ directory)
  2. linux-swap (optional)
  3. ext2 (for root filesystem)

(NB: The partitioning scheme has changed since the first set of posted images.)

First boot

The first boot from the SD card will take a few minutes longer than usual, because the Dalvik VM is generating its cache. I think mine takes around 5 minutes the first time.

Status

The following things work:

  • Basic Android UI
  • Touchscreen
  • Blanking the screen when idle
  • Swap partition on SD card

The following things should work, please test:

  • Wifi
  • SetCPU & other CPU scaling (will need to “root” first)

The following things are untested and probably don’t work:

  • Audio
  • Video playback (probably will be choppy)
  • Battery level tracking
  • Automatic screen rotation (I hope you like landscape)

However I expect all those things should be fairly easy to implement, except for smooth video playback.

The following things definitely don’t work:

  • Graphics acceleration, there isn’t even page flipping/double buffering at the moment, let alone OpenGL ES (which there will never be.) It isn’t as painfully slow as I thought it might be, but it definitely isn’t fast. There are also a few artifacts, like lock screen redraw when turning back on. Also, some apps may not work as expected due to the odd graphics mode.
  • Touchscreen calibration. The device ships with my Eken M001 calibration on it. If mine is no good then you can copy your /data/wmt/touchcal to /etc/touchcal on the SD card to bring it across. But there’s no WM8505 calibration app installed, so someone either needs to port Wondermedia’s or write a new one from scratch.
  • Suspend/Resume (was broken in 1.6, still broken in 2.2 as it’s a kernel deficiency.)

Installing to the flash in the tablet

At the moment, this only supports booting from SD card. However, there’s no reason why someone clever couldn’t build an alternate version that installs to the tablet’s internal flash – all the required pieces exist AFAIK.

Building On This

All the scripts & patches I used are available on github. There should be enough there for a savvy person to fairly easily build this again from an AOSP release.

The kernel used is “my” copy of Wondermedia’s kernel source release. Hopefully as Alexey’s from-scratch kernel adds more features, it will eventually be able to run Android as well.

If you do build anything using this, please please please share source/instructions for what you improve. Every “secret” someone hoards away is a step away from making these devices properly usable.

This Froyo build comes unsupported (sorry), and I’m not likely to do a whole lot more on it. However, one thing I do intend to do is get it running on my Eken M003 (my M001 has serious hardware problems so I can’t really use it as a tablet any more.)

However, I really hope that others will jump in, build on it, and make something good. Enjoy!

  1. I called it a doh! moment []

Ubuntu on Asus eeepc 900AX

Tuesday, October 12th, 2010

These are some quick notes from installing Linux, specifically Ubuntu Netbook Remix 10.10, on the Asus 900AX.

The 900AX is a throwback to the original eee pc 701. Side by side, they look nearly identical – the 900 just has a 9″ screen, different keyboard labels and 2 USB ports (not 3.) There are a few other budget concessions, for example the RAM is apparently soldered directly on the board instead of on a removable DIMM.

This is offset by the fact I picked it up for just $198AU on sale. It boggles my mind that you can walk into a store and buy a fully functioning brand name laptop computer, new with a warranty, for $200.

Installation

First build your USB stick. You can either do it the easy way as described by Ubuntu, or mess around with dd if you’re keen (I went for the easy way.) Once the USB stick is inserted, boot up and press F2 to get to the BIOS menu. With the USB stick inserted, there will be a “Hard Disk Drives” menu (under Boot) which will let you choose the USB stick as your boot device of choice.

For some reason the trackpad didn’t work the first time I booted the installer (it worked on subsequent boots.) Apart from that, the Ubuntu Netbook Remix 10.10 installation went smoothly. Until the system froze when restarting after installation.

The freezing problem persisted, with freezing/lockups on shutdown, restart, suspend or hibernate. The RT3090 wireless was the problem. To fix it, you can install the DKMS kernel module package containing ralink’s proprietary source drivers. I just downloaded the prebuilt DKMS package on that page, I didn’t build it myself (lazy!) Then I blacklisted the OSS ralink modules:

Appending to /etc/modprobe.d/blacklist.conf

# blacklist other Ralink modules in favour of 3090 DKMS mod
blacklist rt2860sta
blacklist rt2870sta
blacklist rt2800pci
blacklist rt2800usb
blacklist rt2x00lib
blacklist rt2x00pci
blacklist rt2x00usb



Asus at MHV

… fixed! Other than that I’ve only noticed two problems:

  • The brightness hotkeys erratically switch between two brightness settings only, bright & dim. I remember this working properly under Windows in the store, so I’m guessing a driver issue.
  • The battery gets hot when charging, and the plug pack tip gets extremely hot – I almost burned myself on it after an hour of charging & using! Not sure if that’s a common fault or just mine. EDIT: This seems like it was me not properly inserting the plug. Has been fine since.
  • EDIT 2: At one point recently the trackpad totally stopped responding to me. After lots of messing around and wasted effort, I fixed it by shutting down, disconnecting power, removing the battery, and waiting for 30 seconds before powering back up.

Everything else seems to work out of the box so far. Nothing at all like the “bad old days” of Linux hardware support.

If I find anything else useful, I’ll append it here.

Unbricking WM8505-based tablets

Monday, August 30th, 2010

I seem to be getting at least two unsolicited questions a day from people who have inadvertently bricked their Eken M001/M002/M003 or Flytouch/noname tablets . So here’s a quick post with what I know about unbricking.

You should also try slatedroid, and hassle whoever is making custom firmwares to remove the unnecessary bootloader reflash steps. These dangerous reflashes are what is causing so many tablets to brick in the first place.

Also, always plug your tablet in to the charger when flashing. Never unplug it or turn it off while it’s flashing, even if you’re accidentally flashing it twice. Seriously, people.

Bootloaders

WM8505 tablets have a pre-bootloader called W-Load, then a bootloader called u-boot, then the main OS boots.

U-boot will read a custom boot script from a file “script/scriptcmd” on an SD card, if it is present. This is how upgrades and reflashes work. U-boot is also capable of interacting with the user via the built-in 3.3v serial port, if you solder some wires to it.

Stuck on the ‘Android Logo’ boot screen

This is the first screen, which also says “Kernel Version X.Y.Z” and “SDK Version X.Y.Z.”. This screen is put up by u-boot.

If you’re stuck on this screen then u-boot is loading, which is a good sign. If putting in an SD card with an upgrade script does not work, then it may be broken in some other way. You may be able to connect a serial cable and interact directly with u-boot to issue commands.

Before you bother with the serial cable, make very sure you have formatted your SD card correctly (FAT32) . Try reformatting and re-copying all the files to the SD card, and then try using a different SD card. Various people have reported that only SD cards 2Gb or smaller work reliably.

Stuck on the ‘Android’ “shimmer” boot screen

If you’re stuck on the next boot screen (the text ‘Android’ that shimmers back and forth) then Android has started loading but is crashing. Reflash via the SD card.

Blank screen

If you have a totally blank screen then this is a much worse sign. In my experience, I’ve seen three possible things:


If the red power light blinks on when you press Power but then immediately goes out

Then you have a fault in your power circuit on the board. In my Eken, I can still make it boot if I take the back off and heat up the board with a heat gun (hair dryer would also work.)


If the red power light stays on and eventually you hear the ‘ding’ startup sound

(Instead of the ‘ding’, another sign is if you can connect it to your computer via USB.)

Then your Eken is working but your LCD panel is not. It might be broken, or it might be a bad connection. I’ve had luck pressing (lightly) around the edges of the screen.


If the red power light stays on but you don’t eventually hear any ‘ding’ startup sound

Then your Eken is probably stuck either loading W-load or u-boot. There are some anecdotal reports that these boards will still take a normal SD card based update, so try some different firmwares via SD card as a first step.

If that doesn’t work then you probably have a brick. The only way from here would be to reflash directly or via JTAG, and noone has found a JTAG pinout on these boards. You can connect the serial port to be 100% sure, but I wouldn’t hold my breath.


EDIT: Ziann123 has posted a comment about unbricking via JTAG. Apparently he has a newer revision board, where the JTAG pinout is broken out and clearly labelled.

I have none of the above

If you have different symptoms, feel free to post in the comments. You’ll probably get better responses by posting on slatedroid, though.

WM8505 Linux kernel development (Eken M001 & others)

Sunday, August 1st, 2010

Have started tidying up a Linux kernel for Eken M001 & similar devices (tablets and netbooks), based on the source release that came from VIA last week.

Very, very, early days yet. http://github.com/projectgus/kernel_wm8505.

Not all of the WM8505 functionality is available in source form yet, in particular VIA have chosen not to give us the video source for some reason. So there’s still quite a lot of work before this will be suitable for an Android 2.1/2.2 port. But it’s a very solid start.

EDIT: Source for all drivers is now available except for the SD/MMC driver. I suggest joining the Google Group if you’re interested in this stuff.

Debian on the Eken M001

Saturday, July 3rd, 2010

(One more Eken post and I’m going to have to rename this blog to Project M001!)

EDIT: Everything here is somewhat out of date now. Jacob Stoner has released a Debian build with X11 & touchscreen support. The links are all posted on the slatedroid forum.

Debian Boots! I wish I had a keyboard!

Debian on the WM8505 netbooks has been around for a while, thanks to the efforts of #easypc’s abrasive. I needed to tweak a couple of things before his release worked on the Eken M001 tablet.

Before you begin

You probably want to start by plugging in either a USB keyboard or a serial cable. Otherwise, all Debian has to offer you is a blank login console.

Howto

Follow abrasive’s directions in the README here to set up the partitions on your SD card.

Before you boot the SD card, make the following 4 changes:

  1. In the FAT partition you made, replace script/scriptcmd with this scriptcmd file.
  2. Download the Eken official Android 1.6 upgrade from here, unzip it and copy the script/uzImage.bin file (kernel image) over script/uzImage.bin on the FAT partition you made.
  3. In the ext2 partition, edit etc/inittab and replace this line:
    #T0:23:respawn:/sbin/getty -L ttyS0 9600 vt100
    with this one:
    T0:23:respawn:/sbin/getty -L ttyS0 115200 vt100
  4. Also in the ext2 partition, run sudo mknod (mount-point-of-ext2-part)/dev/ttyS0 c 4 64(or equivalent)

(The last two steps are only strictly necessary if you want to use the serial console, but the first two are necessary all of the time.)

Then pop the card in and you should boot into Debian! The instructions on the bento-linux Wiki for X11 work as well, although I found I needed a window manager (like xfce4) installed before X11 would stay launched.

Default XFCE4 on my M001 tablet

EDIT: If you’re having trouble booting from SD, I just had an experience where uboot was refusing to load ‘scriptcmd’ even though it was correct. I had to reformat the FAT partition and re-copy the files. Not sure what that was about, but might be worth trying if your Debian suddenly refuses to boot.

Notes

The new scriptcmd adds the kernel command line arg “console=ttyS0,115200n8″ to the command line. Seems unnecessary, but I couldn’t get it to boot successfully at all without this addition.

If you don’t replace the netbook kernel with the one from Eken, you won’t get any graphics display. Although debian will still run fine through the serial port. I’m guessing the netbook kernel has the LCD buffer at a different address.

Eken boots android with mem=109M on the command line whereas abrasive has used mem=112M. I don’t know if the Android version is allocating extra space for framebuffer double buffering, or something else. I haven’t noticed any differences yet so I’m running with mem=109M.

I haven’t tried the optional scriptcmd.install to install Debian to the internal flash, yet. I’m guessing you may need to repartition the mtd to get full use, as the Android partitioning scheme uses two partitions.

Pro tip: to see the insides of a scriptcmd file run ‘tail -c +73 scriptcmd’

Disk access when running from the SD card is sloooow (at least for slow SD cards like mine.) Don’t know if running from internal flash is any better.

I’m guessing that the framebuffer works normally in the Debian install because it isn’t using double-buffering, which is necessary for Android to work. I don’t know if ‘abrasive’ had to do anything special to get the ‘fbcon’ console module to work, I’m going to try and find out though!

EDIT: Jacob Stoner has come up with a small program to init the touchscreen, and a more recent version of evtouch that works for input. info here, init program & recent evtouch. He says he’s going to come out with an installable package (no serial/keyboard required) shortly.

I had a quick try at copying across the wm9715-api.ko & wm9715-ts_800_480.ko touchscreen modules from the Eken firmware, and using them with the package xserver-xorg-input-evtouch to provide a touchscreen mouse. No luck, though. The ‘evtest’ utility shows screen presses coming in, but no X/Y coordinates. A better approach might be to compile the the Wolfson OSS drivers against the 2.6.29 kernel headers.

Finally,

Want a quick laugh?


~# modinfo wm9715-api.ko
filename: wm9715-api.ko
author: VIA ShenZhen MCE SW Team
license: GPL
description: WM9715 api for the driver of touchscreen and battery

GPL, huh? This is kind of “GPL” where noone releases any source code. Ho ho ho! Thanks VIA, Wondermedia & Eken.