I have working pretty hard on multiple projects recently, and that’s why I haven’t got the time to document my experiments with Cubieboard 2, but rest assured a good number of blog posts are coming up on that front.  However, I picked up this game from the internet called the 2048-tile game. Its a pretty neat (and addictive game) you can find the link here.

Here is the jist of what the game is – you have a 4*4 tile board and begins with 2 tiles with the number “2” on them. You can use the arrow keys to move all the tiles on the board in the 4 directions. Two tiles with the same number with combine to form a new tile with the next power of two, when they move in the direction you want them to.

Also, with every direction move, the game spawns a random “2” or “4” in one of the empty spaces on the board.

Image

As an example, I have shown the starting frame, and the frames after the first move in the left directions and the second move in the downward direction, notice how the tiles of 2 combine to make a tile of 4. You win the game when you reach the 2048 tile; or if you run out of space to move (the more likely possibility). Its more difficult than it sounds, not to forget, the game is very addictive. 

A lot of people I know, have played the game, but not many have succeeded in reaching to the 2048 tile (If github is to be believed, even the creator himself hasn’t finished the game yet.) The one thing I realized that was always messing up my game was these godforsaken tiles coming up from all directions and blocking by bigger tiles – and it forced me to take another route which took a lot of space on the board. So I figured that restricting the directions from which the tiles could block would be very crucial to the solution.

A simple way to do the above would be to restrict all your movement to the bottom side of the board and never pressing the up direction, just use the lefts and rights and downs to manoeuvre the tiles as much as you can. There will be a few instances where you will have to use the up direction thus causing a disruption if a 2 or 4 blocks your tiles – but its still possible to control single anomalies.

The second step that you need to take is to ensure that the you block the bottom left corner for the tile with the highest power of two, and the subsequent tiles in the bottom row arranged in the descending order. This is very important – because you will soon realize that when you do this, a single tile can sweep away all tiles taking you to the next higher power of two – making your path and hence your movements defined at any point of time – basically at any point in the game, you would be concentrating in making a power of two sufficient enough to trigger a chain reaction of geometric progressions.

A few pictures will make this clearer:

Image

The above picture is an example of this strategy, I kept the all my movements devoid of the up button, and concentrated on keeping the highest tile in the corner with the bottom row in the descending order. If you notice the images, all it will take in say the first image is a tile of 32 to introduce the 256 tile, similarly you see the strategy being applied in the subsequent images as well.

It takes time, but once you have the flow going you know what particular tile to focus on next and once you do that, the entire game becomes a series of local problems.

And now for the winning set of tiles (Narcissistic ego boost ):

Image

I have tried this strategy, and have reached the end goal three times. It seems like a strategy that is reproducible and seems logical that it will work. However, I am trying to see if the problem can be formalized in mathematical terms, and hence the solution would be a formal one as well.


It’s been a long time since I had/did something worth writing for the blog; never got around to hacking more on the Cubieboards. However, this morning I got a chance to get working on a Cubieboard 2! So got an SD card and was all prepared to get an OS up and running on it. But as luck would have had it, the SD card refused to do anything. Tried checking the dmesg log, and got this:

mmc0: error -110 whilst initializing SD card 

Seemed more or less like a driver issue of some sort, so the first thing that I tried was running lspci and getting what the hardware actually is. This was my lspci output:

abhinav@AsusK55V:/~ lspci
00:00.0 Host bridge: Intel Corporation Ivy Bridge DRAM Controller (rev 09)
00:01.0 PCI bridge: Intel Corporation Ivy Bridge PCI Express Root Port (rev 09)
00:02.0 VGA compatible controller: Intel Corporation Ivy Bridge Graphics Controller (rev 09)
00:14.0 USB controller: Intel Corporation Panther Point USB xHCI Host Controller (rev 04)
00:16.0 Communication controller: Intel Corporation Panther Point MEI Controller #1 (rev 04)
00:1a.0 USB controller: Intel Corporation Panther Point USB Enhanced Host Controller #2 (rev 04)
00:1b.0 Audio device: Intel Corporation Panther Point High Definition Audio Controller (rev 04)
00:1c.0 PCI bridge: Intel Corporation Panther Point PCI Express Root Port 1 (rev c4)
00:1c.1 PCI bridge: Intel Corporation Panther Point PCI Express Root Port 2 (rev c4)
00:1c.3 PCI bridge: Intel Corporation Panther Point PCI Express Root Port 4 (rev c4)
00:1d.0 USB controller: Intel Corporation Panther Point USB Enhanced Host Controller #1 (rev 04)
00:1f.0 ISA bridge: Intel Corporation Panther Point LPC Controller (rev 04)
00:1f.2 SATA controller: Intel Corporation Panther Point 6 port SATA Controller [AHCI mode] (rev 04)
00:1f.3 SMBus: Intel Corporation Panther Point SMBus Controller (rev 04)
01:00.0 VGA compatible controller: NVIDIA Corporation Device 1058 (rev ff)
03:00.0 Network controller: Atheros Communications Inc. AR9485 Wireless Network Adapter (rev 01)
04:00.0 Unassigned class [ff00]: Realtek Semiconductor Co., Ltd. Device 5289 (rev 01)
04:00.2 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168B PCI Express Gigabit Ethernet controller (rev 0a)

The device 04:00.0 seems to be unrecognised by the OS, so my guess was it was the SD card reader, and on googling the part number, turns out it was! And also that these drivers were not on the mainline kernel. The issue is faced by a lot of other brands of laptops as well, HP, Dell what not! On checking the Realtek’s driver download page here. However, they do not have a driver for 5289, the very device that my Asus has (But I still did not lose it on Realtek, I mean they have amazing WiFi drivers/hardware support). So I decided to look around, and luckily found a mirror where they still have the driver for 5289.  In case you are going through the same issue, you can follow the steps here:

abhinav@AsusK55V:/~ wget https://bugs.launchpad.net/bugs/971876/+attachment/2991730/+files/rts_bpp.tar.bz2
abhinav@AsusK55V:/~ tar jxf rts_bpp.tar.bz2
abhinav@AsusK55V:/~ cd rts_bpp
abhinav@AsusK55V:/~ make
abhinav@AsusK55V:/~ su -c 'make install ; modprobe rts_bpp ; depmod -a' 

All hell broke loose after this, I start getting these compilation errors while running make:

/home/abhinav/tmp/rts_pstor/rtsx.c:916:22: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘rtsx_probe’
/home/abhinav/tmp/rts_pstor/rtsx.c:1080:23: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘rtsx_remove’
/home/abhinav/tmp/rts_pstor/rtsx.c:1106:11: error: ‘rtsx_probe’ undeclared here (not in a function)
/home/abhinav/tmp/rts_pstor/rtsx.c:1107:2: error: implicit declaration of function ‘__devexit_p’ [-Werror=implicit-function-declaration]
/home/abhinav/tmp/rts_pstor/rtsx.c:1107:24: error: ‘rtsx_remove’ undeclared here (not in a function)
/home/abhinav/tmp/rts_pstor/rtsx.c:485:12: warning: ‘rtsx_control_thread’ defined but not used [-Wunused-function]
/home/abhinav/tmp/rts_pstor/rtsx.c:596:12: warning: ‘rtsx_polling_thread’ defined but not used [-Wunused-function]
/home/abhinav/tmp/rts_pstor/rtsx.c:745:13: warning: ‘quiesce_and_remove_host’ defined but not used [-Wunused-function]
/home/abhinav/tmp/rts_pstor/rtsx.c:780:13: warning: ‘release_everything’ defined but not used [-Wunused-function]
/home/abhinav/tmp/rts_pstor/rtsx.c:790:12: warning: ‘rtsx_scan_thread’ defined but not used [-Wunused-function]
/home/abhinav/tmp/rts_pstor/rtsx.c:816:13: warning: ‘rtsx_init_options’ defined but not used [-Wunused-function]
cc1: some warnings being treated as errors
make[2]: *** [/home/abhinav/tmp/rts_pstor/rtsx.o] Error 1
make[1]: *** [_module_/home/abhinav/tmp/rts_pstor] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.8.0-26-generic'
make: *** [default] Error 2

After a bit of googling I realized that this error exists for kernel versions above 3.6.x only. Below that, it works like a charm (After this point I had completely lost it on Realtek, I mean write proper drivers for crying out loud!). So the solution as it turns out is to edit the driver file “rtsx.c” and remove all instances of the string  “__devinit” “__devexit” and “__devexit_p” from it, leaving the rest of the code (and the rest of the line they occur in) intact. Meaning a line in the code which looked like :

 static void __devinit rtsx_remove(struct pci_dev *pci) 

Becomes:

 static void rtsx_remove(struct pci_dev *pci) *pci_id) 

After editing the file, I ran make again, the code compiled, and the kernel file was now ready. After this, I had to load the driver file onto the kernel using modprobe :

abhinav@AsusK55V:/~ sudo modprobe rts_bpp
abhinav@AsusK55V:/~ sudo depmod -a 

Now, in an ideal world, my SD card would be running fine and we’d have light sabers and death stars. However, my card reader still gave the same error, but apparently following the above method worked for most people. So I was pretty sure that the driver file wasn’t wrong. On running lspci again, it was clear what the problem was:

 abhinav@AsusK55V:/~ lspci -v -s 04:00.0
04:00.0 Unassigned class [ff00]: Realtek Semiconductor Co., Ltd.
Device 5289 (rev 01)
Subsystem: ASUSTeK Computer Inc. Device 1457
Flags: bus master, fast devsel, latency 0, IRQ 16
Memory at f7800000 (32-bit, non-prefetchable) [size=64K]
Capabilities: <access denied>
Kernel driver in use: rtsx_pci
Kernel modules: rts_bpp, rtsx_pci

So as you can see, although our newly compiled driver for the SD card, “rts_bpp” is available for the OS to use, it still continues to use the old buggy “rtsx_pci”. So the obvious steps would be ideally to unload this module and use our rts_bpp module. So I run:

abhinav@AsusK55V:/~ sudo modprobe -r rtsx_pci
 

Only to get this error:

FATAL: Module still in use
 

Turns out that there are certain other hidden modules which use the rtsx_pci module, so you had to unload them first and then unload this godforesaken module:

abhinav@AsusK55V:/~ lsmod|grep rtsx_pci
rtsx_pci            62705  2  rtsx_pci_sdmmc, rtsx_pci_ms
 

So as we see, the rtsx_pci module cannot be unloaded unless we unload the two modules that uses it, like this:

abhinav@AsusK55V:/~ sudo modprobe -r rtsx_pci_sdmmc
abhinav@AsusK55V:/~ sudo modprobe -r rtsx_pci_ms
abhinav@AsusK55V:/~ sudo modprobe -r rtsx_pci
abhinav@AsusK55V:/~ sudo modprobe -r rts_bpp
abhinav@AsusK55V:/~ sudo depmod -a
abhinav@AsusK55V:/~ sudo modprobe rts_bpp
abhinav@AsusK55V:/~ sudo depmod -a
 

So essentially, I unloaded all the kernel modules, including the one I compiled, ran a depmod, loaded just the rts_bpp and ran a depmod again. After a few seconds, my SD card finally mounted!

However rebooting the laptop reconfigured the settings again, and I was stuck with the rtsx_pci module again. So after running the steps above again, I blacklisted the rtsx_pci module:

abhinav@AsusK55V:/~ sudo nano /etc/modprobe.d/blacklist.conf 

by appending the file above with “blacklist rtsx_pci” in the end. After this you need to update the appropriate init files so that the setting sticks everytime you boot your system. You can do that by running:

abhinav@AsusK55V:/~ sudo updateinitramfs -u 

Its annoying how an error like this takes the whole day, when I could have just gone on Windows and done it. But there is something about fixing a problem that makes you feel happy. Now, I shall get back to getting arch on my SD card for the new Cubieboard 2! Hopefully I get to write some posts about GPIO interrupts, something that I have wanted to experiment with for so long now!


I frequently use GitHub to maintain a lot of my personal projects, minor hacks and if I am upto it, contributing to other open source packages. It is like this free (almost) unlimited remote server where you can push all your code. The downside is, unless you pay them some money, all your code ends up being open to everyone. Now if for some reason, you don’t want the code to be public, you might have to buy private space on GitHub or maybe try and apply for the free educational repositories. (Or move to BitBucket, but again the free ones are limited).

However, there is a cheap, albeit risky alternative to that – You can use your Dropbox space (Or Google Drive – if you are a fan of Google reading through your stuff) as a free Git remote server! This is not a fool proof method and the chances for conflicts arising are high if multiple users are pushing code, so it is best recommended for personal work, where only one person is pushing code to the remote repo.

A lot of people have done this before, so this is old news, but I think its a decent hack and worth telling people about it.

The Steps

Let’s move to the command line and set up our repository!

Step 1 :  Move to your Dropbox folder and create a folder (Git in our example) where you will be creating your repositories and initialize a bare repository like this:

 cd ~/Dropbox/Git
git init --bare dropboxrepo.git 

This will create a folder with the name dropboxrepo.git and inside it, you can see that it has all the essentials for a git repository.

Guts of the bare repository

Guts of the bare repository

Now technically you are making this repository on your local machine, but since it is inside the Dropbox folder, you are syncing it to their servers as well, and can access the folder contents anywhere.

Step 2 : Now go the local repository, where you maintain the code that you want to push to your remote repository, and add the above folder as a remote like this:

 git remote add dropboxremote ~/Dropbox/Git/dropboxrepo.git 

Basically what you did here is  add the path to your dropboxrepo.git folder as a remote alias. So now the alias dropboxremote will refer to this folder and will be identified as a remote repository.

Step 3 : Now that you have initialized a remote repo and added it to the remote alias in your local repo, you can now push your code like this:

 git push -u dropboxremote master </code>
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (6/6), 458 bytes, done.
Total 6 (delta 0), reused 0 (delta 0) Unpacking objects: 100% (6/6), done.
To /Users/abhinav/Dropbox/Git/dropboxrepo.git
* [new branch] master -> master
 Branch master set up to track remote branch master from origin.

After this, you should see the Dropbox spin sign for a while as it syncs all your files. However you will notice that after syncing, you don’t see your files in the folder but the same files you saw before (they are modified now though). But don’t worry all your files are synced. You can now follow the same steps as above and clone this repository on another machine and you will see all your committed code right there!

Word of caution

As I said before, this is not exactly the best way to have your own private remote server (It’s free!) and it comes with its own dangers. Firstly, if you push or pull while the folder is still syncing you might encounter errors like this:

error: unable to find ea2ae105b8955b3f73d79065bc52ee3126cd2e4f
error: refs/heads/master does not point to a valid object!
Your configuration specifies to merge with the ref 'master'
from the remote, but no such ref was fetched. 

If you see this error, just wait for the syncing to finish and try again. If it still doesn’t work, you will have to delete your current remote repo and create a new one and try again.

The above issue occurs frequently if there are a lot of contributors pushing the code to the same remote repo. Of course you can be careful and avoid them, just don’t pull/push while syncing!

I recently started using this method to maintain some of my private projects and it works just fine!

Happy tinkering!


A dedicated Home Server is a useful thing to have if you’re a hacker. You can use it as a remote repository for all your code, for hosting your website, dumping all your media and accessing it with any other device and even printer sharing. This post gives a detailed procedure of making (in my opinion) a near perfect home server using a Cubieboard!

Benefits of using a Cubieboard

Low Cost : For $50, the Cubieboard is like the cheapest computer in the world. Complete with 1GB RAM, 4GB space, 10/100 Ethernet port, two USB ports, SDcard slot, camera interface, audio out, HDMI AND along with all this awesomeness, it also has a complete SATA port. It also comes with a nice glass box for protection.

Low Power : The low cost doesn’t just end there with the pricing, the average power consumption of the Cubieboard is 8W, which if compared to standard low power servers is 5 times less! So it just doesn’t cost less, it consumes less as well!

Getting Started

You will need a functional operating system with SSH and Ethernet ports enabled on the Cubieboard before installing the server stack.In case you haven’t seen already, I have described how to do that in this post. Make sure you have followed the steps and installed a headless Debian on your Cubieboard before reading further. I have released the latest kernel images with fixed patches and SATA power enabled over here.

Now that the SATA is enabled, you can now easily connect a HDD, thus removing any space constraint on your server. (NOTE: The SATA works for a 2.5 inch drive only, for other HDD types, you will need external power source)

To ensure that the SATA interface works on boot, just type this command in your terminal (on the Cubieboard, of course!)

echo "sw_ahci_platform" >> /etc/modules

After connecting the Ethernet port, make sure you note down the IP of your server. You can do that by using the DHCP list or just doing a shell login with the TTL pins and running ifconfig, you will get all the network connection details including the IP.

Now that we have all the hardware and Operating System stuff settled, we consider our server stack options. One of the interesting options is the Napkin Server. It is based on JRuby, Sinatara and Neo4j graph database. The Napkin server offers a REST API with predefined services for storing and retrieving configuration information and collecting time series data from client devices. A plug-in model provides extensibility in HTTP handling and periodic processing of stored data. It is a very interesting project, you can refer to the wiki for Cubieboard installation here.

The second option would be to go for the more traditional LAMP stack. The installation is a very simple 3-step process.

Step 1: Installing Apache 2 and PHP 5

Apache is usually the go-to choice for most linux based servers. You can easily install Apache and configure it with PHP 5 with the package manager tool like this:

 root@cubie:~# apt-get install apache2 php5 libapache2-mod-php5 

The folder holding all the php pages by default is located in /var/www/

To check if php is properly installed, just open a sample php file:

 root@cubie:~# vi /var/www/test_file.php 

and add the following php code

 {codecitation}<?php phpinfo();?>{/codecitation} 

After you have saved this file, you can test by opening a browser on a different machine and connect to the following link: http://%5Bcubieboard’s-ip%5D//test_file.php and you will see this :

ScreenShot007-5

Step 2 : Installing MySQL Database server

The next step would be installing the database backbone. Again, installing MySQL is an easy task with the package manager:

 root@cubie:~# apt-get install mysql-server mysql-client php5-mysql 

While installing, you will get be prompted to insert a root mysql password. You can add it there,but in case you forget you can even add it later like this:

 mysql -u root
mysql> USE mysql;
mysql> UPDATE user SET Password=<your password> WHERE user="root";
mysql> FLUSH PRIVILEGES; 

Step 3 : Installing PHPMyAdmin

PHPMyAdmin is an extremely easy-to-use web-tool to manage the databases on your server. It is a very handy tool to remotely manage databases on your server. To install it simply go:

 root@cubie:~# apt-get install phpmyadmin 

During the installation process, you will be prompted with a screen to choose your choice of web-server. In our case, it is Apache2

debian6-kde-2011-04-07-23-07-56

Once the installation is complete, to test it, open a browser on a different machine connected in the same network, and open the link : http://%5Bcubieboard’s-ip%5D/phpmyadmin

Doing so will result in this:

ScreenShot012-3

To enter, you must use the Cubieboard’s login details. Once you enter the correct values, it should lead you to a Dashboard, which is pretty self explanatory to use!

ScreenShot013-3

Now you have a fully functional web-server!! You can now start experimenting with your server, maybe by installing wordpress on it and using it as a host for your own website!

Happy tinkering!


In my last post, we saw how flexible and powerful the Cubieboard can be, with the correct knowledge of the pin multiplexing and choosing the pin functionality for your application. Given that you have 7 UART ports, and around 3 SPI ports at your disposal, you can only imagine the power that this gives you.

The company that produces the SoC on which the Cubieboard is based on, AllWinner, primarily wanted to develop this chip as a cheap alternative to Android enabled device manufacturers, such as phones, tablets and what not! And hence, the chipset and subsequently the development boards, are powerful, flexible and have ports designed for external device interfacing, including 2 camera interfaces. (However, only one can be active at one time, like front cam and back cam) But, what it makes for in these interfaces, it lacks in the number of ADC’s (Only one, for accelerometer. People argue that it has the ADC’s for the LCD screen, but involves hacking the driver files, interesting project if someone is willing me to pay for it) and PWM channels. Basically, you cannot collect data or move motors by just using the Cubieboard.

So, if you are planning to use the Cubieboard in your Embedded Design Project, you will sooner or later have the need to communicate with a daughter board, either for getting a bunch of sensor data, or performing some actuation. This post comes as a result of a similar need I had, where I had to trigger a bunch of OpenCV codes which depended on certain sensor values.

Since I could not interface my sensors on the Cubieboard, I decided to use an Arduino for measuring the sensor data and communicate the processed values to the Cubieboard via UART.

The Cubieboard has 8 UART ports in all, including the 4-pin TTL port. However, this 4 pin TTL by default is used in the following ways:

  1. Console Messages (including bootup messages)
  2. A getty so you can login via serial

So, I would suggest that you avoid using the TTL pins, since you would need to edit the boot and initab files in order to use them. Plus, this port comes in very handy for debugging purposes. So instead, we will configure the other GPIO pins for UART.

On the Arduino side, instead of connected pins 0 and 1 (The default UART pins) , I decided to use the SoftSerial library instead. Why? Because I wanted to hook up my Arduino to my PC via USB, whilst it communicates with the Cubieboard, for debugging purposes.

Now I will show the codes on the Arduino and the Cubieboard side respectively, after which you can safely wire up the proper pins on both sides and communicate seamlessly.

Arduino side:

As mentioned before, I won’t be using the default serial pins for interfacing and instead use the SoftSerial library to configure pins 2 and 3 instead. However, the SoftSerial library does not support baudrates above 9600. We will see how that is actually a good thing for us later. Following code snippet sends a character to both serial ports if the ADC value is above a threshold, and prints whatever value it gets from CubieBoard to the PC:

/*

 Connects Arduino to Cubieboard
 Arduino: SoftSerial
 Raspberry Pi: GPIO UART

 Based on Arduino SoftSerial example

 */
#include

SoftwareSerial mySerial(2, 3); // RX, TX
int pressure;
int THRESHOLD = 500;

void setup()
{
 // Open serial communications to PC and wait for port to open:
  Serial.begin(57600);

  // set the data rate for the SoftwareSerial port to Cubieboard
  mySerial.begin(9600);

  // Set A1 as input sensor
  pinMode(A1,INPUT);
}

void loop() // run over and over
{
  // Measure the sensor value
  pressure = analogRead(A1);

  // If pressure crosses the threshold, send character to both ports
  if(pressure>THRESHOLD) {
    Serial.write("Y");
    mySerial.write("Y");
  }

  // If data is available on Cubieboard, print it to PC
  if (mySerial.available())
    Serial.write(mySerial.read());
}

Cubieboard side:

First order of business would be to configure a UART port  of our choice on the Cubieboard. For this case, UART5 is an optimal choice, it has only the Rx and Tx ports, just like the Arduino side, thus not wasting any GPIOs unnecessarily.

Now we make changes in the fex file like mentioned in my previous post and note down the pins:

[uart_para5]
uart_used = 1
uart_port = 5
uart_type = 2
uart_tx = port:PH06
uart_rx = port:PH07

The pins are : Tx (Port H, pin 6) and Rx (Porn H, pin 7)

Make sure to compile the fex file to an appropriate bin file, otherwise the changes will not be seen.

Just to check all the UART ports that you have, you can just list by the following command:

ls /dev/tty*

OR

dmesg|grep tty 

Now for the communication part, hackers tend to use Python due to the ease with which you can perform serial communication, thanks to the PySerial library. But in my case, since I had to trigger some OpenCV based codes, I decided to go the C++ way, since I could just include a header file in the main file and save a lot of unwanted mess.

Serial Initialization function

Although you can just open the Serial Port on any linux box as a file, you need to define some flow control and flag options for the desired communication terminal since this is an asynchronous communication and follows a proper handshaking protocol(If you need more clarification on this, please mention on the comments). So we will need some standard libraries for this purpose, you can add them like this:

#include
#include <sys/ioctl.h>

Now we initialize the serial port terminal options :

/*Init function, takes serialport address and baudrate as input */
int serialport_init(const char* serialport, int baud)
{
struct termios toptions;     //from the termios lib
int fd;                      //file descriptor

Next step would be to open the port with the proper flags and initialize the input and output data speed equal to the input baudrate:

//Open the port as a file
//O_RDWR = Open as read and write
//O_NOCTTY = TTY file not to be used for control purposes
fd = open(serialport, O_RDWR | O_NOCTTY)
//set the baudrate
speed_t brate = baud
//setting the input and output speed
cfsetispeed(&toptions, brate);
cfsetospeed(&toptions, brate);

Now that the serial port has been initialized with the correct options, you can just read it as a file and accordingly write the functions for them. For the complete code with the read and write functions, please refer to this link.

Now you can include this library in your main file and initialize the port like this:

 serialport_init("/dev/ttyS5", 9600); 

Final Connections:

Now that we have configured the UART pins and written the appropriate code on both ends, time to hook them up. Following are the pin outs:

Cubieboard Arduino
Rx – Port H, pin 7 Rx – pin 2
Tx – Port H, pin 6 Tx – Pin 3

The possibilities from here are endless, you can send commands from the Board to the Arduino and use them to control motors or actuators. In case you need further clarifications on any of these, feel free to drop a comment here!

NOTE: I mentioned before that the 9600 baudrate on the Arduino is actually a blessing in disguise for us, that is because Arduino supports only 2 pin UART, which is actually not at all ideal for a full duplex communication. Imagine this scenario, the Arduino sends some data and triggers a code on the Cubieboard, now any data that the Arduino sends while the Cubieboard is still executing the code will be lost because of the lack of proper data control pins. A quick fix around this would be to run a thread which accumulates the sensor data in a buffer on the board, or to time your code properly so that it finishes executing before the next data comes in

Happy Tinkering!


In the previous post I had mentioned how you can customize the way you use the Cubieboard’s pins by changing the script.bin file. This post will be expand on that thought further.

Fex files, bin files and sunxi-tools

Every chipset has a human-readble file which sort of acts like a metadata file for the I/O pins of the board, this file is called the fex file.  It is of no use to the chip itself. It needs to be parsed and converted into an equivalent binary file, named script.bin, like the one we saw in the previous post while installing our OS on the board.

Thankfully the tools for converting fex to binary and vice versa for the A10 boards already exist. You will need to get the source files for the same and compile them in order to use them. Run the following command to get the source files:

home@user:~$ git clone git://github.com/linux-sunxi/sunxi-tools.git 

This should clone a copy of the sunxi-tools repository in your folder. The tools provided here are exclusively for AllWinner A10 based boards. They won’t work for generic devices. Now that we have the source files, we can proceed to build the tools:

home@user:~$ cd sunxi-tools
home@user:~$ make fex2bin
home@user:~$ make bin2fex 

This will spit out two executables, fex2bin and bin2fex. These executables do exactly what they are named. Next step would be to transfer both these executables to the folder where you want to keep your script.bin files.

home@user:~$ cp /path/to/sunxi-tools/fex2bin /path/to/script/files

Now we use our existent script file, the one we downloaded from the git repo here, and get it’s equivalent fex file like this:

home@user:~$ ./bin2fex script.bin cubieboard.fex 

If it executes (and it should) successfully, it shows the following lines in the terminal:

fexc-bin: script.bin: version: 0.1.2
fexc-bin: script.bin: size: 44104 (79 sections) 

Now use your favourite text editor to open the cubieboard.fex file. You will see a lot of things that may seem gibberish at present.

Each line consists of a key = value pair combination under a [sectionheader]. All three [sectionheader], key and value are case-sensitive. For comments a semi-colon (;) is used and everything following a semi-colon is ignored.

Configuring the GPIO pins in the fex file

Now since we intend to use some of the GPIO’s here, go to the [gpio-para] section header. You should see the following under this section header :

gpio_used = 1
gpio_num = 4
gpio_pin_1 = port:PG00<1><default><default><default>
gpio_pin_2 = port:PB19<1><default><default><default>
gpio_pin_3 = port:PG02<0><default><default><default>
gpio_pin_4 = port:PG04<0><default><default><default>

The first line has the parameter gpio_used which is initialized to 1. This parameter basically denotes if the functionality described by the section header is enabled(1) or disabled(0). Thus in this case, it seems like the GPIO functionality is enabled for 4 pins (gpio_num). The properties of each pin are given in the subsequent lines.

Description of the GPIO configuration in the form:

port:<port><mux feature><pullup/down><drive capability><output level>

where:

<port> is the port to configure (ie. PH15)
<mux feature> is the function to configure the port for, mux 0 is as input, mux 1 as output and for 2-7 see A10/PIO for details.
<pullup/down> is 0 = disabled; 1 = pullup enabled; 2 = pulldown enabled (only valid when port is an input)
<drive capability> defines the output drive in mA, values are 0-3 corresponding to 10mA, 20mA, 30mA and 40mA.
<output level> sets the initial output level for the port; 0 = low; 1 = high (only valid for outputs)

The <pullup/down> <drive capability> and <output level> can be set to <default> which means don’t change. Any trailing <default> options can be omitted.

You can refer to the following image to see the I/O pins on the Cubieboard:

Cubieboard GPIO

Cubieboard GPIO

Configuring the UART ports

The Cubieboard supports a total of 8 UART ports, apart from the TTL connection provided. To configure them, you can check under the [uart_para$] section header, where the $ stands for a number from 0-7. These are the configuration parameters for UART1 (ttyS1):

[uart_para1]
uart_used = 0
uart_port = 1
uart_type = 8
uart_tx = port:PA10<4><1><default><default>
uart_rx = port:PA11<4><1><default><default>
uart_rts = port:PA12<4><1><default><default>
uart_cts = port:PA13<4><1><default><default>
uart_dtr = port:PA14<4><1><default><default>
uart_dsr = port:PA15<4><1><default><default>
uart_dcd = port:PA16<4><1><default><default>
uart_ring = port:PA17<4><1><default><default>

Since the uart_used parameter here is initialized to zero, this particular UART (ttyS1) is disabled and cannot be used. To enable it, you need to set it’s value to 1 just like we discussed for gpio_used in the previous section. This particular UART allows for the full 8 pin connection (uart_type = pin connections allowed). In case you are not familiar with it, these are the functions of each of the pin:

TX Transmit Data
RX Receive Data
RTS Request To Send
CTS Clear To Send
DSR Data Set Ready
DTR Data Terminal Ready
DCD Data Carrier Detect
RING Ring Indicator (Modem ring)

To interface this UART, you will just have to connect wires from the pins mentioned in the section header above to the appropriate pins on the slave device.

Generating the modified script file

Once we are done making all the modifications and customization we want, we need to generate the chip-readable script.bin file. To do that, we shall use the second executable that was taken from sunxi-tools earlier, the fex2bin.

home@user:~$ ./fex2bin cubieboard.fex script.bin

Succesful execution of this command will generate the new script.bin file which you can now transfer to the appropriate folder of your bootable SD card. On booting up your Cubieboard again, you will be able to use the modified pins just as you configured them in the fex file. To use your newly configured GPIO and UART pins, read ahead!

GPIO: After booting up the Cubieboard, do the following to use the GPIOs:

cubie@board:~$ echo 2 >  /sys/class/gpio/export
cubie@board:~$ ls /sys/class/gpio
export  gpio2_pb19  gpiochip1  unexport

Thus activating the second pin in your GPIO config (PB19) by generating a special file by the name gpio2_pb19. Similarly echoing 1,3 or 4 will activate the appropriate pins.  You can then write/read values from these files thus fulfilling the I/O function.

UART : For UARTs, you need to make the proper connections and then use some serial program like minicom. Or you can write your own code in Python or C to do it. In my next post, I will be writing a C program to perform a UART communication with an Arduino board, this will enable your Cubieboard to make more complicated tasks.


A few weeks back, I had the chance of working with this new family of ARM based System on Chip (SoC) chipset from this company called Allwinner Technologies. My work involved designing a system around the A10 family of chipset. So to get myself acquainted with it and creating a first prototype, I decided to play around with the development boards based on it.

Hackberry and CubieBoard are the two most famous development boards based on the Allwinner A10 chipset. And from its specifications, I can assure you, they are far more powerful and customizable than Raspberry Pi and BeagleBoards. If you want an in detailed comparison between CubieBoard and Raspberry Pi, you can have a look at Alexandre’s blog.

As Alexandre has pointed out rightly in his blog, the CubieBoard community is very young and the support is as good as zero. Hence this post is going to be an in-detail procedure on how to install a customizable version of a headless Debian on the CubieBoard. And maybe later, I might have some posts on how to interface with daughter controllers or something like using the board to set up a dedicated server.

The CubieBoard comes with a stock Android ICS on its NAND flash memory. However, there is a provision to boot from SD card. Hence we create a boot-able SD card for using the OS of our choice. This involves four steps:

  1. Partitioning the SD card (Preferred SD card size = 4GB)
  2. Installing the bootloader
  3. Installing the kernel files and the script.bin
  4. Installing a proper root file-system

A lot of out-of-the-box images for SD cards exist, but if you use them, you won’t be able to customize the GPIOs for your specific purpose. Hence we will manually do each step and look at the flexibilities it provides. To keep the post simple and short, I won’t be discussing how to build the tool-chains and kernel images in this post and use the kernel images I created myself instead. I will have separate posts for building the kernel images and the pin binaries.

The first and foremost requirement is to have Linux on your host machine (Laptop/Desktop).  I am not sure about Mac systems, but I am guessing that should be fine as well. But Windows is a strict no-no.

Partitioning the SD card:

The first MB of the SD card contains the partition table along with the bootloader binaries for booting. The next partition contains the kernel Images and the boot.scr files. The biggest partition contains the rootfs which takes around more than 2GB space. Thus it is best to use a 4GB SD card.

Now assuming that you have installed the sfdisk tools and your card is connected to the host machine, we begin with checking the partition table and the physical characteristics of the SD card, such as bytes per sector. Here we assume that the card is named sdd in the /dev/ folder. To know the name of your SDcard, run the command

home@user:~$ sudo ls -la /dev/sd*

This will list all the disk type devices connected to your machine and you can read the name from there. After running

home@user:~$ fdisk -l

this is the typical 4GB SD card partition that you should see:

Disk /dev/sdd: 3965 MB, 3965190144 bytes
122 heads, 62 sectors/track, 1023 cylinders, total 7744512 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xb4e92fdc

Device Boot    Start      End      Blocks      Id      System
/dev/sdd1      2048      34815     16384       83      Linux
/dev/sdd2     34816    7744511   3854848       83      Linux

Notice how sdd1 starts at 2048 sector. As the byte per sectors is 512, 2048 sector means that the partition sdd1 starts at 1MB. Usually the first  1MB space in a memory device is reserved for the Master Boot Record (MBR), the partition table and in case the memory device is bootable, the Initial Program Loader (IPL) and the Secondary Program Loader (SPL), also known as the bootloader binaries. Resetting the first 1MB of the SDcard ‘formats’ it.  to do that you need to run the following command:

home@user:~$ dd if=/dev/zero of=/dev/sdd bs=1M count=1

This writes zeroes for the byte size (bs) of 1MB, starting from the first sector itself. Thus rewriting over the entire column and subsequently formatting the entire card. If you run

home@user:~$ fdisk -l

now, it will show no partition table exists. Now we will use the sfdisk tools to make our partitions.

Most SD cards have similar properties as the one shown above, i.e bytes per sector is usually 512. Using this information, we calculate the number of sectors for our partitions and start from sector 1MB (Since the first MB is preserved for the above mentioned reasons). The following commands create a 64MB fat partitions and the rest is used as an ext4 partition.

home@user:~$ sfdisk -uS /dev/sdd
2048,131072,c #Here it tells you to define sdd1
131073,,L #Here it tells you to define sdd2. Being the last partition,
just press enter twice to exit 

Now we format these partition appropriately by running the following commands:

home@user:~$ mkfs.vfat /dev/sdd1
home@user:~$ mkfs.ext4 /dev/sdd2
home@user:~$ sync

Installing the kernel image and filesystem on the card:

Now that we have the card partitioned according to our needs, its time to set up the card by putting the appropriate files in their respective partitions. I have prepared three versions of kernel files and the bootloaders for the CubieBoard board. You can get these files from here.

A brief explanation of the files in this repository:

  1. Bootloader : This directory contains the bootloader files for the CubieBoard
  2. kernel_sunxi_3_* : These directories are the different kernel versions
    1. lib : This directory contains the firmware for that specific kernel version
    2. uImage : The actual kernel image file
    3. script.bin : The files that specifies the functionality of each pin.

So the flexibility provided here is that you can make your own script files and hence specify every pin’s function. Furthermore, you can write your own patches for the kernel and make custom images depending on what you desire. How to do generate custom files for these will be shown in later posts.

We should now have 2 partitions. One 64M in vfat format, and another in ext4. We also need to make this bootable, so lets blat in the IPL and SPL to the SD at the appropriate places. These files are in the directory named “bootloader” in the link given above.

Write spl ->8k and then write uBoot ->32k on the SD card.

home@user:~$ dd if=sunxi-spl.bin of=/dev/sdd bs=1024 seek=8
home@user:~$ dd if=u-boot.bin of=/dev/sdd bs=1024 seek=32

Now create a folder on your linux machine and mount both the partitions there. Do the following assuming that you are the superuser (sudo su):

home@user:~$ mkdir /mnt
home@user:~$ mkdir /mnt/boot
home@user:~$ mkdir /mnt/rootfs
home@user:~$ mount -t auto /dev/sdd1 /mnt/boot
home@user:~$ mount -t auto /dev/sdd /mnt/rootfs
home@user:~$ cd /mnt/boot

Now, create a file in the /mnt/boot directory named boot.cmd and write the
following in it:

setenv bootargs console=ttyS0,115200 console=tty0 noinitrd init=/init root=/dev/sdd2
rootfstype=ext4 rootwait panic=10 ${extra}
fatload mmc 0 0x43000000 script.bin
fatload mmc 0 0x48000000 kernel.img
bootm 0x48000000

The first line calls the kernel, and passes parameters onto it. You’ll note that I setup 2 consoles, one on tty0 and another on ttyS0. I like to have both a serial and a display console on kernel bootup. Now we need to compile it, to do that, run the following:

mkimage -C none -A arm -T script -d boot.cmd boot.scr

Next step is to copy the kernel image and the script file. Assuming you are in the folder kernel_sunxi_3-*-* (Depending on your choice of kernel version)

home@user:~$ cp uImage /mnt/boot
home@user:~$ cp script.bin /mnt/boot

Now we have all the pre boot binaries, bootloaders, kernel image and the script.bin files all loaded on to the SD card. Now we come to the last part, uploading the file system. I prefer the newest version of the Debain filesystem as it more flexible and light in nature. Now you need to download the tar file of the filesystem and unpack it at the place where your second partition is mounted
(i.e /mnt/rootfs).

home@user:~$ cd /tmp
home@user:~$ axel http://dl.cubieforums.com/loz/rootfs/debian-unstable-armhf.tar.bz2
home@user:~$ cd /mnt/rootfs
home@user:~$ unp /tmp/debian-unstable-armhf.tar.bz2

This will unpack the Debain filesystem on the second partition. After this, you need to copy the compiled drivers, firmware etc to the appropriate place in the rootfs. This is an absolutely necessary step as any changes in the driver files wont take effects if they are not copied to the appropriate places in the file system. Here is an example snippet of this (Assuming again that the user is in the kernel_sunxi_3-*-*):

home@user:~$ mkdir -p /rootfs/lib/modules
home@user:~$ rm -rf /rootfs/lib/modules/
home@user:~$ cp -r lib /rootfs/

Now just unmount the the SD card:

home@user:~$ umount /mnt/boot
home@user:~$ umount /mnt/rootfs

In case it says, it is busy, open a new instance of the terminal and run. It will surely work. After this, just boot up your cubieboard with this SD card. Use GNU screen command to see the boot sequence (Use this link for reference of TTL-USB Connections and using GNU screen)

If the boot is successful, it will ask you for login and password. They are root and password respectively.

Update: Just FYI, the filesystem you install here gives you direct root access. If you are an advanced linux user, you can maybe add your own profiles for safety!

Follow

Get every new post delivered to your Inbox.