CSE 466 Lab 5: Introduction to the iMote2 and Embedded Linux

Introduction

Now that you've worked with a simple 8-bit microcontroller, we'll be exploring more powerful embedded devices. For the rest of the quarter, we'll be using the iMote2, which has a 32-bit, 416 MHz ARMv5 microcontroller (The PXA271), with 32 MB of flash and 32 MB of RAM. This microcontroller was designed for use in cell phones and PDAs. This lab will introduce you to the iMote2 platform, and using Linux as an embedded operating system.

WARNING: NEVER attach or detach the iMote2 from the debug board or the sensor board when power is attached. ALWAYS make sure you've unplugged ALL of the USB cables when connecting or disconnecting the sensor board or debug board.

Objectives

In this lab, you will learn:

Suggested Reading and Resources

WARNING: There is some important and really useful information in this section. Don't skip over it!

Useful Software

Part 1: Getting acquainted with the platform

WARNING: The iMote2 and BSB are not indestructible. Make sure you observe reasonable precautions for handling static-sensitive components when handling the bare boards (you don't need special grounding straps, but don't rub it all over synthetic fabrics.) Try to keep the boards inside the anti-static bag when you put everything away in your kit.

In your kit, you will have two iMote2 boards and two basic sensor boards. Your kit also contains two USB A to mini B cables to connect the iMote2s to your workstation, and a battery and charger for a SuperBird board, which you will receive later.

iMote2
The iMote2
Basic Sensor Board
The Basic Sensor Board (BSB)
Debug Board
The Debug Board

The Basic Sensor Board (BSB) contains an accelerometer, light sensor, temperature and humidity sensor, and a general-purpose ADC converter. In this course, we will primarily use the BSB for its 3-axis accelerometer.

The debug board features the same USB interface chip you used in Lab 4. It lets you tap into the iMote2's serial ports. While you'll generally be using the USB Ethernet interface on the iMote2 itself to access the Linux console and program the iMote2, the debug board can be helpful for logging in when you cannot establish a network connection to the iMote2. The debug board is not included in your kit, but there are several available should you need one.

We've pre-loaded the Linux kernel, the filesystem, and the bootloader (BLOB) on your iMote2 using the JTAG interface. You should be able to follow these directions and log into the iMote2:

  1. Connect your iMote2 to the computer with a USB cable, press the power button, and wait for the LED to turn green.
  2. Launch PuTTY. If PuTTY is not installed on the lab machines, you can download it here.
  3. Connect to 192.168.24.1
  4. Once you see the login prompt, log in with username root and password rootme.

Your iMote2 is running Linux 2.6.28, with a small set of userspace programs. To enable easy access to the iMote2, it runs an "ethernet gadget" driver that uses the USB interface to make the iMote2 appear as a USB ethernet card. After it's booted up, it starts a small DHCP server so that when you connect it to the PC, an IP address (192.168.24.110) is automatically assigned to this interface on the PC side. The dropbear SSH server is a small, lightweight SSH server that allows you to log in over this network interface to access your iMote2. SFTP is also supported, and we'll be using this to transfer files to and from the iMote2.

NOTE: The Windows driver for connecting to the ethernet gadget is located at /cse/courses/cse466/iMote2/sources/linux-2.6.28/Documentation/usb/linux.inf. You'll need this if you want to connect your iMote2 to your Windows laptop, or if the lab workstations ask for it.

Take a moment to explore the filesystem on your iMote2. There isn't a lot there, so if you've ever wondered what's really essential to a small Linux system, now is a good time to have a look around and familiarize yourself with the essentials.

Now that you've logged in to your iMote2, let's compile our first kernel module and user-level application! First, set up your attu account to use the cross-compilation tools required to produce code that runs on the iMote2's Xscale processor. The tools are located in /cse/courses/cse466/iMote2/cross-compiler/arm-xscale-linux-gnu/bin, which you should add to your $PATH environment variable. If you are using bash, add the following to your .bashrc file and restarting your session (all on one line; it's wrapped here so that it doesn't go off the page on printed copies):

	export PATH=$PATH:/cse/courses/cse466/iMote2/cross-compiler/
	arm-xscale-linux-gnu/bin

If you are using a different shell, Google, or the man page for your shell, can probably tell you how to add things to your profile. You can also always specify the full path to the compiler every time you invoke it, if you really want to do all of that extra typing.

Check to make sure that you can invoke the compiler by running arm-xscale-linux-gnu-gcc from your shell prompt. It should tell you that there are no input files (since you haven't specified any) and exit.

Now, we'll start working on our first kernel module and userspace program. This will be a driver that uses one of the PXA271's hardware timers to blink the red component of the LED on the iMote2. In this section, you'll compile the provided code and get it loaded on your iMote2. In the next, you'll adapt the module to have a shorter period and adjustable duty cycle, so that you will have PWM control of the RGB LED.

  1. Download and unzip the blink starter code to your attu account.
  2. To compile the kernel module, simply run make. This should produce a file called blink-mod.ko, which is the kernel module.
  3. To compile the application, run:

    arm-xscale-linux-gnu-gcc -o blink-app blink-app.c

    This should produce a file called blink-app, which is a user-level utility to set the blink rate of the LED.

  4. Copy the files over to the iMote2 using WinSCP3. To do so:
  5. To load your kernel module, run insmod blink-mod.ko on the iMote2 console. For more information on insmod, see the manual page.
  6. In Linux, like all other Unix-like operating systems, devices appear as special files. Devices can either be character devices, which act like infinite streams of bytes, and block devices, which communicate with fixed-size blocks of data. Devices are part of the regular filesystem namespace, usually appearing under the /dev directory. For each device "file," the filesystem contains an entry mapping that "file" to a device number, split into major and minor parts. Major numbers correspond to a particular kind of device, or a driver responsible for that device. Minor numbers correspond to specific instances of those devices, which are managed by a common driver. You can view these major and minor number by running ls -l /dev.

    Since the number of major device numbers is small, well-behaved drivers request a major number when they are inserted into the kernel. Now that the kernel module has been loaded, we need to find out which major device number Linux has assigned to our new device. To do so, run cat /proc/devices. Under "Character devices," you should see a line like 254 blink. In this case, 254 is the major device number. Since we only have one blink device, we use 0 as the minor number. To make a filesystem entry for the blink device, run mknod /dev/blink c 254 0. This creates a character device named /dev/blink that points to device number 254,0. For more information on mknod, see the manual page.

  7. Execute ./blink-app 1 to blink the LED at 1 Hz. Try some different frequencies.
  8. To remove the blink module, execute rmmod blink. For more information on rmmod, see the manual page.

Part 2: Extending the blink module for PWM

Now that you've successfully built a kernel module and an application that uses it, let's take a look at how it works. From there, you'll extend the blink module to drive three PWM signals to the tri-color LED (similar to lab 3).

The PXA271 does have hardware for PWM. However, the pins that are PWM-capable aren't wired up to the LEDs. (In fact, they're not wired to anything at all on the iMote2.) So, you'll be doing pulse width modulation in software. Remember Question 1 on Lab 3? Now's the time to put that pseudocode into practice.

Let's take a look at the blink-mod.c file.

Now, your task is to modify the blink module and application so that you can set the tri-color LED to any color using PWM. Specifically:

  1. Modify the blink kernel module to generate PWM signals to all three LEDs, like you did in lab 3. You should be able independently control each LED’s duty cycle.
  2. Modify blink-app into a user-level application that sets the color output of the tri-color LED. You’ll need to extend the kernel module’s ioctl interface for this.
  3. You should also rename the module to reflect its new functionality.
NOTE: Hardware timers are a scarce resource. Your PWM module should not use any more timers than the basic blink module, or you will run into problems with other devices that need timers.

Part 3: Using the accelerometer

In this part, you'll finish implementing a driver for the accelerometer on the Basic Sensor Board, and write an application that converts accelerometer readings to colors, like in lab 3.

  1. Download the accelerometer skeleton code here. It should contain the following files:
  2. Before getting started, here's some things to note about the skeleton driver:
  3. Implement accel_irq_handler and accel_ioctl in accel.c.
  4. Test your module with the provided accel-dump application.
  5. Create an application that translates the accelerometer readings into color values. You do not need to do any fancy HSV to RGB mapping -- simply using each axis of the accelerometer to control a single color is sufficient.
  6. You are welcome to change the format of the data in the circular buffer if you wish.

Part 4: Using the radio

In this part, you will be introduced to the radio functionality of the iMote2. We will give you example code for sending and receiving from the radio, but you will have to come up with your own packet structure for your communications protocol.

NOTE: All of the iMote2s are configured to use the same IP address. If you want to connect both iMote2s to your workstation at the same time while you are working with the radio, you should change one of the IP addresses.

The IP address is set in /etc/rcS/S04network.sh, where the interface is brought up by ifconfig. You can change the iMote2 to a different subnet by changing the third octet of the IP address. You should then also edit /etc/udhcpd.conf to set the DHCP server to assign IP addresses in the new subnet.

Remember what you set the new IP address to! However, if you mess up and can't connect, you can always use a debug board to connect over the iMote2's serial port and edit the network settings.
  1. Download the radio code here and un-zip it in your attu account. It should contain the following files:
  2. Change the GROUP_NUMBER constant in both .c files to your group's number. This will let you send and receive messages on a channel unique to your group, which is helpful when you are trying to debug your radio code. Note, however, that your communications protocol in your own programs, when finished, should use some kind of unique identifier or address and ignore packets that are not your own. Your unique channel (again, for debugging purposes only) will be your group number plus 11.
  3. Run make to compile the applications. Load count_and_send onto one of your iMote2s and receive_to_led on the other. (Make sure that you are not running your PWM driver, which will interfere with the basic LED driver.)
  4. You should see the LEDs on both iMote2s updating at the same time to the same colors. The sending iMote2 will also print out the current value that it is sending, and the receiving iMote2 will print out the value that it is receiving.
  5. Once you're convinced that the programs work, change the channel back to 11 (set GROUP_NUMBER to 0) and implement a communications protocol so that your receiving iMote2 will only update its LED based on messages it receives from your sending iMote2, even when there are several other iMote2s transmitting on the same channel. The design of your protocol is up to you, but you should use at least a unique identifier (use your group number) and an arbitrary node ID unique to each of your iMote2s.

Note that the tos_mac driver does not implement the ZigBee protocol stack; rather, it implements the TinyOS MAC (which is where the driver gets its name). The TinyOS MAC includes 16-bit group and address fields; however, the driver is kind of a buggy hack and these don't always work properly. For the labs in this course, you will set the address to 0xFFFF, which broadcasts packets, and should implement your own addressing in the payload of your messages.

Part 5: Putting it all together

In this part, you will combine the elements from Parts 1-4 and add bi-directional communication between your iMote2s.

  1. Using the modules you have developed so far, create two programs to run on your iMote2s:
  2. Your receiving iMote2 should also read from its own accelerometer, and transmit a "stop" signal to the sending iMote2 and turn off its LED when it is turned upside down. When it is turned right-side-up again, it should transmit a "start" signal.
  3. The sending iMote2 should react to a "stop" signal by ceasing to transmit packets and updating the color on its own LED instead. When the "start" signal is received, it should turn off its own LED and begin transmitting packets with accelerometer readings once again.

While you're designing your programs, you should keep the following things in mind:

  1. In the sample code, reading from the tos_mac driver is done in blocking mode. That is, when you try to read from the device, your program will wait until a packet has been received before continuing on to the next line. This works well for uni-directional communication, but not as well for bi-directional communication (unless you implement multiple threads for sending and receiving.) See the man page for open for more information on non-blocking I/O.
  2. You probably don't want to send packets as fast as you possibly can. Your sending iMote2 should wait some amount of time between packets that still feels responsive, but is not as fast as possible. If you're sending as fast as possible, you will jam the channel with an unnecessary amount of traffic, making it difficult for other communication (such as other groups' implementations) to take place. Only use as much bandwidth as is necessary for your system to feel responsive.
  3. Your final implementation should function on channel 11 and ignore packets sent by other groups.

Deliverables

You have two weeks to complete this lab. There are no deliverables for the first week, but to stay on schedule, you should have working LED PWM and accelerometer drivers.

Turn in all required documents an e-mail attachment to cse466-tas@cs. For all files turned in, the comments at the top of the file should contain:

  1. Demonstrate your system of sensor to radio to radio to LEDs to a T.A. You can either do this during lab, or during the first 1/2 hour of the lab section when the assignment is due.
  2. At the end of the second week, you should turn in source files for: You should create a .zip or .tar archive of all of the files you are turning in.