The proliferation of the Internet and wireless networks in the Information Age has made connectivity a standard requirement today for most portable and embedded systems. The ubiquity of personal computers (PCs) has led to Universal Serial Bus (USB) becoming a dominant choice for wired connectivity because of its ease-of-use and its ability to enable high-speed data transfers.
Original equipment manufacturers (OEMs) desire to differentiate their end products by creating unique and customized solutions, and by providing customers with multiple options and new features, all within an ever-tightening time-to-market window of opportunity. This has led to OEMs demanding that suppliers provide solutions that are flexible during design, manufacturing, and end use. Microcontrollers with on-chip flash memory have emerged as a key enabler of these capabilities in end products.
However, combining flash memory with USB in a microcontroller takes these capabilities a step further by increasing functionality and creating new possibilities for product features and their use. Combining these two technologies has two key benefits. First, they enable a high level of technology integration, making possible the development of more intelligent products for cost-sensitive and space-sensitive consumer applications. Second, they allow products to combine the in-system reprogramming capabilities of flash memory with the "plug and play" ease-of-use of USB.
For example, the standard procedure for fixing a defect in firmware code has been for users to take their printer to the store for service. With flash memory and USB connectivity available on a microcontroller, users simply connect the printer via the Internet to the manufacturer's website, download the firmware patch, and the PC and printer implement the patch automatically.
In another example, an MP3 player periodically will have to be updated as new audio standards emerge. The availability of on-chip flash memory enables new standards to be downloaded over the Internet as soon as they are available. Cell phones and personal digital assistants (PDAs) require company-supplied files, applications, and configurationsall of which can be downloaded easily for products after they have shipped from the factory or are already in use by customers.
As non-PC hosts such as gaming consoles, Internet Appliances, and set-top boxes become more commonplace, the number of applications and products requiring USB connectivity and in-system programming will continue to increase.
Flash Programmer Application Example
The primary focus in developing such a system is to create the programming functions, such as in the following example of a flash-programmer application. Standard in-circuit flash programming is generally done through a serial synchronous interface (which has clock, data in, data out, plus some control signals) or an asynchronous interface (which has RS-232 types of transmit and receive signals). In this case, the interface is redesigned to accommodate USB, which provides several advantages over traditional programmer interfaces.
Full-speed USB 1.1, which provides for data transfer rates up to 12 megabits per second (Mbps). This transfer rate dramatically improves programming time compared to RS-232 by enabling the microcontroller to transfer data at speeds more suitable for its internal bus speed, thereby minimizing programming times. The asynchronous nature of RS-232 delays the microcontroller's transfer rate; in addition, RS-232 baud rates are much slower.
One unique aspect of USB-compatible devices is that they can be bus powered. This feature means a device must operate with a total current consumption of less than 100 mA during initialization, then it can draw up to 500 mA thereafter if it is configured as a high-power device (according to the USB 1.1 specification). The Mitsubishi Electric microcontroller used as an example for this article operates at a power level that is low enough to execute its program, provide USB transactions, and achieve flash-memory programming without the need for an additional external power supply. In the case of a portable device, this means being able to reprogram the device without draining the device's batteries, or without batteries altogether.
Developers must implement standard flash-memory programming commands, including Erase, Write, Read, and Verify. They also must allow for additional considerations, such as downloading the hexadecimal code file and handling non-contiguous programs, as well as handling code sections, memory mapping, and block sizes.
To perform in-circuit flash programming, designers must put the microcontroller into boot mode by pulling the CNVss input pin high (to 5 volts) during reset, which executes boot code from the boot area of memory. This includes executing the USB interface code, which will receive and interpret commands from the host and perform those functions on the user flash memory. Individual flash-memory control subroutines, such as Read, Write, and Verify, are copied to RAM as needed to perform the appropriate flash-programming function.
Figure 1: PC application program interface with flash-USB microcontroller and target device
Figure 1 illustrates a file download and programming operation using USB bulk transfers. The flash-USB microcontroller is shown in the target device with its interface to the host PC and application program. The CPU is reset in boot mode and begins executing code from the boot block area. Enumeration is performed and USB communication is established with the host, opening a "pipe" for bulk data transfers. Data is then transferred 64 bytes at a time to the Endpoint 1 FIFO, then transferred via direct memory access (DMA) from the FIFO into a 1-kbyte buffer in RAM. When the buffer is full (or data transfer is completed), the CPU boot program copies appropriate flash command functions to another area of RAM and then jumps to RAM to continue code execution from there. The program, operating out of RAM, transfers data in 1-kbyte blocks from RAM and programs it into the user flash memory.
The USB host and device must have an established framework for command and data transfers. In this example, the programmer establishes four pipes for the data flow:
- A CONTROL pipe to enumerate the device as well as to provide a method for flash command transfers from host to device through Vendor Requests
- A BULK OUT pipe to download hexadecimal files to the device (to prepare for programming, for example)
- A BULK IN pipe to upload data from the device (for Read or Verify operations)
- An INTERRUPT pipe to report status.
The USB specification provides that bulk transfer types guarantee data integrity. Data is transferred in up to 64-byte packets. If there is a Cyclic Redundancy Check (CRC) error, there will be no handshake from the device, a timeout will occur and trigger a retransmit from the host. In this way, the file is transferred error-free.
Figure 2 illustrates a complete Flash-Over-USB communications session for a program download and write operation. After the setup packet (#7501), the host sends a vendor request using the CONTROL pipe comprising the following:
- The FLASH_WRITE command (02)
- The starting memory address in flash memory where the data should be written (8080h)
- The total number of bytes that will be sent for this data segment (10h).
The device acknowledges in packet #7503 and completes the status phase at packet #7506. The initialization of data to Endpoint1 occurs in packet #7509. Packet #7510 shows the transfer of the 16-byte program from the host client software to the USB microcontroller via the BULK OUT pipe. As a handshake method, the client software then waits for an INTERRUPT IN transfer from the device. This INTERRUPT IN transfer will contain one byte signifying the success status of the operation. The client software must wait for this final status phase before it may issue another command to the device. The DATA 01 in packet #7521 signifies success.
On the host side, developers must develop client software. To do this, they first need a Windows device driver or WDM (Win32 Driver Model) to allow users to communicate with the device. This example uses a generic class driver that supports an API for one BULK IN pipe, one BULK OUT pipe, and one INTERRUPT IN pipe, as well as allowing for vendor-specific requests via the CONTROL pipe. These are the minimum pipes needed to achieve a basic programming protocol.
The flowchart in Figure 3 describes the basic steps of the microcontroller including initialization, enumeration, and command response. Commands are passed to the device via USB Vender Request packets over EP0. Inquiry Requests, such as Get Device Info, are also passed via Vender Requests. The device answers by passing back data through EP0.
In-Circuit USB Programming Application
By combining the previously described firmware and flash-USB microcontroller with the PC application software, you can construct the flash-USB programmer. For example, Mitsubishi Electric & Electronics has developed a patent-pending Flash-Over-USB application enabling developers to perform in-circuit USB programming as well as providing the fundamental building blocks for integrating a USB in-system programmer for a full-speed (12 Mbps) USB 1.1 device. The application consists of an 8-bit flash memory USB microcontroller with firmware and boot code; a Windows NT- and Windows 98-compatible USB driver with application program; and a target board.
Figure 4: User interface for Flash-Over-USB application
You use the side menu of the user interface, shown in Figure 4, to select commandsthis is the main window for current status (including indicating when the device has been connected to a USB host), downloaded file size, and flash-memory information.
The application starts by initiating the Flash-Over-USB Windows program and plugging the USB cable into the host and target. This updates "Device Info" to show that the USB device is connected, display the firmware version running on the target system(s), and show security status indicating whether or not the on-chip flash memory is locked.
An ID check function provides security, with the ID check command being stored in the boot block. The host must provide a seven-byte security code to access data stored in the flash memory, and a locked device prohibits reading and programming, as well as erasing individual blocks. However, the entire flash memory can be erased, which also unlocks the device. Selecting the UNLOCK button opens a window for entering a seven-byte ID code and, once unlocked, enables normal programming functions. The OPEN button opens a window for selecting and downloading a hexadecimal program file, followed by a display of file name, size, security ID code, and flash blocks effected in "File Info". A sub-window displays specific memory blocks and size information.
The ERASE function allows the erasure of individual flash-memory blocks or the entire flash memory. The PROGRAM button lets developers specify the erase, program, and verify operations or simply perform the programming operation. The MEMORY button is an additional feature that allows developers to read and write SFR and RAM variables during development and perform simple debugging.
Implementing a USB-Flash In-System Program
To provide the complete benefits of in-system programming, the microcontroller requires a special operating mode called "CPU Rewrite". In this mode, the microcontroller can handle the file transfer from an outside source and reprogram its own flash memory without any external intervention. The CPU Rewrite program is embedded in the device's application code (contained in user flash memory) and comprises flash command routines as well as USB communications and data transfer functions. During operation, the CPU Rewrite program is copied from the user program area to RAM, where it executes to reprogram the user flash memory. A USB device such as a printer or PDA could then reprogram itself by communicating through its established USB connection with a host PC or an appliance and download file or data updates. The key to providing true "plug and play" in-system programming is to integrate the USB CPU Rewrite code with the device application code.
Minimizing RAM use by the CPU Rewrite program is a key programming challenge. The previous programmer example copied into RAM only the appropriate programming subroutine necessary to complete the specified command function (READ, WRITE, ERASE, and so on). For example, when the device receives an erase command from the host, it copies only the erase subroutine from the boot area into RAM and executes that function. However, in an in-system application, the main program that is executing out of the user flash memory also needs to be reprogrammed. Therefore, the entire CPU Rewrite program must be copied into and executed out of RAM. This, of course, places a significant challenge on developers as they work with the small RAM area of many microcontrollers. You can decrease RAM usage by streamlining the USB firmware and protocol to handle only the necessary pipes and flash commands. This is done by including only the flash subroutines that are essential for reprogramming the device (such as Erase and Write operations) and by dropping subroutines that may not be necessary (such as Status Check and even Get Device Info).
When a USB device enumerates, it initially specifies its function with the host. For example, a printer will enumerate as a printer using the printer device-class driver.
The USB specification also allows devices to support multiple configurations. For example, when a printer is first plugged in, it enumerates and associates the proper operating-system drivers so that it can be used as a printer. However, the host PC also knows within its descriptor table (which was transferred during enumeration) that this device supports multiple configurations. Knowing this, if necessary, the host can send down requests that command the printer to change configurations to its alternate setup. This alternate setup might do many different things or do nothing, depending upon the complexity of the application. In the Flash-Over-USB example, different endpoints would be set up and possibly different transfer types implemented. When finished, the host could again ask the device to change back to the original configuration or, if updates were made, to a new configuration.
As previously discussed in this paper, in order to reprogram the flash memory, the CPU Rewrite code must be executed from RAM. This means we must write routines that can be copied into a section of RAM in order to redirect the instruction pointer to run that modular code without accessing any of the flash memory. The simplest way to do that is to instruct the compiler to produce relative addressing code. Another possibility is to write the RAM module code in assembly language so that the proper subroutine calls and other relative addressing is maintained. Finally, a more complicated method might be to set up a code section address to be for a RAM location as opposed to a ROM location. Then, after building and creating a downloadable file (such as an S Record or Hex file), manually modify that code module's location to reside in ROM. During run time, copy that section into its intended RAM location for proper absolute address execution.
Sending flash commands, such as Erase or Write, to the flash controller's Write State Machine will reprogram the flash memory. For in-system programming, you must enter the CPU Rewrite mode by setting the CPU Rewrite Bit in the MCU's Flash Control Register. Once this bit is set, all memory accesses to the flash area are treated as flash commands instead of simple data retrieval. For example, to erase a particular flash block, a Block Erase command code is written to an arbitrary flash address to instruct the flash sequencer that an Erase block address will be sent. Next write a Confirmation command code to the highest even address in the desired flash memory block. This will start the Block Erase operation. While the CPU Rewrite bit is still set, write a Read Status Register command to any arbitrary flash address to instruct the flash sequencer to read the contents of the Status Register for the last flash operation. This will indicate when an Erase operation has terminated and if there is any error. Next, perform a read operation to any flash address and analyze the returned data to determine whether the erase operation was successful. If it was, clear the CPU Rewrite Bit and return back to the program code residing in flash memory (assuming it wasn't in the flash block that was just erased).
Finally, depending on the in-system programming requirements, further considerations must be taken into account, such as:
- What is the maximum size of data that must be transferred at a time? A larger RAM buffer size may provide greater data throughput.
- Do all blocks need to be erased or can one block be allocated for permanent storage? If all blocks must be reprogrammable, special care may have to be taken to protect the CPU Rewrite code (including data transfer/communication code) and Vector Tables. For data logging or other types of data storage, you can use a single Block Erase and multiple Word Writes, simplifying the CPU Rewrite functions and saving time and power.
Other USB Applications on the Horizon
The "mini-host" is a new concept promoted by the USB organization called "USB on the Go," which provides USB compatibility to portable non-PC devices. A mini-host device will act not only as a function controller, but also will have some basic USB host features. Such a device will have a small subset of the standard Host Controller Interface (HCI). A simple driver and protocol like the one this paper discusses would be well suited for the purposes of a mini-host. This will allow products such as a digital camera to print pictures directly to a USB-compatible printer. Similarly, a PDA might be used to reprogram a printer or camera in place of a host PC.
About the Authors
Chris Brandt and Jim Page are microcontroller applications project engineers at Mitsubishi Electric & Electronics USA's Design Engineering Center East in Durham, NC.
Chris has more than three years of experience in developing USB related applications for Mitsubishi Electric's microcontrollers. He is also experienced in system-level microcontroller design as well as in firmware and Windows programming for microcontrollers. He holds a B.S. degree in Computer Engineering Technology from the Rochester Institute of Technology.
Jim has six years of hardware-level microcontroller experience in applications engineering and has developed microcontroller USB applications for four years. He has a B.S. degree in Electronic Engineering Technology from Western Carolina University.