Automated Deployment of MSP430 Firmware (Part 2)

I recommend reading Part 1 to get a general understanding of what this project is trying to achieve and the first steps we took to get our system in place.

Now that we have all the tools needed to deploy firmware, we can start to build an Ansible playbook to automate deployment of new firmware to the MSP430s on the network.

Looking back at the incredibly detailed flowchart I presented in the first section:
Deployment Flowchart

We have compiled the tools to flash the MSP430F5529 firmware using the Raspberry Pi, now we will be setting up the Ansible playbook to automate the firmware deployment.

The hardware setup I'm using consists of two Raspberry Pis (one Raspberry Pi B and one Raspberry Pi 2), along with two MSP-EXP430F5529LP connected over USB to the Raspberry Pis. The setup:
Setup

If you want to skip ahead or run into issues along the way, check out the completed Ansible playbook on my GitHub page.

I highly recommend going through the Ansible docs to learn more about how Ansible works and best practices. The rest of the tutorial will just target our use case and explain the playbook I setup.

Installing Ansible

First off, we will need to install Ansible, the tool we will use to manage the Raspberry Pis on the network. The Ansible Docs are a great resource and should provide steps on how to install in your environment.

Hopefully this is pretty straight forward, I will be running on an Ubuntu machine but the rest of this post should be the same regardless of OS.

Setting Up Hosts File

First create a folder that will be holding our playbook. The first file we want to create is the hosts file that contains the machines we will use to deploy the firmware. So go ahead and create a file in your directory called hosts and add something like this to the file:

[pis]
192.168.0.47 ansible_ssh_user=pi  
192.168.0.48 ansible_ssh_user=pi  

You will need to swap out the IP addresses for the names of the machines you will be using. If you're only using one machine that's fine, Ansible will work the same way no matter how many machines we have in our system. Also note the ansible_ssh_user keyword next to each machine, this defines the user you use to ssh into the machine so change it if you're not using the default raspbian user. Ansible uses ssh to configure the machine.

After creating the file I recommend pinging the machines to ensure ssh is working and Ansible can communicate with the machines. Try running:

ansible -i hosts all -m ping  

Let's break down this command. First we tell ansible to use our hosts file instead of looking in the Ansible installation with -i hosts. Next we tell ansible to run the commands on all hosts found in the hosts file. Finally we define the module to run with -m ping.

Setting Up Roles

Now that Ansible can communicate with the Raspberry Pis on the network we will now define a playbook to deploy the firmware. Our playbook will consist of two roles that machines can be assigned to. The first role is "common" which defines some useful packages and settings we want on all our machines. The second roles is the "mspdebug" role whid is designed to be a reusable role that installs all dependencies to get mspdebug working on a Raspberry Pi, including installing the mspdebug binary we build earlier.

The "Common" Role

For this simple example, all machines we are configuring are also deploying firmware. In a more complex setup, if you wanted to keep one machine as a "build" machine for building the firmware or mspdebug then it would need a separate set of packages installed and environment setup. This is where the "common" role comes into place. This role can define configuration that happens across all machines in the setup, not just ones dedicated to firmware development.

So start off by creating a directory for the common role and the tasks we will be creating.

mkdir -p roles/common/tasks  

In this directory we will create a main.yml file that defines the tasks to complete. Here is my example:

---
# Generic things to get machines up to date and usable

- name: Install packages
  apt:
    pkg={{item}}
    state=installed
  sudo: yes
  with_items:
    - vim
    - zsh
    - git
    - tmux
    - htop

- name: Change default shell
  user:
    name=pi
    shell=/usr/bin/zsh
  sudo: yes

This configuration is pretty personal and is just some general packages I want installed if I need to work on the machine. The first task installs useful optional packages and the second task changes the shell to zsh. Feel free to configure these to your preference. The playbook uses the apt module and the user module to install packages and configure the user.

Ideally our firmware deployment system will be completely automated... but if issues start happening having a decent toolset already installed on all machines will help debugging, that's where the common role comes in handy.

The "MSPDebug" Role

The next role our Raspberry Pis will use is a mspdebug role. This role will use the mspdebug binary we built in the first tutorial to actually program our firmware to the MSP430 LaunchPads.

mkdir -p roles/mspdebug/tasks  

In this directory we will have three separate files. A playbook to install our mspdebug application and a playbook to download the firmware. This separation is necessary so that you can update the firmware without having to reinstall mspdebug. At the same time you can also update mspdebug without updating the firmware of the connected LaunchPad.

We also need to create a directory to keep all the files we'll be copying over to the server in.

mkdir -p roles/mspdebug/tasks  

Looking back at my example on GitHub, you can see I have checked in the binaries we built in the last post.

In the tasks directory for mspdebug we can create a install.yml file that installs mspdebug. Here is my example:

---
# Playbook to install msp debug

- name: Install libmsp430.so
  copy:
    src=libmsp430.so
    dest=/usr/local/lib
  sudo: yes

- name: Install mspdebug
  copy:
    src=mspdebug
    dest=/usr/local/bin
    mode=775
  sudo: yes

- name: Add /usr/local/lib to LD_SEARCH_PATH
  lineinfile:
    dest=/etc/ld.so.conf
    line=/usr/local/lib
    state=present
  sudo: yes
  register: ld

- name: Rebuild LD cache
  command: /sbin/ldconfig
  sudo: yes
  when: ld.changed

This playbook is broken into 4 steps.

  1. Copy the libmsp430.so library to /usr/local/lib
  2. Copy the mspdebug binary to /usr/local/bin and make it executable
  3. Add /usr/local/lib to the library search path
  4. Rebuild the library path if we needed to change the library search path

In this playbook I'm using the copy module which simply copies files to all remote servers as well as the lineinfile module for simple edits to a text file on remote systems and the command module to execute arbitrary commands. Once the installation playbook has run, all dependencies will be met and the Raspberry Pi will be ready to flash an MSP430.

Alongside the install.yml playbook I also created an update_firmware.yml playbook to actually run the commands to download to the MSP430. Here is my playbook implementation:

---
# Playbook to update firmware on connected devices

- name: Create a directory to store the firmware
  file:
    path=/var/ansible
    state=directory
    owner=pi
  sudo: yes

- name: Copy the firmware to the hosts
  copy:
    src={{ firmware_name }}.out
    dest=/var/ansible

- name: Download the firmware to the devices
  shell: mspdebug tilib --allow-fw-update --force-reset "prog /var/ansible/{{ firmware_name }}.out"
  sudo: yes

The new feature in this playbook is my use of ansible variables. Here I use the {{ firmware_name }} variable to substitute the filename of the firmware image. This way, when a new firmware image comes along I can just update the variable, and it will propagate through the playbook.

Finally we need a high level playbook to map the roles to our different hosts. In our example every host we connect to will be deploying firmware. My top level playbook site.yml consists of the following:

---
# This playbook deploys firmware to all hosts

- name: Configure and deploy firmware
  hosts: all
  remote_user: pi
  roles:
    - common
    - mspdebug

This playbook simply tells ansible that all hosts will have the "common" and "mspdebug" role.

If you're following along I recommend comparing your own setup to my GitHub repository.

Running the Code

Now that we have all of our ansible configuration written and the tools we need compiled for the Rapsberry Pi we can start the automatic deployment of our firmware.

To recap, the playbook will do the following:

  1. Install some common tools on all the Pis (vim, tmux, etc...)
  2. Install an ARM compiled mspdebug on all the Pis, along with associated libraries
  3. Copy the firmware to the Raspberry Pis
  4. Invoke mspdebug with the firmware and flash the MSP430

To run the playbook we can invoke it using ansible-playbook:

ansible-playbok -i hosts site.yml  

This tells ansible which hosts file to use and the playbook to run. When we are ready to change the firmware to a new version we can either

  1. Update the group_vars/all file to include the name of the new firmware image
  2. Pass the name of the new firmware image from the command line when invoking anible-playbook.

To pass the firmware image name as a variable on the command line you can invoke:

ansible-playbook -i hosts site.yml --extra-vars "firmware_name=Blink_v2"  

To see a quick demo of the setup in action I program two different firmware images, one that blinks a red LED and one blinking a green LED.

Next Steps

There are a ton of ways to improve this setup. Some next steps might be:

  • Flash multiple MSP430s connected to a single Raspberry Pi
  • Dedicate a Raspberry Pi on the network to building mspdebug and needed libraries. Once an update occurs, push that to all Pis in the system
  • Keep a database of which MSP430s are connected to which Pis, deploy different firmware to different connected devices
  • Integrate with a Continuous Integration tool like Jenkins, so that if all Jenkins tests pass, the firmware gets automatically deployed
  • Flash a device over BSL using the GPIO pins from the Raspberry Pi rather than the on board debugger on the LaunchPad
  • Use ansible tags to skip parts of the playbook that do not need to be run every time when deploying firmware

Want to Get Started?

I recommend reading Part 1 to get a general understanding of what this project is trying to achieve and the first steps we took to get our system in place. Now that we have all the tools needed to deploy firmware, we can start to build an Ansible playbook to…

Read More

Automated Deployment of MSP430 Firmware (Part 1)

I now have completed Part 2 of the article where I discuss the ansible playbook to deploy the firmware.

I have recently started looking into all the DevOps tools that have constant articles on Hacker News and reddit lately. I use linux around my apartment for all my machines (mostly debian based) and wanted a better way to control and configure them. As someone that works with python often, Ansible caught my eye. After reading about this cool demo, I wanted to try out Ansible on a Raspberry Pi cluster of my own but also add in some MSP430s getting programmed.

For those that don't know MSP430 is a ultra low-power microcontroller made by Texas Instruments. A great starting point for information is the TI LaunchPad website.

As a side project I sought out an automated way to deploy MSP430 firmware images to MSP430F5529 LaunchPads connected to Raspberry Pis. The master ansible server is responsible for compiling of the MSP430 firmware images and then using ansible pushes the image to the Raspberry Pis which then program the firmware.

Here's a simple organization chart showing how the firmware images flow.
Organization

Since the Raspberry Pi will be doing the programming of the MSP430F5529 it will need a tool for downloading firmware images. MSPDebug is a command line tool for downloading to MSP430s and the rest of the blog post will cover compiling it for use on the Raspberry Pi.

All the following compiling steps were run on a Raspberry Pi 2 running Raspbian.

Compiling HIDAPI

The first step will be compiling HIDAPI. From their GitHub page, HIDAPI is described as "A Simple library for communicating with USB and Bluetooth HID devices on Linux, Mac, and Windows." The library is used by libmsp430.so that we will be building later on.

There are a few dependencies I found I needed to build the library, so go ahead and install those first.

sudo apt-get update  
sudo apt-get install libusb-1.0-0-dev  
sudo apt-get install libudev-dev  

Now we can download the source code for version 0.7.0 from their GitHub Releases Page. We'll download and build in a "build" directory.

mkdir ~/build  
cd ~/build  
wget https://github.com/signal11/hidapi/archive/hidapi-0.7.0.zip  
unzip hidapi-0.7.0.zip  

After extracting we can now build the library.

cd hidapi-hidapi-0.7.0/linux  
make -j4 CXXFLAGS="-Wall -g -lpthread -lrt"  

If the make successfully completes you should have a hid-libusb.o file located in your current directory.

Compiling MSPDebugStack

Disclaimer: Texas Instruments does not officially support the MSPDebugStack on Raspbian or the Raspberry Pi. This is meant as a learning exercise rather than a production solution.

Next step will be compiling the MSPDebugStack from Texas Instruments. The source is avaiable from the TI website.

There are a few dependencies we are going to need to install for this as well. Go ahead and run the following:

sudo apt-get install libasio-dev  
sudo apt-get install libboost-all-dev  

Now we are ready to build

cd ~/build  
wget http://www.ti.com/lit/sw/slac460k/slac460k.zip  
unzip slac460k.zip  

Now we need to copy the hidapi library we built previously and the hidapi header file.

cd MSPDebugStack_OS_Package/ThirdParty  
mkdir include lib  
cp -p ~/build/hidapi-hidapi-0.7.0/linux/hid-libusb.o lib  
cp -p ~/build/hidapi-hidapi-0.7.0/hidapi/hidapi.h include  

Now that we have the copied dependencies we can build libmsp430 library from the root of the package.

cd ..  
make -j4 STATIC=1  

Go ahead and grab a beer because this will probably take awhile on your Raspberry Pi. Once it's done though you will have a libmsp430.so in your current directory, run the following to copy your library to your library path.

sudo make install  

Compiling MSPDebug

The final piece will be compiling MSPDebug itself. This is the tool that will actually program the MSP430F5529 in our automated deployment.

First let's install the dependencies:

sudo apt-get install libusb-dev  
sudo apt-get install libreadline-dev  

Now we can download the source and extract.

cd ~/build  
wget http://downloads.sourceforge.net/project/mspdebug/mspdebug-0.23.tar.gz  
tar -zxvf mspdebug-0.23.tar.gz  

Now we can compile the source:

cd mspdebug-0.23  
make -j4  

Once the process is complete you will have an executable file mspdebug, go ahead and install the file to your PATH by running

sudo make install  

Testing MSPDebug

Now that everything has been compiled to run on a Raspberry Pi we can finally connect to our device using mspdebug!

Go ahead and plug in your MSP430F5529 LaunchPad and then launch mspdebug with the following commands. The first puts the libmsp430.so that we compiled previously in your linker library path and the second launches mspdebug. The arguments for mspdebug tell it to use the TI library (the one that we built) and to allow a firmware update if the debugger firmware is out of date.

export LD_LIBRARY_PATH=/usr/local/lib:${LD_LIBRARY_PATH}  
mspdebug tilib --allow-fw-update  

If all works fine you should see something like this:
MSPDebug Launched

Indicating you are now connected to the MSP430!

Next Steps

Next we will be using Ansible to distribute MSP430F5529 firmware images to a group of Raspberry Pis which will then use the mspdebug tool to download to their connected LaunchPads.

If you had trouble following any of the steps or have suggestions/improvements for the guide please leave a comment below! If you're having trouble getting it to work and just want the binaries they are checked into my GitHub repository.

I now have completed Part 2 of the article where I discuss the ansible playbook to deploy the firmware. I have recently started looking into all the DevOps tools that have constant articles on Hacker News and reddit lately. I use linux around my apartment for all my machines (mostly…

Read More