Wednesday, October 23, 2013

DIY NAS with a RK3188 device (Radxa Rock)

I currently have a full-blown Linux PC noisy tower serving 3 SATA hard disks full of multimedia as a home server... that is some 80 Watts of power consumption, plus the noise, for just a few hours of use per week.

There must be a better solution for my home network file-sharing (also called NAS) needs!

So, come the Radxa Rock board, equipped with a Quad Core ARM CPU, the Rockchip RK3188, and 2 GB RAM, quite a beast actually (I'm currently blogging from it, and use it for almost all my PC needs).

And here is today's proof-of-concept RK3188 NAS happily serving files from my desk:

1st rev.: RK3188 functioning as NAS home fileserver (using Radxa Rock board)
UPDATE:
2nd rev.: Radxa Rock as a 3 hard disks NAS (11W idle, 33W with 2 disks streaming)

Now, if you want to bear with me on the technical side... I've been doing the math about data bandwidths for some time already and taken into account the Rockchip datasheet briefs to guess the best I/Os for the task:


Hard disk interface:


Let's face it, Rockchip SoCs don't have SATA ports, and other ARM SoC have at most one SATA port, afaik, and that still means an external power for the SATA device is necessary. That is not a solution for NAS, unless you can fit everything in just one hard disk.

So let's get over it and find the second best solution: USB 2.0 ports are the highest bandwidth inputs (to connect the hard disks). The Radxa Rock board has:

- Two full sized USB 2.0 ports, and a third one in the pins of the expansion connector. All these ports are sharing, through an integrated hub, one single USB bus coming from the RK3188.
- One Micro USB 2.0 OTG  port that is directly wired to the RK3188.

Ideally USB 2.0 would mean up to 480 Mbps raw throughput so, to get the best, we don't want to share it with other devices. Hence, we will be plugging our hard disk/s to the USB OTG port.

Thankfully the market is full of external hard disk enclosures that do a very good job at converting SATA to USB. And let's see what that means:

- SATA is currently doing 3 Gbps
- USB 2.0 is "just" 480 Mbps, here is a bottleneck, certainly, but is it?


Why USB 2.0 is fine instead of SATA

Does this sound like a let down? Really? Let's do the math:

Are you going to be streaming 1080p content over Wifi? That really leaves you with <300 Mbps, and most probably <150 Mbps, if you can maintain that incredible wireless speed.

But, let's see what 150 Mbps really means in today's high compression world:

150 Mbps / 8 bits per byte = ~19 MB/s and let's say your content is a 1h30m long movie...
19 MB/second * 90 minutes * 60 seconds/minute = 100 GB movie!

Is your movie larger than that? Then this solution is clearly not for you. For the rest of the world, let's go on:

You may rightly object: movies have well and bad compressed parts, fast action may mean a bandwidth spike!

Well, you are right, and that's why multimedia players use a technique called buffering! This mostly rids us of the problem.

So once we accept that it's OK to stream things at Megabit speeds, we may stop worrying about using SATA hard disks over USB.



Network interface:


As I/O, the Radxa Rock board has an integrated Fast Ethernet, that is connected directly to the RK3188 (through the usual RMII PHY interface). This means 100 Mbps so... people with movies of >66 GB may stop reading now.  ;-)

For the sake of this proof-of-concept, we will be using this 100 Mbps Ethernet port, although a better solution would be to have a Gigabit Ethernet adapter attached to a full sized USB 2.0 port, which would give us up to 480 Mbps of actual bandwidth.

Do not share the USB OTG port with the hard disk/s! The RK3188 (and the RK3066) has two physical USB 2.0 buses: the OTG and the "full sized", so use both as much as possible, instead of cramming all devices onto just one's bandwidth.




File-sharing Speed Testing:


I am using a bare Xubuntu Linux on the Radxa board so it is possible to connect to the SATA hard disk through FTPS out of the box.

The SATA II hard disk is in a external USB 2.0 enclosure and has a 1.5 TB NTFS partition and we will be using a FTPS server (slower than FTP). Not the best case for speed, but will let us see how well it can do on this not ideal setup.

So, first of all, let's test how fast the RK3188 itself can read files from it, by running this command on the connected [but unmounted] drive:
sudo hdparm -t /dev/sda
/dev/sda:
 Timing buffered disk reads:  90 MB in  3.03 seconds =  29.74 MB/sec
The repeated tests result always around and very close to 30 MB/second. That is some 240 Mbps, or 50% the theoretical maximum USB 2.0 speed.
Who is to blame? I fear in this case it's my old USB2SATA's fault, since doing the same speed test on an i7 top of the line PC yields some 33 MB/s.

Good, more of a worst case then, so let's do real life tests with actual multimedia files on the SATA disk served over Fast Ethernet by the Radxa Rock RK3188 board:

Streaming an 11 GB action movie (1080p) requires an average of 2 MB/s and is perfectly watchable on the remote PC, as if it were a local file.

Transferring a large file over Ethernet to another PC maintains a speed of 6.7 MB/s, that is a bit over 50 Mbps.

I've also tested transferring a file from the MicroSD card where Xubuntu runs, just to do a test without USB and SATA, the result is a constant speed of 7.2 MB/s.

For the sake of completeness, I too have tried this same raw transfer (FTPS from MicroSD) using a Gigabit Ethernet to USB 2.0 adapter, the result is a constant speed of 8 MB/s.
Better and more than enough for our purposes, but still below my expectations. Next thing will be to test with an FTP server, without the FTPS encryption burden!

Further details about these tests: the "intermediary" is a Gigabit switch that has been thoroughly tested at 1 Gbps speeds.

So it seems the RK3188 is perfectly able to cope with the task, even using a heavy encrypted FTPS server.



Conclusions for a faster NAS file-sharing solution


1) Use a Gigabit Ethernet to USB 2.0 adapter (and from a reliable source or you'll find yourself with a ridiculous USB 1.1 device able of <11 Mbps) and connect it to the full size USB port on your Rockchip board/stick.

2) Set up a simple FTP server for file-sharing, that makes sure your RK3188 can concentrate on reading the hard-disks through USB and the network protocols, instead of the heavyweight encryption for the FTPS. Even if you go wireless, Wifi already encrypts everything on the air!

3) Use Linux-friendly EXT4 partitions. NTFS is not bad, but will require more CPU to read/write (you'll see a process called "mount.ntfs" often). FAT what?

4) If you want to have a 4-disk NAS or even an 8-disks NAS, no problem! Just know you should still plug them all, through a USB hub, to the same USB port.

5) And the final tip to make a nice NAS solution:
sudo hdparm -B 50 /dev/sda
This wonderful command at NAS startup will take care of turning-off your hard disks when they are unused, saving power and hard-disk life, while keeping a 100% silent environment!


UPDATE: If the drive answers with:
HDIO_DRIVE_CMD failed: Input/output error
 APM_level = not supported
Then try this similar command:
sudo hdparm -S 20 -K 1 /dev/sda

(substitute /dev/sda in these commands with your actual /dev/sdX device)


Next step: a quad hard-disk NAS solution based on Rockchip ARMs for all my file serving needs!




Wednesday, October 16, 2013

Radxa Rock communicating with I2C devices

Since I'm a hardware tinkerer at heart, and my background is more on electronics than on software, the Radxa Rock board had a deeper interest for me.

This board has a lot of potential for all kind of low level electronics, thanks to its two expansion headers:

Expansion Headers from Radxa Rock schematics



As you can see there are two UARTs (number 3 is shared with some GPS pins), one I2C bus, two SPI buses (SPI1 on J8 is shared with GPS pins), a full 24 bits LCD display output (!!), one USB port (HOST_D*2), one audio Line In (LINE_L/R), as well as several other GPIO I/Os.



I then set out to test my latest kernel for booting Linux on the Radxa Rock to access one of the, for me, most interesting low level hardware buses: I2C.

This one is heavily used for low bandwidth (control/status, sensor data readings, EEPROMs, etc...) communications inter integrated circuits (I I C... I2C ;). This bus consists of just two lines: SCL (master clock) and SDA (bi-directional data), which makes it extremely handy.

And for this test, a handy old friend of mine: the BMP085 pressure sensor (featured on this blog's first post) inside a little PCB with an accelerometer chip, gyroscope chip, magnetometer compass chip, and our pressure and temperature sensor chip, the BMP085.

This is all called a 10-DOF or Ten Degrees of Freedom sensor board, since it allows for precise movement/position detection through "sensor fusion" (though I really dislike using nerdy "magic words").

So first's first, I wired the 10-DOF board to the Radxa's left expansion header (J8) in the following manner:
- PCB's VCC (5V) wired to J8 exp. header's pin 40 (DC5V)
- PCB's GND wired to J8 exp. header's pin 39 (GND)
- PCB's SDA wired to pin 32 (I2C0_SDA)
- PCB's SCL wired to pin 31 (I2C0_SCL)


The result looks like this:

Radxa Rock board bus I2C #0 connected to a 10 degrees-of-freedom sensor board


So, what to do to start communicating with the board? Well, since my kernel already has all the needed things built-in, you just have to follow these steps (shamelessly taken from this guide):

#install i2c-tools (user space) for talking to I2C buses/devices
sudo apt-get install i2c-tools
#insmod the I2C-dev module to allow user space access to I2C
sudo modprobe i2c-dev
#probe I2C bus 0, the one at expansion header J8
sudo i2cdetect -y 0

The result of this last command is the possibly detected I2C devices on bus 0 (remember the 10-DOF board has 4 devices sharing the same bus). In our case we do know the I2C address of the BMP085 (0x77), so we can talk to it directly.

Since I know the calibration parameters of my device (see AC* at first screenshot in this post) and their addresses, I can just compare to see if this is random data, or actually the BMP085 chip, being talked to from Linux running on the RK3188 of the Radxa Rock board:

Calibration parameter AC1, which for my 10-DOF board has a 2 byte value of 6746 (0x1A5A) is located at I2C registers 0xAA (MSB) and 0xAB (LSB), by reading the sensor's datasheet.

Let's dump the contents of the device at that address (the BMP085) to confirm we are talking to it:

#dump non-interactively (-y) contents of selected device (0x77)
#on given I2C bus (0) in byte read mode (b)
sudo i2cdump -y 0 0x77 b

Not really illustrating, but the result is:
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
80: a5 94 52 49 a4 27 77 a6 1e 26 1a 5a fb dd c7 bc    ??RI?'w??&?Z????
90: 7c 9e 60 2c 59 11 15 7a 00 37 80 00 d4 bd 09 80    |?`,Y??z.7?.????
a0: a5 94 52 49 a4 27 77 a6 1e 26 1a 5a fb dd c7 bc    ??RI?'w??&?Z????
b0: 7c 9e 60 2c 59 11 15 7a 00 37 80 00 d4 bd 09 80    |?`,Y??z.7?.????
c0: 00 00 bc 33 00 00 00 00 00 00 00 10 00 00 00 03    ..?3.......?...?
d0: 55 01 06 00 00 00 00 00 00 00 00 00 00 00 00 00    U??.............
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
f0: 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00    ......?.........


And sure enough! you can find the values (1a and 5a) of this little example at the expected register addresses (0xAA and 0xAB).

RK3188 is communicating with the 10-DOF board through one I2C bus at the expansion header!

Radxa Rock meets the world of electronics!






Saturday, October 12, 2013

Doubts over Rockchip FB Vsync fix

Almost every owner of a RK3188 stick has noticed video problems, like stuttering or a lost frame every now and then, no matter its being a local file or just a small avi.

Some time ago phjanderson (from Freaktab forum) found a solution to this:
http://www.freaktab.com/showthread.php?5939-Fixing-RK3188-video-playback/page2&p=81489#post81489

It basically eliminated a blocking condition on a function on rk_fb.c, which also happened to apparently solve the stutter problem. This was called phjanderson's Vsync fix and lots of ROMs have added this patch since.

I then set out to test it on Linux along with my framebuffer fix (see https://github.com/Galland/3188-SRC-AP6210/commit/a3ddf7e46c4426e6cc67e09d7eee2a14baeea1f0 ) just to find that after a random amount of minutes after boot, there appeared a new thread called "fb-vsync" that utilized 100% of one of the 4 cores on the RK3188, regardless of the system being idle or never even opening a video.

To me, this is unacceptable since it forces the CPU to run at higher frequencies all the time, as well as consume lots more of power and a 25% performance penalty hit.

I initially thought it had something to do with Linux' screen usage or even with my framebuffer fix. However it did happen without the framebuffer fix, so I just let it out of my kernels.

However, I recently read on a forum ( http://www.rikomagic.co.uk/forum/viewtopic.php?p=15682&sid=e872d9b5e003da9082af7976a28fa50c#p15682 ) that Android people are seeing also the 25% CPU usage constant (1 core out of 4) due to this thread.

So I heavily suspect this patch is great for fixing the Vsync video stutter problems, but at the cost of losing 25% of the CPU performance, consuming more power all the time (+heat!), and thus reducing the component's life.

If you happen to have flashed a rooted ROM with Vsync fix and have an Android monitor installed (able to track system threads), please write a comment sharing if you've been able to see the thread in action.


UPDATE:

I'll try to explain a bit the code related to this problem.
Most of it is located in rk_fb.c where:
1) upon registering fb0 (the main framebuffer) a thread called "fb-vsync" is created.
2) This thread executes the function "rk_fb_wait_for_vsync_thread"
3) This function is an "infinite" loop that emits a "vsync" notification to user-space apps subscribed to it, whenever a Vsync happens, meanwhile it waits idle.

How does it wait for a Vsync?
Through the use of "wait_event_interruptible" with arguments:
   - waitqueue: this is the event queue we're hanging on: dev_drv->vsync_info.wait
   - condition:
!ktime_equal(timestamp, dev_drv->vsync_info.timestamp) && dev_drv->vsync_info.active

The 2nd part of the condition (dev_drv->vsync_info.active) should always be met since it is set to 1 just after creating this thread.
What about the 1st part? It compares:
a) variable "timestamp": which is constant!! and set to the value of "dev_drv->vsync_info.timestamp" as it was just before calling "wait_event_interruptible".
b) dev_drv->vsync_info.timestamp as it IS any time the waitqueue is awaken

Naturally this condition is meant to become true (and exit the wait event to send the "vsync" notification) at the next Vsync.

Why? Because "dev_drv->vsync_info.timestamp" is updated by the lcdc interrupt service routine, which at the same time wakes up our "wait_event_interruptible" above!

Then the !ktime_equal compares the "timestamp" variable that holds the PREVIOUSLY set vsync_info.timestamp (before the wait_event is triggered) with the CURRENT, just updated, vsync_info.timestamp.
Hence the condition may indeed become true.


What did phjanderson's fix do? It just made this wait event to always have a true condition, hence the "while" loop is constantly executing (no wait) and notifying a "vsync".

How does it interact with Galland's framebuffer fix? Note that in the lcdc isr, the fb fix excludes the wake_up_... call, so what it does is make the wait event above to never be woken up. Kind of the opposite to phjanderson's.

The union of both fixes is... unfortunate too :) so I just left out phjanderson's fix, since the isr changes are needed for the overall fb fix.


Monday, October 7, 2013

Bitbanging Radxa Rock gpios

This post assumes you're using the latest Linux kernel from here on your Radxa Rock RK3188 board.

As you may already know, by looking at the openly available Radxa Rock schematics, this board has many GPIOs accessible through two expansion headers (along with other buses like LCD, SPI, I2C, etc.) as well as three user LEDs.

In this brief post I'll explain how to access any of these GPIOs to read/write its value. I've chosen one of the user LEDs to easily see the results of our actions.


By checking the schematics, it is easy to see there is a Red LED connected to GPIO0_B7 (gpio 175), an active low Green LED at GPIO0_B4 (gpio 172), and another active low Yellow LED at GPIO0_B6 (gpio 174).

How do I know the gpio number from the pin name? Relatively easy, look for your pin name here, and calculate the gpio number by taking into account that GPIO_BASE = 160 and NUM_GROUP = 32.


In this example we will toggle the Green LED on and off by following these commands in a Terminal within Linux in your Radxa (or through ssh to the board):

#become root
su root
#tell Linux we want to have access to gpio pin 172
echo 172 > /sys/class/gpio/export
#set it as an output pin (though we will be able to readback its value)
echo "out" > /sys/class/gpio/gpio172/direction
#set its value to 1 (turn off led)
echo 1 > /sys/class/gpio/gpio172/value
#set its value to 0 (turn on led)
echo 0 > /sys/class/gpio/gpio172/value
#in any case read the pin value
cat /sys/class/gpio/gpio172/value

Now, I'll be figuring out how to communicate with SPI and I2C devices hooked to the RR's expansion headers.




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!