Hello again, Indy Module fans! Today, we're going to show how to write firmware for a TI MSP430 host microcontroller to use that device as an Impinj Radio Interface (IRI) host for the Indy Modules. The MSP430 will control the Indy Module, performing tag inventories, and printing out read results and other information over a USB-UART COM port to the host PC.
This post is the second of a series of three that will show systems using the Indy UHF RFID Modules along with an MSP430 host microcontroller. All three use the MSP430 USB LaunchPad evaluation kit, which showcases the MSP430F5529 microcontroller. This kit was chosen because it is low cost(only $12.99!), includes a programmer and debugger, is easy to use, and comes with a variety of useful USB firmware examples. Each post of the three will focus on a single MSP430 firmware configuration that interacts with the Indy Modules in a unique way. We will post one each week here on the Impinj Support Portal.
Update - Check out the rest of the postings in the series here:
Bonus Post 1: Indy Module With MSP430 IRI-LT Host - Non-Blocking
Bonus Post 2: Indy Module With MSP430 IRI Host and USB-UART Printf
This week's example will showcase using a host microcontroller (the MSP430) to control the Indy Module, by generating IRI-LT traffic over its UART. Unlike our previous example, this one will control the Indy Module even in the absence of a PC host application. It will produce a stream of ASCII describing startup and inventory activity, accessible via both a USB-UART COM port, and a 3.3V UART interface.
The physical arrangement of the example is shown in the block diagram in Figure 1.
Figure 1: Example Simple Block Diagram
This example is the first in our series to show the Impinj Radio Interface (IRI) in detail, so we'll spend some time learning about it here. IRI is the communication scheme that is used to communicate with Indy Modules from a host, such as a PC, microcontroller, or microprocessor. Impinj provides the ITK Release Package, which includes two IRI toolkits: ITK-C and ITK-LT-C. These two toolkits include C libraries and examples that can be ported to the platform of choice for any application. The two differ in their size and complexity, with the LT version providing reduced memory usage and more basic functionality. We're going to use the LT version so that we aren't constrained by microcontroller flash size.
The IRI libraries interface with host firmware in the manner shown in Figure 2. Customers are responsible for writing their own main firmware and platform specific code, which then interface with the IRI libraries. The main portion shown below exercises the IRI library behavior, and the platform specific API are called by the IRI libraries to interact with the Indy Module via the host device's peripherals.
In the case of this example, we've provided a fully functional host firmware, including both the IRI C Toolkit portions and the host specific main.c and platform_msp430f5529.c. Of course, they may require modification for use in specific applications.
For more detail on the host firmware in this example, see the MSP430 Firmware Details section below.
Figure 2: IRI Firmware Stack Diagram
Example Hardware Setup
In order to exercise our example, we will have to connect the various parts such that they can communicate with each other. Block diagrams of the connections are shown in Figure 3. A picture of RS500 example hardware is shown in Figure 4. The connections are listed below.
Note: These are the same connections as those used in the previous MSP430 example: Indy Module With MSP430 USB-UART Bridge.
- The MSP430 launchpad should be connected to the PC via USB.
- The Indy Module development board should be powered
- The RS500 development board is powered by a USB connection
- The RS2000 development board is powered by a 12V DC adapter
- The Mini-Guardrail antenna (or other UHF RFID antenna) should be connected to the Module
- SMA connector J2 on the RS500 dev kit
- SMA connector J201 on the RS2000 dev kit
- The MSP430's UART pins must be connected to the Indy Module.
- The MSP430 UART pins are connected to J1, on pins P3.3 (MSP430 TX) and P3.4 (MSP430 RX), which are labeled in silkscreen on the kit.
- The RS500 development board allows connection to the UART using J14 and J16.
- MSP430 J1 P3.3 should connect to the center pin of J16 (Module RX)
- MSP430 J1 P3.4 should connect to the center pin of J14 (Module TX)
- The RS2000 development board allows connection to the UART using JP209 and JP210.
- MSP430 J1 P3.3 should connect to the center pin of JP210 (Module RX)
- MSP430 J1 P3.4 should connect to the center pin of JP209 (Module TX)
- These connections can be easily made using 100 mil pitch jumper wires, or mini-grabber wires.
- The jumpers for the Indy Module development board headers should be set aside for this example.
Figure 3: Example Block Diagrams
Figure 4: Example RS500 Hardware
Example Firmware and Software Setup
This example requires the Indy Module have firmware that is capable of communicating via IRI-LT, which may require a firmware update. Update your firmware to the latest version using the Indy Demo Tool, by following the directions on the page here.
To configure the MSP430 on the USB Launchpad board, simply debug the attached project (MSP430 Indy SiP IRI-LT Host with USB-UART Printf.zip below) or program the device with the firmware image attached to the page(MSP430 Indy SiP IRI-LT Host with USB-UART Printf.txt below). This image can be programmed using the standalone MSP430Flasher utility. This utility is included with the MSP-EXP430F5529LP software package in the "Binary" directory. It can be used to program the attached firmware image using the following command-line input:
MSP430Flasher.exe -n MSP430F5529 -w "MSP430 Indy SiP IRI-LT Host with USB-UART Printf.txt" -v -z [VCC] -m SBW2 (-i USB) (-e ERASE_ALL)
When connecting the MSP430 device to the PC, you will need a driver file for the USB-UART to work properly. This driver is included in the MSP-EXP430F5529LP software package, and is also attached to this page ("SimpleUsbBackChannel.inf" below). The device will appear as "F5529LP simpleUsbBackchannel".
Once the MSP430 is configured as a USB-UART bridge, and is connected to the Indy Module development board and host PC, the host PC can communicate with the Indy Module via the USB-UART COM port. The MSP430 will immediately configure the Indy Module and start performing EPC reads, as indicated by the "Status" and "Health" LEDs on the Indy Module development board.
The MSP430 will also print the results of the EPC reads to its USB-UART COM port, which can be observed using any terminal application. Configure your terminal application to use the correct COM port, with the correct terminal settings: 115,200 Baud, 8 data bits, no parity bit, 1 stop bit, no handshaking/flow control. To determine which COM port the MSP430 is attached to, you can look for the entry "F5529LP simpleUsbBackchannel" in the Windows Device Manager, as shown in Figure 5.
Once the PC is connected to the MSP430 USB-UART COM port, EPC reads should appear in your terminal program as shown in Figure 6 below.
Figure 5: MSP430 COM Port in Windows Device Manager
Figure 6: Terminal COM Port Traffic
MSP430 Firmware Details
In this section we'll go into detail about the firmware loaded on the MSP430.
This firmware was created by combining the previous example in the series, Indy Module With MSP430 USB-UART Bridge, with the introductory Indy Module IRI-LT example from the ITK Release Package. Adding the functionality of the introductory IRI-LT project changes the MSP430 from a USB-UART pass-though to an IRI-LT host that is merely reporting on read results to an attached PC, if present.
MSP430 IRI-LT Implementation
The Impinj provided IRI libraries are meant to be exercised by host firmware as shown in Figure 7. This diagram shows the way the different source files in the example call functions from one another. In the Impinj examples, and in this firmware, main.c calls functions from ipj_utils.c, which exercises the functions from the IRI libraries in iri.c, which interfaces with the hardware using the functions from platform_*.c. Although Impinj provides examples of both ipj_utils and platform_*, customers are responsible for generating these for their application.
To put it another way, the ipj_utils code provides an interface for the main firmware to exercise configuration of the Indy Module through IRI, and the platform_* code allows the IRI libraries to generate IRI UART traffic and also exercise other basic functionality of the device, like implementing a timer for timing events.
Figure 7: IRI Source Dependencies
In ipj_utils.c, there are three key functions that we will use in the example: ipj_util_setup(), ipj_util_perform_inventory(), and ipj_report_handler(). The _setup() function initializes the IRI communication link with the Indy Module, and thus is called during the MSP430 initialization portion of firmware. The _perform_inventory() function configures the Indy Module to perform an inventory of a set period, and is called repeatedly in the main while(1) loop. Finally, the _report_handler() function defines the behavior that is performed each time a report is received. In this example, the only modification to the ipj_utils.c functions is the addition of a function call during the _perform_inventory() loop to transmit the USB-UART buffer contents while waiting for the inventory to end. This keeps the buffer from overflowing during long inventories.
In the platform_msp430f5529.c file, there are a number of functions that must implement MSP430-specific behavior, most notably for UART RX and TX, and also for providing timing for events. Code is required both for initialization of hardware and firmware resources, and also event handling. The platform_init() function initializes all of the platform specific resources, and is called by main() during startup. The _init() function calls functions to initialize the clocks, debug and host UART interfaces, and the timer used for event timing. The two functions platform_transmit_handler() and platform_receive_handler() are used by the IRI library code to transmit and receive messages to and from the Indy Module via the UART physical layer. In this example, we use a blocking control loop in the _transmit_handler() to stuff data into the UART TX register, and in the _receive_handler(), we simply pull data out of a software circular buffer that is populated in the UART RX interrupt. The UART RX interrupt function USCI_A0_rx() simply adds the most recently received byte into a circular buffer and updates the head buffer pointer.
The platform library also contains string printing functions fputc() and fputs(), which are used by the ipj_utils library report handlers to print event information. In this example, we print information both to a secondary UART, and also the PC USB-UART interface via a circular buffer. This circular buffer's contents are transmitted to the PC host in main().
Having explained some detail of the functions from each of the three source files, Figure 8 elaborates further, showing a call tree for the example, which visually displays the ways that the functions call one another.
Note: Some less notable function calls have been excluded from Figure 8 to keep the figure relatively concise.
Figure 8: Firmware Function Call Tree
MSP430 main.c Implementation
With the Indy Module interface safely contained within the three source files described above, all that remains for our main.c code is to exercise the library code, and handle the resulting outputs. This means initializing the device and defining the infinitely executing while(1) behavior.
Initialization requires performing general purpose hardware initialization such as configuring clocks, regulators, and pins, in addition to specific resources used in the example. Indy Module interface initialization requires initialization of both the physical hardware resources required for communication, performed by the platform_init() function, and also initialization of the IRI library interface to the Indy Module, performed by the Indy_SiP_init() function. Initialization of the USB-UART interface is also performed using the TI example functions.
The while(1) behavior is simply performing an EPC inventory of a set length, and then transmitting the newly generated USB-UART traffic. Inventories are performed using the ipj_util_perform_inventory() function. When reports are received during inventories, the report handler functions call the addCharToUSBBuffer() function to add strings to the buffer that will be transmitted over the USB-UART interface to the host PC. After an inventory is completed, and also during the _perform_inventory() function call, the transmitUSBBuffer() function is called to transmit the contents of the USB-UART buffer to the PC.
For more details on the TI firmware, see the documentation distributed with the MSP-EXP430F5529LP software package(slac623c.zip).
See you next time!
Tune in next week to see MSP430 firmware with the Indy Module IRI libraries on-board, typing seen EPCs over a USB HID keyboard interface to a PC!