Sunday, October 6, 2013

Booting Linux on Radxa Rock


For anybody interested, here is a preliminary working kernel for the Radxa Rock board.

UPDATE (2013/10/11): IR and Audio I/O working, updated links to new flash images

Xubuntu Linux on Radxa Rock RK3188 board


This is WORK IN PROGRESS, so few things are supported, even though it's already almost as usable as any stick. This is the current state of affairs (check commits for updated info):

What works?
- Integrated Ethernet 10/100
- USB 2
- HDMI
- Flash
- MicroSD
- RK1000-S sound (integrated mic, audio out jack)
- IR (point a remote at it and press a button while monitoring cat /proc/interrupts ;)

What doesn't work yet?
- Wifi+BT

Not tested?
- Expansion headers
- SPDIF Audio Out / Exp.header Line In
- RTC


I've based development on this repository. To compile it for yourself, you'll have to clone it and use the arch/arm/configs/rk3188_Radxa_Rock_Linux_galland_defconfig file as your .config (UPDATE: the initramfs file necessary for this defconfig, with rknand support, is initramfs-3.0.36+.cpio from here).


OR, if you have the board and want to go ahead with the flashing (supposing you already have an Ubuntu Linux in a MicroSD card inserted in the Radxa board), you have two options:

A) Boot to Linux only: Flash "kernel" partition with this file, so you boot directly to Linux (warning: it won't boot to Android unless you revert this step). Follow these steps:

//backup the Android "kernel" to be able to revert this
sudo ./rkflashtool r 0x4000 0x5000 > radxa_stock_kernel.img
//flash the downloaded Linux kernel instead
sudo ./rkflashtool w 0x4000 0x5000 < kernel.img
//safely reboot (into Linux)
sudo ./rkflashtool b

Now the Radxa board will boot directly into Linux.
In order to recover Android booting you'd have to reflash the stock kernel you've backed up.


B) Usual way: flash the Linux kernel (decompressing this different file) into the recovery partition to be able to dual boot Android/Linux:

//flash the downloaded and uncompressed recovery.img
sudo ./rkflashtool w 0x10000 0x10000 < recovery.img
//safely reboot (into Android)
sudo ./rkflashtool b

Now to get into Linux you have to boot into Android and have again two options:

- Enable Debug Mode, connect OTG USB port to PC, go to Settings->USB->Connect to PC, and then in the PC issue an "adb shell reboot recovery"

- Or, install an Android Terminal emulator (beware there is no Google Play in the RR!) get into it and, with root, issue a: reboot recovery




Since booting back to recovery partition tends to be cumbersome and since I only care about Linux, I have flashed kernel partition and always just boot to Linux!



PS: Just in case you don't have the latest modules and firmware, get these ones into the root (not "root" folder!) of your MicroSD Linux (I insert the uSD card in the PC, open a file explorer as root and copy them at uSD's root).



Booting to Linux instead of Android (flashing kernel partition) for RK


1) Get the software

You'll first need to fetch the Linux RK flashing tool (ignore the git name, the tool is valid for RK2*, RK30, RK31 devices), and the Linux rkcrc tool (for pre-/post-fixing a kernel image with the right RK values):

git clone https://github.com/Galland/rkflashtool_rk3066 rkflashtool
cd rkflashtool
make
cd..

git clone https://github.com/Galland/rk-tools.git
cd rk-tools
make rkcrc
cd ..

2) Prepare your own kernel


After compiling your kernel, you have to convert/sign the zImage output file with this command:

./rk-tools/rkcrc -k Linux3188/arch/arm/boot/zImage kernel.img

Substitute "Linux3188" with the folder name where your kernel sources are.


3) Getting device into Recovery mode


This is most usually done by keeping pressed a pushbutton while plugging the USB OTG connector to your PC and then releasing it after a >2 seconds. If upon typing Linux command "lsusb" on the PC we see a nameless device (with ID 2207:...), that's our RK device in recovery mode.

Warning: some devices (like the Radxa Rock) have a 2 minutes timeout for the recovery mode after which it will power off, the timeout restarts upon any flash reading/writing.



4) Know your partitions


Before any flashing operation, we must be sure of at what offset and what size does the partition of interest have. To do it, while in recovery mode, issue the following command in your PC:

sudo ./rkflashtool r 0x0 0x1 | head -n 11

That will result in several lines of parameter information from your stick. We are interested in the last text paragraph, from "mtdparts" to the end.

For example, in my MK908 (check yours, since there are several versions), it is:
mtdparts=rk29xxnand:0x00002000@0x00002000(misc),0x00006000@0x00004000(kernel),0x00008000@0x0000A000(boot),0x00010000@0x00012000(recovery),0x00020000@0x00022000(backup),0x00040000@0x00042000(cache),0x00400000@0x00082000(userdata),0x00002000@0x00482000(kpanic),0x00100000@0x00484000(system),-@0x00584000(user)
These are the partitions' parameters, where each partition is described as:
partition_size@partition_offset(partition_name)
So the "kernel" partition in my MK908 is at offset 0x4000 and has a size of 0x6000  (= 24,576 sectors of 512 bytes each = 12,582,912 bytes).

Warning: If your partition of interest has an offset that is not multiple of 4MB, you MUST follow the "misaligned" instructions below, using your device's offsets.


Always remember that the flashing tool requires the numbers in reversed position compared to what appears in the mtdparts above, that is: first the offset, then the size, like:
sudo ./rkflashtool r (offset) (size)



5) Backup stock partitions!


I strongly recommend to read and store in your PC at least the boot, kernel, and recovery stock partitions of your devices, before you start tinkering with it!

This is very easily done with these commands (substitute the offsets and sizes with the ones from your mtdparts):


sudo ./rkflashtool r 0x4000 0x6000 > stock_kernel.img
sudo ./rkflashtool r 0xA000 0x8000 > stock_boot.img

sudo ./rkflashtool r 0x12000 0x10000 > stock_recovery.img


6) Flash your new kernel


Since my kernel partition's offset (0x4000 = 16384 => *512B = 8 MB) is a multiple of 4MB, flashing it becomes as easy as:
sudo ./rkflashtool w 0x4000 0x6000 < kernel.img


NOTE: If for some unknown reason you wanted to flash a kernel into boot partition, you should flash the same one that is used to flash recovery.

In order to ensure flashing is done correctly, always reboot the stick after flashing with the following command:
sudo ./rkflashtool b

Now your device will always boot to your kernel!

If it is a Linux kernel, then RK will directly boot to it, ignoring Android (until you revert these changes, by flashing back the stock kernel image)



Misaligned partitions (offset not at 4 MB boundary)


If the partition you want to write/flash starts at an offset not multiple of 4 MB then you will find that the first <4 MB that you write are wrong when/if you read them back.

An example of this can be found in Radxa Rock's boot partition, which starts at offset 0x9000 and has a size of 0x7000. If naively flashing boot with the command:

sudo ./rkflashtool w 0x9000 0x7000 < boot.img
That is: flash boot.img from 0x9000 up to, but not including, 0x10000 (= 0x9000 + 0x7000). If we proceed to read back the just written data, in order to verify it:
sudo ./rkflashtool r 0x9000 0x7000 > boot_readback.img

The result will be:
- Wrong, apparently random, data from 0x9000 up to, but not including, 0xA000 (note this is the first 4 MB boundary within boot partition)
- Good data from 0xA000 up to, but not including, 0x10000, that is: just what we've written, as expected.

This will cause the RK device to ignore the bad boot partition and jump on to recovery partition.

As far as I know, this problem arises when writing images, not when reading. It happens for Linux rkflashtool as well as for Windows RKAndroidTool.exe.



Workaround to flash misaligned partitions


The workaround I've found is to flash the previous partition (kernel) at the same time than boot partition. Why? Because kernel partition's offset is aligned to a 4 MB boundary, so there is no problem flashing it. Hence the operation would be:

//read stock kernel (padded to the full size of the partition)
sudo ./rkflashtool r 0x4000 0x5000 > radxa_stock_kernel.img
//concatenate the kernel partition with your own boot partition
cat radxa_stock_kernel.img my_own_boot_partition.img > kernelboot.img
//flash both partitions at the same time (0x5000+0x7000=0xC000)
sudo ./rkflashtool w 0x4000 0xC000 < kernelboot.img

//optionally read back to verify flashing operation
sudo ./rkflashtool r 0x4000 0xC000 > kernelboot_readback.img
//compare what we wanted to write, to what has been written
cmp -b kernelboot.img kernelboot_readback.img

//always safely reboot the RK device after flashing
sudo ./rkflashtool b



Friday, October 4, 2013

Radxa Rock board Linux development starts!

So, finally the Radxa Rock board (early developer sample) arrived.

First of all a big thanks to Tom Cubie and his team at Radxa for kindly donating it to further Linux development!



Overview


This tiny board looks fantastic, first and foremost because it has EXPANSION HEADERS, apart from this varied assortment of ports and peripherals:

- CPU RK3188 quad-core @ 1.6 GHz
- 2 GB DDR3 RAM
- 8 GB Flash
- Wifi + BT
- 10/100 Eth
- Audio I/O + integrated microphone + SPDIF Out
- IR RX
- 2 full size USB ports
- 1 OTG USB port
- Power connector (doesn't take up a USB port)

Very nice specs but, to me, what makes this board unique is the expansion headers (along with openly available schematics!) where you can directly plug and access devices through I2C, SPI, UART, ... there is even an LCD output as well as another USB port at those pins!


First boot


After screwing in the protective top/bottom methacrylate plastics you will need a power adapter and an HDMI cable (normal size connector, not mini/micro) to attach it to a display and be ready to boot.

When you power the board for the first time it boots into Android, scaled 720p and in English, version 4.2.2 with kernel 3.0.36+ based on RK3188 R-BOX Android 4.2.2 SDK v1.0.0-130514.
However, beware, there is no Google Play, so you're on your own to install apps.


Hack it!


If you want to tinker with it, nothing easier, turn it off, unplug power and then: while keeping pressed the Recovery push-button nearby the USB ports, plug the OTG USB port to your PC.

A board red LED will light immediately, give it 2 seconds (or it'll boot Android) and, then, you can release the pushbutton and go to your PC.

I'm supposing you're on Linux, so if you go to a Terminal and write "lsusb" you'll see a new nameless device with ID: 2207:310b which corresponds to a RK3188 SoC awaiting flashing instructions.


IMPORTANT TIMEOUT: This recovery mode for flashing powers off after 2 minutes from last flash operation  or from being plugged in (if you do no operations). So it will issue a "power off" command through the serial console and just disappear from "lsusb" output. You'll have to re-plug it again to access it.

Then, through the usual Windows RK-provided tool or with the Linux rkflashtool that you can download and compile with ease from: https://github.com/Galland/rkflashtool_rk3066   (I know, worst name ever, it does handle RK29* and RK31* too).

So download and compile the Linux USB flashing tool:

git clone https://github.com/Galland/rkflashtool_rk3066 rkflashtool
cd rkflashtool
sudo apt-get install libusb-1.0-0-dev
gcc -o rkflashtool rkflashtool.c -lusb-1.0 -O2 -W -Wall -s


Ask the Radxa board about its partition sizes and offsets:

sudo ./rkflashtool r 0x0 0x1 | head -n 11

the result should be:

FIRMWARE_VER:4.1.1
MACHINE_MODEL:rk31sdk
MACHINE_ID:007
MANUFACTURER:RK31SDK
MAGIC: 0x5041524B
ATAG: 0x60000800
MACHINE: 3066
CHECK_MASK: 0x80
KERNEL_IMG: 0x60408000
#RECOVER_KEY: 1,1,0,20,0
CMDLINE:console=ttyFIQ0 androidboot.console=ttyFIQ0 init=/init initrd=0x62000000,0x00800000 mtdparts=rk29xxnand:0x00002000@0x00002000(misc),0x00005000@0x00004000(kernel),0x00007000@0x00009000(boot),0x00010000@0x00010000(recovery),0x00020000@0x00020000(backup),0x00040000@0x00040000(cache),0x00200000@0x00080000(userdata),0x00002000@0x00280000(kpanic),0x00100000@0x00282000(system),-@0x00382000(user)

What does this tell us?

Well, for us Linux developers, used to sharing sticks' space with Android (unless you decide to wipe it and make your Linux take over the flash...) we are bound to flashing our kernels into the "recovery" partition so that we can dual boot Android or Linux by having the latter's filesystem in a MicroSD (also called uSD) card.

And then, from above parameters, where each partition is described as:
        partition_size@partition_offset(partition_name)
we infer that our "recovery" partition is at 0x10000 and has a size of 0x10000
Please remember that the flashing tool requires these numbers in reversed position (first the offset, then the size), like   sudo ./rkflashtool r (offset) (size)


Hence, once you have downloaded/compiled your Linux kernel and have a Ubuntu rfs (root file system) in your uSD, you can go ahead and flash your Linux kernel with these simple commands:

sudo ./rkflashtool w 0x10000 0x10000  <   my_kernel_recovery.img
sudo ./rkflashtool b

The "b" command safely reboots the RK device when the flash is written.

I'll initially be using my most up to date kernel for booting Linux, so you may see some activity there:
https://github.com/Galland/Linux3188

Have fun hacking!

Monday, September 16, 2013

DWC USB interrupt spam in Rockchip SoCs

Some time ago, when looking for answers to some USB 1.1 problems on the RK chips, like:
- USB 1.1 to Ethernet dongle not working
- Repeated or missing key presses
I stumbled upon some Raspberry Pi forums complaining about the same things.

This is logical since both the Rasp. Pi SoC and the RK3066/3188 are using the same USB HW IP cores (from DesignWare, that is DWC).

One of the problems they were reporting was an excessive number of interrupts per second coming from the USB while the system was idle (I've confirmed it, even with just a USB 1.1 keyboard attached).

One way to check this is with the console command:
vmstat 1
Looking below label "in" will tell you how many interrupts are there per second. In my case, Linux3188 kernel ( http://github.com/Galland/Linux3188 ) on a RK3188 Cozyswan S400 (kindly donated by KSK Electrics) the result is some 10600 interrupts per second.

And a way to see who is interrupting is simply to type:
cat /proc/interrupts
In my case, the "dwc_otg_hcd:usb1, dwc_otg_pcd" is the root cause for some more than 8000 interrupts per second, just as it happens to RPi guys.

The problem seems to stem from the DWC driver, as explained here:
"the Synopsys driver relies on the start of frame interrupt for scheduling transfers if "descriptor DMA" is not implemented (which it isn't, on BCM2835).  8000 is one interrupt per microframe."
and propose the use of a FIQ (ARM fast interrupt handler) for USB IRQs to discard USB microframes that contain no data. More info here...

And the FIQ enabled code lies in this repo (see commits starting in April 2013 by Gordon Hollingworth): https://github.com/ghollingworth/linux/commits/rpi-3.6.y


Testing real screen resolution on RK Linux

Problem:


You think you have a 1080p screen resolution but when you draw a non-aliased one pixel width line and move the window around, it doesn't look one solid line anymore.

You're not on 1080p, but likely on a scaled 720p (even if Linux reports 1080p).


Test:


On a console type:

cat /sys/devices/platform/rk-fb/graphics/fb0/disp_info

for a working 1080p setup, the result should be something like:

win0:enabled
xvir:960
xact:1920
yact:1080
xdsp:1920
ydsp:1080
x_st:192
y_st:41
x_scale:1.0
y_scale:1.0
format:RGB565
win1:disabled
xvir:0
xdsp:320
ydsp:240
x_st:10
y_st:10
format:ARGB888

That is xact and yact (the virtual resolution seen by Linux) must be the same as xdsp and ydsp (the real resolution been sent to the screen), or else you have a scaled output (x_scale and y_scale not 1.0).

Solution:


If this is the case and you find that xdsp=1280 and ydsp=720, whereas you expected a 1080p display, the solution is in this commit:
https://github.com/Galland/3188-SRC-AP6210/commit/130c1ad6bb47f3b2401b6156f205dcb5882255c7


BTW, notice the 16 bits color: RGB565
I couldn't tell the difference with normal desktop usage, but it means half the memory operations (32 bits ARGB888 <-> 16 bits RGB565).

Wednesday, September 11, 2013

Root Rockchip sticks/tablets from Linux

Since with every new device it becomes a nightmare (at least for me, that I seldom use Windows) to find the right Windows drivers for ADB access... I noticed that the rooting procedure (TPSparky Vondroid) relies only on the adb command and... that is readily accessible from Linux.

Hence this little guide came up as I put together the necessary little bits and has been tested with a RK3066 based tablet (RK3188 devices should also be rootable with this method, confirmed with Minix Neo X7).


1st Set up Linux ADB access to the device


This step is entirely done from the Linux PC (Ubuntu in this case) where the RK device is connected (through the USB). 

Please note that if your RK device has several USB ports, there will be only one that can be connected to the PC, usually marked as OTG or Slave.


1) Download the lightweight adb tools:
sudo apt-get install android-tools-adb
or, if you don't have Ubuntu, proceed to download and install the whole Android SDK :S


2) Open/create the following text file to let your standard user connect to the RK device:
sudo gedit /etc/udev/rules.d/51-android.rules
and then add a new line with the following text:
SUBSYSTEM=="usb", ATTR{idVendor}=="2207", MODE="0666", GROUP="plugdev"
Of course make sure that your Linux user is part of group "plugdev" with the following terminal command:
groups user

3) Force a reload of the USB access rules to get the latest one on:
sudo udevadm control --reload-rules

4) Add RK devices USB Vendor ID to what adb may expect for your currently logged user:
echo "0x2207" >> ~/.android/adb_usb.ini


2nd Set up the RK device for ADB access


Unplug the RK device from the USB and go to its Settings page to follow this steps:

1) Go to Settings->Storage and click at the top right on the three dots

2) Select USB computer connection in the dropdown

3) Select "Mass Storage" check box and go back to Settings

4) Browse down in Settings and select Security

5) In Security Settings, select "Unknown sources"

6) Back in Settings, select Developer Options

7) In Developer Options, select "USB debugging"

8) Close settings, and any other open apps.

9) Using a known good USB cable, connect the RK device to the PC, you'll get "Connecting to USB" in the notifications area in Android, and a USB icon in the notification area. You Do Not want to select "Connect to Pc to Transfer Files", in the notification menu, just plug in the cable and let it be.

PS: If you don't get a connection you may have to go back into Settings and select USB, then click on "Connect to PC".

3rd Rooting the RK device from Linux


The following steps are just a COPY of those in "TPSparkyRoot.bat" with a minor fix for correct SuperSU installation.

These are to be done on the Linux PC:

1) Download the package with the needed su, SuperSU, busybox, and RootExplorer binaries

2) Extract the package into a folder, open a terminal and cd into that folder

3) Create a new text file (i.e. "gedit script.sh") and copy the following contents:

   echo "*---* VonDroid.com RK device Root Tool based on work by sunnydavid *---*"
   echo "--- Plug in your device, make sure debugging is enabled in Developer Options"
   echo "--- This script will now copy files over to your RK device"
   
   adb shell mv /data/local/tmp /data/local/tmp.bak
   adb shell ln -s /data /data/local/tmp
   adb reboot
   
   echo "--- Reboot 1/3 - Press Enter once the device has rebooted (if USB debugging doesn't appear in the Android bar you may have to click Settings->USB->Connect to PC)"
   read -p "or CTRL-C to exit"
   
   adb shell rm /data/local.prop > nul
   adb shell "echo \"ro.kernel.qemu=1\" > /data/local.prop"
   adb reboot
   
   echo "--- Reboot 2/3 - Press Enter once the device has rebooted (if USB debugging doesn't appear in the Android bar you may have to click Settings->USB->Connect to PC)"
   read -p "or CTRL-C to exit"
   
   adb shell id
   
   echo "--- If the ID shows as 0(root) then continue, otherwise CTRL+C to cancel and start over"
   read -p "CTRL-C to exit"
   
   adb remount
   adb push su /system/bin/su
   adb shell chown root.shell /system/bin/su
   adb shell chmod 6755 /system/bin/su
   adb push busybox /system/bin/busybox
   adb shell chown root.shell /system/bin/busybox
   adb shell chmod 0755 /system/bin/busybox
   
   echo "--- Installing SuperSU"
   
   adb push SuperSU.apk /system/app/SuperSU.apk
   adb shell chown root.root /system/app/SuperSU.apk
   adb shell chmod 0644 /system/app/SuperSU.apk
   adb push RootExplorer.apk /system/app/RootExplorer.apk
   adb shell chown root.root /system/app/RootExplorer.apk
   adb shell chmod 0644 /system/app/RootExplorer.apk
   
   echo "Completing Root ..."
   
   adb shell rm /data/local.prop
   adb shell rm /data/local/tmp
   adb shell mv /data/local/tmp.bak /data/local/tmp
   adb reboot
   
   echo "--- Reboot 3/3 - Your RK device should now be rooted!"


4) Make the script executable with: 
chmod +x script.sh


5) Restart the adb server by typing:
adb kill-server; adb start-server
6) And now when typing the following terminal command:
adb devices
you should see the connected device listed (my tablet for example is named 12345678...)


7) Execute the previously created script ( ./script.sh ) and follow the steps to the letter, including patiently waiting for the potential several-minutes-long pauses

PS: After every reboot you MUST check that in the Android status bar the "USB Debugging" message appears (so that there is adb connection with the PC), or else you'll have to go back into Settings and select USB, then click on "Connect to PC". Only then you can hit Enter in the script to let it go on.


That's it, your device should be rooted, all from within Linux!



DISCLAIMER: I've followed this instructions to root my own devices without any trouble. The rooting procedure itself is simply the very widely used TPSparky method. However I take no responsibility for any mishappenings that may arise from your trying it on your devices. That is entirely yours.


References:
http://forum.xda-developers.com/showthread.php?t=1526487
http://linux-rockchip.info/mw/index.php?title=ADB_shell_with_RK3066
http://forum.xda-developers.com/showthread.php?t=2127573

Friday, July 12, 2013

Serial console mod for RK3188 stick Cozyswan S400

First of all, I would like to thank KSK Electrics for kindly donating this S400 stick (and a MK908) to support the Linux kernel porting on RK3188 devices.


A serial console for the Cozyswan S400 was needed in order to debug the boot problems encountered with the RK3188 kernel source "freed" by Andy from Rikomagic.

Also, since this kernel removed support for the framebuffer console (the text you [should] see on screen at boot, or in text Linux, before installing any XFCE/Gnome/...), the serial console is the only way to see what's happening when there is something wrong.

Fortunately I was able to successfully backport the framebuffer console so that now text is back on screen for Linux!

In any case here is the mod to get the serial console pins, thanks to Alok Sinha, who found those pads to be the serial output. They looked to me so much like an IR tx/rx connector that I would have tested every other pad before trying those! :)

Left to Right: The R (RX) pad for receiving keystrokes, the T (TX) pad for sending to your
Serial2USB module the text, and the required G (Ground) 

Actually only TX and Gnd are needed to receive the boot text, so I usually solder just those two.


The pads are small, with a tiny bit of solder on the iron tip and
another tiny bit on the cable, you should get good results

Omegamoon, who did the MK808 (RK3066) and MK908 (RK3188) sticks' serial console mods, recommends this nice Serial2USB module.


The three clams, as I call them

You can find here the Serial mod instructions for the Measy U2C RK3066 stick.

I hope it helps!