Friday, June 26, 2015

Oz 0.14.0 Release

All, I'm pleased to announce release 0.14.0 of Oz. Oz is a program for doing automated installation of guest operating systems with limited input from the user. Release 0.14.0 is a bugfix and feature release for Oz. Some of the highlights between Oz 0.13.0 and 0.14.0 are: Fix a bug in checksum checking (this should work again) Add a global lock around pool refresh; should get rid of a user-visible failure Support for Debian 8 Support for Ubuntu 15.04 Support for Fedora 22 Support for installing aarch64 guests Support for installing POWER guests Support for install arm 32-bit guests A tarball and zipfile of this release is available on the Github releases page: https://github.com/clalancette/oz/releases . Packages for Rawhide, Fedora-21, Fedora-22, EPEL-7, and EPEL-6 have been built in Koji and will eventually make their way to stable. Instructions on how to get and use Oz are available at http://github.com/clalancette/oz/wiki . If you have questions or comments about Oz, please feel free to contact me at clalancette at gmail.com, or open up an issue on the github page: http://github.com/clalancette/oz/issues . Thanks to everyone who contributed to this release through bug reports, patches, and suggestions for improvement.

Saturday, March 7, 2015

Oz 0.13.0 release

I'm pleased to announce release 0.13.0 of Oz. Oz is a program for doing automated installation of guest operating systems with limited input from the user. Release 0.13.0 is a bugfix and feature release for Oz. Some of the highlights between Oz 0.12.0 and 0.13.0 are:
  • For Fedora, if the user specifies a version, but that isn't supported yet, try the last supported version (in this case), as that will often work.
  • Fix a regression where we forgot to force the qcow2 image type
  • Allow installs that use more than one installation device
  • Add support for RHEL 6.5
  • Rename OEL-6 to OL-6
  • Add support for Ubuntu 14.04
  • Add Windows 8.1 support
  • Add CentOS-7 support
  • Add the ability to specify kernel parameters in the TDL
  • Make sure to remove dhcp leases from guests after the install
  • Fix support for FreeBSD
  • Add in support for TDL "precommands"; these are commands that are run *before* package installation
  • Fix up file locking
  • Add support for RHEL 5.11
  • Remove Ubuntu ssh keys at the end of installation
  • Add support for Ubuntu 14.10
  • Add support for XInclude, for merging various TDLs together
  • Add Fedora 21 support
  • Add support for ppc64 and ppc64le
A tarball and zipfile of this release is available on the Github releases page: https://github.com/clalancette/oz/releases. Packages for Fedora-20, Fedora-21, Fedora-22, EPEL-6, and EPEL-7 have been built in Koji and will eventually make their way to stable. Instructions on how to get and use Oz are available at http://github.com/clalancette/oz/wiki. If you have questions or comments about Oz, please feel free to contact me at clalancette at gmail.com, or open up an issue on the github page: http://github.com/clalancette/oz/issues. Thanks to everyone who contributed to this release through bug reports, patches, and suggestions for improvement.

Wednesday, January 15, 2014

Developing STM32 microcontroller code on Linux (Part 7 of 8, building and running a simple STM32 program)

The first post of this series covered the steps to build and run code for the STM32. The second post covered how to build a cross-compiler for the STM32. The third post covered how to build a debugger for the STM32. The fourth post covered building and configuring OpenOCD for your development environment. The fifth post covered building the device library, libopencm3. The sixth post covered linker scripts and command-line options necessary for building and linking programs to run on the STM32. This post will cover building and running a program on the STM32.

In the previous posts we dealt with all of the set up necessary to build programs for the STM32. It is finally time to take advantage of all of those tools and build and run something. Recall that from previous posts, we already have an OpenOCD configuration file setup, a linker script setup, and a Makefile setup. All that really remains is for us to write the code, build it, and flash it to our device. The code below is very STM32F3DISCOVERY specific; that is, it very much requires that the GPIO for the LED be on GPIO bank E, pin 12 on the board. If you have one of the other STM32 DISCOVERY boards, you'll need to look at the schematics and find one of the GPIOs that are hooked to an LED.

We are going to take an extremely simple example from libopencm3. This example does nothing more than blink one of the LEDs on the board on and off continuously. While this is simple, it will validate that everything that we've done before is actually correct.

Here is the code:

$ cd ~/stm32-project
$ cat <<EOF > tut.c
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>

static void gpio_setup(void)
{
        /* Enable GPIOE clock. */
        rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_IOPEEN);

        /* Set GPIO12 (in GPIO port E) to 'output push-pull'. */
        gpio_mode_setup(GPIOE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE,
                        GPIO12);
}

int main(void)
{
        int i;

        gpio_setup();

        /* Blink the LED (PC8) on the board. */
        while (1) {
                /* Using API function gpio_toggle(): */
                gpio_toggle(GPIOE, GPIO12);     /* LED on/off */
                for (i = 0; i < 2000000; i++) /* Wait a bit. */
                        __asm__("nop");
        }

        return 0;
}
EOF
You should now be able to type "make", and the thing should build. Typing "make flash" should run OpenOCD, install the program to the board, and start blinking an LED. Remember that our Makefile required sudo access to actually run openocd. If you don't have sudo access, you can either add sudo access (by adding your user to the wheel group), or just su to root and run the openocd command by hand.

Monday, January 13, 2014

Developing STM32 microcontroller code on Linux (Part 6 of 8, building and linking STM32 programs)

The first post of this series covered the steps to build and run code for the STM32. The second post covered how to build a cross-compiler for the STM32. The third post covered how to build a debugger for the STM32. The fourth post covered building and configuring OpenOCD for your development environment. The fifth post covered building the device library, libopencm3. This post will cover linker scripts and command-line options necessary for building and linking programs to run on the STM32.

Once we have all of the previous steps done, we are achingly close to being able to build and run code on our target STM32 processor. However, there is one more set of low-level details that we have to understand before we can get there. Those details revolve around how our C code gets turned into machine code, and how that code is laid out in memory.

As you may know, compiling code to run on a target is roughly a two-step process:
  1. Turn C/C++ code into machine code the target processor understands. The output of this step are what are known as object files.
  2. Take the object files and link them together to form a coherent binary. The output of this step is generally an ELF file.
Let's talk about these two steps in more detail.

Compile step

During compilation, the compiler parses the C/C++ code and turns it into an object file. A little more concretely, what we want to have our cross-compiler do is to take our C code, turn it into ARM instructions that can run on the STM32, and then output that into object files.

To do this, we use our cross-compiler. As with any version of gcc, there are many flags that can be passed to our cross-compiler, and they can have many effects on the code that is output. What I'm going to present here is a set of flags that I've found works pretty well. This isn't necessarily optimal in any dimension, but will at least serve as a starting point for our code. I'll also point out that this is where we start to get into the differences between the various STM32F* processors. For instance, the STM32F4 processor has an FPU, while the STM32F3 does not. This will affect the flags that we will pass to the compiler.

For the STM32F3, Cortex-M3 processor that I am using, here are the compiler flags: -Wall -Wextra -Wimplicit-function-declaration -Wredundant-decls -Wstrict-prototypes -Wundef -Wshadow -g -fno-common -mcpu=cortex-m3 -mthumb -mfloat-abi=hard -MD
Let's go through each of them. The -W* flags tell the compiler to generate compile-time warnings for several classes of common errors. I find that enabling these warnings and getting rid of them usually makes the code much better. The -g flag tells the compiler to include debugging symbols in the binary; this makes the code easier to debug, at the expense of some code space. The -fno-common flag tells gcc to place uninitialized global variables into the data section of the binary, which improves performance a bit. The -mcpu=cortex-m3 flag tells the compiler that we have a Cortex-M3, and thus to generate code optimized for the Cortex-M3. The -mthumb flag tells gcc to generate ARM thumb code, which is smaller and more compact than full ARM code. The -mfloat-abi=hard flag tells gcc that we want to use a hard float ABI; this doesn't make a huge difference on a processor without an FPU, but is a good habit to get into. Finally, the -MD flag tells gcc to generate dependency files while compiling, which is useful for Makefiles.

Linking step

Once all of the individual files have been compiled, they are put together into the final binary by the linker. This is more complicated when targeting an embedded platform vs. a regular program. In particular, we have to tell the linker not only which files to link together, but also how to lay the resulting binary out on flash and in memory.

We'll first start by talking about the flags that we need to pass to the linker to make this work. Here are the set of flags we are going to start with: --static -lc -lnosys -T tut.ld -nostartfiles -Wl,--gc-sections -mcpu=cortex-m3 -mthumb -mfloat-abi=hard -lm -Wl,-Map=tut.map
Again, let's go through each of them. The --static flag tells the linker to link a static, not a dynamically linked, binary. This flag probably isn't strictly necessary in this case, but we add it anyway. The -lc flag tells the linker to link this binary against the C library, which is newlib in our case. That gives us access to various convenient functions, such as printf(), scanf(), etc. The -lnosys flag tells the linker to link this binary against the "nosys" library. Several of the convenience functions in the C library require underlying implementations of certain functions to operate, such as _write() for printf(). Since we don't have a POSIX operating system that can provide these for us, the nosys library provides empty stub functions for these. If we want, we can later on define our own versions of these stub functions that will get used instead. The -T tut.ld flag tells the linker to use tut.ld as the linker script; we'll talk more about linker scripts below. The -nostartfiles flag tells the linker not to use standard system startup files. Since we don't have an OS here, we can't rely on the standard OS utilities to start our program up. The -Wl,--gc-sections flag tells the linker to garbage collect unused sections. That is, any sections that are not referenced are removed from the resulting binary, which can shrink the binary. The -mcpu=cortex-m3, -mthumb, and -mfloat-abi=hard flags have the same meaning as for the compile flags. The -lm flag tells the linker to link this binary against the math library. It isn't strictly required for our little programs, but most programs want it sooner or later. Finally, the -Wl,-Map=tut.map tells the linker to generate a map file and stick it into tut.map. The map file is helpful for debugging, but is informational only.

Linker script

As mentioned before, the linker script tells the linker how to lay out the resulting binary in memory. This script is highly chip specific. The details have to do with where the processor jumps to on reset, and where it expects certain things to be. Note that most chips are actually configurable (based on some jumper settings), so where it jumps to on reset can change. Luckily, for most off-the-shelf STM32 designs, including the DISCOVERY boards, it is always configured to expect the code to start out in flash. Therefore, the linker script tells the linker to lay out the code in flash, but to put the data and bss in RAM.

With all that said, libopencm3 actually makes this easy on you. They have default linker scripts for each of the chips that are supported. All you really need to do is to fill in a small linker script with the RAM and FLASH size of your chip, include the default libopencm3 one, and away you go.

So we are going to put all of the above together and write a Makefile and a linker script into the project directory we created in the last tutorial. Neither of these are necessarily the best examples of what to do, but they will get the job done. First the Makefile:

$ cd ~/stm32-project
$ cat <<EOF > Makefile
CC=arm-none-eabi-gcc
LD=\$(CC)
OBJCOPY=arm-none-eabi-objcopy
OPENOCD=~/opt/cross/bin/openocd
CFLAGS=-Wall -Wextra -Wimplicit-function-declaration -Wredundant-decls -Wstrict-prototypes -Wundef -Wshadow -g -fno-common -mcpu=cortex-m3 -mthumb -mfloat-abi=hard -MD -DSTM32F3
LDFLAGS=--static -lc -lnosys -T tut.ld -nostartfiles -Wl,--gc-sections -mcpu=cortex-m3 -mthumb -mfloat-abi=hard -lm -Wl,-Map=tut.map
OBJS=tut.o

all: tut.bin

tut.bin: tut.elf
$( echo -e "\t" )\$(OBJCOPY) -Obinary tut.elf tut.bin

tut.elf: \$(OBJS)
$( echo -e "\t" )\$(CC) -o tut.elf \$(OBJS) ~/opt/cross/arm-none-eabi/lib/libopencm3_stm32f3.a --static -lc -lnosys -T tut.ld -nostartfiles -Wl,--gc-sections -mcpu=cortex-m3 -mthumb -mfloat-abi=hard -lm -Wl,-Map=tut.map

flash: tut.bin
$( echo -e "\t" )sudo \$(OPENOCD) -f stm32-openocd.cfg -c "init" -c "reset init" -c "flash write_image erase tut.bin 0x08000000" -c "reset run" -c "shutdown"

clean:
$( echo -e "\t")rm -f *.elf *.bin *.list *.map *.o *.d *~
EOF
You should notice a couple of things in the Makefile. First, we use all of the compiler and linker flags that we talked about earlier. Second, our objects ($OBJS) are tut.c, which we'll create in the next post. And third, we have a flash target that will build the project and flash it onto the target processor. This requires the OpenOCD configuration file that we created a couple of posts ago.

Now the linker script:

$ cat <<EOF > tut.ld
MEMORY
{
        rom (rx) : ORIGIN = 0x08000000, LENGTH = 256K
        ram (rwx) : ORIGIN = 0x20000000, LENGTH = 40K
}

/* Include the common ld script. */
INCLUDE libopencm3_stm32f3.ld
EOF
You'll notice that there isn't a lot here. We just have to define the RAM location and size, and the ROM (Flash) location and size, and the default libopencm3 linker script will take care of the rest.

We now have all of the parts in place. The next post will write, compile, and run a simple program on the board.

Friday, January 10, 2014

Developing STM32 microcontroller code on Linux (Part 5 of 8, building libopencm3)

The first post of this series covered the steps to build and run code for the STM32. The second post covered how to build a cross-compiler for the STM32. The third post covered how to build a debugger for the STM32. The fourth post covered building and configuring OpenOCD for your development environment. This post will cover building the device library, libopencm3.

As mentioned in the introductory post, it makes our life a lot easier if we use a device library. This is a library that abstracts the low-level details of the hardware registers away from us, and gives us a nice consistent API to use. While ST provides one these directly, it is not open-source (or more specifically, it's open-source status is murky). Luckily there is libopencm3, an open-source re-implementation that is also a better library in my opinion. As usual, I'm going to compile a certain version of libopencm3; newer or later versions may or may not work better for you.

As before, we start out by exporting some environment variables:

$ export TOPDIR=~/cross-src
$ export TARGET=arm-none-eabi
$ export PREFIX=~/opt/cross
$ export BUILDPROCS=$( getconf _NPROCESSORS_ONLN )
$ export PATH=$PREFIX/bin:$PATH
The TOPDIR environment variable is the directory in which the sources are stored. The TARGET environment variable is the architecture that we want our compiler to emit code for. For ARM chips without an operating system (like the STM32), we want arm-none-eabi. The PREFIX environment variable is the location we want our cross-compile tools to end up in; feel free to change this to something more suitable. The BUILDPROCS environment variable is the number of processors that we can use; we will use all of them while building to substantially speed up the build process. Finally, we need to add the location of the cross-compile binaries to our PATH so that later building stages can find it.

Now that we have our environment set up, we can get the code. Note that unlike most of the other tools covered in this tutorial, libopencm3 does not do releases. They expect (more specifically, require) that you clone the latest version and use that. That's what we are going to do here. As of this writing, the latest libopencm3 git hash tag is a909b5ca9e18f802e3caef19e63d38861662c128. Since the libopencm3 developers don't guarantee API stability, all of the steps below will assume the API as of that hash tag. If you decide to use a newer version of libopencm3, you may have to update the example code I give you to conform to the new API. With that out of the way, let's get it:

$ sudo yum install git
$ cd $TOPDIR
$ git clone git://github.com/libopencm3/libopencm3.git
$ cd libopencm3
$ git checkout -b clalancette-tutorial \
a909b5ca9e18f802e3caef19e63d38861662c128
What we've done here is to clone the repository, then checkout a new branch with the head at hash a909b5ca9e18f802e3caef19e63d38861662c128. This ensures that even if the library moves forward in the future, we will always use that hash tag for the purposes of this tutorial. Next we build the library:

$ unset PREFIX
$ make DETECT_TOOLCHAIN=1
$ make DETECT_TOOLCHAIN=1 install
$ export PREFIX=~/opt/cross
Here we need to unset PREFIX because libopencm3 uses PREFIX for the toolchain name prefix (arm-none-eabi), not the path prefix. Once we've done that, we can tell libopencm3 to detect the toolchain, and then use it to build libopencm3. Finally we use the install target to install the headers and the static libraries (.a files) to our toolchain. Assuming this is successful, everything necessary should be in ~/opt/cross/arm-none-eabi/, with the libraries in lib/libopencm3* and the header files in include/libopencm3. Note that there is one .a file per chip that is supported by libopencm3; we'll return to this later when we start building code for our chip.

Thursday, January 9, 2014

Developing STM32 microcontroller code on Linux (Part 4 of 8, building openocd)

The first post of this series covered the steps to build and run code for the STM32. The second post covered how to build a cross-compiler for the STM32. The third post covered how to build a debugger for the STM32. This post is going to cover building OpenOCD for your development environment.

As mentioned in the introductory post, we need OpenOCD so we can take binaries that we build and upload them onto the STM32. OpenOCD is a highly configurable tool and understands a number of different protocols. For our purposes, we really only need it to understand STLinkV2, which is what the STM32 uses. Also note that unlike previous posts, this post does not need or build a cross-compiled tool. That's because OpenOCD itself runs on our development machine, so we just need to do a normal compile. As before, I'm going to compile a certain version of OpenOCD (0.7.0). Newer or older versions may work, but your mileage may vary.

As before, we start out by exporting some environment variables:

$ export TOPDIR=~/cross-src
$ export TARGET=arm-none-eabi
$ export PREFIX=~/opt/cross
$ export BUILDPROCS=$( getconf _NPROCESSORS_ONLN )
$ export PATH=$PREFIX/bin:$PATH
The TOPDIR environment variable is the directory in which the sources are stored. The TARGET environment variable is the architecture that we want our compiler to emit code for. For ARM chips without an operating system (like the STM32), we want arm-none-eabi. The PREFIX environment variable is the location we want our cross-compile tools to end up in; feel free to change this to something more suitable. The BUILDPROCS environment variable is the number of processors that we can use; we will use all of them while building to substantially speed up the build process. Finally, we need to add the location of the cross-compile binaries to our PATH so that later building stages can find it.

Now we are ready to start. Let's fetch openocd:

$ cd $TOPDIR
$ wget http://downloads.sourceforge.net/project/openocd/\
openocd/0.7.0/openocd-0.7.0.tar.gz
To start the compile, we first need to install a dependency:

$ sudo yum install libusbx-devel
Now let's unpack and build openocd:

$ tar -xvf openocd-0.7.0.tar.gz
$ cd openocd-0.7.0
$ ./configure --enable-stlink --prefix=$PREFIX
$ make
$ make install
Here we are unpacking, configuring, building, and installing OpenOCD. The configure flags require a bit of explanation. The --enable-stlink flag means to enable support for STLink and STLinkV2, which is what we need for this board. The --prefix flag tells the build system to install OpenOCD to our ~/opt/cross location. This isn't strictly correct; this isn't a cross compile tool. However, it is convenient to have everything in one place, so we install it there.

Assuming everything went properly, we should now have a openocd binary in ~/opt/cross/bin. There will also be a bunch of configuration files installed to ~/opt/cross/share/openocd. These are important as these are pre-canned configuration files provided by OpenOCD. While it is possible to create your own from scratch, the syntax is baroque and it is a lot more work than you would think. Luckily OpenOCD already comes with scripts for STLinkV2 and STM32, so we'll just use those.

In order to have a working configuration, we are going to start creating our "project" directory. This is where the code that eventually runs on the STM32 is going to be placed. I'm going to call my directory ~/stm32-project; feel free to change it for your project. So we do:

$ mkdir ~/stm32-project
$ cd ~/stm32-project
$ cat <<EOF > stm32-openocd.cfg
source [find interface/stlink-v2.cfg]
source [find target/stm32f3x_stlink.cfg]
reset_config srst_only srst_nogate
EOF
Here we create the project directory, cd into it, and then create the configuration file for OpenOCD. The configuration file deserves a bit of explanation. First, we tell it to "find" the stlink-v2.cfg configuration file. Where it looks depends on the PREFIX we configured, so in our case it is going to look through ~/opt/cross/share/openocd for that file (where it should find it). Next we tell OpenOCD to "find" the stm32f3x_stlink.cfg file. Again, that file is located in ~/opt/cross/share/openocd, and it again should find it. Note that if you have a different STM32 chip, you should substitute f3x with whatever version of the chip you have. Finally there is a line about reset_config srst_only, and srst_nogate. I honestly don't know what those are for, though they seem to be necessary.

That's it for OpenOCD. Everything should be built, configured, and ready to go.

Wednesday, January 8, 2014

Release of ruby-libvirt 0.5.2

This is a release notification for ruby-libvirt 0.5.2. ruby-libvirt is a ruby wrapper around the libvirt API. The changelog between 0.5.1 and 0.5.2 is:
  • Fix to make sure we don't free more entries than retrieved (potential crash)
Version 0.5.2 is available from http://libvirt.org/ruby:

Tarball: http://libvirt.org/ruby/download/ruby-libvirt-0.5.2.tgz
Gem: http://libvirt.org/ruby/download/ruby-libvirt-0.5.2.gem

It is also available from rubygems.org; to get the latest version, run:

$ gem install ruby-libvirt

As usual, if you run into questions, problems, or bugs, please feel free to mail me (clalancette@gmail com) and the libvirt mailing list.

Thanks to Guido Günther for the patch to fix this problem.