From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15553 invoked by alias); 5 Jun 2006 18:34:19 -0000 Received: (qmail 15544 invoked by uid 22791); 5 Jun 2006 18:34:18 -0000 X-Spam-Check-By: sourceware.org Received: from intranet.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.6) by sourceware.org (qpsmtpd/0.31) with ESMTP; Mon, 05 Jun 2006 18:34:15 +0000 Received: (qmail 27100 invoked from network); 5 Jun 2006 18:34:13 -0000 Received: from unknown (HELO localhost) (jimb@127.0.0.2) by mail.codesourcery.com with ESMTPA; 5 Jun 2006 18:34:13 -0000 To: gdb@sourceware.org Subject: GDB support for flash: implementation From: Jim Blandy Date: Mon, 05 Jun 2006 18:34:00 -0000 Message-ID: User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-IsSubscribed: yes Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org X-SW-Source: 2006-06/txt/msg00020.txt.bz2 Thanks very much to the folks who contributed to the thread the other week about GDB's flash programming support! Based on the feedback, I've made the following adjustments to our user interface sketch/spec: * Drop the requirement that 'load' preserve the contents of those portions of the flash that the binary being loaded doesn't touch. Since erase operations affect entire sectors, these semantics would require a read-erase-write cycle covering, in the worst case, a complete flash sector. When programming flash directly over a JTAG interface, it's not unusual for it to take tens of seconds to write a sector; this is an unacceptable cost when the user knows the old contents aren't worth preserving. * Note that we could extend GDB's memory region facilities to establish different settings for different regions of flash, or for different flash devices. However, we'll leave developing this idea for later. But with those changes, people seemed to feel that the facilities proposed would cover their daily use cases. So I think now we can start talking about the implementation. Here's an edit of the original document that goes further and describes an implementation that seemed reasonable to us; search down for "Implementation". So, what do people think? Would this proposal work for you? ---- Background Flash memory is a popular form of non-volatile memory. When reading, it is byte-addressable, like traditional RAM or ROM. An entire block (many kilobytes, typically) of flash can be erased with a single command. Individual bytes can be written only if they have been erased, but not subsequently written. Therefore, to write a single byte, without changing other bytes in the same block, one must read the block, erase the block, and then re-write the block using the previously read data, as modified by the intended write. Flash is typically used for program storage. On some systems, flash is in fact the only place to store programs. For example, some systems have have relatively large amounts of flash, but very small amounts of RAM. If the flash memory controller has a JTAG interface (most do) then the flash memory can typically be programmed using the same ICE/BDM unit that is used for debugging. Because GDB already communicates with these ICE units (typically via a GDB stub), and because GDB already supports loading programs onto embedded systems (via the load command), it is natural that GDB support loading programs into flash memory as well. This document proposes a GDB user interface for loading programs into flash memory. In what follows, the term "GDB" refers to the user's view of GDB, which includes GDB, any applicable stub, the ICE units, etc. Thus statements like "GDB must do X" are not meant to imply that GDB proper must do X, but rather that GDB must cause X to occur. Rationale paragraphs appear in (parenthesis). Program Images If the program image loaded by the load command will result in any portion of the program image being placed in flash memory, then GDB is responsible for programming those portions of the flash accordingly. GDB may also arbitrarily modify bytes in flash that fall outside of the program image. If the target hardware requires any other modifications to special memory addresses (such as placing the initial value of the program counter at a specified address), then it is the responsibility of the programmer to ensure that the program image contains appropriate values at those addresses; GDB's responsibility is simply to accurately copy the program image to the target. (The rationale for using load (rather than an alternative flash command) is that, on a system in which programs are located in flash, loading a program implies placing it in flash. Furthermore, GUIs, scripts, etc., that use load (or the MI equivalent thereof) will not require change to work with flash systems.) (The proposal originally required the load command to leave portions of flash that fell outside the program image unchanged. While this rule would minimize side effects, it may be impractical to follow on some devices. Since erase operations affect entire sectors, preserving bytes outside the image would require a read-erase-write cycle covering, in the worst case, a complete flash sector. When programming flash directly over a JTAG interface, it's not unusual for it to take tens of seconds to write a sector; this is an unacceptable cost when the user knows the old contents aren't worth preserving. However, it might be valuable to provide the original behavior as an option.) Variables and Data By default, variables and other data located in flash may not be modified by the user, other than by use of the load command. For example, if i is located in flash, then: set var i = 10 will result in an error message. (As a consequence, GDB must be able to determine which addresses lie in flash; otherwise, GDB, using a stub with a 100% transparent interface to flash, would not be able to issue an error.) (The rationale for forbidding modification of variables is that most such attempted modifications probably represent user error. Furthermore, because setting a single variable requires erasing and writing an entire flash sector, there might be some noticable delay in implementing this request.) Customization GDB will have a new write-flash variable. This variable will have three possible states: * on All writes to flash, including those to variables/data, are permitted. This mode may be used to permit explicit "poke" operations. * load The load command may write to flash; no other commands may write to flash. This mode is the default. * off No commands may write to flash. This mode may be used for safety when debugging a production system. (In the future, we may want to adapt GDB's memory regions to allow different parts of the address space to carry different settings.) Implementation There are many different flash devices in general use, from many different manufacturers. The algorithms required to load new data into flash vary from one chip to the next. Some devices support more than one programming method; the best choice may depend on what resources are available elsewhere in the system (RAM for buffering, and so on). To contain this complexity, code specific to particular flash devices is placed in the GDB stub, and GDB itself uses flash-specific but device-independent remote protocol requests and replies to program the flash. The GDB load command initially tries to place the program image in memory using ordinary memory write requests --- remote protocol M or X requests. However, when the stub detects that GDB has attempted to write to flash memory, it returns an error code of the form: Eflash:addr;length In this reply, addr and length are the start address and length of the block of flash memory the write request attempted to modify. That is, a write that overlaps any portion of a region of flash memory elicits an Eflash response giving the location and size of the entire flash memory. If the write request overlaps two areas of flash, the Eflash request reports the lowest-addressed area. When the stub returns an Eflash result, it should discard the entire write request; if portions of the request cover non-flash memory, the contents of that memory should be unchanged. GDB's reaction to an Eflash response depends on the current write-flash setting. If write-flash is off, or if it is load and the write was not part of an image load, GDB displays an error message to the user, and gives up on the command. Otherwise, GDB follows this procedure:: * First, it sends zero or more packets of the following form to the stub: vFlashErase:addr;length This directs the stub to erase all flash sectors that overlap with the region from addr to length. The region need not be aligned on flash sector boundaries, and may cover any number of sectors; it is the stub's responsibility to expand the region to the smallest set of sectors that completely contains the given region. * Then, it sends the data to be loaded into flash using packets of the following form: vFlashWrite:addr,length:data where addr, length, and data all have the same form as they do in the X binary download packet. The set of vFlashWrite packets preceding a vFlashDone packet (see below) must not overlap, and must appear in order of increasing address. Writes may fall outside the regions given by the previously transmitted vFlashErase packets, but the results are unpredictable if a given area of flash is rewritten without being erased. * Finally, it indicates that all the data to be programmed has been sent, with a packet of the form: vFlashDone Until the vFlashDone packet is received, the effects of prior vFlashErase and vFlashWrite packets may be unpredictable. Receipt of an Eflash response to a memory write indicates that the stub supports the vFlashErase, vFlashWrite, and vFlashDone requests. (Rationale: * The Eflash response allows the stub to screen writes to flash. It would certainly be possible for GDB itself to screen writes by address, and it could be useful for GDB to have detailed knowledge of the target's address space for other reasons as well. However, stub-based screening is also an important case to support, because it allows detailed knowledge of the device to be held in software more tightly coupled to the device than GDB is. And it's simple: on targets with a single flash device, the stub need only make a simple address overlap comparison and return a fixed-string Eflash response. * By itself, the existing X packet is not suitable for flash programming. To allow multiple X packets to load data into the same flash sector, X would have to follow a save-erase-combine procedure, which can be extremely slow on some devices. So a separate erasure packet, at least, is necessary. * It is possible to use the X packet for both flash programming and ordinary memory writes, instead of introducing a new vFlashWrite packet. However, the procedure for programming flash can be very different from the procedure for writing ordinary memory --- for example, many devices require some handshaking to allow them time to complete the write --- so the code handling the X packet would need to dispatch to different routines depending on the address anyway. It seems simpler to restrict X to writing ordinary memory, and introduce a new packet for flash programming. Also, using separate packets for memory writes (X, M) and flash writes (vFlashWrite) makes it easy for the stub to tell whether to respond to a write request with an Eflash result, or whether to call the flash-programming code. Certainly, the stub could keep track of whether the write occurs between a vFlashErase and a vFlashDone, but that would make the protocol stateful, and thus a bit more fragile. Finally, using separate packets makes it unnecessary for the stub to handle writes overlapping different kinds of memory, removing some complexity. * We allow writes without preceding erases in order to support cases where the user understands the mechanics of their flash device, and knows that a given combination of writes will work as intended. For example, a flash-without-erase command could allow a careful user to combine several program images on a single flash sector. * Some devices allow faster programming in blocks. Requiring vFlashWrite packets to appear in order of increasing address and requiring GDB to send a vFlashDone packet when all the data has been transmitted allow the stub to buffer data into blocks, and then write them when the buffer is full, or when all data has been transmitted.)