From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5833 invoked by alias); 24 May 2006 01:12:04 -0000 Received: (qmail 5687 invoked from network); 24 May 2006 01:11:52 -0000 Received: from unknown (202.80.33.51) by sourceware.org with QMTP; 24 May 2006 01:11:52 -0000 Received: (qmail 6330 invoked from network); 24 May 2006 01:11:48 -0000 X-Anti-Virus: Message scanned for viruses by TVL Received: from dsl2-modem31.tvl.vu (HELO [192.168.2.14]) ([202.80.43.31]) (envelope-sender ) by mail.vanuatu.com.vu (qmail-ldap-1.03) with SMTP for ; 24 May 2006 01:11:47 -0000 Message-ID: <4473B2D2.9000104@sakuraindustries.com> Date: Wed, 24 May 2006 02:03:00 -0000 From: Steven Johnson User-Agent: Mozilla Thunderbird 1.0.6-7.2.20060mdk (X11/20050322) MIME-Version: 1.0 To: Jim Blandy CC: gdb@sourceware.org Subject: Re: GDB support for Flash memory programming References: In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit 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-05/txt/msg00344.txt.bz2 Hi, I've been using GDB to debug programs (and load them with "load") in flash for a long time. What I do, isn't necessarily generic, but i thought it worth relaying given the current topic, my experience may be useful (or not). What I do is this: GDB has "pre" and "post" hooks to commands. If I want to flash load, what I do is this: Install a "Pre" hook on load. "define hook-load" something like this: # Set memory variables set $FLASH_BASE=0xFFF00000 set $RAM_BASE=0x00000000 set $FLASH_SIZE=(512*1024) define hook-load # Initialise the target so it is downloadable. # Macro which resets the target TARGET_RESET # Macro which sets the processor speed SET_SPEED # Macro which sets up the chip select logic SETUP_SRAM_AND_FLASH_CS # Macro which sets up sdram, so it can be used. SETUP_SDRAM # If flash contained stuff that you wanted to preserve, it could be "copy before over-write" with another stub command like this: # monitor memcopy $FLASH_BASE $RAM_BASE $FLASH_SIZE # so that anything not "loaded" over would be re-written back to the flash. # but we don't care, so we don't do it. # re-map memory, so a load to flash, goes to SDRAM monitor memremap $RAM_BASE $FLASH_BASE $FLASH_SIZE # Now any writes or reads to flash, by the remote protocol will be re-directed from # the flash base address to the ram base address, up to flash_size # for example, a write to 0xFFF00300 will be remaped by the stub to be a write to 0x00000300 # Set the size of the download packet for maximum performance. set download-write-size 1024 end So, before a "load" the montor (or target stub) is told to re-direct all writes and reads to flash to an area of ram, where it is safe to do so. The load then occurs, and the load can write to the flash area, but the target will actually put the data loaded, in ram, at a known location. Then I define a post-load hook, like this: define hookpost-load # Clear all memory remapping installed by the pre-hook. monitor resetmemremap # download a small flash burning stub (binary image) directly to address 0x100000 # This works, because my monitor is in the PC, and it uses JTAG to talk to the target # If the monitor was resident in the target, the flash burn stub could be part of # the monitor and this step could be skipped # for example, you could just call something like "monitor burn # bput is a command which allows the monitor to squirt an arbitrary binary image # anywhere into memory, we use it to do downloads when we don't want GDB to know # about them set remotetimeout 60 monitor bput utility/flashburn.bin 00100000 set remotetimeout 5 # Run the flash burn stub. By convention the first instruction of the stub # jumps to the stub code, and the second instruction of the stub is where # all execution will end. It makes it easier to call stubs this way, because # we can easily put a breakpoint on the end of the stub execution set $r0=$FLASH_BASE set $r1=$RAM_BASE set $r2=$FLASH_SIZE break *0x100004 jump *0x100000 clear *0x100004 # After this, the flash has been programmed with the contents of memory from address 0x00000000 # which was put there by the load. # Macro which causes a hardware reset of the target. TARGET_RESET end Then after the load has completed, the code to be loaded is in flash at the correct place, and because the code we are downloading here specifically is executed immediately after a hardware reset (its the boot code) the target is in the correct state. As far as GDB is concerned it just "loaded" the memory, which it did, but by these "hooks" we managed the process of burning the load into flash (transparently). Its a little clunky and requires some small custom commands to be added to the monitor stub (none of which are very difficult), but it works well is 100% reliable and is fast. Now if bput'ing and mem-remapping (or the like) became standard commands and gdb did it, instead of the stub, so much better. In my opinion that's all that's really required for a GDB generic approach, because, there are so many different targets with different flash programming requirements (different algorithms, 8, 16, 32 bit, etc.) that I'm not sure a fully "generic" approach is ever going to be very workable. At the very least, there is going to need to be different flash programming algorithms, and then GDB is going to have to be taught what ones are appropriate for a particular memory space on a particulat target, and it may have multiple different ones, etc.. With the method I describe here it doesn't matter, because the user provides a "flash burning stub" which takes care of it for the target in question. I have concerns about GDB "Burning" flash directly, because burning flash directly over a JTAG interface is (in my experience) orders of magnitude slower than burning from target ram to flash. Provided the target has available ram to do it, i would always prefer a load to ram, burn from there approach, because it is heaps faster, and speed matters (especially at load). no one wants to wait 10 minutes or more, every time they want to do a new "load" to test a bug. Anyway, I'm not evangelising this approach, its just what I do, and it works for me. Steven J Jim Blandy wrote: >One of the problems GDB has in the embedded development world is its >lack of support for loading programs into flash memory. After some >conversation amongst ourselves to weed out patently stupid stuff (none >of the text below is mine... hey), we at CodeSourcery put together the >following proposal for general comments and criticism. > >We'd like to reach consensus on what the user interface should be >before we worry about implementation details --- possible remote >protocol changes, and so on --- so let's leave those topics aside for >the time being. > >What do folks think? > >--- > >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. 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 modifying the flash accordingly. GDB must not modify >bytes outside of the program image itself. Therefore, if the program >image occupies only a portion of a flash sector, GDB is responsible >for arranging flash read/erase/write commands appropriately so as to >avoid changing unmodified portions of the sector. > >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. 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, like the assignment above. > > * 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. > > > >