Access gerrit in command line

If you want to automate some gerrit operations in command line, try the following commands

# To find the patchset you want to review
ssh review gerrit query status:open –patch-sets | less
# To approve the patchset
ssh review gerrit review –code-review=+2 <hash_of_the_patchset>
# To approve and submit
ssh review gerrit review –code-review=+2 –submit <hash_of_the_patchset>
# To add reviewers
ssh review gerrit set-reviewers -a user1 -a user2 <changeId>

Build googletest for Baremetal targets (stm32)

googletest(gtest) is a test framework famous for its powerful assertions and easy setup. After switching from boost-test to gtest several years ago, I have been using gtest a lot at work and in personal projects. It is super easy to set up a new test and add test suites/cases.

To make the code unit-testable, when working on embedded software, usually the code is separated into the-code-that-runs-anywhere and the-code-that-runs-only-on-this-hardware. The portable part (usually command parsing, state machines that are hardware unrelated) is put into their own module and is tested by unit test on desktop. It then is linked together with the hardware-specific setup/drivers for the target which usually runs FreeRTOS even baremetal.

Fortunately istarc has created a template project which has gtest integrated for baremetal targets on stm32 processors. You can choose the easy way of using this template or do the hard way by integrating gtest into your existing makefile.

The Easy Way – Use istarc’s stm32 template project

If you do not mind the dependency on mbed, just go to https://github.com/istarc/stm32 and follow the instructions to get all the dependencies.

Then

# Create a folder outside stm32

mkdir stm32-gtest & cd stm32-gtest

# Create project

${ISTARC_STM32_DIR}/mbed-project-wizard/gen-stm32f407-GCC-project.sh mbed-none-shgtest

# Configure gtest

make test-deps

# Make unit test

make test

Easy, isn’t it?

Unfortunately, however, this template project has dependencies to mbed SDK. So if you already have a project setup, you probably just want to integrate gtest into the existing project instead of making a new one. Then you need to read on –

The Slightly Harder Way – Integrate Gtest into your own project

Patch gtest by one line

Firstly you need to patch googletest by ONE LINE to support baremetal platforms.

gtest-diff

(The patch can also be found at https://github.com/clarkli86/googletest/commit/b0d72ca81f4acf80be27f133e5eace346a7128d7)

Configure and build gtest

Usually people use the fused-src of gtest because it does not require building gtest. But to support baremetal targets, gtest really needs to be configured properly

autoreconf -fvi
# Change cpu and mpu setings to suit your platform
./configure --disable-shared --without-pthreads --disable-libtool-lock --prefix=/home/clark/googletest --exec-prefix=/home/clark/googletest --host=arm-none-eabi LDFLAGS="-mcpu=cortex-m4 -mthumb -mfloat-abi=soft -mthumb-interwork  --specs=nosys.specs " CFLAGS="-mcpu=cortex-m4 -mthumb -mfloat-abi=soft -mthumb-interwork -Iinc -DGTEST_HAS_POSIX_RE=0 -DGTEST_HAS_PTHREAD=0 -DGTEST_HAS_DEATH_TEST=0 -DGTEST_HAS_STREAM_REDIRECTION=0 -DGTEST_OS_NONE -std=c99 -Os" CXXFLAGS="-mcpu=cortex-m4 -mthumb -mfloat-abi=soft -mthumb-interwork -Iinc -DGTEST_HAS_POSIX_RE=0 -DGTEST_HAS_PTHREAD=0 -DGTEST_HAS_DEATH_TEST=0 -DGTEST_HAS_STREAM_REDIRECTION=0 -DGTEST_OS_NONE -std=gnu++11 -Os -D_POSIX_PATH_MAX=255"
make & make install-libLTLIBRARIES

After this, libgtest.la should have been installed at the location specified by PREFIX. Now just link to it in your main project!

Possible Issues

  • gtest does require stdlib, so make sure you do not have -nostdlib in your linker flags.

 

References

  1. https://istarc.wordpress.com/2015/01/06/stm32f4-unit-testing/

NFS boot beaglebone-black

Recently I was trying to boot my new beaglebone black (http://beagleboard.org/black) from NFS for some application development. It is a pretty popular dev board, so not surprisingly there are already many tutorials and quick start guides online. Unfortunately most of them boot the board from sdcard only. So I have decided to write up the steps I have followed to boot from NFS.

Get yocto and prerequisites

$ git clone http://git.yoctoproject.org/git/poky
$ cd poky
$ git checkout -b fido origin/fido
# ~/build will be the build directory for beaglebone
$ source oe-init-build-env ~/build

Configure for Beaglebone-black

$ cd ~/build
$ vim conf/local.conf

In local.conf, you need to uncomment this line.

MACHINE ?= "beaglebone"

Also make sure debug-tweaks is added to IMAGE_FEATURES

EXTRA_IMAGE_FEATURES = "debug-tweaks"

Now save the file and run

$bitbake core-image-minimal

It will take several hours to download and compile everything. When it finishes, you would have got all the files need for NFS-boot

Set up tftp server

# Create the directory for tftp server
$mkdir -p ~/tftpboot/boot
# Make it readable by anyone
$sudo chmod 777 -R ~/tftpboot
$sudo apt-get install tftpd-hpa
$cp ~/build/tmp/deploy/image/beaglebone/beagle/zImage ~/tftpboot/boot
$cp ~/build/tmp/deploy/image/beaglebone/beagle/zImage-am335x-boneblack.dtb ~/tftpboot/boot/am335x-boneblack.dtb
$vim /etc/defaults/tftpd-hpa

Change the directory to

TFTP_DIRECTORY="/home/user/tftpbot"

Set up NFS server
Download and install unfsd from http://unfs3.sourceforge.net

$wget http://downloads.sourceforge.net/unfs3/unfs3-0.9.22.tar.gz
$tar xvf unfs3-0.9.22.tar.gz
$cd unfs3-0.9.22
$./configure
$make
$sudo make install
# This exports file can sit anywhere including /etc/exports
$vim ~/exports

Change the content of the exports file to

# This folder is created by bitbake core-image-minimal
# 192.168.1.0 can be changed to your own subnetwork ip like 10.0.0.0
~/build/tmp/work/beaglebone-poky-linux-gnueabi/core-image-minimal/1.0-r0/rootfs 192.168.1.0/24(rw,no_root_squash)

Now run both tftp and NFS servers

# This is the IP beaglebone-black is going to look for
$sudo ifcofig eth0 192.168.1.11
$sudo service tftpd-hpa restart
$sudo unfsd -e ~/exports -d

Set up u-boot on beaglebone-black board
Follow this to prepare the SD card (http://git.yoctoproject.org/cgit.cgi/poky/tree/README.hardware)
Then update the content of uEnv.txt on your SD card to
https://github.com/clarkli86/beagleboneblack_uEnv

optargs=
loadfdt=tftp ${fdtaddr} /boot/${fdtfile}
loaduimage=mw.l 4804c134 fe1fffff; set loadaddr 0x82000000; set ipaddr 192.168.1.100; set serverip 192.168.1.11; tftp ${loadaddr} boot/zImage
mmcboot=run mmcargs; bootz ${loadaddr} - ${fdtaddr}
uenvcmd=i2c mw 0x24 1 0x3e; run findfdt; if test $board_name = A335BNLT; then setenv mmcdev 1; mmc dev ${mmcdev}; if mmc rescan; then setenv mmc1 1; else setenv mmc1 0; fi; fi; setenv mmcdev 0; mmc dev ${mmcdev}; if mmc rescan; then setenv mmc0 1; else setenv mmc0 0; fi; run loaduimage && run loadfdt && run mmcboot

mmcroot="/dev/nfs rw ip=192.168.1.100 nfsroot=192.168.1.11:/home/clark/beagle/tmp/work/beaglebone-poky-linux-gnueabi/core-image-minimal/1.0-r0/rootfs,v3,tcp"; set mmcrootfstype nfs; boot

Now you can insert the SD card to beagle and boot it!

Troubleshooting

  • My beaglebone-black is not booting from SD card
  • Follow http://elinux.org/Beagleboard:MicroSD_As_Extra_Storage

  • U-boot fails to get kernel from tftp
  • Check if your host IP is set to 192.168.1.11. Also check if the ethernet connection is setup correctly.

  • I can see the login prompt but I can’t login as root
  • This is due to the permission of some files in the rootfs folder. On the host, do

    sudo chown user -R ~/build/tmp/work/beaglebone-poky-linux-gnueabi/core-image-minimal/1.0-r0/rootfs
    sudo chgrp user -R ~/build/tmp/work/beaglebone-poky-linux-gnueabi/core-image-minimal/1.0-r0/rootfs
    

    If this still does not work, do

    sudo rm ~/build/tmp/work/beaglebone-poky-linux-gnueabi/core-image-minimal/1.0-r0/rootfs/* -rf
    # Re-create the rootfs content
    $tar x -C ~/build/tmp/work/beaglebone-poky-linux-gnueabi/core-image-minimal/1.0-r0/rootfs/ -f ~/build/tmp/deploy/image/beaglebone/beagle/modules-beaglaebone.tgz
    $tar x -C ~/build/tmp/work/beaglebone-poky-linux-gnueabi/core-image-minimal/1.0-r0/rootfs/ -f ~/build/tmp/deploy/image/beaglebone/beagle/core-image-minimal-beaglebone.tar.bz2
    

    mutex + vTaskPrioritySet() = DANGER!!!

    In the recent FreeRTOS project, we have a task – say Task B – which initialises the Bluetooth Stack. The code is as

    // Task is created with priority 1
    while(true) {
        mutex_.Lock();
        const task_priority = uxTaskPriorityGet();
        // Raise priority to speed up initialisation
        vTaskPrioritySet(task_priority + 1);
        very_time_consuming_initialisation();
        // Get back to the original priority
        vTaskPrioritySet(task_priority);
        mutex_.Unlock();
    }
    

    So Task B runs at priority 2 when calling very_time_consuming_function() and gets back to 1?

    Not if priority inversion exists. [1]

    In the real production code, we have another task – Task A – which runs at priority 2 and tries to get the same mutex. So what happens when Task A wants the mutex while Task B holds it?

    Priority of Task B is raised to 2 due to Priority Inheritance in FreeRTOS[2]

    So the code snippet actually works like

    // Task is created with priority 1
    while(true) {
        mutex_.Lock();
        // Returns 2 instead of 1 due to Priority Inheritance
        const task_priority = uxTaskPriorityGet();
        // Raise priority to speed up initialisation
        // vTaskPrioritySet() detects if priority is inherited, if so only
        // base priority is set
        // Task priority is set 2 and base priority is set to 3
        // See the implementation in FreeRTOS source
        vTaskPrioritySet(task_priority + 1);
        very_time_consuming_initialisation();
        // Get back to the original priority
        // Task priority is set 2 and base priority is set to 2
        // See the implementation in FreeRTOS source
        vTaskPrioritySet(task_priority);
        mutex_.Unlock();
        // Priority Inheritance ends. But it does not set priority back to 1 because
        // base priority has been set to 2
        // See the implementation in FreeRTOS source
    }
    

    Conclusion: Always check if you have priority inversion when using mutex.


    References:

    1. http://en.wikipedia.org/wiki/Priority_inversion
    2. http://www.freertos.org/Real-time-embedded-RTOS-mutexes.html

    functools.partialmethod()

    When I was writing a module that generates Python classes, I wanted to add a partially bound method to the generated class. As the code

    def generate_class(class_name, a_value):
       def method(self, a, b, c):
         pass
       # Bound 'a' to the first parameter
       f = functools.partial(method, a_value) 
       return type(class_name, (Object,), {"f" : f})
    ...
    # C is the generated class using type()
    c = C()
    # You would expect c passes itself as self to method, wouldn't you?
    c.f('b', 'c')
    

    Unfortunately the partial object returned functools.partial() is not a descriptor[1]. Long story short, it does not pass the caller as self to the bound method. The code above will complain about missing arguments unless you do

    # N.B. a needs to be bound as a named argument
    def generate_class(class_name, a_value):
       def method(self, a, b, c):
         pass
       # Bound a as named argument
       f = functools.partial(method, a = a_value) 
       return type(class_name, (Object,), {"f" : f})
    ...
    # Ugly. Isn't it?
    c.f(c, 'b', 'c')
    

    There are different ways to make it look better depending on the Python version you use.

    Prior to Python 3.4

    # Use the mutable default parameter hack [2]
    def generate_class(class_name, a_value):
       def method(self, a = a_value, b, c):
         pass
       # Bound 'a' to the first parameter
       return type(class_name, (Object,), {"f" : method})
    ...
    # f passes c as self to method, because f is a function object
    c.f('b', 'c')
    

    After Python 3.4

    # Use the new functools.partialmethod() [3]
    def generate_class(class_name, a_value):
       def method(self, a, b, c):
         pass
    
       f = functools.partialmethod(method, a) 
       return type(class_name, (Object,), {"f" : f})
    ...
    # f is a descriptor and it passes c as self to method
    c.f('b', 'c')
    

    References:

    1. http://stackoverflow.com/questions/3803517/convert-partial-function-to-method-in-python
    2. http://docs.python-guide.org/en/latest/writing/gotchas/
    3. https://docs.python.org/3/library/functools.html

    Depoly qt application to Windows/Linux

    I have to admit that I have sweared many times that why Qt does not integrate this into QtCreator. Anyhow, but today I finally found what I have always wanted – windeployqt

    Get the source

    git clone https://github.com/qtproject/qttools

    Just build with QtCreator or qmake

    Alternatively, you can

    Get the prebuilt binary

    git clone https://github.com/clarkli86/windeployqt

    Test Bluetooth LE Pairing in BlueZ

    Bluetooth LE paring/bonding is available since Linux kernel 3.5 and BlueZ 5.0

    Pair with DBUS API

    doc/device-api.txt provides a pair method but it is not used in any example provided by BlueZ. So if you really want to use DBUS API, you need to modify test/test-device and call Pair() method after connecting.

    if (args[0] == "connect"):
    »·······if (len(args)  2):
    »·······»·······»·······device.ConnectProfile(args[2])
    »·······»·······else:
    »·······»·······»·······device.Connect()
    ·······»·······device.Pair() # Explicitly pair after connecting
    »·······sys.exit(0)
    

    Pair with C API

    BlueZ provides a very good example for pairing using C API. Just run gatttool

    >connect 
    >sec-level medium # Force pairing/bonding with the connected device
    

    Because Bluepy is based on the C API, it supports pairing as well. Just call btle.setSecurityLevel()

    References:
    The 5.0 BlueZ – http://lwn.net/Articles/531133/

    Enable Box2d debug draw in Cocos2d-x V3

    Refer to box2d test bed in cpp-tests which is part of the Cocos2d-x package.

    Step 1: Get GLES-Render from box2d test which is in cpp-tests/Classes/Box2DTestBed

    Do not forget to GLES-Render.cpp to your Android.mk

    Step 2: Override the draw() method of your layer

    Add the following to the header

        // Enable debug draw of Box2D
        void draw(cocos2d::Renderer *renderer, const cocos2d::Mat4 &transform, uint32_t flags) override;
    #if CC_ENABLE_BOX2D_INTEGRATION
    protected:
        cocos2d::Mat4 _modelViewMV;
        void onDraw(const cocos2d::Mat4 &transform, uint32_t flags);
        cocos2d::CustomCommand _customCommand;
    #endif
        GLESDebugDraw m_debugDraw;
    

    Add this to the cpp

    void GameScene::draw(Renderer *renderer, const Mat4 &transform, uint32_t flags)
    {
        //
        // IMPORTANT:
        // This is only for debug purposes
        // It is recommend to disable it
        //
        Layer::draw(renderer, transform, flags);
    
        _customCommand.init(_globalZOrder);
        _customCommand.func = CC_CALLBACK_0(GameScene::onDraw, this, transform, flags);
        renderer->addCommand(&_customCommand);
    }
    
    #if CC_ENABLE_BOX2D_INTEGRATION
    void GameScene::onDraw(const Mat4 &transform, uint32_t flags)
    {
    	Director* director = Director::getInstance();
    	CCASSERT(nullptr != director, "Director is null when seting matrix stack");
    	director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
    	director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, transform);
    
    	GL::enableVertexAttribs( cocos2d::GL::VERTEX_ATTRIB_FLAG_POSITION );
    	world_->DrawDebugData();
    	CHECK_GL_ERROR_DEBUG();
    
    	director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
    }
    #endif
    

    And, it’s Done!

    Screenshot_2015-01-05-21-57-49

    Using Box2d in Cocos2d-x V3 Android

    Cocos2d-x V3 has got its own built-in physics engine based on chipmunks. However, using Box2d is still possible. And, simpler!

    Plus you don’t have to set the position and rotation of sprites manually anymore. Cocos2d-x will take care of that once the PTM Ratio is set up properly.

    Step 1: Enable Box2d Integration

    Go to your Android.mk and uncomment this line

    $(call import-module,Box2D)

    Go to your Application.mk and change APP_FLAGS to

    APP_CPPFLAGS := -frtti -DCC_ENABLE_BOX2D_INTEGRATION=1 -std=c++11 -fsigned-char

    Step 2: Create a Box2D world and b2Body

    #include "Box2D/Box2D.h"
    ...
    // Create Box2d physics world
    world_ = new b2World({0, 0});
    

    Step 3: Create a PhysicsSprite and bind it to the body

    #include "extensions/cocos-ext.h" // header for PhysicsSprite
    USING_NS_CC_EXT;
    ...
    // PhysicsSprite inherits from Sprite and supports setPTMRatio
    sprite_ = PhysicsSprite::create("tire.png");
    sprite_->setOpacity(100);
    sprite_->setTag(CAR_TAG);
    
    b2BodyDef bodyDef;
    bodyDef.type = b2_dynamicBody;
    bodyDef.userData = sprite_;
    body_ = world->CreateBody(&bodyDef);
    
    b2PolygonShape polygonShape;
    polygonShape.SetAsBox( sprite_->getContentSize().width / PTM_RATIO / 2,  sprite_->getContentSize().height /PTM_RATIO / 2);
    //polygonShape.SetAsBox( 5,  12.5f);
    b2Fixture* fixture = body_->CreateFixture(&polygonShape, DENSITY);//shape, density
    
    sprite_->setB2Body(body_);
    sprite_->setPTMRatio(PTM_RATIO);
    layer->addChild(sprite_);
    

    For a complete example, go to https://github.com/clarkli86/top_down_car_physics

    Screenshot_2015-01-05-21-56-23