Lerning Qt

When a software product is developed, not only the product is the outcome, but sometimes many tools, which support the development process. I work as an embedded software developer. In my work many times I faced situations, that I do the same operation or set of operations repeatedly. When there is opportunity, I try to automate. Of course, if there is time to automate, because sometimes it’s not so obvious what or how to automate. Many times I create small command line tools, which usage is known only to me. When working with other developers it’s better to share these tools, but not always command line is the best. When developing helper tools, it’s better to have a GUI. A developer just selects what he or she wants and does not have to think about what command and following option should be typed.

My weapon of choice is Qt library. Why Qt? Qt is portable, is very rich when it comes to various components, if the developed tool will be free, the library is also free. The library provides a layer of abstraction, it abstracts the underlying operating system’s functions and hardware. Building Qt application is very easy with Qt Creator, Qt’s IDE with very strong C++ awareness and a graphical UI designer, the GUI can be quick created and the logic, which will drive the GUI’s operations is written in C++.

I want to learn programming with Qt and C++, because I want to make standalone tools, which can be loaded on a USB memory. Qt applications can be deployed as normal, which use shared Qt libraries, installed separately in the OS or they can be deployed as standalone applications. Of course, the only thing is that a Qt application is compiled for a given target OS. If another target OS should be support, the application has to be rebuild for that OS.

Learning resources:

  • Book: C++ GUI Programming with Qt 4, Second Edition by Jasmin Blanchette; Mark Summerfield
  • Book: Advanced Qt Programming, Creating Great Software with C++ and Qt 4 by Mark Summerfield
  • C++ Qt Programming video tutorials by VoidRealms
  • And of course examples from Qt Creator

First book is very simple, goes from basic, through intermediate to advanced topics. Second book explains on the topics more deeply. Exploring Qt Creator’s examples is very easy, on the welcoming screen is a tab with examples – Demos and Examples.

I was previously trying to tackle the topic of learning Qt using the first book, but I couldn’t get it how some things should be made in Qt Creator. I prefer some live example, so the video tutorials by VoidRealms are just great. He does all the examples in Qt Creator, so it is easier to get familiar with this IDE.

Programming STM32F4 Discovery Board under Linux

Some months ago I bought a STM32F4 Discovery Board. It’s a good start to ARM programming. The good thing about this starter kit is that it can be programmed with open source tools. Also ST Electronics provides a neat peripheral library, which will save me a lot of time.

I followed a great description how to get running the compilation and programming environment from mikrocontroller.net. This description is written in German. I will describe steps, which I performed to get it running.

Toolchain installtion – Sourcery CodeBench

Free toolchain can be obtained from Mentor Graphics website. It’s called Sourcery CodeBench.

To download the package with the toolchain, goto Sourcery CodeBench website. In the ‘ARM Processors’ section click on the link ‘Download the EABI Release’, fill the form. An e-mail will be sent with a download link. After entering the link from the e-mail, choose a release. I chose ‘Sourcery CodeBench Lite 2012.09-63’ and the ‘IA32 GNU/Linux TAR’ package.

Now after downloading the package with toolchain software, we can install it in a place which would be accessible for all users.

sudo mkdir -v /opt/CodeSourcery
cd /opt/CodeSourcery
sudo tar xjvf arm-2012.09-63-arm-none-eabi-i686-pc-linux-gnu.tar.bz2

Programming tool installation

Checkout from texane’s github the stlink tool. This will be needed to flash the program to the chip’s memory.

git clone git://github.com/texane/stlink.git
cd stlink

Some additional packages were needed to compile this software:

sudo apt-get install autoconf libusb-1.0-0-dev

Now we can compile:

./autogen.sh
./configure
make

Create installation dir and copy executables:

sudo mkdir -v /opt/stlink
sudo cp -v st-flash /opt/stlink
sudo cp -v st-util /opt/stlink

Udev rules to recognize the Discovery board when connected to the USB port.

sudo cp -v 49-stlinkv*.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules

Now add path information to /etc/environment file. It needs to be edited with root privileges. Add to the end of file:

/opt/CodeSourcery/arm-2012.09/bin
/opt/stlink

PATH="$PATH:/opt/CodeSourcery/arm-2012.09/bin:/opt/stlink"

In order to update all environment paths, a logout and login is needed. My Eclipse did not recognize new PATH variable and there were no include paths added when a new project was created.

Now, let’s test our programmer. Only a read is sufficient to check if everything works. Connect the board to PC (via the miniUSB, not the micro) and try to download the demo binary from the board:

st-flash read ~/STM32F4-Discovery.bin 0x8000000 0x100000

If this works, then everything is setup for programming from the command line. To make it easier to develop programs, there is a possibility to integrate these tools with Eclipse IDE.

Eclipse IDE configuration

The only thing right now to do is to install ARM development plugin. Once it is installed, there will be new entries in the ‘New project’ wizard. Of course, CDT (C/C++) plugin should be also installed.

Link to Eclipse installation site: http://gnuarmeclipse.sourceforge.net/updates

Let’s test out new development environment

1. Open Eclipse IDE
2. File > New > C Project
3. ARM Cross Target Application > Empty Project
4. Toolchains = ARM Linux GCC (Sourcery G++ Lite)
5. Type in “Project name”
6. Finish

If the PATH variable is properly recognized by Eclipse, after creating a new project, there will be automatically added include paths:

/opt/CodeSourcery/arm-2012.09/arm-none-eabi/include
/opt/CodeSourcery/arm-2012.09/lib/gcc/arm-none-eabi/4.7.2/include
/opt/CodeSourcery/arm-2012.09/lib/gcc/arm-none-eabi/4.7.2/include-fixed

Now we have to download a libraries package from ST Electronics: STM32F4 Standard Peripheral Library. Download it and extract it. Now we will add include paths to this library.

1. Project -> Properties
2. C/C++ General > Paths and Symbols
3. Configuration = [All configurations]
4. Includes tab, Languages = GNU C
5. Add -> File system…

<path_to_extracted_lib_files>/STM32F4xx_DSP_StdPeriph_Lib_V1.0.1/Libraries/CMSIS/Include
<path_to_extracted_lib_files>/STM32F4xx_DSP_StdPeriph_Lib_V1.0.1/Libraries/CMSIS/Device/ST/STM32F4xx/Include
<path_to_extracted_lib_files>/STM32F4xx_DSP_StdPeriph_Lib_V1.0.1/Libraries/STM32F4xx_StdPeriph_Driver/inc
${ProjDirPath}

The last one type in manually.

Now we will add a link source path.
1. Source location tab.
2. Link folder…
3. Name: StdPeriph
4. Check: Link to folder in the filesystem
5. Browse…

<path_to_extracted_lib_files>/STM32F4xx_DSP_StdPeriph_Lib_V1.0.1/Libraries/STM32F4xx_StdPeriph_Driver/src

Next we have to add some symbols.
1. Symbols tab.
2. Add… -> USE_STDPERIPH_DRIVER
3. Add… -> USE_STM32_DISCOVERY
4. Add… -> HSE_VALUE = 8000000

Also the linker script has to be setup.
1. C/C++ Build > Settings
2. Configuration = [All configurations]
3. ARM Sourcery Linux GCC Linker > General
4. Script File (-T) = ${ProjDirPath}/stm32_flash.ld
5. ARM Sourcery Linux GNU Create Flash Image -> Output
6. Output file format (-O) -> binary

In order to have all the symbols indexed, we have to setup some last things.
1. C/C++ General > Indexer
2. Check the following:
– Enable project specific settings
– Store settings with project
– Enable indexer
– Index source files not included in the build
– Index unused headers
– Index source and header files opened in editor
– Allow heuristic resolution of includes

Now we can close the project properties and proceed. To start develop, we have to copy from the standard peripheral library directory four files.

<path_to_extracted_lib_files>/home/user/eclipse/STM32/STM32F4xx StdPeriphLib V1.0.0/Project/STM32F4xx_StdPeriph_Templates/TrueSTUDIO/STM324xG_EVAL/stm32_flash.ld
<path_to_extracted_lib_files>/home/user/eclipse/STM32/STM32F4xx StdPeriphLib V1.0.0/Libraries/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c
<path_to_extracted_lib_files>/home/user/eclipse/STM32/STM32F4xx StdPeriphLib V1.0.0/Libraries/CMSIS/Device/ST/STM32F4xx/Source/Templates/TrueSTUDIO/startup_stm32f4xx.s
<path_to_extracted_lib_files>/STM32F4xx_DSP_StdPeriph_Lib_V1.0.1/Project/STM32F4xx_StdPeriph_Templates/stm32f4xx_conf.h

Change the extension of ‘startup_stm32f4xx.s’ to capital ‘S’ and comment out:

/* Call static constructors */
//    bl __libc_init_array

In the stm32f4xx_conf.h comment out all the includes except for:

#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"

main.c source file content:

#include "stm32f4xx_conf.h"
#include "stm32f4xx.h"
 
GPIO_InitTypeDef  GPIO_InitStructure;
 
void Delay(__IO uint32_t nCount) {
  while(nCount--) {
  }
}
 
int main(void) {
  /* GPIOD Periph clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
 
  /* Configure PD12, 13, 14 and PD15 in output pushpull mode */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
 
  while (1) {
    /* Set PD12 Green */
    GPIOD->BSRRL = GPIO_Pin_12;
    /* Reset PD13 Orange, PD14 Red, PD15 Blue */
    GPIOD->BSRRH = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    Delay(10000000L);
 
    /* Set PD13 Orange */
    GPIOD->BSRRL = GPIO_Pin_13;
    /* Reset PD12 Green, PD14 Red, PD15 Blue */
    GPIOD->BSRRH = GPIO_Pin_12 | GPIO_Pin_14 | GPIO_Pin_15;
    Delay(10000000L);
 
    /* Set PD14 Red */
    GPIOD->BSRRL = GPIO_Pin_14;
    /* Reset PD12 Green, PD13 Orange, PD15 Blue */
    GPIOD->BSRRH = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15;
    Delay(10000000L);
 
    /* Set PD15 Blue */
    GPIOD->BSRRL = GPIO_Pin_15;
    /* Reset PD12 Green, PD13 Orange, PD14 Red */
    GPIOD->BSRRH = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;
    Delay(10000000L);
  }
}

The above code will turn on and off four LEDs on the board. They are placed in the middle of the board. One diode will be turned at a time.

So if everything was setup properly, we can build the project and flash it into the board’s chips memory:

st-flash write Debug/STM32F4Test.hex 0x8000000

2012-11-25T21:24:20 INFO src/stlink-usb.c: -- exit_dfu_mode
2012-11-25T21:24:20 INFO src/stlink-common.c: Loading device parameters....
2012-11-25T21:24:20 INFO src/stlink-common.c: Device connected is: F4 device, id 0x20006411
2012-11-25T21:24:20 INFO src/stlink-common.c: SRAM size: 0x30000 bytes (192 KiB), Flash: 0x100000 bytes (1024 KiB) in pages of 16384 bytes
2012-11-25T21:24:20 INFO src/stlink-common.c: Attempting to write 56836 (0xde04) bytes to stm32 address: 134217728 (0x8000000)
EraseFlash - Sector:0x0 Size:0x4000
Flash page at addr: 0x08000000 erasedEraseFlash - Sector:0x1 Size:0x4000
Flash page at addr: 0x08004000 erasedEraseFlash - Sector:0x2 Size:0x4000
Flash page at addr: 0x08008000 erasedEraseFlash - Sector:0x3 Size:0x4000
Flash page at addr: 0x0800c000 erased
2012-11-25T21:24:22 INFO src/stlink-common.c: Finished erasing 4 pages of 16384 (0x4000) bytes
2012-11-25T21:24:22 INFO src/stlink-common.c: Starting Flash write for F2/F4
2012-11-25T21:24:22 INFO src/stlink-common.c: Successfully loaded flash loader in sram
size: 32768
size: 24068
2012-11-25T21:24:23 INFO src/stlink-common.c: Starting verification of write complete
2012-11-25T21:24:24 INFO src/stlink-common.c: Flash written and verified! jolly good!

USB to Serial Converter

I recently bought two USB to Serial converters. This little devices are based on the CP2102 chip from Silicon Labs.

I am now using Linux as my development environment, so I did not have to install any drivers. I just plugged the device in and it worked. There was only one thing with device permissions. In order to use is I had to be root. To avoid this situation I created a file with udev rule to set proper permissions next time the device will be plugged in, so then I could use it as a normal user:

File: /etc/udev/rules.d/50-usb-serial.rules

SUBSYSTEMS=="usb",ATTRS{idVendor}=="10c4",ATTRS{idProduct}=="ea60",MODE:="0666"

Now, using the screen program I can open this serial port as a normal user.

The serial port is under /dev/ttyUSB0, we can see it from /var/log/syslog, when plugging in the device:

kernel: [35849.009413] usb 2-1.3.4: cp210x converter now attached to ttyUSB0

To test the converter just loop the RX to TX and open the serial port with the command:

screen /dev/ttyUSB0 115200

The two arguments to the screen command are: serial port device and baud rate (speed of transmission). When the loop is closed (TX is connected to RX), then every character sent will be immediately received, so when a key on the keyboard is pressed a corresponding character symbol should appear on the console. When the loop isn’t closed, only the transmit diode on the device blinks, but no characters appear on the console.

The USB to Serial converter is a simple device but very useful in embedded programming. Until now I could only blink with LEDs when I was programming my miniSUMO robot. Now I can sent at least one character, so I can trace what is the state of the robot. Also I have two radio receiver/transmitter, one for PC and one for the robot, but I couldn’t configure then properly, I always received garbage. With help of a SUB2Serial converter I can now attach both communications devices to the PC and try to figure it out how they should be configured. Without this I had to flash a new binary file to the miniSUMO robot whenever I wanted to test new configuration.

Simple project directory structure

For small programs with only few source files there is no need to setup a directory structure. In case of medium and large project a proper directory structure is necessary to control project files, it also provides the means for dividing the project into smaller modules, which can be compiled separately and independent from other modules. Also running unit tests again after something goes wrong takes less time.

I am not creating big projects, but lets start small. Below is a simple directory structure:

Project
│
├───doc
├───inc
├───lib
├───src
├───CMakeLists.txt
└───README

I added two files (README and CMakeLists.txt). The README file contains a brief description what is the project and what it does, contains installation instruction and information about the author. The CMakeLists.txt is the cmake build automation tool configuration script, which contains all the rules to build, package and install the software.

The inc folder holds all the header files (C/C++ header files), the src contains the source code. I also added the lib folder, because sometimes there is a need to include a library, which isn’t in the system.

STM32F4-Discovery

Yesterday I finally received my STM32F4 ARM Discovery Board.

Right now I am a little bit busy, so I can’t play with it. I only peered to the datasheet and checked if it works. To my surprise it has a lot more features, than I thought. Among others there are interfaces for CAN Network, Camera interface, LCD interface and Secure Digital I/O, for memory cards.

There is a demo software installed on the board, which uses the three axis accelerometer and blinks LEDs after power is connected. When the board is connected with a second USB cable to the PC it acts as a standard mouse.

This is awesome. The cost of this board isn’t high, I paid for it less than 100,- PLN. There are open source tools, a lot of documentation and the community surrounding it is very large.

Waiting for ARM Discovery Board STM32F4

I decided to learn embedded programming for the ARM and my weapon of choice is ARM Discovery Board STM32F4. Ordered one from an internet auction and awaiting.

This board is very simple, yet very powerful. Open source tool-chain support is an advantage. Many people write programs for this board and on the Internet there is a lot of information.

I have also a Renesas Promotional Kit, which I got at Embedded World 2012 exhibition. It is also a small development board, but the tools are most proprietary and limit in use by time or compilation size. Also finding information when something went wrong is difficult, because the number of people using this board is small and I was the first to encounter a particular problem.