Handy Board 2 Documentation

Contents:

1. Introduction


Figure 1.1: Handy Board 2 Prototype

Fig. 1

Handy Board 2 is a state of the art robot controller. It has been designed to be a drop-in replacement of its predecessor. The original Handy Board was created about 15 years ago and is used world wide by students and hobbyists. However, many people feel they have reached the limits of the original Handy Board.

Features

  • 66Mhz ARM Thumb Processor
  • 256KB internal SRAM
  • 8MB Flash Program Memory
  • 14 Analog Inputs
  • 14 Digital Inputs
  • 8 Digital Outputs
  • 4 H-bridge Motor Controllers
  • 2 Cricket bus ports

Overview of Student Work

In the Spring of 2004 George Pantazopoulos did a directed study where he researched the microchips to use and then he designed the entire circuit.

In the Spring of 2005, Andrew Chanler did a directed study where he put some finishing touches on the circuit, designed the printed circuit board art work, got the board manufactured and built the first prototypes.

All work for this project has been done at Dr. Fred Martin's Engaging Computing Lab in the Computer Science Department at the University of Massachusetts Lowell.

2. Hardware Design

Most of the Hardware design was done by George Pantazopoulos during 2004. In the spring of 2005, George and Andrew worked together to finish the hardware design. We added the motor circuit, the RJ11 connector, the piezo, and cricket bus support to the schematics.

Note: All schematics and board layout art work was designed using Eagle CAD from cadsoft.de


Figure 2.1: Handy Board 2 Architechure

Fig. 1

PCBoard Layout

This was a very difficult task! I hand routed the power traces near the motors and regulators. I also hand routed all of the power traces of the processor and flash memory.

I learned a lot about Eagle CAD during this process. One thing that helped me reach 100% during auto route was to change the design rules so that vias have to be farther away from SMD pads. What would happen is the processor would get surrounded by vias and then the vias would block traces from connecting to the pads. By keeping the vias away from the pads, this left room for the autorouter to figure out how to connect all the signals to the pads. Another lesson learned is that you can not use polygons to fill in an area with copper until the auto router has already routed all signals. If you draw the polygons first, you get a message that says "Polygons fell apart" and then when you hit the rats nest button you will see lots of unrouted signals.

Manfacture the Boards

We used Advanced Circuit's $33 each deal to get three boards manufactured. And we ordered all the parts from Digikey and Mouser. To view the parts list, click here. The version of the board layout that we had manufactured for the first prototypes can be found in ~andrew/eagle/my_work/HandyArm/Rumble/Rumble_1.19-100percent.brd and the openoffice part list spread sheet is in the same directory and named Rumble_1.19_parlist.sxc

3. Bringing up the First Board

The first thing to do was so bring up the different voltage regulators and verify that they are functioning. This was very straight forward and worked imediately. Next we had to get the processor on the board. I knew we had to use solder paste and the hot air station in the inner-lab. To get some practice, I desoldered some chips off of a random junk board and tried resoldering them with the paste. After doing this a few times I felt confident in soldering the board. The actual amount of solder paste you need to use is very small.

Fine Pitch Surface Mount Soldering

  1. Sqeeze out a thin thread of paste and then try to smeer it evenly around the pads around with the tip of the suringe.
  2. Place the chip on the pads and use tweezers to get it perfectly lined up.
  3. Attach the pencil tip to the hot air station, set the temperature to XXX degrees celcius, and put the air speed pretty low.
  4. Preheat the board and activate the flux in the solder paste. To do this, hold the hot air pump about 2 or 3 inches above the chip and hold it there for 2 minutes.
  5. The solder paste should turn from gritty to glossy/shinny. That means its ready.
  6. Set the air speed even slower and lower the tool in close to a corner of the chip and the solder should wick up onto the legs of the chip and the pads. As it wicks up, move along the edge until the entire side is done.
  7. Then do the same for the other sides of the chip and you are done!

Warning: If the hot air station temperature is set too high, you will destory the chips you are soldering!

Next I soldered down the CPU LED which is connected directly to one of the PIO pins of the processor. Then it was time to try and talk to the chip through JTAG.

4. JTAG Interface

Wiggler Hardware


Figure 4.1: Wiggler JTAG Schematic

Fig. 1

We are using a homemade Wiggler JTAG circuit whose design came from Hardware Recycling Initiative (HRI). We used a 541 buffer instead of a 244 buffer because we had some 541's laying around the lab. The only difference between the two buffer chips is the pin out. The other place our JTAG circuit differs from the schematic is that we are using an invertor instead of a transistor on the NRST line. This needs to be changed because right now our inverter could be driving the line high while something on the board (like the processor itself) could be trying to drive it low. It must have been late when we built that circuit.


Figure 4.2: Our Wiggler Ciruit on Breadboard

Fig. 2

Click here for full size image of Circuit.

JTAG Software

Jtager is the best open source jtag software I have found yet. It uses a really nice command line interface that keeps a history and has other features of the readline library. One thing I have not figured out how to do yet is in circuit debugging with gdb.

Important: For the rest of this document, code examples for loading things into the prototype must be run from the jtager command line.

Note: While installing jtager, after you run make and make install, then you need to copy a file called jtager.conf to /etc/jtager/ and you can find this file in the source subdirectory labeled extras. Also you need to set the core variable inside of jtager.conf to ARM7TDMI

Note: You must be the root user when running jtager.

Another tool that I got working is ARMTOOL. You can find out more about this tool at HRI's JTAG FAQ.I got this working before I tried jtager. The problem with this tool is that everytime you run it, it causes the board to reset.

What didn't work

OCD Commander for Windows says that it supports the wiggler jtag interface, however it did not work. I am glad it didn't work because I moved on to test open source tools that we can use in linux.

5. Driver

A major part of the project was to create the software to use each on board component. I called this code Driver. It is basically a library of functions to talk to each component on the system bus. I had some major issues with poor solder joints on almost all the data bus lines and several of the address bus lines. I learned how to debug this using the osciloscope.

Flash Memory

void clear_flash(short *a);

void burn_flash(short *addr, short *data, int size);

The flash is 16-bit half-word addressable. You cannot write a given address more than once without erasing it inbetween writes. The other caveat is that when you erase part of flash you have to erase an entire 128k page. So when you call clear_flash() it will erase the 128k page that contains the address that is passed to it.

Note: The size parameter passed to burn_flash() is the number of 16-bit half-words to be written.

Warning: I have not tested these functions with any interrupts enabled. If users are going to be writing data into flash, perhaps interrupts should be disabled while the write is going on. So the question is will the timer interrupt break writing/erasing flash?

Digital I/O

int digital(int x);

void digital_output(unsigned char x);

int start_button();

int stop_button();

void start_press();

void stop_press();

All of these functions control the digital input and output latches on the system bus. The start and stop button functions work identical to the Interactice C functions. Also digital_ouput() takes one byte and writes it to the latch. Later functions could be created to set/clear the individual bits on the digital outputs, but this is fine for now.

Motor Control

void fd(int x);

void bk(int x);

void stop(int x);

void coast(int x);

void alloff();

void allstop();

void motor(int x, int speed);

These should look very familiar to the Interactive C Handy Board motor functions. One feature of our design in the Handy Board 2 is active braking. The stop() and allstop() functions enable the braking. The coast() and alloff() functions turn power off and let the motors spin freely.

Note: The speed parameter to motor() is a number from 0 to 7. And the this pwm control uses a method created by George. Also I have not tested out the pwm to see how well the different power levels work.

LCD Display

void lcd_string( const char *s);

The LCD driver is very cool! The display is updated by the system interrupt. The interrupt simple copies the LCD's buffer to the display. And the user code writes the buffer with lcd_string(). This is a huge performance boost because the user code can write the buffer extremely fast and then go back to sensing and acting. However the original Handy Board would stop executing user code until the entire string was written to the lcd hardware.

Another interesting thing about my LCD driver is that it automatically wraps around the end of the buffer and in the original handyboard, you would have to print a '\n' character to cause it to go back to the begining of the LCD display. My LCD driver also supports any LCD display from 1x8 to 4x20! And the way it is implemented, it scrolls the display upwards with each line that is written. Just the way a unix terminal behaves.

One thing I would like to implement in the future is the ability to save a specified number of lines instead of just buffering the size of the display. This would help in debugging. The user could go back and view the LCD log to see what their program was doing. Also, I could implement a way to halt a program and go into a debug mode where the knob controls scrolling up and down in the log to see things the scrolled off the top of the display. Also give the ability to write the LCD log to a location in flash so that even if the board crashes and power dies, you could still view the log later. It would be very easy to implement this LCD log.

Note: To change driver to use a different size LCD screen, set the two #define lines near the top of driver.h

Other Functions

void init_system();

This is a crusial function that enables the system timer interrupt and also sets up a lot of variables for the different peripherals controlled by Driver.

void beep(int rate);

This function turns the Piezo on. Right now the highest pitch tone you can generate is 500hz because the system interrupt generates the squarewave and the system interrupt is 1000hz.

void msleep(unsigned long length);

This function sleeps for a given number of milliseconds.

6. CRT0.S

This is the piece of code that starts execution. It creates a vector table at the beginning of ram, sets the external bus registers, and performs the memory remap. Then it initializes the stack for each of those interrupt modes and the regular stack. The next thing it does is call main.

There are still somethings that need to be done in this code. Globals need to be initialized by copying the data section into ram. Also the bss section needs to be zeroed. The last thing that needs to be done is call init_system() right before main() so that every use program does not need that at the top of their main(). There are probably more things that need to be done if you are writing C++ code. Like figure out how to call the constructors of global objects.

Note: Before the remap is executed, only the first megabyte of flash memory is accessible.

7. Linker Scripts

Code listing 7.1: Linker Script to Run Everything Out of RAM


MEMORY
{
 /*  0x000 to 0x040 is for vecotors and such */
 /*  0x040 to 0x100 is for driver's ram */
 ram : ORIGIN = 0x00000040 , LENGTH = 0x10000 - 0x40
 rom : ORIGIN = 0x00010000 , LENGTH = 0x30000
}

SECTIONS
{
        . = 0x00040;
        __bss_start__ = .;
        .bss : { *(.bss) } >ram
        __bss_end__ = .;
        _end = .;
        end = .;

        . = 0x10000;
        .text : { *(.text) *(.glue_7t) *(.glue_7)} >rom
        .data : { *(.data) } >rom
        .rodata : { *(.rodata) *(.rodata.str1.4) } >rom
}

Code listing 7.2: Linker Script to Execute out of Flash

MEMORY
{
 /*  0x000 to 0x040 is for vecotors and such */
 /*  0x040 to 0x100 is for driver's ram */
 ram : ORIGIN = 0x00000100 , LENGTH = 262144 - 0x100
 rom : ORIGIN = 0x10000000 , LENGTH = 8M
}

SECTIONS
{
        . = 0x00040;
        .data : { *(.data) } >ram
        __bss_start__ = .;
        .bss : { *(.bss) } >ram
        __bss_end__ = .;

        . = 0x10000000;
        .text : { *(.text) *(.glue_7t) *(.glue_7) } >rom
        .data : { *(.data) } >rom
        .rodata : { *(.rodata) *(.rodata.str1.4) } >rom
}

8. Memory Maps

Write Address Map After REMAP is executed

Address Range Peripheral
0x00000000 - 0x0003FFFF Internal RAM
0x10000000 - 0x107FFFFF Flash Memory
0x20080000 - 0x2008FFFF LCD Latch
0x20090000 - 0x2009FFFF Motor Latch 1
0x200A0000 - 0x200AFFFF Motor Latch 2
0x200B0000 - 0x200BFFFF Digital Output Latch
0x200C0000 - 0x200CFFFF Analog to Digital Converter
0x200D0000 - 0x200DFFFF ADC Channel Select Latch
0xFFC00000 - 0xFFFFFFFF On-Chip Peripherals

Read Address Map After REMAP is executed

Address Range Peripheral
0x00000000 - 0x0003FFFF Internal RAM
0x10000000 - 0x107FFFFF Flash Memory
0x20080000 - 0x2008FFFF Digital Input Latch 2
0x20090000 - 0x2009FFFF Digital Input Latch 1
0x200C0000 - 0x200CFFFF Analog to Digital Converter
0xFFC00000 - 0xFFFFFFFF On-Chip Peripherals

Read and Write Address Map Before REMAP is executed

Address Range Peripheral
0x00000000 - 0x000FFFFF Flash Memory
0x00300000 - 0x0033FFFF Internal RAM
0xFFC00000 - 0xFFFFFFFF On-Chip Peripherals

9. Example Program that uses Driver

This program will beep a tone and turn a motor on while either the start or stop buttons are being pressed down. The first important thing is the init_system() function. This enables the system timer interrupt which is a needed for the LCD, motor PWM, beep, and msleep(). It also sets up various variables that are in RAM that Driver needs. Other than that, everything else should look very familiar to a Interactive C Handy Board program.

Code listing 9.1: code listing for demo.c

#include "driver.h"
#include "rumble.h"

int main()
{
	init_system();
	lcd_string( "Rumble\n" );
	while (1)
	{

		if ( !start_button() )
		{
			beep(440);
			fd(0);
			lcd_string( "Engaging\n" );
		
			while(!start_button());
			coast(0);
			beep(0);
		}

		if ( !stop_button() )
		{
			beep(440);
			fd(3);
			lcd_string( "Computing Lab\n" );
		
			while(!stop_button());
			coast(3);
			beep(0);
		}
	}
        return 0;
}

10. Building the Example Program

11. Running the Example Program

12. Errata

13. What's next?

14. Links

15. About this Doc

This document was written in an xml format designed by the people who created Gentoo Linux. To learn how to create similar documents, read Gentoo Linux XML Guide and Documentation Development Tips & Tricks.



line
Updated 19 May 2005
line
Andrew Chanler
Student

line
Summary: This guide contains all the information regaurding Handy Board 2.
line
Copyright 2005 Andrew Chanler. Questions, Comments, Corrections? Email Orlot@rocketmail.com.