Categories
Uncategorized

Drone for Continuous Integration

Recently, we have been evaluating Continuous Integration (CI) systems for a variety of projects (both OSS and customer). There are many OSS options to chose from. Because we already use Docker containers for Yocto/OE builds, Concourse and Drone made the short list. Both communities seem responsive and helpful.

Categories
Uncategorized

Reflections on KiCad and EDA Tools

A recent interview with a KiCad developer prompted some reflection on KiCad and EDA (electronic design automation) tools in general. Below are samples of several PCB (printed circuit board) designs, created with KiCAD, and implemented as part of the SimpleIoT project in the last couple months.

The experience has been excellent. Above all, the tool is very fast, efficient to use, and stable. Schematic and PCB integration works well enough, and routing and copper pours are easy. Switching between inches and millimeters can be done on the fly. The KiCad library has many parts in it, and other organizations, such as DigiKey, Seeed, SnapEDA, and Ultra Librarian are also providing libraries. If a KiCad symbol/footprint for a part is not already available, it is relatively easy to create new symbols and footprints as needed. There is a good KiCad support forum. KiCad is a pleasure to use and production-ready for standard PCB designs.

Categories
Uncategorized

Auto-formatting/linting Go code

Some things in life you just have to experience to truly appreciate the value. One of these is auto-formatting/linting source code. When I started programming in Go in Vim, I naturally looked for editor support, and found the excellent vim-go project. Through this, I learned about gofmt and then goimports. These tools can be configured in your editor to automatically format your code when you save. goimports goes a step beyond and adds missing imports and removes unused ones.

Auto-formatting is quickly becoming the norm. The Javascript world also has an excellent formatter available named Prettier. There are formatters for many other languages as well including C/C++, shell, Elm, Rust, etc. The neoformat and ALE plugins add auto-formatting functionality to Vim/Neovim. An example of how to enable these plugins in Neovim is included in my dotfiles.

Categories
Uncategorized

SD Card Write Speed Tests

During Embedded Linux development, we often need to write large operating system images to SD cards for testing. Recently, I purchased a USB 3.0 SD card reader from Plugable. Before that, I used a USB 2.0 SD card reader from IOGear.

Categories
Uncategorized

Why Git?

Some time back, I gave a presentation that included an overview of the Git version control system.  I still occasionally get asked why Git should be used instead of Subversion, as it seems harder at first.  Most developers don’t really understand Git until they have used it for awhile, and then they will have an “aha moment.”  There are 3 features of Git that are especially interesting to me:

  1. many repositories (vs. one large repository)
  2. distributed development
  3. cheap branches
Categories
Uncategorized

Using Go in place of a Spreadsheet

Recently I needed to calculate NAND partition tables for a project where we will be supporting a number of different flash parts from 500MB to 2GB.  I first tried this in a spreadsheet, but found it difficult to work easily with hex numbers and do the calculations I needed.  I then looked into options for formatting text in columns from a program and found the nice text/tabwriter Go library.  With a few lines of code, I was then able to get the below output, which is quite easy to read.  The only tricky part was figuring out that for right justified data, you need to:

  1. not use tabs for the padding character
  2. add a trailing \t in the input data
Categories
Uncategorized

PCB Schematics Style Guide

As I work at the intersection of hardware and software, I spend a fair amount of time reading schematics for printed circuit boards (PCBs).  I’m astounded at how sloppy most schematics are, and have come up with a few suggestions to consider.

Categories
Uncategorized

A quick way to share files from any directory

Did you ever need a quick way to share files from a directory on your computer?  Or perhaps transfer a large file to another person?  With nodejs and express, you can easily set up a temporary web server that allows users to browse and access a list of files in a directory.  For convenience, I created a simple github project that can be cloned into any directory, and then a server started in a matter of seconds.  Yes, you could upload files to a server, or share them with a file sharing service, but if you can expose a random port on your computer to the person who needs the files, then this is faster, and does not require any intermediate steps.  Check out https://github.com/cbrake/http-file-server for more information.

Categories
Uncategorized

Perisistent device names for USB serial ports

Currently, my workstation has two 8-port USB<->RS232 devices, one dual port USB<->RS422/RS485 adapter, and several single port adapters such as the very useful BUBII.  So with around 20 USB->serial devices, figuring out which /dev/ttyUSBx entry corresponds to which port is not really practical.  However, with udev in Linux, you can easily give static names to each device.  This is especially convenient to do with FTDI devices because each FTDI device has a serial number.  In devices such as the 8-port RS232 adapter, there are 4, 2-port FTDI chips.  I could not find a serial number available in the adapter with a Prolific IC, so I would avoid those until that is sorted.

udevadm can be used to discover the serial number for a FTDI device:

udevadm info --attribute-walk -n /dev/ttyUSB0|grep serial 

After the serial number is known, rules can be created in the /etc/udev/rules.d/99-usb-serial.rules as shown in this example.  Now, serial ports can be accessed using convenient names such as /dev/ttyUSB_beagle.

Categories
Uncategorized

A Linux Kernel Tracing Tutorial

The Linux kernel has a fairly extensive tracing infrastructure that is quite useful for debugging.  There are a number of things you can do with tracing, but the focus of this article will be the traditional printk type debugging we often end up doing to trace initialization issues with a driver.  The following links provide additional information on the linux kernel tracing infrastructure:

In this example, I am working on a new audio driver.  The typical experience with a new driver is that you install it and nothing happens because something is not registered correctly with the Linux driver model.  So, the first thing I do is start with with the platform_device_add() function in my drivers init function.  To observe the kernel activity around the kernel platform code, I can do the following:

cd /sys/kernel/debug/tracing/
echo 0 > tracing_on (keep trace from filling up until we set filter)
echo function_graph > current_tracer
echo platform* > set_ftrace_filter
echo 1 > tracing_on
cat trace_pipe (leave running in a different shell)
<insmod my driver>

After executing the above, we see the following.  For this example, trace_pipe is preferred because the trace is then emptied and only new information is shown.

0) + 30.518 us   |  platform_device_alloc();
0)               |  platform_device_add() {
0)   0.000 us    |    platform_uevent();
0) + 30.518 us   |  platform_uevent();
0)   0.000 us    |  platform_uevent();
0) + 30.518 us   |    platform_match();
0) + 30.518 us   |    platform_match();
0)   0.000 us    |    platform_match();
0)   0.000 us    |    platform_match();

...

0) + 30.518 us   |    platform_match();
0)   0.000 us    |    platform_match();
0)   0.000 us    |    platform_match();
0)   0.000 us    |    platform_match();
0)   0.000 us    |    platform_match();
0) ! 3936.767 us |  }
0) + 30.518 us   |  platform_uevent();
0) + 30.518 us   |  platform_device_alloc();

From the above, I can conclude that the platform_match() is not succeeding, because I would expect some more activity.  At this point I chose to add a printk:

diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 7a24895..f9ce0c7 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -662,6 +662,8 @@ static int platform_match(struct device *dev, struct device_driver *drv)
        struct platform_device *pdev = to_platform_device(dev);
        struct platform_driver *pdrv = to_platform_driver(drv);

+       trace_printk("pdev->name = %s, drv->name = %s", pdev->name, drv->name);
+
        /* Attempt an OF style match first */
        if (of_driver_match_device(dev, drv))
                return 1;

Now, if I re-run the trace, I see the following:

 0)               |      /* pdev->name = soc_audio, drv->name = davinci_emac */
 0)   0.000 us    |    }
 0)               |    platform_match() {
 0)               |      /* pdev->name = soc_audio, drv->name = snd-soc-dummy */
 0)   0.000 us    |    }
 0)               |    platform_match() {
 0)               |      /* pdev->name = soc_audio, drv->name = soc-audio */
 0)   0.000 us    |    }
 0)               |    platform_match() {
 0)               |      /* pdev->name = soc_audio, drv->name = omap-pcm-audio */
 0)   0.000 us    |    }
 0) ! 4241.943 us |  } /* platform_device_add */

From the above, it looks like we have a simple mismatch between “soc_audio” and “soc-audio.”  Fixing this problem, and re-installing the module, we now have:

 0)               |    platform_match() {
 0)               |      /* pdev->name = soc-audio, drv->name = snd-soc-dummy */
 0)   0.000 us    |    }
 0)               |    platform_match() {
 0)               |      /* pdev->name = soc-audio, drv->name = soc-audio */
 0)   0.000 us    |    }
 0) + 91.553 us   |    platform_drv_probe();
 0) ! 4241.943 us |  } /* platform_device_add */

Now we can see that the names match, and the probe function is now being called.  At this point, we may want to turn on tracing of some additional functions to try to determine what is happening next.

echo "platform* snd* mydriver*" > set_ftrace_filter

And the result:

 0)               |      /* pdev->name = soc-audio, drv->name = snd-soc-dummy */
 0)   0.000 us    |    }
 0)               |    platform_match() {
 0)               |      /* pdev->name = soc-audio, drv->name = soc-audio */
 0) + 30.517 us   |    }
 0)               |    platform_drv_probe() {
 0)               |      snd_soc_register_card() {
 0) + 30.518 us   |        snd_soc_instantiate_cards();
 0) ! 17852.78 us |      }
 0) ! 17883.30 us |    }
 0) ! 22125.24 us |  } /* platform_device_add */

With the above additional information, we can continue to learn more about the flow through the kernel.

While all of the above could have been done with printk’s, it would have been more time consuming.  The kernel function tracing capabilities allow us to quickly get a high level view of the flow through the kernel without manually adding a bunch of printk statements.  The kernel tracing features are completely contained in the kernel without requiring additional user space utilities which makes it very convenient to use in embedded systems.  The low overhead is also important in resource constrained embedded systems.

Categories
Uncategorized

The easy way to get serial terminal in Linux

When doing embedded Linux development, most of us spend out time tethered to a target system with a serial cable, which is used for a serial console.  Minicom is the defacto serial terminal software for Linux.  However, Minicom is a little fussy in that you typically have to set it up for each port you want to use.  This is no big deal, but is generally difficult for new users to understand, and yet another hurdle.  And with 8-port USB->serial adapters, I have a lot of ports to set up.

Just recently, I discovered that screen can be used as a serial terminal program:

screen /dev/ttyUSB0 115200

A few notes on using:

  • to exit screen: Ctrl-a k
  • to write a hardcopy of the screen image: Ctrl-a h
  • to get help: Ctrl-?

All the neat features of screen are two numerous to list here, but one more that I’ll point out is the scrollback/copy feature (activated by Ctrl-a [ ).  This allows you to scroll back and the navigation works much like VI — what could be nicer?

Categories
Uncategorized

Qt Creator for C/C++ development

Recently, I’ve been evaluating Qt Creator for general C/C++ development.  I’m currently involved in the development of a rather large C++ application that is approaching 200,000 lines of code and 1000 source modules.  In the past, I’ve typically used Vim for editing, and Eclipse as a gdb front-end when needed.  Qt Creator is a rather new tool developed by Nokia’s Qt team.  What initially attracted my attention was that one of the reasons the project was started was no existing tools effectively handled the Qt codebase, which is quite large.  Things I like about Qt Creator:

  • it works fairly well with any C++ Make based project.  This includes projects built with autotools as well as the Qt Qmake build system.
  • easy to import existing projects
  • it is very fast.  Indexing 200,000 lines of code happens in around a minute or so.
  • Provides a Vim compatibility mode that actually works
  • provides fast methods for finding files, symbols, and seeing where symbols are used
  • did I mention yet it is fast?

I also recorded a screencast that demos Qt Creator with a large project (can be viewed in firefox).  As always, I’m interested in what others find interesting in this or other tools.  Future efforts will be to use Qt Creator to build and remotely debug ARM binaries — I am interested in what others have done in this regard.

If you do try Qt Creator, I recommend the latest pre-release snapshot.

Categories
Uncategorized

A quick serial logging application

Recently when debugging a device connected to a rs485 bus, I needed a simple application to dump the raw data coming over the rs485 bus.  Minicom does all kinds of weird terminal stuff, plus it will not display binary data, so that was out.  While looking for serial analyzer programs for Linux, and pondering writing my own simple C application, it occurred to me to use pyserial.  With a few lines of code, I got exactly what I needed:

import serial
import sys
import struct

if len(sys.argv) != 3:
    print "Usage: serial-dump.py <serial port> <baud rate>"
    sys.exit(-1)

print "Dumping data on %s" % (sys.argv[1])

ser = serial.Serial(sys.argv[1], sys.argv[2], timeout=0.3)

while(1):
    buf = ser.read(500)
    if len(buf) > 0:
        print "Read %i bytes:" % (len(buf)),

        for i in buf:
            value = struct.unpack('B', i)[0]
            print "%02x" % (value),

        print ""

The full source is available here.  This could obviously be improved to do true blocking reads, automatically parse protocols, implement a gui, etc.  Ideas for efficiently reading data using pyserial is available in a previous post.  Another example of using a scripting language for quick tasks is http://bec-systems.com/site/226/a-really-nice-hex-calculator.

Categories
Uncategorized

Apache and how to correctly use NameVirtualHost

As I often get involved in server administration (SVN, git, redmine, etc setup), I deal with Apache on a regular basis.  For simple configurations, the default Ubuntu/debian config works well.  However, for a more complex setup with virtual hosts, multiple IP addresses, and SSL support, it is common to run into the following message:

mixing * ports and non-* ports with a NameVirtualHost address is not supported, proceeding with undefined results

Googling does not return a clear explanation to this problem, so that is why I’m writing this article. The impulsive approach of randomly changing things does not get you too far — especially with the Debian/Ubuntu Apache configuration that is composed of seperate files for each virtual host.  After reading the documentation, things become clearer:

Note that the argument to the <VirtualHost> directive must exactly match the argument to the NameVirtualHost directive.

And, by considering the fact that the seperate virtual host config files really just get concatenated into one big file, it makes sense that you can’t have more than one NameVirtualHost entry.  Ubuntu by default puts the NameVirtualHost in the default virtual host file, which gets soft linked to sites-enabled/000-default.  I presume the ‘000’ means it gets loaded first.  I find it much more intuitive to put the NameVitualHost directives in the /etc/apache2/httpd.conf file.  This way it is clear that these entries are common to all virtual host entries.  So what I end up with is:

/etc/apache2/httpd.conf

NameVirtualHost 74.208.184.45:80
NameVirtualHost 74.208.184.46:80
NameVirtualHost 74.208.184.45:443

/etc/apache2/sites-available/bec-systems.com

<VirtualHost 74.208.184.45:80>
        ServerName bec-systems.com
...

/etc/apach2/sites-available/bec-systems.com.ssl

<VirtualHost 74.208.184.45:443>
        ServerName bec-systems.com
...

/etc/apach2/sites-available/svn.bec-systems.com

<VirtualHost 74.208.184.45:80>
        ServerName svn.bec-systems.com
...

/etc/apach2/sites-available/site2.com (with different IP address)

<VirtualHost 74.208.184.46:80>
        ServerName site2.com
...

Again, the points to remember are:

  1. The argument to VirtualHost must match a NameVirtualHost directive
  2. the NameVirtualHost directive is common, so there should only be one entry
Categories
Uncategorized

converting digital camera movies to ogg format

Now that firefox (v3.5) has built in support for ogg videos, ogg is now the most convenient format for “easy to view” video files (assuming you don’t want to use a service like youtube).  Some digital cameras (like my Canon) records movies in AVI format.  I created a script that uses gstreamer to convert the AVI file to an ogg file for easy viewing.

http://dev.bec-systems.com/svn/pub/avi_to_ogg/avi_to_ogg

And some of the results:

http://bec-systems.com/video/

(hint, download firefox 3.5 to view these videos)