Compare commits

...

207 Commits

Author SHA1 Message Date
David Brownell
56e74908d1 Label builds as OpenOCD v0.4.0
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-21 12:20:13 -08:00
David Brownell
4aa0a4d811 User's Guide mentions OS-specific installation
Specifically the Linux issue of needing "udev" rules, and MS-Windows
needing driver configuration.

Also, update the existing udev note to use the correct name of that
rules file in the source tree.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-21 09:29:24 -08:00
David Brownell
bb4cb7935e arm920t line length cleanup
The recent patch to fixbreakpoints and dcache handling added
a bunch of overlong lines (80+ chars) ... shrink them, and do
the same to a few lines which were already overlong.

Also add a few FIXME comments to nudge (a) replacement of some
magic numbers with opcode macros, which will be much better at
showing what's actually going on, and (b) correct return codes.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-20 20:47:38 -08:00
David Brownell
57d5673dea CSB337 board cleanup (quasi-regression)
Get rid of new nasty warning:

NOTE! Severe performance degradation without fast memory access enabled...

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-20 20:47:38 -08:00
David Brownell
d2a2c14d20 FreeBSD buildfix
Fix an unused variable warning seen when building the parport driver
under FreeBSD.

Using information from Xiaofan Chen <xiaofanc@gmail.com>

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-20 11:11:43 -08:00
Marc Pignat
3f30563c88 atm920t : fix breakpoints and data cache handling
Breakpoints did not work because the data cache was not flushed
properly.

As a bonus add capability to write to memory marked as read only
by the MMU, which allows software breakpoints in such memory
regions.
2010-02-19 08:18:12 +01:00
David Brownell
aa8db989b9 ARM920T scanchain 15 comments/cleanup
For folk who don't know the ARM920 JTAG interface very well, the
two modes of scan chain 15 access to CP15 are confusing.

Make those parts of the ARM920 code less opaque, by:

 - Adding comments referencing the relevant parts of the TRM,
   catching up to similar updates in the User's Guide.

 - Replacing magic numbers in physical access clients with
   symbolic equivalents.

No functional change.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-16 18:50:16 -08:00
Øyvind Harboe
fa1cfc2d4d gpl: fix GPL startup message
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-02-15 22:59:41 +01:00
David Brownell
5869992314 LPC1768.cfg -- partial fixes for bogus reset-init handler
Cortex-M targets don't support ARM instructions.

Leave the NVIC.VTOR setup alone, but comment how the whole
routine looks like one big bug...

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-15 13:39:16 -08:00
Mathias Kuester
52d4ba3467 fix crash with DSP563XX
When a DSP563xx-aware GDB asks OpenOCD for target registers,
the result should be a GDB with register data ... not an
OpenOCD crash.

(Note that mainline GDB doesn't currently support this core,
so for now, this requires a GDB with FreeScale patches.)

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-14 12:59:10 -08:00
David Brownell
a2ce3a51df NEWS: mention removal of obsolete commands
Removed remaining support for various commands, like advice for
migrating old-style TAP declarations.

The documentation no longer describes them either ... so if users have
been delaying config updates, they may need to consult older releases.

ALL this stuff has been clearly marked as "do not use" for at least a
year now, so anyone still using it hasn't been holding up their end.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-13 20:14:49 -08:00
David Brownell
4c4ec09110 Restore "-dev" version suffix (0.4.0-rc2-dev)
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-13 15:28:05 -08:00
David Brownell
a0a1be5cd6 v4.0-rc2 milestone
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-13 14:47:17 -08:00
Spencer Oliver
f7a6e62776 STR9xpec: issue warning when unlocking device
Issue warning to user when unlocking or writing the option bytes.
The new settings will not take effect until a target reset.

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-02-12 10:49:18 +00:00
Spencer Oliver
747a607aef STM32x: issue warning when unlocking device (bug #16)
Issue warning to user when unlocking or writing the option bytes.
The new settings will not take effect until a target reset.

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-02-12 10:49:11 +00:00
Øyvind Harboe
d4d4b11a77 arm720t: virt2phys callback added
This is a copy and paste of arm926ejs. Not tested, but
ready for testing at least. There is a good chance that
it will work if the generic armv4_5 fn's are robust enough...

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-02-12 08:39:56 +01:00
Marc Pignat
ff404da155 arm920: add virt2phys fn
Copy of the 926ejs function. I have tested it only using
my rtems application (where virtual address mapping == physical).

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-02-12 08:31:06 +01:00
Viktar Palstsiuk
32188c5004 target library: configuration files for openocd tested with Atmel SAM-ICE V6 JTAG.
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-02-11 21:10:51 +01:00
David Brownell
527e073bba User's Guide: "#" in filesystems names is bad
Sometimes MS-Windows users try to use filesystem names which include
the "#" character.  That's generally unwise, since it begins Tcl
comments.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-10 16:42:37 -08:00
Øyvind Harboe
65cc81ddb6 arm11: fix another infinite loop bug
reset init would get stuck in an infinite loop when
e.g. khz was too high. Added timeout. This is a copy
of paste of a number of such bugfixes in the arm11
code.

Arm11 code reviewed for further such infinite loop bugs
and I couldn't find any more. Xing fingers it's the last
one...

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-02-10 22:54:06 +01:00
David Brownell
84ac6bb0d9 User's Guide: clarify jtag_rclk advice
Not all cores and boards support adaptive clocking, so qualify
all advice to use it to depend on core and board support.

It's primarily ARM cores which support this; and many of the
newer ones (like Cortex-M series) don't.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-10 11:27:48 -08:00
Øyvind Harboe
c646b76797 target: add todo in target_write_memory() about alignment
target_write_buffer() does not align "buffer" in host
memory passed to target_write_memory().

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-02-09 21:57:23 +01:00
Spencer Oliver
f899c2aa97 str730.cfg: fix incorrect mem regions
- update str73x mem regions to correct values.

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-02-09 14:49:47 +00:00
David Brownell
885a2f5b96 Re-title Developer's Guide
The Doxygen output was previously titled "OpenOCD Reference Manual",
which was quite misleading ... the User's Guide is the reference
manual which folk should consult about how to use the software.

Just rename it to match how it's been discussed previously, and to
bring out its intended audience:  developers of this software.  As a
rule, Doxygen is only for folk who work with the code it documents.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-06 19:19:25 -08:00
David Brownell
6f262b69f4 ADIv5: doxygen
Provide doxygen for many of the public ADIv5 interfaces (i.e. the ones
called from Cortex core support code).

Add FIXMEs (and a TODO) to help resolve implementation issues which
became more apparent when trying to document this code:

 - Error-prone context-sensitivity (queued/nonqueued) in many procedures.

 - Procedures that lie by ignoring errors and wrongly claiming success.

Also, there was no point in a return from dap_ap_select(); it can't fail,
and no caller checks its return status.  Clean that up, make it void.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-06 19:16:21 -08:00
Øyvind Harboe
41d0901115 zy1000: complete zy1000_uart to jim command switch
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-02-05 14:38:26 +01:00
David Brownell
ff5deeeeaa ARMv7-M: make DAP commands verify target is an ARMv7-M
Init the ARMv7-M magic number.  Define predicate verifying it.
Use it to resolve a lurking bug/FIXME:  make sure the ARMv7-M
specific DAP ops reject non-ARMv7-M targets.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-04 14:39:51 -08:00
David Brownell
3ea9e62189 Documentation: mention bug database
Have the User's Guide and BUG handling notes both reference
the fact that we now have a bug database at SourceForge.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-04 11:10:15 -08:00
David Brownell
e380930478 JLink: reference protocol documentation
Segger publishes some documentation on this protocol;
reference it, so future maintainers can know it exists.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-04 10:50:24 -08:00
Spencer Oliver
709f08f17a CMD: duplicate cmd error msg
When registering cmds we report duplicate attempts to register a cmd
as a LOG_ERROR.
Some situations need this, such as when registering dual flash banks.
http://www.mail-archive.com/openocd-development@lists.berlios.de/msg11152.html

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-02-04 10:33:33 +00:00
Ethan Eade
8b049fdba5 scripts: Phytec/LPC2350 config scripts
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-02-04 10:25:44 +01:00
Spencer Oliver
95ed9c4393 JTAG: fix bug when no interface connected
- fix coredump when OpenOCD is started without a jtag interface connected.

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-02-03 13:09:24 +00:00
Harald Kipp
18969466c9 AT91R40008/Ethernut 3 configuration
Moved board specific settings from target/at91r40008.cfg to a new
file board/ethernut3.cfg.

Set correct CPUTAPID.  Reset delay increased, see MIC2775 data sheet.
Increased work area size from 16k to 128k.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-02 11:09:53 -08:00
David Brownell
5750e899e0 NOR: User's Guide updates
Remove long-obsolete text about "erase_check" affecting "flash info" output.
Move parts of that text to "protect_check", where it's still relevant; and
update the "flash info" description to mention the issue.

(This is still awkward.  It might be best to make "protect_check" mirror
"erase_check" by dumping what it finds, so "flash info" doesn't dump any
potentially-stale cache info.)

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-02 10:53:13 -08:00
Edgar Grimberg
cc440ca1d4 tcl/str7x: Reset init unlocks the flash
For STR7x flash, the device cannot be queried for the protect status.
The solution is to remove the protection on reset init. The driver
also initialises the sector protect field to unprotected.

[dbrownell@users.sourceforge.net: line length shrinkage]

Signed-off-by: Edgar Grimberg <edgar.grimberg@zylin.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-02 09:30:33 -08:00
Edgar Grimberg
503f6139c7 flash/str7x: After reset init the flash is unlocked
The default state of the STR7 flash after a reset init is unlocked.
The information in the flash driver now reflects this.

The information about the lock status cannot be read from the
flash chip, so the user is informed that flash info might not
contain accurate information.

[dbrownell@users.sourceforge.net: line length shrinkage]

Signed-off-by: Edgar Grimberg <edgar.grimberg@zylin.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-02-02 09:30:33 -08:00
Nicolas Pitre
3d2d5dcc9c ARM semihosting: fix EOF handling with SYS_READ
The semihosting interface has a strange convention for read/write where
the unused amount of buffer must be returned.  We failed to return the
total buffer size when the local read() call returned 0.

Signed-off-by: Nicolas Pitre <nico@marvell.com>
2010-02-02 00:05:42 -05:00
Edgar Grimberg
bef37ceba2 Test cases ran on v0.4.0-rc1
Test cases ran on v0.4.0-rc1 for a number of targets:
AT91FR40162
LPC2148
SAM7
STR710
STR912

The goal of the testing session was to prove basic functionality of OpenOCD for different targets.

Signed-off-by: Edgar Grimberg <edgar.grimberg@zylin.com>
2010-02-01 15:44:06 +01:00
Øyvind Harboe
91e3268737 gdb: restore behavior from 0.3.1 for srst_asserted and power_restore
srst_asserted and power_restore can now be overriden to do
nothing. By default they will "reset init" the targets and
halt gdb.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-02-01 13:45:09 +01:00
David Brownell
82f2492138 ADIv5: more messaging cleanup, docs
When the TAR cache was explicitly invalidated, don't bother
printing it; the actual hardware status is more informative.

Provide some doxygen for the MEM-AP setup routine.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-31 14:16:53 -08:00
Øyvind Harboe
02731cf78b build: fix problems with "struct stat" not being defined under eCos
Include <sys/stat.h> according to
http://www.opengroup.org/onlinepubs/000095399/functions/stat.html

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-31 15:48:14 +01:00
Øyvind Harboe
f68dff6690 telnet: fix strage blank spaces at beginning of telnet lines
Sometimes we saw two strange blank spaces at the beginning
of the telnet lines.

progress
  ogress
>

This patch fixes this problem:

progress
progress
>

The code changes are *reasonably* clean, but perhaps it could be
made a bit more elegant, but I didn't want to change things after
I finished diagnosis/testing & submitting the patch.

The problem was that logging can send the text and the newline
separately in two different requests and the telnet code would
incorrectly remove the prompt from the end of a line.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-31 15:06:02 +01:00
David Brownell
e11ce3e6b0 Subject: ADIv5: fix more diagnostics
If the MEM-AP cache is invalid, don't display it; just report that
invalidity as an error.  (This bug has been observed with "mdw 0 32"
after just a "reset halt".  Some code is being wrongly bypassed...)

If it's valid, display that cache at DEBUG level, not ERROR.  Also,
don't assume it's an AHB-AP; it could be another flavor of MEM-AP.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-31 00:26:21 -08:00
David Brownell
695666d294 ADIv5 error checking for Tcl commands
Reject invalid AP numbers (256+) as Tcl operation parameters.
Shrink one of the overlong lines.

Add my copyright to the ADIv5 code (multiple contributions).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-30 22:46:00 -08:00
David Brownell
46b6d5bfe6 ARM ADIv5: fix diagnostics for block writes
They were reporting "read" errors, not "write" errors.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-30 18:08:19 -08:00
David Brownell
3d3128a8f5 ADIv5: cleanup, rename swjdp_transaction_endcheck()
Make messages reference "DAP" if they're actually transport-agnostic, or
"JTAG-DP" when they're JTAG-specific.  Saying SWJ-DP is often wrong (on
most Cortex-A8 chips) and is confusing even if correct (since we don't
yet support SWD).

Rename a JTAG-specific routine to jtagdp_transaction_endcheck() to highlight
that it's JTAG-specific, and that identify DAP clients undesirably depending
on JTAG.  (They will all need to change for SWD support.)

Shrink a few overlong lines of code.  Copy a comment from code removed
in a previous patch (for the ARMv7-M "dap baseaddr" command).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-29 14:31:19 -08:00
David Brownell
2248c387f2 ARMv7-M: use command handler for "dap baseaddr".
Make the ARMv7-M DAP code reuse the command handler for "dap baseaddr".
For some reason, this DAP command wasn't converted earlier.

This is a code shrink and simplification; it also removes a needless
transport dependency on JTAG.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-29 14:16:14 -08:00
David Brownell
303b493c22 NOR: cleanup driver decls
Fix goofy struct indents.  Function names *are* their addresses.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-29 13:52:08 -08:00
Alex Austin
cd3017cffa Clang buildfixes
Building with clang took a few very small changes. The change to
helper/log.h is because clang doesn't like an expression where the
result is unused. In helper/system.h, I just defined true and false
since clang doesn't have them builtin.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-29 00:02:12 -08:00
David Brownell
804c0b2ad3 doc clarifications for server flags
The "-f" is a shortcut for "-c" ... and providing any "-c" options
means the "openocd.cfg" file isn't implicitly used.  Both the User's
Guide and the manual page were weak on these points, which has led
to some confusion.

Also update the manual page to include highlights of the search path
mechanism, including the facts that it exists and that "-s" adds to it.
Stop saying only the current directory is involved; the OpenOCD
script library is quite significant.

(Missing: complete manpage coverage of the search path, including a
FILES section listing all components and saying where the script
library is found.)

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-28 14:03:29 -08:00
David Brownell
5dcf7898f6 ARM: reference DPM defn from v6/v7 arch spec
The term "DPM" is probably not well known ("Device Power Management"?),
so identify its source in the current ARM architecture specification.
It's relevant to ARMv6, ARMv7-A, and ARMv7-R ... but not "M" profiles.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-28 13:58:20 -08:00
Spencer Oliver
75cfda4cd1 ARM semihosting: win32 and cygwin fixes
Cygwin would fail to reopen a previously written file if the mode is
not given.

Simplified converting the open flags and made sure the win32 O_BINARY
bit is set.

Added define for systems that do not support O_BINARY.

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-01-28 21:05:09 +00:00
Spencer Oliver
465a06dfdc ARM semihosting: fix writing to stdout
SYS_FLEN would be called before a write on a descriptor to check its size.
Currently lseek would fail with -1 when given the stdout/stderr descriptor.
Changing to use fstat seems to be the standard way of handling this.

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-01-28 20:21:31 +00:00
David Brownell
3172be80a3 Cortex-M3: report lockup, and recover
ARMv7-M defines a "lockup" state that's entered in certain double
fault sequences which can't be recovered from without external help.
OpenOCD has previously ignored this.

Issue a diagnostic saying the chip has locked up, and force exit
from this state by halting the core.  It's not clear this is the
best way to handle lockup; but there should now be less confusion.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-27 13:47:48 -08:00
David Brownell
d44f1aaeff ARM ADIv5: messaging tweaks
Add space missing after the invalid ACK value.  On init, say
which AP is being used, and don't assume it's an AHP-AP.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-27 13:40:05 -08:00
David Brownell
2b5c444a32 Cortex-A8: debug messaging tweaks
Make that "TODO" message say what needs to be done.
Say what part of examining failed.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-27 13:24:21 -08:00
David Brownell
30365886da various: don't mention wiki
The openfacts.berlios wiki isn't particularly current, and isn't
publicly editable.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-26 18:13:10 -08:00
David Brownell
9e52957efc cygwin buildfix
isspace() parameter must be an integer, else a 'char' gets
used as an array index (sigh).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-26 17:54:49 -08:00
simon qian
33fc60befc SVF: all content between parentheses is one parameter
More SVF fixes:

 * Treat all content between parentheses as part of the same
   parameter; don't (wrongly) treat whitespace as a delimiter.

 * Use isspace() to catch that whitespace; it's not all single
   spaces, newlines etc are also valid.

 * When parsing bitstrings, strip leading whitespace too.

So for example, these are equivalent and should (now) be OK:

  "TDI( 1234 )"
  "TDI( 1 2 3 4 )"
  "TDI(00 12 34 )"
  "TDI(
  	00 12
	34)"

[dbrownell@users.sourceforge.net: comment updates; trivial cleanup]

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-25 13:06:46 -08:00
Edgar Grimberg
1dad2ee602 core arm11: Silence logs at level 3 if there is no activity
If the target and openocd are idling, the log should normally
be silent at level 3.  (Given no verbose logging options.)

Signed-off-by: Edgar Grimberg <edgar.grimberg@zylin.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-25 12:19:52 -08:00
simon qian
9ff16575d2 SVF: insert space before '(' and after ')'
See http://forum.sparkfun.com/viewtopic.php?p=90983#90983 for discussion;
basically, the SVF parser wrongly expects "TDI (123)" but the space is
optional and it should accept "TDI(123)" too.

In the same way, "TDI(123)TDO(456)" should work too.

Rather than update the command parsing, this just makes sure the expected
spaces are present.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-23 14:24:10 -08:00
David Brownell
718ee762e7 EmbeddedICE - fix Feroceon/Dragonite message
The breakpoint/watchpoint message was wrong for Feroceon and
Dragonite, which have only one working watchpoint unit.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-22 22:54:39 -08:00
David Brownell
82c3c47825 NEWS updates
Summarize most ARM11 and Cortex-A8 updates as "acting much more
like other ARMs", and mention code sharing.

Clarify a few other points, including support for "reset-assert"
on all ARMs except Cortex-M (which doesn't exactly need it).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-22 22:49:42 -08:00
David Brownell
b7fa16eeac ARM11: fix breakpoints with GDB
This fixes a bug whereby GDB's breakpoints weren't activated.
The root cause is a confused interface to resume().  Fix by
almost ignoring the "handle breakpoints" parameter; it only
seems related to the case of skipping breakpoint-at-PC.

Update a few coments to clarify what's happening.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-22 22:37:15 -08:00
David Brownell
4960c9018f Various doc/comment updates
Doxygen: don't be needlessly verbose; alphabetically sort members
TODO: add random bits; clarify which manuals are referenced
ARM disassembler: mention a few opcodes that still aren't handled

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-21 16:45:00 -08:00
David Brownell
08b0be94b5 User's Guide secton on target hardware setup
Highlight the needs to properly jumper development boards; to
make the OpenOCD configuration match the jumpering; and to have
a usable "reset-init" method when debugging early boot code.

Specific mention of the "ATX Mode" that seems useful on
many i.MX boards, forcing NAND boot.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-21 16:15:41 -08:00
David Brownell
f06148612b ADIv5 header cleanup (+ #defines)
Update the comments about DP registers and some of the bitfields.
Remove inappropriate (and unused) DP_ZERO declaration.

Add some (currently unused) #defines needed for SWD protocol support,
based on previous patches from Andreas Fritiofson and Simon Qian.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-21 13:39:22 -08:00
Øyvind Harboe
98f7c2127b target: print reason why GDB halts
If GDB halts unexpectedly, print reason: srst assert or power
out detected.

If polling fails, then things are a bit trickier. We do not
want to spam telnet or the log with polling failed messages.
Leave that case be w/a comment in a code for now.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-21 16:20:58 +01:00
Edgar Grimberg
dfba7fa949 interface: Changed parport address to LPT1
Changed the parport address to LPT1, since it's the most obvious default value.

Signed-off-by: Edgar Grimberg <edgar.grimberg@zylin.com>
2010-01-21 15:58:59 +01:00
Edgar Grimberg
bc088b302b target: Fixed format problem for mdh
Fixed format problem for mdh. It needs to display 4 chars.

Signed-off-by: Edgar Grimberg <edgar.grimberg@zylin.com>
2010-01-21 15:58:59 +01:00
Øyvind Harboe
1350b6aad0 gdb_server: handle stepi/continue packet while target is running with more grace
Rather than issuing a halt and then stepi/resume, just
wait for target to halt.

Issue a sterner warning via gdb console that any gdb
register changes will be ignored in this case.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-21 15:57:30 +01:00
Øyvind Harboe
60cb5bdd30 ecos: add missing PRId8 definition
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-21 08:11:39 +01:00
Spencer Oliver
dbecb13b24 BUILD: remove cygwin gcc 3.4.4 build warnings
Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-01-20 23:11:25 +00:00
David Brownell
2a0c9b08d7 Cortex-M3 vector_catch testing support
The "cm3-ftest.cfg" can be used to verify that OpenOCD handles
certain faults correctly:

 - Test #1: it ignores faults that it wasn't told to catch
 - Test #2: if vector_catch is told to catch, it catches

The "fault.c" generates ASM code to trigger faults, while the
config script loads and runs pre-compiled code.

This covers most, but not all, of the vector_catch options.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-20 11:07:42 -08:00
David Brownell
22d25e6921 board configs -- unique names for flash chips
Don't give the same names to both flash chips on two OMAP boards.

For OSK, enable DCC downloads (removing a warning).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-20 10:46:53 -08:00
David Brownell
6f2b88448f gdb_server: correctly report flash sector sizes
Report each region of same-size sectors separately, instead of
incorrectly reporting that every sector has the same size.

This is a longstanding bug on NOR flash chips with non-uniform
sector sizes.  It was largely hidden by other bugs in flash
handling.  When some of those were recently fixed, this one was
exposed as a regression on str710.

[oyvind.harboe@zylin.com: update the loop to behave on str7 ]

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-20 10:43:32 -08:00
Michael Grzeschik
d036f17001 tcl/target/at91sam3u4e.cfg: changed case in dependent file
openocd does not start with the target configfile due to the case in the
dependent config file.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-20 10:32:53 -08:00
Øyvind Harboe
87cb29dcfe testing: fix str710 test case now builds
Make the test case easily adjustable in size. str710
has very peculiar flash sector layout, nice for testing,
but a larget test_rom.elf is required.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-20 15:12:31 +01:00
Øyvind Harboe
ff976cdb29 arm7/9: add nags upon reset about options to improve performance
arm7_9 fast_memory_access and working area nags added.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-20 14:51:17 +01:00
Spencer Oliver
0c3a4b4d81 ARMV7M: handle bkpt instruction on resume/step
Skip over a bkpt instruction if found on resume/step.
Only software breakpoints known to OpenOCD are currently handled.

So this handles the special case of either a user added bkpt
or library added, eg. semi-hosting support.

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-01-20 09:07:55 +00:00
David Brownell
20d1ef70e8 User's guide: mention lpc2000 checksum issue
Folk almost certainly want to have OpenOCD compute the checksum
when they modify the vector table.  However, that almost guarantees
that "verify_image" will fail.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-20 00:04:17 -08:00
David Brownell
44aaba3d08 gdb_server -- subroutinize memory map logic
Put the memory map logic into its own subroutine.
This will make it a bit easier to package bugfixes,
and simplifies the query packet handling.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-19 23:32:54 -08:00
David Brownell
bf1e9a83c8 gdb_server -- symbol cleanup
Make most methods static; net minor object code shrink.
Likewise various data symbols; no net change.
Shrink some overlong lines.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-19 23:30:36 -08:00
Andreas Fritiofson
4f310aa0c9 update win32 script search path
The default script search path on Windows is out of date with
the current layout (from installation and documentation), which
makes the standard script library not be found after a normal

	./configure && make && make install

under msys/MinGW. The same should hold true for cygwin native builds
(not verified).

Update search path to ../share/openocd/scripts not ../lib/openocd,
relative to the openocd executable.

Signed-off-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-19 15:02:15 -08:00
David Brownell
fb4239866c NOR: fix diagnostic
The "NOR: last_addr also needs correction when checking alignment"
patch omitted a necessary update to the key diagnostic; fix.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-19 13:56:33 -08:00
Øyvind Harboe
924bf27596 zy1000: flush jtag buffer before changing speed
It is conceivable that there could be commands in the
queue when a speed change request comes in. Flush the
hw queue before changing speed. Not observed, found by
inspection.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-19 10:58:48 +01:00
Øyvind Harboe
c795b0d8f1 zy1000: print out PCB revision upon boot
Simplify debugging a bit.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-19 10:58:48 +01:00
Øyvind Harboe
cdcb9b0885 flash: add error messages upon incorrect arguments to flash iteration
According to OpenOCD error handling rules the error is
logged at where it occurs(same site where an exception
would have been thrown).

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-19 10:58:48 +01:00
David Brownell
5ab34b28ce vsllink -- add comment
Previous patch deserved *inline* comment, not just
in git revision history.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-18 13:18:33 -08:00
Øyvind Harboe
56d2c86500 commands: allow scan_chain command to be executed during config
Adding taps and then dumping them is quite reasonable thing
to do in a config script.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-18 21:42:34 +01:00
simon qian
0b641dac71 read target voltage first in vsllink
The very first command after init command should be "read target voltage".

This is a tweak for the Old Versaloon firmware.  Without this, in most
most cases, it works.   Under Ubuntu9.04, there is a chance that the USB
will fail.  The problem disappears if I read target voltage first.

For the lastest Versaloon firmware, it's OK.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-17 23:37:15 -08:00
richard vegh
daa1ff3535 NAND: lpc3180 crashes on LPC3250
The LPC3180 NAND driver was crashing on some large page chips.
Fix:

 - Crash and related functionality (don't memset too much OOB data)
 - Some debug messages
 - Command handling now works

[dbrownell@users.sourceforge.net: whitespace/linelength/message cleanup]

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-16 12:27:45 -08:00
David Brownell
183765707f ADIv5 improved diagnostic
Don't just complain about an invalid ACK; say what the
value was, to help troubleshooting.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-15 13:02:45 -08:00
David Brownell
6c4a643d63 ARM DPM: disable some nyet-ready breakpoint code
Until we manage breakpoints at runtime (patches not ready for 0.4)
the only way this code should touch them is to disable them at server
startup (a previous debug session may have left them active).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-15 12:53:26 -08:00
David Brownell
187ccb60ee NEWS: include s3c64xx NAND driver
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-15 09:36:01 -08:00
David Brownell
0f7cea2847 jtag.h whitespace/comment cleanup
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-14 14:38:24 -08:00
David Brownell
8e1b5c3138 ARM ADIv5: add comments
Add doxygen and other comments for what's more or less the lowest
level JDAG-DP primitive, to access JTAG_DP_{A,D}PACC registers.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-14 12:58:39 -08:00
David Brownell
1d140c4dcd ARM7/ARM9: improved reset support
Teach most remaining ARM cores how to use the "reset-assert" event.

Same model as elsewhere:  iff a handler is provided for that event,
use that instead of trying to assert SRST (which may be unavailable,
or inappropriate since it resets too much).  Else no change.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-14 12:46:33 -08:00
Peter Korsgaard
000a1cfd01 nand flash support for s3c64xx
Identical to the existing 2412/2443 support except for the base address
and NFCONF value (bit 2 is reserved and should be written as 1 ref UM).

Tested on a s3c6410 board, but controller is identical in 6400/6410
except for 8bit MLC ECC support in 6410 which isn't supported by the
driver.

Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-14 21:07:46 +01:00
Laurentiu Cocanu
24653c950a str9x.c: remove optimization when erasing the whole bank
Using the erase bank command will cause a time out error. Replacing
this with the erase sector bank will provide a slower but safer and
stable method to erase the flash.

Signed-off-by: Laurentiu Cocanu <laurentiu.cocanu@zylin.com>
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-14 15:07:24 +01:00
David Brownell
e1679a29f0 ARM7/9 minor cleanups
Shrink some overlong lines.  Add my 2009 copyright.
Move a declaration to the beginning of its block.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-14 03:16:07 -08:00
Spencer Oliver
e2d3266ff1 GDB: change gdb_breakpoint_override to COMMAND_ANY
- enable gdb_breakpoint_override to be used within config script.

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-01-14 09:35:33 +00:00
David Brownell
b60dd35e33 User's Guide updates
Capture various bits of useful information that have come up on the
list but haven't yet gotten into the documentation:

 - Watchdog timers firing during JTAG debug need attention;

 - Some chips have special registers to help JTAG debug;

 - Cortex-M3 stepping example with IRQs and maskisr;

 - Clarifications re adaptive clocking:  not all ARMs do it, and
   explain it a bit better.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-13 23:33:53 -08:00
David Brownell
73566405b6 NOR: add optional "flash erase_address" sector padding
Add a NOR flash mechanism where erase_address ranges can be padded
out to sector boundaries, triggering a diagnostic:

  > flash erase_address 0x0001f980 16
  address range 0x0001f980 .. 0x0001f98f is not sector-aligned
  Command handler execution failed
  in procedure 'flash' called at file "command.c", line 647
  called at file "command.c", line 361
  >

  > flash erase_address pad 0x0001f980 16
  Adding extra erase range, 0x0001f800 to 0x0001f97f
  Adding extra erase range, 0x0001f990 to 0x0001fbff
  erased address 0x0001f980 (length 16) in 0.095975s (0.163 kb/s)
  >

This addresses what would otherwise be something of a functional
regression.  An earlier version of the interface had a dangerous
problem:  it would silently erase data outside the range it was
told to erase.  Fixing that bug turned up some folk who relied on
that unsafe behavior.  (The classic problem with interface bugs!)
Now they can get that behavior again.  If they really need it,
just specify "pad".

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-13 23:33:25 -08:00
David Brownell
d91941d5a0 Cortex-M3: improved core exception handling
This updates three aspects of debugger/exception interactions:

 - Save the user's "vector_catch" setting, and restore it after reset.
   Previously, it was obliterated (rather annoyingly) each time.

 - Don't catch BusFault and HardFault exceptions unless the user says
   to do so.  Target firmware may need to handle them.

 - Don't modify SHCSR to prevent escalating BusFault to HardFault.
   Target firmware may expect to handle it as a HardFault.

Those simplifications fix several bugs.  In one annoying case, OpenOCD
would cause the target to lock up on ome faults which triggered after
the debugger disconnected.

NOTE:  a known remaining issue is that OpenOCD can still leave DEMCR
set after an otherwise-clean OpenOCD shutdown.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-13 03:17:23 -08:00
Øyvind Harboe
b8e930e3bf arm7/9: enable check that DCC downloads have been enabled
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-13 12:00:02 +01:00
Øyvind Harboe
ee519ab356 arm7/9: add fn to check if dcc downloads have been enabled
DCC downloads should be enabled for any self repecting
openocd config file for arm7/9. Print out note about
it otherwise.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-13 12:00:02 +01:00
Øyvind Harboe
dc793455e9 target: add check_reset hook
Allow targets to run checks post reset. Used to check
that e.g. DCC downloads have been enabled.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-13 12:00:02 +01:00
Øyvind Harboe
3e33393078 gdbserver: fix typo that broke read/write watchpoint
It looks like a bugfix from normal breakpoints was not
copied over.

Do not use clever mathematics and assumptions to convert from
GDB enum for break/watchpoints to OpenOCD enum.

Drop connection upon unknown breakpoint type, this code path
was not really considered by the previous code I think.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-13 12:00:02 +01:00
Øyvind Harboe
6c75f5249c debug: make logging of commands terser
one line / command instead of one line per argument.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-13 08:32:15 +01:00
David Brownell
b4a4d5c731 ARM: bugfix for "movt" disassembly
Use the correct bitfield to specify the register whose
top halfword gets replaced.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-12 12:40:39 -08:00
Vladimir Zapolskiy
1de107a5a2 Added Openmoko USB JTAG interface config file.
Added interface config file for JTAG/RS232 debug board originally
integrated to Neo 1973 and Neo FreeRunner phones.
Adapter was tested with i.MX31, S3C2410 and AT91SAM9260 processors.

Signed-off-by: Vladimir Zapolskiy <vzapolskiy@gmail.com>
2010-01-11 15:58:13 +01:00
Øyvind Harboe
e5349bfb49 target: return JIM_OK instead of ERROR_OK
No change in actual binary as JIM_OK == ERROR_OK,
but JIM_OK is correct here.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-11 15:01:02 +01:00
Øyvind Harboe
fb71a0a0dd reset: better error messages
Use correct tcl syntax to throw exception.

the syntax is "return -code error" not "return -error"

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-11 12:58:06 +01:00
Øyvind Harboe
6d8604de37 commands: make error messages a bit more terse
we don't need to know the build path of command.c when
reading normal user level error messages.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-11 12:58:06 +01:00
Øyvind Harboe
c74ca40e09 zy1000: reset bugfix
flush JTAG FIFO before reset. Fixes RCLK problems observed
w/lpc2148, but really fixes a wider range of problems.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-11 10:25:13 +01:00
David Brownell
8c730aaee2 Doxygen file comments
Add file comments to a few files.  Make the GDB server use
more conventional (pointer-free) hex digit conversion.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-11 00:16:57 -08:00
Øyvind Harboe
88907cc7f9 shutdown: more graceful shutdown
Shutdown is not an error condition, do not return error
from main.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-11 08:13:17 +01:00
Spencer Oliver
d746dee833 build: doxygen build
- Fix for building doxygen out of tree

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-01-10 21:00:48 +00:00
David Brownell
c8267930c7 FreeBSD build fixes
Based on notes from Tomek Cedro <tomek.cedro@gmail.com> and
Steve Franks <bahamasfranks@gmail.com>.

In the User's Guide, sort the list of operating systems reported
through Tcl with $ocd_HOSTOS ... and include FreeBSD.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-10 10:06:58 -08:00
David Brownell
5e221fa3a7 Presto: doxygen fix
Newline needed.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-09 22:24:43 -08:00
David Brownell
ab4307e693 jtag/tcl help/usage fixups
The usual: expand several helptexts to be more correct and to use
full sentences; make the usage messages use the same EBNF as the
User's Guide; use function names for their addresses.

Also add a comment about that odd jtag_command_handlers_to_move[] thing.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-09 22:15:57 -08:00
David Brownell
5cb1dcfad3 ZY1000 help/usage fixups
The usual:  same EBNF as in the User's Guide, full sentence helptext,
function names *are* their addresses.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-09 22:14:08 -08:00
David Brownell
0811f6b192 jtag: presto, parport help/usage updates
Presto: add doxygen file comment.

Parport: note a couple gaps in layout config.

Both: use the uniform EBNF for usage, bugfix helptexts, use function
name as its address not "&name".

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-09 22:09:08 -08:00
David Brownell
ad5fd39063 jtag/gw16012 usage/help updates
Use standard BNF.  Improve/correct helptext for its "parport_port"
command.  Function address is just its name.
2010-01-09 22:05:55 -08:00
David Brownell
ff647e6bb4 parport (mostly) doc fixes
The "parport_port" commands generally don't *require* a port_number;
they're of the "apply any parameter, then print result" variety.  Update
the User's Guide accordingly.

Some of those commands are intended to be write-once: parport_port,
and parport_cable.  Say so.

Use proper EBNF for the parport_write_on_exit parameter.

Parport address 0xc8b8 is evidently mutant.  Say so in the "parport.cfg"
file, to avoid breaking anyone with that mutant config.  But update the
User's Guide to include a sane example for the LP2 port.

Finally document the "presto_serial" command.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-09 21:56:11 -08:00
David Brownell
1dd5277ba3 src/helper: usage/help updates
Make "usage" messages use the same EBNF as the User's Guide;
no angle brackets.  Improve and correct various helptexts.

Don't use "&function"; a function's name is its address.
Fix some whitespace glitches, shrink a few overlong lines.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-09 13:32:08 -08:00
David Brownell
1c5c57ec8e src/flash/nor: usage/help/doc updates
Make "usage" messages use the same EBNF as the User's Guide;
no angle brackets.  Improve and correct various helptexts.

Don't use "&function"; a function's name is its address.
Remove a couple instances of pointless whitespace; shrink a
few overlong lines; fix some bad indents.

Add TODO list entry re full support for NAND/NOR bank names.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-09 10:25:03 -08:00
Spencer Oliver
70738bd75d MIPS: update arch_info access to match other targets
- add target_to_mips32 and target_to_m4k to match test of codebase.
 - mips32_arch_state now shows if processer is running mips16e isa.

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-01-09 13:37:02 +00:00
David Brownell
fc9a2d0e6f src/server: usage/help/doc updates
Make "usage" messages use the same EBNF as the User's Guide;
no angle brackets.  Improve and correct various helptexts.

Specifically for the port commands, clarify that the number
is optional, and omitting it causes the current number to be
displayed.

Don't use "&function"; a function's name is its address.
Remove a couple instances of pointless whitespace; shrink a
few overlong lines.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-09 00:55:41 -08:00
Masaki Muranaka
aafd3877e6 buildfix on MacOS
Recent Apple gcc versions use __APPLE__ instead of __DARWIN__; accept
that too.

Also use #warning, not #warn; neither is standard, but most CPP versions
require it to be spelled out.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-09 00:10:18 -08:00
David Brownell
973cd9a299 PLD: usage/help updates
Make "usage" messages use the same EBNF as the User's Guide;
no angle brackets.  Improve and correct various helptexts.

Don't use "&function"; a function's name is its address.
Remove a couple instances of pointless whitespace, shrink
a few overlong lines.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-08 23:23:55 -08:00
David Brownell
2a76c1bcf9 NAND: help/usage/doc updates
Usage messages should use the same EBNF as the User's Guide;
no angle brackets.  Be more complete too ... some params were
missing.  Improve and correct various helptexts.

Make user's guide refer to the NAND "driver" name, not the
controller name; that's a bit more precise.

Don't use "&function"; its name is its address.  Line up struct
initializers properly.  Remove some blank lines.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-08 23:18:46 -08:00
David Brownell
ae71005929 Doc/examples: clarify usage messages
Update/bugfix the "hello" example; emphasize using EBNF syntax,
matching the User's Guide.  Correct the Texinfo style guide to
say EBNF, not BNF.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-08 23:13:39 -08:00
David Brownell
b800eb0336 *SVF: help/usage updates
Usage messages should use the same EBNF as the User's Guide;
no angle brackets.  Be more complete too ... some params were
missing.

Don't use "&function"; its name is its address.

Unrelated: fix typo in one "target.c" usage message.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-08 20:16:05 -08:00
David Brownell
1a2c258ed4 MFLASH: help/usage updates
Make "usage" messages use the same EBNF as the User's Guide;
no angle brackets.  Improve and correct various helptexts.

Don't use "&function"; a function's name is its address.
Remove a couple instances of pointless whitespace.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-08 20:12:18 -08:00
David Brownell
c1cb20971e Coexist with quilt: rename PATCHES --> PATCHES.txt
The issues is on Win32, which ignores case in filesystem
and thus doesn't tolerate the quilt "patches" directory.

Rename, and add "patches" to .gitignore so that developers
can choose to use quilt for local patch management.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-08 17:20:47 -08:00
David Brownell
296a011db5 NOR: add FIXMEs for writing ones
It can invalidate ECC codes, and in general is not guaranteed
to work.  (However on some chips it _appears_ to behave.)  Just
don't do it; don't write in those cases.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-08 16:47:58 -08:00
David Brownell
12c143d594 misc ARM help/usage updates
Usage syntax messages have the same EBNF as the User's Guide;
there should be no angle brackets in either place.

Uupdate some helptext to be more accurate.

Don't use "&function"; functions are like arrays, their address
is their name.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-07 16:41:42 -08:00
David Brownell
82c0fb5277 ARM966: help/usage updates
Usage syntax messages have the same EBNF as the User's Guide;
there should be no angle brackets in either place.

Fix the User's Guide to say where the magic CP15 bits are defined;
and add comments in case someone provides mcr/mrc methods.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-07 16:39:32 -08:00
David Brownell
e7965cd3eb Xscale: User's Guide updates
Fix some EBNF goofs ... these commands have *optional* params, etc

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-07 16:34:44 -08:00
David Brownell
a42bea654c ARM720: help/usage updates
Deprecate the "pass an instruction opcode" flavor of cp15
access in favor of the "arm mcr ..." and "arm mrc ..."
commands, which offer fewer ways to break things.

Use the same EBNF syntax in the code as for the user's guide.

Update User's Guide to say where to find those magic values
(which table in the ARM920 TRM).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-07 16:30:09 -08:00
David Brownell
e0b6e5deef ARM720: help/usage updates
Deprecate the "pass an instruction opcode" flavor of cp15 access
in favor of the "arm mcr ..." and "arm mrc ..." commands, which
offer fewer ways to break things.

Use the same EBNF syntax in the code as for the user's guide.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-07 16:25:03 -08:00
David Brownell
199abf49ea ARM11: help/usage updates
Usage syntax messages have the same EBNF as the User's Guide;
there should be no angle brackets in either place.

Uupdate some helptext to be more accurate.

Fix the User's Guide in a few places to be more consistent (mostly
to use brackets not parentheses) and to recognize that parameter may
be entirely optional (in which case the command just displays output,
and changes nothing).  Also reference NXP, not Philips, for LPC chips.

Don't use "&function"; functions are like arrays, their address
is their name.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-07 16:21:24 -08:00
David Brownell
48d51e1719 ARM7/ARM9: help/usage updates
Provide helptext which was sometimes missing; update some of it
to be more accurate.

Usage syntax messages have the same EBNF as the User's Guide;
there should be no angle brackets in either place.

Fix the User's Guide in a few places to be more consistent (mostly
to use brackets not parentheses) and to recognize that parameter may
be entirely optional (in which case the command just displays output,
and changes nothing).  Also reference NXP, not Philips, for LPC chips.

Don't use "&function"; functions are like arrays, their address
is their name.  Shrink some overlong lines.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-07 16:20:14 -08:00
David Brownell
17921f51ab ARMv7: help/usage updates
Provide helptext which was sometimes missing; update some of it
to be more accurate.

Usage syntax messages have the same EBNF as the User's Guide;
there should be no angle brackets in either place.

Don't use "&function"; functions are like arrays, their address
is their name.  Shrink some overlong lines, remove some empties.

Add a couple comments about things that should change:  those
extra TCK cycles for MEM-AP reads are in the wrong place (that
might explain some problems we've seen); the DAP command tables
should be shared, not copied.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-07 16:18:01 -08:00
David Brownell
e19fe9ad09 ARM ETM/ETB/trace: help/usage updates
Provide helptext which was sometimes missing; update some of it
to be more accurate.

Usage syntax messages have the same EBNF as the User's Guide;
no angle brackets in either place.

Don't use "&function"; functions are like arrays, their address
is their name.  Shrink some overlong lines, remove some empties.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-07 15:22:41 -08:00
David Brownell
dd8f679aa2 target misc: help/usage updates
Provide helptext which was sometimes missing; update some of it
to be more accurate.

Usage syntax messages have the same EBNF as the User's Guide.

Don't use "&function"; functions are like arrays, their address
is their name.  Shrink some overlong lines; remove some empties.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-07 15:05:26 -08:00
David Brownell
7c3aee96b2 XScale: help/usage updates
Provide helptext which was sometimes missing; update some of it
to be more accurate (mostly they display something w/no args).

Usage syntax messages have the same EBNF as the User's Guide.
In some cases, *exactly* what the user's guide shows... e.g.
talking about "offset" not "address" for trace_image.

Don't use "&function"; functions are like arrays, their name
is their address.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-07 14:51:59 -08:00
Spencer Oliver
991d030fcc MIPS: change bulk_write_memory fallback msg to LOG_DEBUG
Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-01-07 22:39:35 +00:00
Spencer Oliver
c68c2751f3 MIPS: whitespace cleanup
Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-01-07 20:56:07 +00:00
Spencer Oliver
2d450b9033 MIPS: fastdata bulk write fallback
If fastdata access fails, then fallback to default mips_m4k_write_memory
Remove unnecessary fastdata loader verify check

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-01-06 20:24:31 +00:00
David Brownell
2bc7446bb8 buildfix with -DNDEBUG
Don't save that state unless its only user, an assertion,
is compiled.  Saving it broke a cygwin build.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-05 14:11:03 -08:00
David Brownell
844b5eb49d don't require 'openocd.cfg' to start
Starting the daemon with with just a bare "openocd" I saw:

	Can't find openocd.cfg

That's not an error; don't treat it as if it were.  There may
be an error later -- like, "no interface set up" -- but let
messages only report real errors, not fake ones.
2010-01-05 13:32:39 -08:00
David Brownell
fccb812f82 ARM: add #defines for JTAG ack codes
JTAG has only two possible JTAG ack codes for APACC and DPACC
register reads/writes.  Define them, and remove empty "else"
clause in the code which now uses those codes.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-05 13:03:27 -08:00
David Brownell
adf2a9a267 ARM: add comments re DAP assumptions
I think some of these assumptions are not well-founded.
Related, that swjdp_transaction_endcheck() is a bit iffy.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-05 12:55:46 -08:00
Spencer Oliver
9d83df72dc MIPS: pracc access tweaks
reorder the pracc access so we can save a few access cycles

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-01-05 19:54:37 +00:00
Spencer Oliver
ba96fc3e9d PIC32: enable ram execution
add reset-init script to allow ram execution from reset, this is required for ejtag fastdata access.

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-01-05 19:54:37 +00:00
Spencer Oliver
f6412d9c7b MIPS: optimize pracc access
remove unnecessary nops when accessing ejtag pracc
general fastdata patch cleanup

Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-01-05 19:54:36 +00:00
Spencer Oliver
faad9e5923 parport: output port as hex rather than dec
Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-01-05 19:54:36 +00:00
David Claffey
03e8649bc6 MIPS: merge mips fast_data patch from David N. Claffey
Signed-off-by: Spencer Oliver <ntfreak@users.sourceforge.net>
2010-01-05 19:54:35 +00:00
Øyvind Harboe
95f86e8e05 gdb: fix regression in gdb_port command
The gdb_port command can be invoked during normal execution
to report the port used for gdb, whereas it was listed as
CONFIG stage only, which caused an error when excuting
it to return the reported error.

Also in line with the grander goal of making more commands
available during all "modes" (perhaps retiring config mode),
there is no particular reason to limit gdb_port to the
config stage.

Regression was introduced in:

b3bf1d12b2 aka
v0.4.0-rc1-32-gb3bf1d1

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2010-01-05 15:28:23 +01:00
Johannes Stezenbach
6d4abe906f update udev rules for new udev version
New versions of udev (148+) emit the following warnings:

udevd[425]: BUS= will be removed in a future udev version,
  please use SUBSYSTEM= to match the event device, or
  SUBSYSTEMS= to match a parent device, in /lib/udev/rules.d/60-openocd.rules:1
udevd[425]: SYSFS{}= will be removed in a future udev version,
  please use ATTR{}= to match the event device, or
  ATTRS{}= to match a parent device, in /lib/udev/rules.d/60-openocd.rules:4
udevd[425]: SYSFS{}= will be removed in a future udev version,
  please use ATTR{}= to match the event device, or
  ATTRS{}= to match a parent device, in /lib/udev/rules.d/60-openocd.rules:7
...

See also http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=560141

[dbrownell@users.sourceforge.net: add IDs for Stellaris ICDI, Olimex Tiny-H]

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-05 01:54:06 -08:00
David Brownell
1b3f15d51e ARMv7-M: use AP_REG_* symbol
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-04 22:11:34 -08:00
David Brownell
237a707f96 FT2232: fix doc typo
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-03 15:02:51 -08:00
David Brownell
e1258c703b JTAG/drivers: ft2232 docs
Add doxyegen description for this driver.

Correct the helptext (configures *or* displays based on #params),
and usage (use the same BNF as the User's Guide).

Remove superfluous #include

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-03 14:54:52 -08:00
David Brownell
50fb3a5129 JTAG/Drivers: Amontec JTAG accelerator fixes
Remove superfluous #include.

Correct the helptext (configures *or* displays based on #params),
and usage (use the same BNF as the User's Guide).

Add doxygen -- file-level description and a @todo for doing
RTCK correctly.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-03 14:51:01 -08:00
David Brownell
4aedb02fcd JTAG: Amontec JTAG accelerater "rtck" is back
The command processing conversion a while back lost the
"rtck" enable/disable command; restore it.

NOTE that having such a command is wrong; there's a standard
way to enable adaptive clocking ("speed 0").

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-03 13:30:06 -08:00
David Brownell
e0338293b8 JTAG/drivers: cleanup jtag_interface structs
Get rid of excess indents.
Ditto superfluous "&" before function pointers.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-03 13:07:18 -08:00
David Brownell
d9508b30e0 JTAG/drivers: amt_jtagaccel fixes + cleanup
Build fixes:  it failed abysmally with PPDEV enabled.  Swapped
a build-time error with a FIXME comment in the affected macros.

Cleanup: remove "&" before function pointers, and excess indent,
for the interface struct declaration.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-03 12:59:51 -08:00
David Brownell
4ed5b45097 ARM: ADIv5 JTAG symbol cleanup
Rename DAP_IR_* as JTAG_DP_* since those symbols are specifically
for JTAG-DP (or SWJ-DP in JTAG mode), and won't work with SWD.
Define the JTAG ABORT and IDCODE instructions for completeness;
add a comment about where to (someday) use ABORT.

Fix messaging which assumes everything is an SWJ-DP; say "JTAG-DP"
instead, it's at least more appropriate for all JTAG transports.

Shrink the affected lines.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-02 15:53:33 -08:00
David Brownell
858226aae2 ARM: dap info fix + tweaks
Fix: don't print the BASE address except if it's a MEM-AP;
that's an unlikely error, but there's no point getting it wrong.
Tweaks: comments, capitalization.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-02 15:53:18 -08:00
David Brownell
6105f2bc4a ARM: ADIv5 export cleanup
Make some private functions "static".  Remove their public declarations,
and what is now an obviously unused function.  Shrinks this object's size
(about 5% on x86_64) while making the code's scope easier to understand.
Shrink the affected lines.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-02 15:53:06 -08:00
David Brownell
e60c164cdb ARM: ADIv5 symbol and comment cleanup
Instead of magic numbers, use their AP_REG_* constants.  Rename
the ROM address symbol as BASE to match ARM's documentation.

Comment various other symbols in the header; add some missing ones.
Remove an unused struct.  Add some doxygen for stuff including the
DAP structure and initialization.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-02 15:53:03 -08:00
David Brownell
ec88ccc51c Cortex-M3: minor breakpoint cleanup
Shrink some lines, add some comments, simplify some tests.
During debug startup, log the core revision level too.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-02 15:52:52 -08:00
David Brownell
b3bf1d12b2 streamline and document helptext mode displays
Most commands are usable only at runtime; so don't bother saying
that, it's noise.  Moreover, tokens like EXEC are cryptic.  Be
more clear: highlight only the commands which may (also) be used
during the config stage, thus matching the docs more closely.
There are

 - Configuration commands (per documentation)
 - And also some commands that valid at *any* time.

Update the docs to note that "help" now shows this mode info.

This also highlighted a few mistakes in command configuration,
mostly commands listed as "valid at any time" which shouldn't
have been.  This just fixes ones I noted when sanity testing.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-02 15:52:35 -08:00
Dean Glazeski
9d167d62f2 Fix usage/help search for subcommands.
This makes it so that the usage/help command properly uses the whole command,
including subcommand, in the search for help information.  This previously
caused erroneous output from the usage command handler.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-02 02:10:55 -08:00
Dean Glazeski
be01786186 Add the current command to the command information
I wanted to make it so I can be ignorant of a commands invocation string, so
I tried to use CMD_CURRENT (aka cmd->current) which is supposed to house a
pointer to the current command.  It turns out that this wasn't being set.

This patch adds the current command structure to the command invocation
structure before sending it along to the command handler.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-02 01:50:57 -08:00
Antonio Borneo
668f20d0ab Added ST FlashLINK interface config file.
The relevant cable config is already in OpenOCD, but not a config for
the JTAG adapter.  I have tested with FlashLINK on ARM926.

Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2010-01-02 01:50:57 -08:00
David Brownell
384e9193e9 User's Guide: warn about the forum
Namely, that developers don't hang out; it's a users-only club.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2009-12-31 03:09:03 -08:00
Dean Glazeski
7cef6d650c Remove some more Eclipse stuff from Git's eyes.
This adds the .settings folder and the .cproject file put down
by Eclipse from the eyes of Git.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2009-12-30 23:26:16 -08:00
Antonio Borneo
3ed254c18a ARM7_9: Fix segfaults
Handlers for commands
 - arm7_9 semihosting <enable | disable>
 - $_TARGETNAME arp_reset assert 1
didn't check if target has already been examined, and could
segfault when using the NULL pointer "arm7_9->eice_cache".

Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2009-12-30 16:58:27 -08:00
Antonio Borneo
7c5acf8660 whitespace cleanup, mostly for docs
Remove useless space/tab at end of lines.
Remove spaces in indentation and replace with tab.

Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2009-12-30 11:51:29 -08:00
Antonio Borneo
17fb7ead4b ARM9TDMI: Fix segfault.
The handler for "arm9tdmi vector_catch ..." did not check
if target has already been examined.  Without this fix it
segfaults when using NULL pointer "arm7_9->eice_cache".

Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2009-12-30 11:51:29 -08:00
Antonio Borneo
c116d8f6bc Fix parport_dcl5 config file.
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
2009-12-30 19:07:44 +01:00
Øyvind Harboe
20354a66b9 zy1000: add zy1000_ prefix to uart command
less polution of the general namespace(preventive action,
no problems reported).

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2009-12-30 13:13:31 +01:00
Øyvind Harboe
2cf6d47375 zy1000: unlock flash upon startup for revc
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2009-12-30 12:36:22 +01:00
Øyvind Harboe
272c33c190 zy1000: reconfigure FPGA upon reset instead of just the CPU
Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2009-12-30 12:12:32 +01:00
Øyvind Harboe
bd3700e89d zy1000: firmware upgrade fixes for revc
Use ecos firmwareutil upgrade utilities

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2009-12-30 12:12:24 +01:00
Øyvind Harboe
12618e4c6d zy1000: less warnings
use inline for static functions in header files to
avoid warnings about fn not being used.

Signed-off-by: Øyvind Harboe <oyvind.harboe@zylin.com>
2009-12-30 12:11:33 +01:00
Piotr Esden-Tempski
d4bef466c3 Added Open-BLDC board config file. 2009-12-29 12:41:43 +01:00
Piotr Esden-Tempski
aa81462618 Added floss-jtag interface config file. 2009-12-29 12:41:43 +01:00
Freddie Chopin
6b1eeb92fe MinGW build fixes
Print "ssize_t" as "%ld" (+ cast to long) not as "%zu".
Official MinGW (gcc 3.4.5) doesn't understand "z" flag.

Signed-off-by: Freddie Chopin <freddie_chopin@op.pl>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2009-12-28 13:09:31 -08:00
Freddie Chopin
37cc6c495f stm32x commands get "usage"
Add .usage fields to stm32x command_registration,
so that "help stm32x" shows required parameters.

Signed-off-by: Freddie Chopin <freddie_chopin@op.pl>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2009-12-28 13:05:50 -08:00
David Brownell
ec297e4bf1 Fix Luminary FT2232 layout docs/configs
Most of this patch updates documentation and comments for various
Luminary boards, supporting two bug fixes by helping to make sense
of the current mess:

 - Recent rev C lm3s811 eval boards didn't work.  They must use
   the ICDI layout, which sets up some signals that the older
   boards didn't need.  This is actually safe and appropriate
   for *all* recent boards ... so just make "luminary.cfg" use
   the ICDI layout.

 - "luminary-lm3s811.cfg", was previously unusable!  No VID/PID;
   and the wrong vendor string.  Make it work, but reserve it
   for older boards where the ICDI layout is wrong.

 - Default the LM3748 eval board to "luminary.cfg", like the
   other boards.  If someone uses an external JTAG adapter, all
   boards will use the same workaround (override that default).

The difference between the two FT2232 layouts is that eventually
the EVB layout will fail cleanly when asked to enable SWO trace,
but the ICDI layout will as cleanly be able to enable it.  Folk
using "luminary.cfg" with Rev B boards won't see anything going
wrong until SWO support is (someday) added.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2009-12-28 12:59:47 -08:00
Piotr Esden-Tempski
cba1813d5c NOR: last_addr also needs correction when checking alignment
Otherwise the new alignment checking algorithm thinks that the
address is not aligned, because it is way beyond the last sector.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2009-12-28 12:31:47 -08:00
David Brownell
3ace333663 create tcl/board/dm365evm.cfg
This config is only lightly tested, and doesn't work well yet;
but it's a start.

 * Notably missing is PLL configuration, since each DaVinci
   does that just a bit differently; and thus DDR2 setup.

 * The SRST workaround needed for the goof in the CPLD's VHDL
   depends on at least the not-yet-merged patch letting ARM9
   (and ARM7) chips perform resets that don't use SRST.

So this isn't yet suitable for debugging U-Boot.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2009-12-27 12:16:55 -08:00
David Brownell
155a6a2c0b NOR: make flash_write_unlock() pad to sector end
Resolve a regression when using newish automagic "write_image"
modes, by always padding to the end of affected sectors.

Also document some issues associated with those automagic options,
in the User's Guide and also some related code comments.

We might need similar padding at the *beginning* of some sectors,
but this is a minimalist fix for the problems which have currently
been reported (plus doc updates).

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2009-12-27 11:34:31 -08:00
Catalin Patulea
84dbf8ab5a Driver for USB-JTAG, Altera USB-Blaster and compatibles
The 10-pin JTAG layout used with these adapters is used by
a variety of platforms including AVR.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2009-12-26 15:05:06 -08:00
Dean Glazeski
900d745567 Olimex SAM9-L9260 board configuration update.
This updates the board configuration for the SAM9-L9260 board with the
configuration for the on-board NAND and dataflash.  Included are commands
for configuring the AT91SAM9 NAND flash driver.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2009-12-26 13:08:24 -08:00
David Brownell
3a84436afb ARM: add comment re register exports
Modern versions of GDB can understand VFP3 and iwMMXt hardware.
2009-12-26 11:25:44 -08:00
David Brownell
e7f81c11c9 User's Guide: update GDB info
Advise leaving background polling enabled; fix broken URL;
add simple program startup example.
2009-12-26 10:35:24 -08:00
David Brownell
df58812b52 NOR: messaging fix
Fix syntax error:  default to "wrote N bytes"; writing a
single byte is an unusual case, not the normal one.
2009-12-26 10:24:39 -08:00
David Brownell
396b0f3012 NOR: Allocate the right amount of memory
Switch to calloc() to simplify review and initialization.
2009-12-26 10:22:28 -08:00
David Brownell
08a890e4aa cygwin 1.7 build fixes
It's less accepting of signed char ... insisting that e.g. tolower()
not receive one as a parameter.

It's probably good to phase out such usage, given the number of bugs
that lurk in the vicinity (assumptions that char is unsigned), so fix
these even though such usage is actually legal.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2009-12-26 10:19:19 -08:00
Antonio Borneo
f9d203d1e6 PARPORT code cleanup:
Align elements in array.

Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
2009-12-26 10:19:57 +01:00
David Brownell
4e2b15fc93 Restore "-dev" version suffix
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
2009-12-21 14:49:36 -08:00
194 changed files with 11574 additions and 2936 deletions

6
.gitignore vendored
View File

@@ -66,6 +66,10 @@ stamp-vti
INSTALL INSTALL
NOTES NOTES
# coexist with quilt
patches
# Eclipse stuff # Eclipse stuff
.project .project
.cproject
.settings

10
BUGS
View File

@@ -6,6 +6,12 @@ posting a message with your report:
openocd-development@lists.berlios.de openocd-development@lists.berlios.de
Also, please check the Trac bug database to see if a ticket for
the bug has already been opened. You might be asked to open
such a ticket, or to update an existing ticket with more data.
https://sourceforge.net/apps/trac/openocd/
To minimize work for OpenOCD developers, you should try to include To minimize work for OpenOCD developers, you should try to include
all of the information listed below. If you feel that some of the all of the information listed below. If you feel that some of the
items below are unnecessary for a clear bug report, you may leave items below are unnecessary for a clear bug report, you may leave
@@ -26,8 +32,8 @@ that may be important.
http://www.kernel.org/pub/software/scm/git/docs/git-bisect.html http://www.kernel.org/pub/software/scm/git/docs/git-bisect.html
If possible, please develop and attach a patch that helps to expose or If possible, please develop and attach a patch that helps to expose or
solve the reported problem. See the PATCHES file for more information solve the reported problem. See the PATCHES.txt file for information
for that process. about that process.
Attach all files directly to your posting. The mailing list knows to Attach all files directly to your posting. The mailing list knows to
transform attachments to links, but attachments must be less than 300KB transform attachments to links, but attachments must be less than 300KB

View File

@@ -384,7 +384,7 @@ HIDE_SCOPE_NAMES = NO
# will put a list of the files that are included by a file in the documentation # will put a list of the files that are included by a file in the documentation
# of that file. # of that file.
SHOW_INCLUDE_FILES = YES SHOW_INCLUDE_FILES = NO
# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
# is inserted in the documentation for inline members. # is inserted in the documentation for inline members.
@@ -403,7 +403,7 @@ SORT_MEMBER_DOCS = YES
# by member name. If set to NO (the default) the members will appear in # by member name. If set to NO (the default) the members will appear in
# declaration order. # declaration order.
SORT_BRIEF_DOCS = NO SORT_BRIEF_DOCS = YES
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
# hierarchy of group names into alphabetical order. If set to NO (the default) # hierarchy of group names into alphabetical order. If set to NO (the default)
@@ -567,9 +567,9 @@ WARN_LOGFILE =
INPUT = @srcdir@/doc/manual \ INPUT = @srcdir@/doc/manual \
@srcdir@/TODO \ @srcdir@/TODO \
@srcdir@/BUGS \ @srcdir@/BUGS \
@srcdir@/PATCHES \ @srcdir@/PATCHES.txt \
@srcdir@/src \ @srcdir@/src \
@srcdir@/config.h @builddir@/config.h
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
@@ -692,13 +692,13 @@ SOURCE_BROWSER = YES
# Setting the INLINE_SOURCES tag to YES will include the body # Setting the INLINE_SOURCES tag to YES will include the body
# of functions and classes directly in the documentation. # of functions and classes directly in the documentation.
INLINE_SOURCES = YES INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
# doxygen to hide any special comment blocks from generated source code # doxygen to hide any special comment blocks from generated source code
# fragments. Normal C and C++ comments will always remain visible. # fragments. Normal C and C++ comments will always remain visible.
STRIP_CODE_COMMENTS = NO STRIP_CODE_COMMENTS = YES
# If the REFERENCED_BY_RELATION tag is set to YES # If the REFERENCED_BY_RELATION tag is set to YES
# then for each documented function all documented # then for each documented function all documented

View File

@@ -26,6 +26,7 @@ Doxyfile: $(srcdir)/Doxyfile.in
echo "### @@@ -= DO NOT EDIT THIS FILE =- @@@ ###" && \ echo "### @@@ -= DO NOT EDIT THIS FILE =- @@@ ###" && \
echo "### @@@ Make changes to Doxyfile.in @@@ ###" && \ echo "### @@@ Make changes to Doxyfile.in @@@ ###" && \
sed -e 's,@srcdir\@,$(srcdir),' \ sed -e 's,@srcdir\@,$(srcdir),' \
-e 's,@builddir\@,$(builddir),' \
-e 's,@doxygen_as_html\@,$(doxygen_as_html),' \ -e 's,@doxygen_as_html\@,$(doxygen_as_html),' \
-e 's,@doxygen_as_pdf\@,$(doxygen_as_pdf),' $< \ -e 's,@doxygen_as_pdf\@,$(doxygen_as_pdf),' $< \
) > $@ ) > $@

44
NEWS
View File

@@ -5,36 +5,48 @@ and other issues not mentioned here.
JTAG Layer: JTAG Layer:
Support KT-Link JTAG adapter. Support KT-Link JTAG adapter.
Support USB-JTAG, Altera USB-Blaster and compatibles.
Boundary Scan: Boundary Scan:
Target Layer: Target Layer:
General General
- Removed commands which have been obsolete for at least
a year (from both documentation and, sometimes, code).
- new "reset-assert" event, for systems without SRST - new "reset-assert" event, for systems without SRST
ARM ARM
- supports "reset-assert" event (except on Cortex-M3)
- renamed "armv4_5" command prefix as "arm" - renamed "armv4_5" command prefix as "arm"
- recognize TrustZone "Secure Monitor" mode - recognize TrustZone "Secure Monitor" mode
- "arm regs" command output changed - "arm regs" command output changed
- register names use "sp" not "r13" - register names use "sp" not "r13"
- add top-level "mcr" and "mrc" commands, replacing - add top-level "mcr" and "mrc" commands, replacing
various core-specific operations various core-specific operations
- basic semihosting support - basic semihosting support (ARM7/ARM9 only, for now)
ARM11 ARM11
- Preliminary ETM and ETB hookup - Should act much more like other ARM cores:
- accelerated "flash erase_check" * Preliminary ETM and ETB hookup
- accelerated GDB memory checksum * accelerated "flash erase_check"
- support "arm regs" command * accelerated GDB memory checksum
- can access all core modes and registers * support "arm regs" command
- watchpoint support * can access all core modes and registers
* watchpoint support
- Shares some core debug code with Cortex-A8
Cortex-A8 Cortex-A8
- support "arm regs" command - Should act much more like other ARM cores:
- can access all core modes and registers * support "arm regs" command
- supports "reset-assert" event (used on OMAP3530) * can access all core modes and registers
- watchpoint support * watchpoint support
- Shares some core debug code with ARM11
Cortex-M3 Cortex-M3
- Exposed DWT registers like cycle counter - Exposed DWT registers like cycle counter
- vector_catch settings not clobbered by resets
- no longer interferes with firmware's fault handling
ETM, ETB ETM, ETB
- "trigger_percent" command moved ETM --> ETB - "trigger_percent" command moved ETM --> ETB
- "etm trigger_debug" command added - "etm trigger_debug" command added
MIPS
- use fastdata writes
Freescale DSP563xx cores (partial support) Freescale DSP563xx cores (partial support)
Flash Layer: Flash Layer:
@@ -44,13 +56,19 @@ Flash Layer:
- <driver_name>[.N]: reference the driver's Nth bank - <driver_name>[.N]: reference the driver's Nth bank
New 'nand verify' command to check bank against an image file. New 'nand verify' command to check bank against an image file.
The "flash erase_address" command now rejects partial sectors; The "flash erase_address" command now rejects partial sectors;
previously it would silently erase extra data. previously it would silently erase extra data. If you
want to erase the rest of the first and/or last sectors
instead of failing, you must pass an explicit "pad" flag.
New at91sam9 NAND controller driver. New at91sam9 NAND controller driver.
New s3c64xx NAND controller driver.
Board, Target, and Interface Configuration Scripts: Board, Target, and Interface Configuration Scripts:
ARM9 ARM9
- ETM and ETB hookup for iMX2* targets - ETM and ETB hookup for iMX2* targets
Add $HOME/.openocd to the search path. Add $HOME/.openocd to the search path.
Handle Rev C of LM3S811 eval boards.
- use "luminary-lm3s811.cfg" for older boards
- use "luminary.cfg" for RevC and newer
Core Jim/TCL Scripting: Core Jim/TCL Scripting:
New 'usage' command to provide terse command help. New 'usage' command to provide terse command help.
@@ -77,4 +95,4 @@ For older NEWS, see the NEWS files associated with each release
For more information about contributing test reports, bug fixes, or new For more information about contributing test reports, bug fixes, or new
features and device support, please read the new Developer Manual (or features and device support, please read the new Developer Manual (or
the BUGS and PATCHES files in the source archive). the BUGS and PATCHES.txt files in the source archive).

4
README
View File

@@ -64,8 +64,8 @@ you can build the in-tree documentation.
Installing OpenOCD Installing OpenOCD
================== ==================
On Linux, you may have permissions problems to address. The best On Linux, you may have permissions problems to address. The best way
way to do this is to use the contrib/udev.rules file. It probably to do this is to use the contrib/openocd.udev rules file. It probably
belongs somewhere in /etc/udev/rules.d, but consult your operating belongs somewhere in /etc/udev/rules.d, but consult your operating
system documentation to be sure. In particular, make sure that it system documentation to be sure. In particular, make sure that it
matches the syntax used by your operating system's version of udev. matches the syntax used by your operating system's version of udev.

28
TODO
View File

@@ -142,6 +142,8 @@ Once the above are completed:
https://lists.berlios.de/pipermail/openocd-development/2009-May/006590.html https://lists.berlios.de/pipermail/openocd-development/2009-May/006590.html
- regression: "reset halt" between 729(works) and 788(fails): @par - regression: "reset halt" between 729(works) and 788(fails): @par
https://lists.berlios.de/pipermail/openocd-development/2009-July/009206.html https://lists.berlios.de/pipermail/openocd-development/2009-July/009206.html
- registers
- add flush-value operation, call them all on resume/reset
- mcr/mrc target->type support - mcr/mrc target->type support
- missing from ARM920t, ARM966e, XScale. - missing from ARM920t, ARM966e, XScale.
It's possible that the current syntax is unable to support read-modify-write It's possible that the current syntax is unable to support read-modify-write
@@ -170,10 +172,18 @@ https://lists.berlios.de/pipermail/openocd-development/2009-October/011506.html
- Thumb2 single stepping: ARM1156T2 needs simulator support - Thumb2 single stepping: ARM1156T2 needs simulator support
- Cortex A8 support (ML) - Cortex A8 support (ML)
- add target implementation (ML) - add target implementation (ML)
- Cortex M3 support
- when stepping, only write dirtied registers (be faster)
- when connecting to halted core, fetch registers (startup is quirky)
- Generic ARM run_algorithm() interface - Generic ARM run_algorithm() interface
- tagged struct wrapping ARM instructions and metadata - tagged struct wrapping ARM instructions and metadata
- not revision-specific (current: ARMv4+ARMv5 -or- ARMv6 -or- ARMv7) - not revision-specific (current: ARMv4+ARMv5 -or- ARMv6 -or- ARMv7)
- usable with at least arm_nandwrite() and generic CFI drivers - usable with at least arm_nandwrite() and generic CFI drivers
- ETM
- don't show FIFOFULL registers if they're not supported
- use comparators to get more breakpoints and watchpoints
- add "etm drivers" command
- trace driver init() via examine() paths only, not setup()/reset
- MC1322x support (JW/DE?) - MC1322x support (JW/DE?)
- integrate and test support from JW (and DE?) - integrate and test support from JW (and DE?)
- get working with a known good interface (i.e. not today's jlink) - get working with a known good interface (i.e. not today's jlink)
@@ -209,6 +219,16 @@ https://lists.berlios.de/pipermail/openocd-development/2009-October/011506.html
- ocl - ocl
- str9xpec - str9xpec
- Don't expect writing all-ones to be a safe way to write without
changing bit values. Minimally it loses on flash modules with
internal ECC, where it may change the ECC.
- NOR flash_write_unlock() does that between sectors
- there may be other cases too
- Make sure all commands accept either a bank name or a bank number,
and be sure both identifiers show up in "flash banks" and "nand list".
Right now the user-friendly names are pretty much hidden...
@subsection thelistflashcfi CFI @subsection thelistflashcfi CFI
- finish implementing bus width/chip width handling (suggested by NC) - finish implementing bus width/chip width handling (suggested by NC)
@@ -346,9 +366,11 @@ to complete:
- Develop milestone and release guidelines, processes, and scripts. - Develop milestone and release guidelines, processes, and scripts.
- Develop "style" guidelines (and scripts) for maintainers: - Develop "style" guidelines (and scripts) for maintainers:
- reviewing patches - reviewing patches
- committing to Subversion - committing to git
- Review The Guide for OpenOCD Users for documentation errors or omissions - Review Users' Guide for documentation errors or omissions
- Update The Manual for OpenOCD Developers: - "capture" and "ocd_find" commands
- "ocd_" prefix on various stuff
- Update Developer's Manual (doxygen output)
- Add documentation describing the architecture of each module - Add documentation describing the architecture of each module
- Provide more Technical Primers to bootstrap contributor knowledge - Provide more Technical Primers to bootstrap contributor knowledge

View File

@@ -1,5 +1,5 @@
AC_PREREQ(2.60) AC_PREREQ(2.60)
AC_INIT([openocd], [0.4.0-rc1], AC_INIT([openocd], [0.4.0],
[OpenOCD Mailing List <openocd-development@lists.berlios.de>]) [OpenOCD Mailing List <openocd-development@lists.berlios.de>])
AC_CONFIG_SRCDIR([src/openocd.c]) AC_CONFIG_SRCDIR([src/openocd.c])
@@ -392,6 +392,14 @@ AC_ARG_ENABLE(ft2232_ftd2xx,
AS_HELP_STRING([--enable-ft2232_ftd2xx], [Enable building support for FT2232 based devices using the FTD2XX driver from ftdichip.com]), AS_HELP_STRING([--enable-ft2232_ftd2xx], [Enable building support for FT2232 based devices using the FTD2XX driver from ftdichip.com]),
[build_ft2232_ftd2xx=$enableval], [build_ft2232_ftd2xx=no]) [build_ft2232_ftd2xx=$enableval], [build_ft2232_ftd2xx=no])
AC_ARG_ENABLE(usb_blaster_libftdi,
AS_HELP_STRING([--enable-usb_blaster_libftdi], [Enable building support for the Altera USB-Blaster using the libftdi driver, opensource alternate of FTD2XX]),
[build_usb_blaster_libftdi=$enableval], [build_usb_blaster_libftdi=no])
AC_ARG_ENABLE(usb_blaster_ftd2xx,
AS_HELP_STRING([--enable-usb_blaster_ftd2xx], [Enable building support for the Altera USB-Blaster using the FTD2XX driver from ftdichip.com]),
[build_usb_blaster_ftd2xx=$enableval], [build_usb_blaster_ftd2xx=no])
AC_ARG_ENABLE(amtjtagaccel, AC_ARG_ENABLE(amtjtagaccel,
AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]), AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]),
[build_amtjtagaccel=$enableval], [build_amtjtagaccel=no]) [build_amtjtagaccel=$enableval], [build_amtjtagaccel=no])
@@ -651,6 +659,20 @@ else
AC_DEFINE(BUILD_FT2232_FTD2XX, 0, [0 if you don't want ftd2xx ft2232.]) AC_DEFINE(BUILD_FT2232_FTD2XX, 0, [0 if you don't want ftd2xx ft2232.])
fi fi
if test $build_usb_blaster_libftdi = yes; then
build_bitbang=yes
AC_DEFINE(BUILD_USB_BLASTER_LIBFTDI, 1, [1 if you want libftdi usb_blaster.])
else
AC_DEFINE(BUILD_USB_BLASTER_LIBFTDI, 0, [0 if you don't want libftdi usb_blaster.])
fi
if test $build_usb_blaster_ftd2xx = yes; then
build_bitbang=yes
AC_DEFINE(BUILD_USB_BLASTER_FTD2XX, 1, [1 if you want ftd2xx usb_blaster.])
else
AC_DEFINE(BUILD_USB_BLASTER_FTD2XX, 0, [0 if you don't want ftd2xx usb_blaster.])
fi
if test $build_amtjtagaccel = yes; then if test $build_amtjtagaccel = yes; then
AC_DEFINE(BUILD_AMTJTAGACCEL, 1, [1 if you want the Amontec JTAG-Accelerator driver.]) AC_DEFINE(BUILD_AMTJTAGACCEL, 1, [1 if you want the Amontec JTAG-Accelerator driver.])
else else
@@ -727,7 +749,7 @@ then
AC_MSG_ERROR([The option: with_ftd2xx_linux_tardir is for LINUX only.]) AC_MSG_ERROR([The option: with_ftd2xx_linux_tardir is for LINUX only.])
fi fi
if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes ; then if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes ; then
AC_MSG_CHECKING([for ftd2xx.lib exists (win32)]) AC_MSG_CHECKING([for ftd2xx.lib exists (win32)])
# if we are given a zipdir... # if we are given a zipdir...
@@ -1001,6 +1023,8 @@ AM_CONDITIONAL(AT91RM9200, test $build_at91rm9200 = yes)
AM_CONDITIONAL(BITBANG, test $build_bitbang = yes) AM_CONDITIONAL(BITBANG, test $build_bitbang = yes)
AM_CONDITIONAL(FT2232_LIBFTDI, test $build_ft2232_libftdi = yes) AM_CONDITIONAL(FT2232_LIBFTDI, test $build_ft2232_libftdi = yes)
AM_CONDITIONAL(FT2232_DRIVER, test $build_ft2232_ftd2xx = yes -o $build_ft2232_libftdi = yes) AM_CONDITIONAL(FT2232_DRIVER, test $build_ft2232_ftd2xx = yes -o $build_ft2232_libftdi = yes)
AM_CONDITIONAL(USB_BLASTER_LIBFTDI, test $build_usb_blaster_libftdi = yes)
AM_CONDITIONAL(USB_BLASTER_DRIVER, test $build_usb_blaster_ftd2xx = yes -o $build_usb_blaster_libftdi = yes)
AM_CONDITIONAL(AMTJTAGACCEL, test $build_amtjtagaccel = yes) AM_CONDITIONAL(AMTJTAGACCEL, test $build_amtjtagaccel = yes)
AM_CONDITIONAL(GW16012, test $build_gw16012 = yes) AM_CONDITIONAL(GW16012, test $build_gw16012 = yes)
AM_CONDITIONAL(PRESTO_LIBFTDI, test $build_presto_libftdi = yes) AM_CONDITIONAL(PRESTO_LIBFTDI, test $build_presto_libftdi = yes)

View File

@@ -1,60 +1,68 @@
BUS!="usb", ACTION!="add", SUBSYSTEM!=="usb_device", GOTO="openocd_rules_end" ACTION!="add|change", GOTO="openocd_rules_end"
SUBSYSTEM!="usb", GOTO="openocd_rules_end"
ENV{DEVTYPE}!="usb_device", GOTO="openocd_rules_end"
# Olimex ARM-USB-OCD # Olimex ARM-USB-OCD
SYSFS{idVendor}=="15ba", SYSFS{idProduct}=="0003", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0003", MODE="664", GROUP="plugdev"
# Olimex ARM-USB-OCD-TINY # Olimex ARM-USB-OCD-TINY
SYSFS{idVendor}=="15ba", SYSFS{idProduct}=="0004", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0004", MODE="664", GROUP="plugdev"
# Olimex ARM-JTAG-EW # Olimex ARM-JTAG-EW
SYSFS{idVendor}=="15ba", SYSFS{idProduct}=="001e", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="001e", MODE="664", GROUP="plugdev"
# Olimex ARM-USB-OCD-TINY-H
ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002a", MODE="664", GROUP="plugdev"
# USBprog with OpenOCD firmware # USBprog with OpenOCD firmware
SYSFS{idVendor}=="1781", SYSFS{idProduct}=="0c63", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="664", GROUP="plugdev"
# Amontec JTAGkey and JTAGkey-tiny # Amontec JTAGkey and JTAGkey-tiny
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="cff8", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="cff8", MODE="664", GROUP="plugdev"
# Amontec JTAGkey-HiSpeed # Amontec JTAGkey-HiSpeed
SYSFS{idVendor}=="0fbb", SYSFS{idProduct}=="1000", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="0fbb", ATTRS{idProduct}=="1000", MODE="664", GROUP="plugdev"
# Axiom AXM-0432 Link (Symphony SoundBite?) # Axiom AXM-0432 Link (Symphony SoundBite?)
# Calao Systems USB-A9260-C01 # Calao Systems USB-A9260-C01
# TinCanTools Flyswatter # TinCanTools Flyswatter
# OOCD-Link # OOCD-Link
# Marvell Sheevaplug (early development versions) # Marvell Sheevaplug (early development versions)
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="6010", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="664", GROUP="plugdev"
# Calao Systems USB-A9260-C02 # Calao Systems USB-A9260-C02
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="6001", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="664", GROUP="plugdev"
# IAR J-Link USB # IAR J-Link USB
SYSFS{idVendor}=="1366", SYSFS{idProduct}=="0101", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0101", MODE="664", GROUP="plugdev"
# Raisonance RLink # Raisonance RLink
SYSFS{idVendor}=="138e", SYSFS{idProduct}=="9000", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="138e", ATTRS{idProduct}=="9000", MODE="664", GROUP="plugdev"
# Hitex STR9-comStick # Hitex STR9-comStick
SYSFS{idVendor}=="0640", SYSFS{idProduct}=="002c", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002c", MODE="664", GROUP="plugdev"
# Hitex STM32-PerformanceStick # Hitex STM32-PerformanceStick
SYSFS{idVendor}=="0640", SYSFS{idProduct}=="002d", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002d", MODE="664", GROUP="plugdev"
# Luminary Micro Stellaris/LM3S811 # TI/Luminary Stellaris Evaluation Board (several)
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="bcd9", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcd9", MODE="664", GROUP="plugdev"
# TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board
ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcda", MODE="664", GROUP="plugdev"
# Xverve Signalyzer Tool (DT-USB-ST) # Xverve Signalyzer Tool (DT-USB-ST)
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="bca0", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca0", MODE="664", GROUP="plugdev"
# egnite Turtelizer 2 # egnite Turtelizer 2
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="bdc8", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bdc8", MODE="664", GROUP="plugdev"
# Marvell Sheevaplug # Marvell Sheevaplug
SYSFS{idVendor}=="9e88", SYSFS{idProduct}=="9e8f", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="664", GROUP="plugdev"
# Section5 ICEbear # Section5 ICEbear
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="c140", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c140", MODE="664", GROUP="plugdev"
SYSFS{idVendor}=="0403", SYSFS{idProduct}=="c141", MODE="664", GROUP="plugdev" ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c141", MODE="664", GROUP="plugdev"
LABEL="openocd_rules_end" LABEL="openocd_rules_end"

View File

@@ -1,6 +1,6 @@
/** @mainpage OpenOCD Reference Manual /** @mainpage OpenOCD Developer's Guide
Welcome to the OpenOCD Reference Manual -- the developer's resource for Welcome to the OpenOCD Developer's Guide -- the developer's resource for
learning about the internal architecture of the OpenOCD project. @par learning about the internal architecture of the OpenOCD project. @par
In addition, this document contains the tactical and strategic plans In addition, this document contains the tactical and strategic plans

View File

@@ -68,9 +68,9 @@ static const struct command_registration hello_command_handlers[] = {
{ {
.name = "hello", .name = "hello",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.handler = &handle_hello_command, .handler = handle_hello_command,
.help = "print a warm greetings", .help = "print a warm greeting",
.usage = "[<name>]", .usage = "[name]",
}, },
{ {
.chain = foo_command_handlers, .chain = foo_command_handlers,
@@ -84,7 +84,12 @@ int hello_register_commands(struct command_context_s *cmd_ctx)
} }
@endcode @endcode
That's it! The command should now be registered and avaiable to scripts. Note that the "usage" text should use the same EBNF that's found
in the User's Guide: literals in 'single quotes', sequences of
optional parameters in [square brackets], and alternatives in
(parentheses|with|vertical bars), and so forth. No angle brackets.
That's it! The command should now be registered and available to scripts.
@section primercmdchain Command Chaining @section primercmdchain Command Chaining

View File

@@ -308,7 +308,7 @@ For technical reference material:
- Else it's a "Config Command" if it must be used before the - Else it's a "Config Command" if it must be used before the
configuration stage completes. configuration stage completes.
- For a "Driver", list its name. - For a "Driver", list its name.
- Use BNF style regular expressions to define parameters: - Use EBNF style regular expressions to define parameters:
brackets around zero-or-one choices, parentheses around brackets around zero-or-one choices, parentheses around
exactly-one choices. exactly-one choices.
- Use \@option, \@file, \@var and other mechanisms where appropriate. - Use \@option, \@file, \@var and other mechanisms where appropriate.

View File

@@ -22,19 +22,23 @@ please check the \fIopenocd\fR info page for the complete list.
.SH "OPTIONS" .SH "OPTIONS"
.TP .TP
.B "\-f, \-\-file <filename>" .B "\-f, \-\-file <filename>"
Use configuration file This is a shortcut for a \fB\-c "[script \fI<filename>\fB]"\fR
.BR <filename> . command, using a search path to load the configuration file
.IR <filename> .
In order to specify multiple config files, you can use multiple In order to specify multiple config files, you can use multiple
.B \-\-file .B \-\-file
arguments. If this option is omitted, the config file arguments. If no such \fB\-c\fR
options are included, the first config file
.B openocd.cfg .B openocd.cfg
in the current working directory will be used. in the search path will be used.
.TP .TP
.B "\-s, \-\-search <dirname>" .B "\-s, \-\-search <dirname>"
Search for config files and scripts in the directory Add
.BR <dirname> . .I <dirname>
If this option is omitted, OpenOCD searches for config files and scripts to the search path used for config files and scripts.
in the current directory. The search path begins with the current directory,
then includes these additional directories before other
components such as the standard OpenOCD script libraries.
.TP .TP
.B "\-d, \-\-debug <debuglevel>" .B "\-d, \-\-debug <debuglevel>"
Set debug level. Possible values are: Set debug level. Possible values are:
@@ -52,13 +56,17 @@ The default level is
.TP .TP
.B "\-l, \-\-log_output <filename>" .B "\-l, \-\-log_output <filename>"
Redirect log output to the file Redirect log output to the file
.BR <filename> . .IR <filename> .
Per default the log output is printed on Per default the log output is printed on
.BR stderr . .BR stderr .
.TP .TP
.B "\-c, \-\-command <cmd>" .B "\-c, \-\-command <cmd>"
Run the command Add the command
.BR <cmd> . .I <cmd>
to a list of commands executed on server startup.
Note that you will need to explicitly invoke
.I init
if the command requires access to a target or flash.
.TP .TP
.B "\-p, \-\-pipe" .B "\-p, \-\-pipe"
Use pipes when talking to gdb. Use pipes when talking to gdb.
@@ -88,9 +96,6 @@ and
programs are properly installed at your site, the command programs are properly installed at your site, the command
.B info openocd .B info openocd
should give you access to the complete manual. should give you access to the complete manual.
.PP
Also, the OpenOCD wiki contains some more information and examples:
.B http://openfacts.berlios.de/index-en.phtml?title=Open_On-Chip_Debugger
.SH "AUTHORS" .SH "AUTHORS"
Please see the file AUTHORS. Please see the file AUTHORS.
.PP .PP

File diff suppressed because it is too large Load Diff

View File

@@ -60,12 +60,16 @@ endif
if FT2232_LIBFTDI if FT2232_LIBFTDI
FTDI2232LIB = -lftdi -lusb FTDI2232LIB = -lftdi -lusb
else else
if USB_BLASTER_LIBFTDI
FTDI2232LIB = -lftdi -lusb
else
if PRESTO_LIBFTDI if PRESTO_LIBFTDI
FTDI2232LIB = -lftdi -lusb FTDI2232LIB = -lftdi -lusb
else else
FTDI2232LIB = FTDI2232LIB =
endif endif
endif endif
endif
if USBPROG if USBPROG
LIBUSB = -lusb LIBUSB = -lusb

View File

@@ -62,6 +62,7 @@
#include "rom.h" #include "rom.h"
#ifdef CYGPKG_HAL_NIOS2 #ifdef CYGPKG_HAL_NIOS2
#include <cyg/hal/io.h>
#define ZY1000_SER_DEV "/dev/uart_0" #define ZY1000_SER_DEV "/dev/uart_0"
#else #else
#define ZY1000_SER_DEV "/dev/ser0" #define ZY1000_SER_DEV "/dev/ser0"
@@ -145,7 +146,14 @@ static void zylinjtag_reboot(cyg_addrword_t data)
diag_printf("Unmounting /config..\n"); diag_printf("Unmounting /config..\n");
umount("/config"); umount("/config");
diag_printf("Rebooting..\n"); diag_printf("Rebooting..\n");
#ifdef CYGPKG_HAL_NIOS2
/* This will reboot & reconfigure the FPGA from the bootloader
* and on.
*/
IOWR(REMOTE_UPDATE_BASE, 0x20, 0x1);
#else
HAL_PLATFORM_RESET(); HAL_PLATFORM_RESET();
#endif
} }
static cyg_thread zylinjtag_thread_object; static cyg_thread zylinjtag_thread_object;
static cyg_handle_t zylinjtag_thread_handle; static cyg_handle_t zylinjtag_thread_handle;
@@ -839,7 +847,7 @@ static int zylinjtag_Jim_Command_uart(Jim_Interp *interp, int argc,
static int current_baud = 38400; static int current_baud = 38400;
if (argc == 1) if (argc == 1)
{ {
command_print(cmd_ctx, "%d", current_baud); Jim_SetResult(interp, Jim_NewIntObj(interp, current_baud));
return JIM_OK; return JIM_OK;
} }
else if (argc != 2) else if (argc != 2)
@@ -875,8 +883,8 @@ static int zylinjtag_Jim_Command_uart(Jim_Interp *interp, int argc,
baud = CYGNUM_SERIAL_BAUD_230400; baud = CYGNUM_SERIAL_BAUD_230400;
break; break;
default: default:
command_print(cmd_ctx, "unsupported baudrate"); Jim_SetResult(interp, Jim_NewStringObj(interp, "unsupported baudrate", -1));
return ERROR_INVALID_ARGUMENTS; return JIM_ERR;
} }
cyg_serial_info_t buf; cyg_serial_info_t buf;
@@ -889,7 +897,7 @@ static int zylinjtag_Jim_Command_uart(Jim_Interp *interp, int argc,
err = cyg_io_lookup(ZY1000_SER_DEV, &serial_handle); err = cyg_io_lookup(ZY1000_SER_DEV, &serial_handle);
if (err != ENOERR) if (err != ENOERR)
{ {
LOG_ERROR("Could not open serial port\n"); Jim_SetResult(interp, Jim_NewStringObj(interp, "Could not open serial port", -1));
return JIM_ERR; return JIM_ERR;
} }
@@ -899,7 +907,7 @@ static int zylinjtag_Jim_Command_uart(Jim_Interp *interp, int argc,
&len); &len);
if (err != ENOERR) if (err != ENOERR)
{ {
LOG_ERROR("Failed to get serial port settings %d", err); Jim_SetResult(interp, Jim_NewStringObj(interp, "Failed to get serial port settings", -1));
return JIM_ERR; return JIM_ERR;
} }
buf.baud = baud; buf.baud = baud;
@@ -908,7 +916,7 @@ static int zylinjtag_Jim_Command_uart(Jim_Interp *interp, int argc,
&len); &len);
if (err != ENOERR) if (err != ENOERR)
{ {
LOG_ERROR("Failed to set serial port settings %d", err); Jim_SetResult(interp, Jim_NewStringObj(interp, "Failed to set serial port settings", -1));
return JIM_ERR; return JIM_ERR;
} }
@@ -948,7 +956,11 @@ int main(int argc, char *argv[])
diag_init_putc(_zylinjtag_diag_write_char); diag_init_putc(_zylinjtag_diag_write_char);
// We want this in the log. // We want this in the log.
diag_printf("Zylin ZY1000.\n"); #ifdef CYGPKG_HAL_NIOS2
diag_printf("Zylin ZY1000 PCB revc.\n");
#else
diag_printf("Zylin ZY1000 PCB revb.\n");
#endif
err = mount("", "/ram", "ramfs"); err = mount("", "/ram", "ramfs");
if (err < 0) if (err < 0)
@@ -987,6 +999,20 @@ int main(int argc, char *argv[])
copydir("/rom", "/ram/cgi"); copydir("/rom", "/ram/cgi");
#ifdef CYGPKG_HAL_NIOS2
cyg_flashaddr_t err_address;
#define UNCACHED_EXT_FLASH_BASE (0x80000000 + EXT_FLASH_BASE)
/* The revc flash is locked upon reset, unlock it */
#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
if ((err = flash_unlock((void *) UNCACHED_EXT_FLASH_BASE, EXT_FLASH_SPAN,
(void **) &err_address)) != 0)
{
diag_printf("Error: could not unlock flash\n");
}
#endif
#endif
err = mount("/dev/flash1", "/config", "jffs2"); err = mount("/dev/flash1", "/config", "jffs2");
if (err < 0) if (err < 0)
{ {
@@ -1075,7 +1101,7 @@ int main(int argc, char *argv[])
NULL, NULL); NULL, NULL);
#endif #endif
Jim_CreateCommand(httpstate.jim_interp, "uart", zylinjtag_Jim_Command_uart, NULL, NULL); Jim_CreateCommand(httpstate.jim_interp, "zy1000_uart", zylinjtag_Jim_Command_uart, NULL, NULL);
log_init(); log_init();

View File

@@ -751,8 +751,8 @@ COMMAND_HANDLER(mg_write_cmd)
if (duration_measure(&bench) == ERROR_OK) if (duration_measure(&bench) == ERROR_OK)
{ {
command_print(CMD_CTX, "wrote %zu byte from file %s " command_print(CMD_CTX, "wrote %ld bytes from file %s "
"in %fs (%0.3f kB/s)", fileio.size, CMD_ARGV[1], "in %fs (%0.3f kB/s)", (long)fileio.size, CMD_ARGV[1],
duration_elapsed(&bench), duration_kbps(&bench, fileio.size)); duration_elapsed(&bench), duration_kbps(&bench, fileio.size));
} }
@@ -1271,30 +1271,33 @@ COMMAND_HANDLER(mg_config_cmd)
static const struct command_registration mflash_exec_command_handlers[] = { static const struct command_registration mflash_exec_command_handlers[] = {
{ {
.name = "probe", .name = "probe",
.handler = &mg_probe_cmd, .handler = mg_probe_cmd,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "Detect bank configuration information", .help = "Detect bank configuration information",
}, },
{ {
.name = "write", .name = "write",
.handler = &mg_write_cmd, .handler = mg_write_cmd,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<num> <file> <address>", /* FIXME bank_num is unused */
.help = "Write a file at the specified address", .usage = "bank_num filename address",
.help = "Write binary file at the specified address.",
}, },
{ {
.name = "dump", .name = "dump",
.handler = &mg_dump_cmd, .handler = mg_dump_cmd,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<num> <file> <address> <size>", /* FIXME bank_num is unused */
.help = "Dump to a file from the specified address", .usage = "bank_num filename address size",
.help = "Write specified number of bytes from a binary file "
"to the specified, address.",
}, },
{ {
.name = "config", .name = "config",
.handler = &mg_config_cmd, .handler = mg_config_cmd,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<num> <stage>", .help = "Configure MFLASH options.",
.help = "Dump to a file from the specified address", .usage = "('boot'|'storage'|'pll' frequency)",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -1345,7 +1348,8 @@ COMMAND_HANDLER(mg_bank_cmd)
char *str; char *str;
mflash_bank->rst_pin.num = strtoul(CMD_ARGV[2], &str, 0); mflash_bank->rst_pin.num = strtoul(CMD_ARGV[2], &str, 0);
if (*str) if (*str)
mflash_bank->rst_pin.port[0] = (uint16_t)tolower(str[0]); mflash_bank->rst_pin.port[0] = (uint16_t)
tolower((unsigned)str[0]);
mflash_bank->target = target; mflash_bank->target = target;
@@ -1366,15 +1370,15 @@ COMMAND_HANDLER(mg_bank_cmd)
static const struct command_registration mflash_config_command_handlers[] = { static const struct command_registration mflash_config_command_handlers[] = {
{ {
.name = "bank", .name = "bank",
.handler = &mg_bank_cmd, .handler = mg_bank_cmd,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "configure a mflash device bank", .help = "configure a mflash device bank",
.usage = "<soc> <base> <RST pin> <target #>", .usage = "soc_type base_addr pin_id target",
}, },
{ {
.name = "init", .name = "init",
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.handler = &handle_mflash_init_command, .handler = handle_mflash_init_command,
.help = "initialize mflash devices", .help = "initialize mflash devices",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE

View File

@@ -25,6 +25,7 @@ NAND_DRIVERS = \
s3c2412.c \ s3c2412.c \
s3c2440.c \ s3c2440.c \
s3c2443.c \ s3c2443.c \
s3c6400.c \
at91sam9.c at91sam9.c
noinst_HEADERS = \ noinst_HEADERS = \

View File

@@ -697,28 +697,30 @@ static const struct command_registration at91sam9_sub_command_handlers[] = {
.handler = handle_at91sam9_cle_command, .handler = handle_at91sam9_cle_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "set command latch enable address line (default is 22)", .help = "set command latch enable address line (default is 22)",
.usage = "<device_id> <address_line>", .usage = "bank_id address_line",
}, },
{ {
.name = "ale", .name = "ale",
.handler = handle_at91sam9_ale_command, .handler = handle_at91sam9_ale_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "set address latch enable address line (default is 21)", .help = "set address latch enable address line (default is 21)",
.usage = "<device_id> <address_line>", .usage = "bank_id address_line",
}, },
{ {
.name = "rdy_busy", .name = "rdy_busy",
.handler = handle_at91sam9_rdy_busy_command, .handler = handle_at91sam9_rdy_busy_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "set the input pin connected to RDY/~BUSY signal (no default)", .help = "set the GPIO input pin connected to "
.usage = "<device_id> <base_pioc> <pin_num>", "the RDY/~BUSY signal (no default)",
.usage = "bank_id pio_base_addr pin_num",
}, },
{ {
.name = "ce", .name = "ce",
.handler = handle_at91sam9_ce_command, .handler = handle_at91sam9_ce_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "set the output pin connected to chip enable signal (no default)", .help = "set the GPIO output pin connected to "
.usage = "<device_id> <base_pioc> <pin_num>", "the chip enable signal (no default)",
.usage = "bank_id pio_base_addr pin_num",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@@ -36,6 +36,7 @@ extern struct nand_flash_controller s3c2410_nand_controller;
extern struct nand_flash_controller s3c2412_nand_controller; extern struct nand_flash_controller s3c2412_nand_controller;
extern struct nand_flash_controller s3c2440_nand_controller; extern struct nand_flash_controller s3c2440_nand_controller;
extern struct nand_flash_controller s3c2443_nand_controller; extern struct nand_flash_controller s3c2443_nand_controller;
extern struct nand_flash_controller s3c6400_nand_controller;
extern struct nand_flash_controller imx31_nand_flash_controller; extern struct nand_flash_controller imx31_nand_flash_controller;
extern struct nand_flash_controller at91sam9_nand_controller; extern struct nand_flash_controller at91sam9_nand_controller;
@@ -51,6 +52,7 @@ static struct nand_flash_controller *nand_flash_controllers[] =
&s3c2412_nand_controller, &s3c2412_nand_controller,
&s3c2440_nand_controller, &s3c2440_nand_controller,
&s3c2443_nand_controller, &s3c2443_nand_controller,
&s3c6400_nand_controller,
&imx31_nand_flash_controller, &imx31_nand_flash_controller,
&at91sam9_nand_controller, &at91sam9_nand_controller,
/* &boundary_scan_nand_controller, */ /* &boundary_scan_nand_controller, */

View File

@@ -500,9 +500,10 @@ static int lpc3180_write_page(struct nand_device *nand, uint32_t page, uint8_t *
return ERROR_NAND_OPERATION_NOT_SUPPORTED; return ERROR_NAND_OPERATION_NOT_SUPPORTED;
} }
if (oob && (oob_size > 6)) if (oob && (oob_size > 24))
{ {
LOG_ERROR("LPC3180 MLC controller can't write more than 6 bytes of OOB data"); LOG_ERROR("LPC3180 MLC controller can't write more "
"than 6 bytes for each quarter's OOB data");
return ERROR_NAND_OPERATION_NOT_SUPPORTED; return ERROR_NAND_OPERATION_NOT_SUPPORTED;
} }
@@ -559,10 +560,10 @@ static int lpc3180_write_page(struct nand_device *nand, uint32_t page, uint8_t *
data += thisrun_data_size; data += thisrun_data_size;
} }
memset(oob_buffer, 0xff, (nand->page_size == 512) ? 6 : 24); memset(oob_buffer, 0xff, 6);
if (oob) if (oob)
{ {
memcpy(page_buffer, oob, thisrun_oob_size); memcpy(oob_buffer, oob, thisrun_oob_size);
oob_size -= thisrun_oob_size; oob_size -= thisrun_oob_size;
oob += thisrun_oob_size; oob += thisrun_oob_size;
} }
@@ -570,8 +571,10 @@ static int lpc3180_write_page(struct nand_device *nand, uint32_t page, uint8_t *
/* write MLC_ECC_ENC_REG to start encode cycle */ /* write MLC_ECC_ENC_REG to start encode cycle */
target_write_u32(target, 0x200b8008, 0x0); target_write_u32(target, 0x200b8008, 0x0);
target_write_memory(target, 0x200a8000, 4, 128, page_buffer + (quarter * 512)); target_write_memory(target, 0x200a8000,
target_write_memory(target, 0x200a8000, 1, 6, oob_buffer + (quarter * 6)); 4, 128, page_buffer);
target_write_memory(target, 0x200a8000,
1, 6, oob_buffer);
/* write MLC_ECC_AUTO_ENC_REG to start auto encode */ /* write MLC_ECC_AUTO_ENC_REG to start auto encode */
target_write_u32(target, 0x200b8010, 0x0); target_write_u32(target, 0x200b8010, 0x0);
@@ -760,7 +763,6 @@ static int lpc3180_controller_ready(struct nand_device *nand, int timeout)
{ {
struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv; struct lpc3180_nand_controller *lpc3180_info = nand->controller_priv;
struct target *target = lpc3180_info->target; struct target *target = lpc3180_info->target;
uint8_t status = 0x0;
if (target->state != TARGET_HALTED) if (target->state != TARGET_HALTED)
{ {
@@ -768,21 +770,36 @@ static int lpc3180_controller_ready(struct nand_device *nand, int timeout)
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
LOG_DEBUG("lpc3180_controller_ready count start=%d", timeout);
do do
{ {
if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
{ {
uint8_t status;
/* Read MLC_ISR, wait for controller to become ready */ /* Read MLC_ISR, wait for controller to become ready */
target_read_u8(target, 0x200b8048, &status); target_read_u8(target, 0x200b8048, &status);
if (status & 2) if (status & 2) {
LOG_DEBUG("lpc3180_controller_ready count=%d",
timeout);
return 1; return 1;
} }
}
else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
{ {
/* we pretend that the SLC controller is always ready */ uint32_t status;
/* Read SLC_STAT and check READY bit */
target_read_u32(target, 0x20020018, &status);
if (status & 1) {
LOG_DEBUG("lpc3180_controller_ready count=%d",
timeout);
return 1; return 1;
} }
}
alive_sleep(1); alive_sleep(1);
} while (timeout-- > 0); } while (timeout-- > 0);
@@ -801,6 +818,8 @@ static int lpc3180_nand_ready(struct nand_device *nand, int timeout)
return ERROR_NAND_OPERATION_FAILED; return ERROR_NAND_OPERATION_FAILED;
} }
LOG_DEBUG("lpc3180_nand_ready count start=%d", timeout);
do do
{ {
if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER) if (lpc3180_info->selected_controller == LPC3180_MLC_CONTROLLER)
@@ -810,9 +829,12 @@ static int lpc3180_nand_ready(struct nand_device *nand, int timeout)
/* Read MLC_ISR, wait for NAND flash device to become ready */ /* Read MLC_ISR, wait for NAND flash device to become ready */
target_read_u8(target, 0x200b8048, &status); target_read_u8(target, 0x200b8048, &status);
if (status & 1) if (status & 1) {
LOG_DEBUG("lpc3180_nand_ready count end=%d",
timeout);
return 1; return 1;
} }
}
else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER) else if (lpc3180_info->selected_controller == LPC3180_SLC_CONTROLLER)
{ {
uint32_t status = 0x0; uint32_t status = 0x0;
@@ -820,9 +842,12 @@ static int lpc3180_nand_ready(struct nand_device *nand, int timeout)
/* Read SLC_STAT and check READY bit */ /* Read SLC_STAT and check READY bit */
target_read_u32(target, 0x20020018, &status); target_read_u32(target, 0x20020018, &status);
if (status & 1) if (status & 1) {
LOG_DEBUG("lpc3180_nand_ready count end=%d",
timeout);
return 1; return 1;
} }
}
alive_sleep(1); alive_sleep(1);
} while (timeout-- > 0); } while (timeout-- > 0);
@@ -844,7 +869,7 @@ COMMAND_HANDLER(handle_lpc3180_select_command)
} }
unsigned num; unsigned num;
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], num); COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], num);
struct nand_device *nand = get_nand_device_by_num(num); struct nand_device *nand = get_nand_device_by_num(num);
if (!nand) if (!nand)
{ {
@@ -878,10 +903,10 @@ COMMAND_HANDLER(handle_lpc3180_select_command)
static const struct command_registration lpc3180_exec_command_handlers[] = { static const struct command_registration lpc3180_exec_command_handlers[] = {
{ {
.name = "select", .name = "select",
.handler = &handle_lpc3180_select_command, .handler = handle_lpc3180_select_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "select <'mlc'|'slc'> controller (default is mlc)", .help = "select MLC or SLC controller (default is MLC)",
.usage = "<device_id> (mlc|slc)", .usage = "bank_id ['mlc'|'slc']",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -909,4 +934,4 @@ struct nand_flash_controller lpc3180_nand_controller = {
.read_page = lpc3180_read_page, .read_page = lpc3180_read_page,
.controller_ready = lpc3180_controller_ready, .controller_ready = lpc3180_controller_ready,
.nand_ready = lpc3180_nand_ready, .nand_ready = lpc3180_nand_ready,
}; };

76
src/flash/nand/s3c6400.c Normal file
View File

@@ -0,0 +1,76 @@
/***************************************************************************
* Copyright (C) 2010 by Peter Korsgaard <jacmet@sunsite.dk> *
* Heavily based on s3c2412.c by Ben Dooks <ben@fluff.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "s3c24xx.h"
/* s3c64xx uses another base address for the nand controller than 24xx */
#undef S3C2410_NFREG
#define S3C2410_NFREG(x) ((x) + 0x70200000)
NAND_DEVICE_COMMAND_HANDLER(s3c6400_nand_device_command)
{
struct s3c24xx_nand_controller *info;
CALL_S3C24XX_DEVICE_COMMAND(nand, &info);
/* fill in the address fields for the core device */
info->cmd = S3C2440_NFCMD;
info->addr = S3C2440_NFADDR;
info->data = S3C2440_NFDATA;
info->nfstat = S3C2412_NFSTAT;
return ERROR_OK;
}
static int s3c6400_init(struct nand_device *nand)
{
struct s3c24xx_nand_controller *s3c24xx_info = nand->controller_priv;
struct target *target = s3c24xx_info->target;
target_write_u32(target, S3C2410_NFCONF,
S3C2440_NFCONF_TACLS(3) |
S3C2440_NFCONF_TWRPH0(7) |
S3C2440_NFCONF_TWRPH1(7) | 4);
target_write_u32(target, S3C2440_NFCONT,
S3C2412_NFCONT_INIT_MAIN_ECC |
S3C2440_NFCONT_ENABLE);
return ERROR_OK;
}
struct nand_flash_controller s3c6400_nand_controller = {
.name = "s3c6400",
.nand_device_command = &s3c6400_nand_device_command,
.init = &s3c6400_init,
.reset = &s3c24xx_reset,
.command = &s3c24xx_command,
.address = &s3c24xx_address,
.write_data = &s3c24xx_write_data,
.read_data = &s3c24xx_read_data,
.write_page = s3c24xx_write_page,
.read_page = s3c24xx_read_page,
.write_block_data = &s3c2440_write_block_data,
.read_block_data = &s3c2440_read_block_data,
.controller_ready = &s3c24xx_controller_ready,
.nand_ready = &s3c2440_nand_ready,
};

View File

@@ -409,8 +409,8 @@ COMMAND_HANDLER(handle_nand_dump_command)
if (nand_fileio_finish(&s) == ERROR_OK) if (nand_fileio_finish(&s) == ERROR_OK)
{ {
command_print(CMD_CTX, "dumped %zu bytes in %fs (%0.3f kb/s)", command_print(CMD_CTX, "dumped %ld bytes in %fs (%0.3f kb/s)",
s.fileio.size, duration_elapsed(&s.bench), (long)s.fileio.size, duration_elapsed(&s.bench),
duration_kbps(&s.bench, s.fileio.size)); duration_kbps(&s.bench, s.fileio.size));
} }
return ERROR_OK; return ERROR_OK;
@@ -446,68 +446,67 @@ COMMAND_HANDLER(handle_nand_raw_access_command)
static const struct command_registration nand_exec_command_handlers[] = { static const struct command_registration nand_exec_command_handlers[] = {
{ {
.name = "list", .name = "list",
.handler = &handle_nand_list_command, .handler = handle_nand_list_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "list configured NAND flash devices", .help = "list configured NAND flash devices",
}, },
{ {
.name = "info", .name = "info",
.handler = &handle_nand_info_command, .handler = handle_nand_info_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank>", .usage = "[banknum | first_bank_num last_bank_num]",
.help = "print info about a NAND flash device", .help = "print info about one or more NAND flash devices",
}, },
{ {
.name = "probe", .name = "probe",
.handler = &handle_nand_probe_command, .handler = handle_nand_probe_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank>", .usage = "bank_id",
.help = "identify NAND flash device <num>", .help = "identify NAND flash device",
}, },
{ {
.name = "check_bad_blocks", .name = "check_bad_blocks",
.handler = &handle_nand_check_bad_blocks_command, .handler = handle_nand_check_bad_blocks_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank> [<offset> <length>]", .usage = "bank_id [offset length]",
.help = "check NAND flash device <num> for bad blocks", .help = "check all or part of NAND flash device for bad blocks",
}, },
{ {
.name = "erase", .name = "erase",
.handler = &handle_nand_erase_command, .handler = handle_nand_erase_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank> [<offset> <length>]", .usage = "bank_id [offset length]",
.help = "erase blocks on NAND flash device", .help = "erase all or subset of blocks on NAND flash device",
}, },
{ {
.name = "dump", .name = "dump",
.handler = &handle_nand_dump_command, .handler = handle_nand_dump_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank> <filename> <offset> <length> " .usage = "bank_id filename offset length "
"[oob_raw | oob_only]", "['oob_raw'|'oob_only']",
.help = "dump from NAND flash device", .help = "dump from NAND flash device",
}, },
{ {
.name = "verify", .name = "verify",
.handler = &handle_nand_verify_command, .handler = handle_nand_verify_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank> <filename> <offset> " .usage = "bank_id filename offset "
"[oob_raw | oob_only | oob_softecc | oob_softecc_kw]", "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
.help = "verify NAND flash device", .help = "verify NAND flash device",
}, },
{ {
.name = "write", .name = "write",
.handler = &handle_nand_write_command, .handler = handle_nand_write_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank> <filename> <offset> " .usage = "bank_id filename offset "
"[oob_raw | oob_only | oob_softecc | oob_softecc_kw]", "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
.help = "write to NAND flash device", .help = "write to NAND flash device",
}, },
{ {
.name = "raw_access", .name = "raw_access",
.handler = &handle_nand_raw_access_command, .handler = handle_nand_raw_access_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<num> ['enable'|'disable']", .usage = "bank_id ['enable'|'disable']",
.help = "raw access to NAND flash device", .help = "raw access to NAND flash device",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
@@ -614,6 +613,7 @@ static const struct command_registration nand_config_command_handlers[] = {
.handler = &handle_nand_device_command, .handler = &handle_nand_device_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "defines a new NAND bank", .help = "defines a new NAND bank",
.usage = "bank_id driver target [driver_options ...]",
}, },
{ {
.name = "drivers", .name = "drivers",

View File

@@ -413,13 +413,13 @@ static int aduc702x_check_flash_completion(struct target* target, unsigned int t
struct flash_driver aduc702x_flash = { struct flash_driver aduc702x_flash = {
.name = "aduc702x", .name = "aduc702x",
.flash_bank_command = &aduc702x_flash_bank_command, .flash_bank_command = aduc702x_flash_bank_command,
.erase = &aduc702x_erase, .erase = aduc702x_erase,
.protect = &aduc702x_protect, .protect = aduc702x_protect,
.write = &aduc702x_write, .write = aduc702x_write,
.probe = &aduc702x_probe, .probe = aduc702x_probe,
.auto_probe = &aduc702x_probe, .auto_probe = aduc702x_probe,
.erase_check = &default_flash_blank_check, .erase_check = default_flash_blank_check,
.protect_check = &aduc702x_protect_check, .protect_check = aduc702x_protect_check,
.info = &aduc702x_info .info = aduc702x_info
}; };

View File

@@ -2288,7 +2288,7 @@ COMMAND_HANDLER(sam3_handle_info_command)
return ERROR_FAIL; return ERROR_FAIL;
} }
} }
// above garentees the "chip details" structure is valid // above guarantees the "chip details" structure is valid
// and thus, bank private areas are valid // and thus, bank private areas are valid
// and we have a SAM3 chip, what a concept! // and we have a SAM3 chip, what a concept!
@@ -2386,7 +2386,7 @@ COMMAND_HANDLER(sam3_handle_gpnvm_command)
if (0 == strcmp("show", CMD_ARGV[0])) { if (0 == strcmp("show", CMD_ARGV[0])) {
if (who == -1) { if (who == -1) {
showall: showall:
r = ERROR_OK; r = ERROR_OK;
for (x = 0 ; x < pChip->details.n_gpnvms ; x++) { for (x = 0 ; x < pChip->details.n_gpnvms ; x++) {
r = FLASHD_GetGPNVM(&(pChip->details.bank[0]), x, &v); r = FLASHD_GetGPNVM(&(pChip->details.bank[0]), x, &v);
@@ -2466,24 +2466,27 @@ COMMAND_HANDLER(sam3_handle_slowclk_command)
static const struct command_registration at91sam3_exec_command_handlers[] = { static const struct command_registration at91sam3_exec_command_handlers[] = {
{ {
.name = "gpnvm", .name = "gpnvm",
.handler = &sam3_handle_gpnvm_command, .handler = sam3_handle_gpnvm_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "[(set|clear) [<bit_id>]]", .usage = "[('clr'|'set'|'show') bitnum]",
.help = "Without arguments, shows the gpnvm register; " .help = "Without arguments, shows all bits in the gpnvm "
"otherwise, sets or clear the specified bit.", "register. Otherwise, clears, sets, or shows one "
"General Purpose Non-Volatile Memory (gpnvm) bit.",
}, },
{ {
.name = "info", .name = "info",
.handler = &sam3_handle_info_command, .handler = sam3_handle_info_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "print information about the current sam3 chip", .help = "Print information about the current at91sam3 chip"
"and its flash configuration.",
}, },
{ {
.name = "slowclk", .name = "slowclk",
.handler = &sam3_handle_slowclk_command, .handler = sam3_handle_slowclk_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<value>", .usage = "[clock_hz]",
.help = "set the slowclock frequency (default 32768hz)", .help = "Display or set the slowclock frequency "
"(default 32768 Hz).",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -2500,13 +2503,13 @@ static const struct command_registration at91sam3_command_handlers[] = {
struct flash_driver at91sam3_flash = { struct flash_driver at91sam3_flash = {
.name = "at91sam3", .name = "at91sam3",
.commands = at91sam3_command_handlers, .commands = at91sam3_command_handlers,
.flash_bank_command = &sam3_flash_bank_command, .flash_bank_command = sam3_flash_bank_command,
.erase = &sam3_erase, .erase = sam3_erase,
.protect = &sam3_protect, .protect = sam3_protect,
.write = &sam3_write, .write = sam3_write,
.probe = &sam3_probe, .probe = sam3_probe,
.auto_probe = &sam3_auto_probe, .auto_probe = sam3_auto_probe,
.erase_check = &sam3_erase_check, .erase_check = sam3_erase_check,
.protect_check = &sam3_protect_check, .protect_check = sam3_protect_check,
.info = &sam3_info, .info = sam3_info,
}; };

View File

@@ -1182,10 +1182,11 @@ COMMAND_HANDLER(at91sam7_handle_gpnvm_command)
static const struct command_registration at91sam7_exec_command_handlers[] = { static const struct command_registration at91sam7_exec_command_handlers[] = {
{ {
.name = "gpnvm", .name = "gpnvm",
.handler = &at91sam7_handle_gpnvm_command, .handler = at91sam7_handle_gpnvm_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "gpnvm <bit> set | clear, " .help = "set or clear one General Purpose Non-Volatile Memory "
"set or clear one gpnvm bit", "(gpnvm) bit",
.usage = "bitnum ('set'|'clear')",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -1202,13 +1203,13 @@ static const struct command_registration at91sam7_command_handlers[] = {
struct flash_driver at91sam7_flash = { struct flash_driver at91sam7_flash = {
.name = "at91sam7", .name = "at91sam7",
.commands = at91sam7_command_handlers, .commands = at91sam7_command_handlers,
.flash_bank_command = &at91sam7_flash_bank_command, .flash_bank_command = at91sam7_flash_bank_command,
.erase = &at91sam7_erase, .erase = at91sam7_erase,
.protect = &at91sam7_protect, .protect = at91sam7_protect,
.write = &at91sam7_write, .write = at91sam7_write,
.probe = &at91sam7_probe, .probe = at91sam7_probe,
.auto_probe = &at91sam7_probe, .auto_probe = at91sam7_probe,
.erase_check = &at91sam7_erase_check, .erase_check = at91sam7_erase_check,
.protect_check = &at91sam7_protect_check, .protect_check = at91sam7_protect_check,
.info = &at91sam7_info, .info = at91sam7_info,
}; };

View File

@@ -452,7 +452,7 @@ COMMAND_HANDLER(avrf_handle_mass_erase_command)
static const struct command_registration avrf_exec_command_handlers[] = { static const struct command_registration avrf_exec_command_handlers[] = {
{ {
.name = "mass_erase", .name = "mass_erase",
.handler = &avrf_handle_mass_erase_command, .handler = avrf_handle_mass_erase_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "erase entire device", .help = "erase entire device",
}, },
@@ -471,13 +471,13 @@ static const struct command_registration avrf_command_handlers[] = {
struct flash_driver avr_flash = { struct flash_driver avr_flash = {
.name = "avr", .name = "avr",
.commands = avrf_command_handlers, .commands = avrf_command_handlers,
.flash_bank_command = &avrf_flash_bank_command, .flash_bank_command = avrf_flash_bank_command,
.erase = &avrf_erase, .erase = avrf_erase,
.protect = &avrf_protect, .protect = avrf_protect,
.write = &avrf_write, .write = avrf_write,
.probe = &avrf_probe, .probe = avrf_probe,
.auto_probe = &avrf_auto_probe, .auto_probe = avrf_auto_probe,
.erase_check = &default_flash_mem_blank_check, .erase_check = default_flash_mem_blank_check,
.protect_check = &avrf_protect_check, .protect_check = avrf_protect_check,
.info = &avrf_info, .info = avrf_info,
}; };

View File

@@ -2619,13 +2619,13 @@ static int cfi_info(struct flash_bank *bank, char *buf, int buf_size)
struct flash_driver cfi_flash = { struct flash_driver cfi_flash = {
.name = "cfi", .name = "cfi",
.flash_bank_command = &cfi_flash_bank_command, .flash_bank_command = cfi_flash_bank_command,
.erase = &cfi_erase, .erase = cfi_erase,
.protect = &cfi_protect, .protect = cfi_protect,
.write = &cfi_write, .write = cfi_write,
.probe = &cfi_probe, .probe = cfi_probe,
.auto_probe = &cfi_auto_probe, .auto_probe = cfi_auto_probe,
.erase_check = &default_flash_blank_check, .erase_check = default_flash_blank_check,
.protect_check = &cfi_protect_check, .protect_check = cfi_protect_check,
.info = &cfi_info, .info = cfi_info,
}; };

View File

@@ -29,6 +29,13 @@
#include <target/image.h> #include <target/image.h>
/**
* @file
* Upper level of NOR flash framework.
* The lower level interfaces are to drivers. These upper level ones
* primarily support access from Tcl scripts or from GDB.
*/
struct flash_bank *flash_banks; struct flash_bank *flash_banks;
int flash_driver_erase(struct flash_bank *bank, int first, int last) int flash_driver_erase(struct flash_bank *bank, int first, int last)
@@ -280,9 +287,22 @@ int default_flash_blank_check(struct flash_bank *bank)
return ERROR_OK; return ERROR_OK;
} }
/* erase given flash region, selects proper bank according to target and address */ /* Manipulate given flash region, selecting the bank according to target
* and address. Maps an address range to a set of sectors, and issues
* the callback() on that set ... e.g. to erase or unprotect its members.
*
* (Note a current bad assumption: that protection operates on the same
* size sectors as erase operations use.)
*
* The "pad_reason" parameter is a kind of boolean: when it's NULL, the
* range must fit those sectors exactly. This is clearly safe; it can't
* erase data which the caller said to leave alone, for example. If it's
* non-NULL, rather than failing, extra data in the first and/or last
* sectors will be added to the range, and that reason string is used when
* warning about those additions.
*/
static int flash_iterate_address_range(struct target *target, static int flash_iterate_address_range(struct target *target,
uint32_t addr, uint32_t length, char *pad_reason, uint32_t addr, uint32_t length,
int (*callback)(struct flash_bank *bank, int first, int last)) int (*callback)(struct flash_bank *bank, int first, int last))
{ {
struct flash_bank *c; struct flash_bank *c;
@@ -304,34 +324,76 @@ static int flash_iterate_address_range(struct target *target,
{ {
/* special case, erase whole bank when length is zero */ /* special case, erase whole bank when length is zero */
if (addr != c->base) if (addr != c->base)
{
LOG_ERROR("Whole bank access must start at beginning of bank.");
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}
return callback(c, 0, c->num_sectors - 1); return callback(c, 0, c->num_sectors - 1);
} }
/* check whether it all fits in this bank */ /* check whether it all fits in this bank */
if (addr + length - 1 > c->base + c->size - 1) if (addr + length - 1 > c->base + c->size - 1)
{
LOG_ERROR("Flash access does not fit into bank.");
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
}
/** @todo: handle erasures that cross into adjacent banks */ /** @todo: handle erasures that cross into adjacent banks */
addr -= c->base; addr -= c->base;
last_addr -= c->base;
for (i = 0; i < c->num_sectors; i++) for (i = 0; i < c->num_sectors; i++)
{ {
struct flash_sector *f = c->sectors + i; struct flash_sector *f = c->sectors + i;
uint32_t end = f->offset + f->size;
/* start only on a sector boundary */ /* start only on a sector boundary */
if (first < 0) { if (first < 0) {
/* scanned past the first sector? */
if (addr < f->offset)
break;
/* is this the first sector? */ /* is this the first sector? */
if (addr == f->offset) if (addr == f->offset)
first = i; first = i;
else if (addr < f->offset)
break; /* Does this need head-padding? If so, pad and warn;
* or else force an error.
*
* Such padding can make trouble, since *WE* can't
* ever know if that data was in use. The warning
* should help users sort out messes later.
*/
else if (addr < end && pad_reason) {
/* FIXME say how many bytes (e.g. 80 KB) */
LOG_WARNING("Adding extra %s range, "
"%#8.8x to %#8.8x",
pad_reason,
(unsigned) f->offset,
(unsigned) addr - 1);
first = i;
} else
continue;
} }
/* is this (also?) the last sector? */ /* is this (also?) the last sector? */
if (last_addr == f->offset + f->size) { if (last_addr == end) {
last = i;
break;
}
/* Does this need tail-padding? If so, pad and warn;
* or else force an error.
*/
if (last_addr < end && pad_reason) {
/* FIXME say how many bytes (e.g. 80 KB) */
LOG_WARNING("Adding extra %s range, "
"%#8.8x to %#8.8x",
pad_reason,
(unsigned) last_addr,
(unsigned) end - 1);
last = i; last = i;
break; break;
} }
@@ -346,22 +408,21 @@ static int flash_iterate_address_range(struct target *target,
LOG_ERROR("address range 0x%8.8x .. 0x%8.8x " LOG_ERROR("address range 0x%8.8x .. 0x%8.8x "
"is not sector-aligned", "is not sector-aligned",
(unsigned) (c->base + addr), (unsigned) (c->base + addr),
(unsigned) (last_addr - 1)); (unsigned) (c->base + last_addr - 1));
return ERROR_FLASH_DST_BREAKS_ALIGNMENT; return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
} }
/* The NOR driver may trim this range down, based on /* The NOR driver may trim this range down, based on what
* whether or not a given sector is already erased. * sectors are already erased/unprotected. GDB currently
* * blocks such optimizations.
* REVISIT should *we* trim it... ?
*/ */
return callback(c, first, last); return callback(c, first, last);
} }
int flash_erase_address_range(struct target *target, int flash_erase_address_range(struct target *target,
uint32_t addr, uint32_t length) bool pad, uint32_t addr, uint32_t length)
{ {
return flash_iterate_address_range(target, return flash_iterate_address_range(target, pad ? "erase" : NULL,
addr, length, &flash_driver_erase); addr, length, &flash_driver_erase);
} }
@@ -372,7 +433,11 @@ static int flash_driver_unprotect(struct flash_bank *bank, int first, int last)
static int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length) static int flash_unlock_address_range(struct target *target, uint32_t addr, uint32_t length)
{ {
return flash_iterate_address_range(target, /* By default, pad to sector boundaries ... the real issue here
* is that our (only) caller *permanently* removes protection,
* and doesn't restore it.
*/
return flash_iterate_address_range(target, "unprotect",
addr, length, &flash_driver_unprotect); addr, length, &flash_driver_unprotect);
} }
@@ -386,6 +451,12 @@ int flash_write_unlock(struct target *target, struct image *image,
struct flash_bank *c; struct flash_bank *c;
int *padding; int *padding;
/* REVISIT do_pad should perhaps just be another parameter.
* GDB wouldn't ever need it, since it erases separately.
* But "flash write_image" commands might want that option.
*/
bool do_pad = false;
section = 0; section = 0;
section_offset = 0; section_offset = 0;
@@ -401,7 +472,7 @@ int flash_write_unlock(struct target *target, struct image *image,
} }
/* allocate padding array */ /* allocate padding array */
padding = malloc(image->num_sections * sizeof(padding)); padding = calloc(image->num_sections, sizeof(*padding));
/* loop until we reach end of the image */ /* loop until we reach end of the image */
while (section < image->num_sections) while (section < image->num_sections)
@@ -439,10 +510,31 @@ int flash_write_unlock(struct target *target, struct image *image,
{ {
if (image->sections[section_last + 1].base_address < (run_address + run_size)) if (image->sections[section_last + 1].base_address < (run_address + run_size))
{ {
LOG_DEBUG("section %d out of order(very slightly surprising, but supported)", section_last + 1); LOG_DEBUG("section %d out of order "
"(surprising, but supported)",
section_last + 1);
/* REVISIT this can break with autoerase ...
* clobbering data after it's written.
*/
break; break;
} }
/* if we have multiple sections within our image, flash programming could fail due to alignment issues
/* FIXME This needlessly touches sectors BETWEEN the
* sections it's writing. Without auto erase, it just
* writes ones. That WILL INVALIDATE data in cases
* like Stellaris Tempest chips, corrupting internal
* ECC codes; and at least FreeScale suggests issues
* with that approach (in HC11 documentation).
*
* With auto erase enabled, data in those sectors will
* be needlessly destroyed; and some of the limited
* number of flash erase cycles will be wasted...
*
* In both cases, the extra writes slow things down.
*/
/* if we have multiple sections within our image,
* flash programming could fail due to alignment issues
* attempt to rebuild a consecutive buffer for the flash loader */ * attempt to rebuild a consecutive buffer for the flash loader */
pad_bytes = (image->sections[section_last + 1].base_address) - (run_address + run_size); pad_bytes = (image->sections[section_last + 1].base_address) - (run_address + run_size);
if ((run_address + run_size + pad_bytes) > (c->base + c->size)) if ((run_address + run_size + pad_bytes) > (c->base + c->size))
@@ -450,7 +542,6 @@ int flash_write_unlock(struct target *target, struct image *image,
padding[section_last] = pad_bytes; padding[section_last] = pad_bytes;
run_size += image->sections[++section_last].size; run_size += image->sections[++section_last].size;
run_size += pad_bytes; run_size += pad_bytes;
padding[section_last] = 0;
LOG_INFO("Padding image section %d with %d bytes", section_last-1, pad_bytes); LOG_INFO("Padding image section %d with %d bytes", section_last-1, pad_bytes);
} }
@@ -458,11 +549,35 @@ int flash_write_unlock(struct target *target, struct image *image,
/* fit the run into bank constraints */ /* fit the run into bank constraints */
if (run_address + run_size - 1 > c->base + c->size - 1) if (run_address + run_size - 1 > c->base + c->size - 1)
{ {
/* REVISIT isn't this superfluous, given the while()
* loop conditions above??
*/
LOG_WARNING("writing %d bytes only - as image section is %d bytes and bank is only %d bytes", \ LOG_WARNING("writing %d bytes only - as image section is %d bytes and bank is only %d bytes", \
(int)(c->base + c->size - run_address), (int)(run_size), (int)(c->size)); (int)(c->base + c->size - run_address), (int)(run_size), (int)(c->size));
run_size = c->base + c->size - run_address; run_size = c->base + c->size - run_address;
} }
/* If we're applying any sector automagic, then pad this
* (maybe-combined) segment to the end of its last sector.
*/
if (unlock || erase) {
int sector;
uint32_t offset_start = run_address - c->base;
uint32_t offset_end = offset_start + run_size;
uint32_t end = offset_end, delta;
for (sector = 0; sector < c->num_sectors; sector++) {
end = c->sectors[sector].offset
+ c->sectors[sector].size;
if (offset_end <= end)
break;
}
delta = end - offset_end;
padding[section_last] += delta;
run_size += delta;
}
/* allocate buffer */ /* allocate buffer */
buffer = malloc(run_size); buffer = malloc(run_size);
buffer_size = 0; buffer_size = 0;
@@ -509,7 +624,8 @@ int flash_write_unlock(struct target *target, struct image *image,
if (erase) if (erase)
{ {
/* calculate and erase sectors */ /* calculate and erase sectors */
retval = flash_erase_address_range(target, run_address, run_size); retval = flash_erase_address_range(target,
do_pad, run_address, run_size);
} }
} }

View File

@@ -24,6 +24,11 @@
#include <flash/common.h> #include <flash/common.h>
/**
* @file
* Upper level NOR flash interfaces.
*/
struct image; struct image;
#define FLASH_MAX_ERROR_STR (128) #define FLASH_MAX_ERROR_STR (128)
@@ -97,10 +102,14 @@ int flash_init_drivers(struct command_context *cmd_ctx);
/** /**
* Erases @a length bytes in the @a target flash, starting at @a addr. * Erases @a length bytes in the @a target flash, starting at @a addr.
* The range @a addr to @a addr + @a length - 1 must be strictly
* sector aligned, unless @a pad is true. Setting @a pad true extends
* the range, at beginning and/or end, if needed for sector alignment.
* @returns ERROR_OK if successful; otherwise, an error code. * @returns ERROR_OK if successful; otherwise, an error code.
*/ */
int flash_erase_address_range(struct target *target, int flash_erase_address_range(struct target *target,
uint32_t addr, uint32_t length); bool pad, uint32_t addr, uint32_t length);
/** /**
* Writes @a image into the @a target flash. The @a written parameter * Writes @a image into the @a target flash. The @a written parameter
* will contain the * will contain the

View File

@@ -432,13 +432,13 @@ static int ecosflash_handle_gpnvm_command(struct command_context *cmd_ctx, char
struct flash_driver ecosflash_flash = { struct flash_driver ecosflash_flash = {
.name = "ecosflash", .name = "ecosflash",
.flash_bank_command = &ecosflash_flash_bank_command, .flash_bank_command = ecosflash_flash_bank_command,
.erase = &ecosflash_erase, .erase = ecosflash_erase,
.protect = &ecosflash_protect, .protect = ecosflash_protect,
.write = &ecosflash_write, .write = ecosflash_write,
.probe = &ecosflash_probe, .probe = ecosflash_probe,
.auto_probe = &ecosflash_probe, .auto_probe = ecosflash_probe,
.erase_check = &default_flash_blank_check, .erase_check = default_flash_blank_check,
.protect_check = &ecosflash_protect_check, .protect_check = ecosflash_protect_check,
.info = &ecosflash_info .info = ecosflash_info
}; };

View File

@@ -137,13 +137,13 @@ static const struct command_registration faux_command_handlers[] = {
struct flash_driver faux_flash = { struct flash_driver faux_flash = {
.name = "faux", .name = "faux",
.commands = faux_command_handlers, .commands = faux_command_handlers,
.flash_bank_command = &faux_flash_bank_command, .flash_bank_command = faux_flash_bank_command,
.erase = &faux_erase, .erase = faux_erase,
.protect = &faux_protect, .protect = faux_protect,
.write = &faux_write, .write = faux_write,
.probe = &faux_probe, .probe = faux_probe,
.auto_probe = &faux_probe, .auto_probe = faux_probe,
.erase_check = &default_flash_blank_check, .erase_check = default_flash_blank_check,
.protect_check = &faux_protect_check, .protect_check = faux_protect_check,
.info = &faux_info .info = faux_info
}; };

View File

@@ -783,7 +783,7 @@ COMMAND_HANDLER(lpc2000_handle_part_id_command)
static const struct command_registration lpc2000_exec_command_handlers[] = { static const struct command_registration lpc2000_exec_command_handlers[] = {
{ {
.name = "part_id", .name = "part_id",
.handler = &lpc2000_handle_part_id_command, .handler = lpc2000_handle_part_id_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "print part id of lpc2000 flash bank <num>", .help = "print part id of lpc2000 flash bank <num>",
}, },
@@ -802,15 +802,13 @@ static const struct command_registration lpc2000_command_handlers[] = {
struct flash_driver lpc2000_flash = { struct flash_driver lpc2000_flash = {
.name = "lpc2000", .name = "lpc2000",
.commands = lpc2000_command_handlers, .commands = lpc2000_command_handlers,
.flash_bank_command = &lpc2000_flash_bank_command, .flash_bank_command = lpc2000_flash_bank_command,
.erase = &lpc2000_erase, .erase = lpc2000_erase,
.protect = &lpc2000_protect, .protect = lpc2000_protect,
.write = &lpc2000_write, .write = lpc2000_write,
.probe = &lpc2000_probe, .probe = lpc2000_probe,
.auto_probe = &lpc2000_probe, .auto_probe = lpc2000_probe,
.erase_check = &lpc2000_erase_check, .erase_check = lpc2000_erase_check,
.protect_check = &lpc2000_protect_check, .protect_check = lpc2000_protect_check,
.info = &lpc2000_info, .info = lpc2000_info,
}; };

View File

@@ -474,13 +474,13 @@ static int lpc288x_protect(struct flash_bank *bank, int set, int first, int last
struct flash_driver lpc288x_flash = { struct flash_driver lpc288x_flash = {
.name = "lpc288x", .name = "lpc288x",
.flash_bank_command = &lpc288x_flash_bank_command, .flash_bank_command = lpc288x_flash_bank_command,
.erase = &lpc288x_erase, .erase = lpc288x_erase,
.protect = &lpc288x_protect, .protect = lpc288x_protect,
.write = &lpc288x_write, .write = lpc288x_write,
.probe = &lpc288x_probe, .probe = lpc288x_probe,
.auto_probe = &lpc288x_probe, .auto_probe = lpc288x_probe,
.erase_check = &lpc288x_erase_check, .erase_check = lpc288x_erase_check,
.protect_check = &lpc288x_protect_check, .protect_check = lpc288x_protect_check,
.info = &lpc288x_info, .info = lpc288x_info,
}; };

View File

@@ -951,45 +951,49 @@ COMMAND_HANDLER(lpc2900_handle_secure_jtag_command)
static const struct command_registration lpc2900_exec_command_handlers[] = { static const struct command_registration lpc2900_exec_command_handlers[] = {
{ {
.name = "signature", .name = "signature",
.handler = &lpc2900_handle_signature_command, .handler = lpc2900_handle_signature_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank>", .usage = "bank_id",
.help = "print device signature of flash bank", .help = "Calculate and display signature of flash bank.",
}, },
{ {
.name = "read_custom", .name = "read_custom",
.handler = &lpc2900_handle_read_custom_command, .handler = lpc2900_handle_read_custom_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank> <filename>", .usage = "bank_id filename",
.help = "read customer information from index sector to file", .help = "Copies 912 bytes of customer information "
"from index sector into file.",
}, },
{ {
.name = "password", .name = "password",
.handler = &lpc2900_handle_password_command, .handler = lpc2900_handle_password_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank> <password>", .usage = "bank_id password",
.help = "enter password to enable 'dangerous' options", .help = "Enter fixed password to enable 'dangerous' options.",
}, },
{ {
.name = "write_custom", .name = "write_custom",
.handler = &lpc2900_handle_write_custom_command, .handler = lpc2900_handle_write_custom_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank> <filename> [<type>]", .usage = "bank_id filename ('bin'|'ihex'|'elf'|'s19')",
.help = "write customer info from file to index sector", .help = "Copies 912 bytes of customer info from file "
"to index sector.",
}, },
{ {
.name = "secure_sector", .name = "secure_sector",
.handler = &lpc2900_handle_secure_sector_command, .handler = lpc2900_handle_secure_sector_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank> <first> <last>", .usage = "bank_id first_sector last_sector",
.help = "activate sector security for a range of sectors", .help = "Activate sector security for a range of sectors. "
"It will be effective after a power cycle.",
}, },
{ {
.name = "secure_jtag", .name = "secure_jtag",
.handler = &lpc2900_handle_secure_jtag_command, .handler = lpc2900_handle_secure_jtag_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank> <level>", .usage = "bank_id",
.help = "activate JTAG security", .help = "Disable the JTAG port. "
"It will be effective after a power cycle.",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@@ -349,13 +349,13 @@ static int ocl_auto_probe(struct flash_bank *bank)
struct flash_driver ocl_flash = { struct flash_driver ocl_flash = {
.name = "ocl", .name = "ocl",
.flash_bank_command = &ocl_flash_bank_command, .flash_bank_command = ocl_flash_bank_command,
.erase = &ocl_erase, .erase = ocl_erase,
.protect = &ocl_protect, .protect = ocl_protect,
.write = &ocl_write, .write = ocl_write,
.probe = &ocl_probe, .probe = ocl_probe,
.erase_check = &ocl_erase_check, .erase_check = ocl_erase_check,
.protect_check = &ocl_protect_check, .protect_check = ocl_protect_check,
.info = &ocl_info, .info = ocl_info,
.auto_probe = &ocl_auto_probe, .auto_probe = ocl_auto_probe,
}; };

View File

@@ -886,13 +886,13 @@ COMMAND_HANDLER(pic32mx_handle_pgm_word_command)
static const struct command_registration pic32mx_exec_command_handlers[] = { static const struct command_registration pic32mx_exec_command_handlers[] = {
{ {
.name = "chip_erase", .name = "chip_erase",
.handler = &pic32mx_handle_chip_erase_command, .handler = pic32mx_handle_chip_erase_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "erase device", .help = "erase device",
}, },
{ {
.name = "pgm_word", .name = "pgm_word",
.handler = &pic32mx_handle_pgm_word_command, .handler = pic32mx_handle_pgm_word_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "program a word", .help = "program a word",
}, },
@@ -911,13 +911,13 @@ static const struct command_registration pic32mx_command_handlers[] = {
struct flash_driver pic32mx_flash = { struct flash_driver pic32mx_flash = {
.name = "pic32mx", .name = "pic32mx",
.commands = pic32mx_command_handlers, .commands = pic32mx_command_handlers,
.flash_bank_command = &pic32mx_flash_bank_command, .flash_bank_command = pic32mx_flash_bank_command,
.erase = &pic32mx_erase, .erase = pic32mx_erase,
.protect = &pic32mx_protect, .protect = pic32mx_protect,
.write = &pic32mx_write, .write = pic32mx_write,
.probe = &pic32mx_probe, .probe = pic32mx_probe,
.auto_probe = &pic32mx_auto_probe, .auto_probe = pic32mx_auto_probe,
.erase_check = &default_flash_mem_blank_check, .erase_check = default_flash_mem_blank_check,
.protect_check = &pic32mx_protect_check, .protect_check = pic32mx_protect_check,
.info = &pic32mx_info, .info = pic32mx_info,
}; };

View File

@@ -1173,7 +1173,7 @@ COMMAND_HANDLER(stellaris_handle_mass_erase_command)
static const struct command_registration stellaris_exec_command_handlers[] = { static const struct command_registration stellaris_exec_command_handlers[] = {
{ {
.name = "mass_erase", .name = "mass_erase",
.handler = &stellaris_handle_mass_erase_command, .handler = stellaris_handle_mass_erase_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "erase entire device", .help = "erase entire device",
}, },
@@ -1182,7 +1182,7 @@ static const struct command_registration stellaris_exec_command_handlers[] = {
static const struct command_registration stellaris_command_handlers[] = { static const struct command_registration stellaris_command_handlers[] = {
{ {
.name = "stellaris", .name = "stellaris",
.mode = COMMAND_ANY, .mode = COMMAND_EXEC,
.help = "Stellaris flash command group", .help = "Stellaris flash command group",
.chain = stellaris_exec_command_handlers, .chain = stellaris_exec_command_handlers,
}, },

View File

@@ -978,7 +978,9 @@ COMMAND_HANDLER(stm32x_handle_unlock_command)
return ERROR_OK; return ERROR_OK;
} }
command_print(CMD_CTX, "stm32x unlocked"); command_print(CMD_CTX, "stm32x unlocked.\n"
"INFO: a reset or power cycle is required "
"for the new settings to take effect.");
return ERROR_OK; return ERROR_OK;
} }
@@ -1066,29 +1068,36 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
/* REVISIT: ignores some options which we will display...
* and doesn't insist on the specified syntax.
*/
/* OPT_RDWDGSW */
if (strcmp(CMD_ARGV[1], "SWWDG") == 0) if (strcmp(CMD_ARGV[1], "SWWDG") == 0)
{ {
optionbyte |= (1 << 0); optionbyte |= (1 << 0);
} }
else else /* REVISIT must be "HWWDG" then ... */
{ {
optionbyte &= ~(1 << 0); optionbyte &= ~(1 << 0);
} }
/* OPT_RDRSTSTDBY */
if (strcmp(CMD_ARGV[2], "NORSTSTNDBY") == 0) if (strcmp(CMD_ARGV[2], "NORSTSTNDBY") == 0)
{ {
optionbyte |= (1 << 1); optionbyte |= (1 << 1);
} }
else else /* REVISIT must be "RSTSTNDBY" then ... */
{ {
optionbyte &= ~(1 << 1); optionbyte &= ~(1 << 1);
} }
/* OPT_RDRSTSTOP */
if (strcmp(CMD_ARGV[3], "NORSTSTOP") == 0) if (strcmp(CMD_ARGV[3], "NORSTSTOP") == 0)
{ {
optionbyte |= (1 << 2); optionbyte |= (1 << 2);
} }
else else /* REVISIT must be "RSTSTOP" then ... */
{ {
optionbyte &= ~(1 << 2); optionbyte &= ~(1 << 2);
} }
@@ -1107,7 +1116,9 @@ COMMAND_HANDLER(stm32x_handle_options_write_command)
return ERROR_OK; return ERROR_OK;
} }
command_print(CMD_CTX, "stm32x write options complete"); command_print(CMD_CTX, "stm32x write options complete.\n"
"INFO: a reset or power cycle is required "
"for the new settings to take effect.");
return ERROR_OK; return ERROR_OK;
} }
@@ -1186,33 +1197,40 @@ COMMAND_HANDLER(stm32x_handle_mass_erase_command)
static const struct command_registration stm32x_exec_command_handlers[] = { static const struct command_registration stm32x_exec_command_handlers[] = {
{ {
.name = "lock", .name = "lock",
.handler = &stm32x_handle_lock_command, .handler = stm32x_handle_lock_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "lock device", .usage = "bank_id",
.help = "Lock entire flash device.",
}, },
{ {
.name = "unlock", .name = "unlock",
.handler = &stm32x_handle_unlock_command, .handler = stm32x_handle_unlock_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "unlock protected device", .usage = "bank_id",
.help = "Unlock entire protected flash device.",
}, },
{ {
.name = "mass_erase", .name = "mass_erase",
.handler = &stm32x_handle_mass_erase_command, .handler = stm32x_handle_mass_erase_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "mass erase device", .usage = "bank_id",
.help = "Erase entire flash device.",
}, },
{ {
.name = "options_read", .name = "options_read",
.handler = &stm32x_handle_options_read_command, .handler = stm32x_handle_options_read_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "read device option bytes", .usage = "bank_id",
.help = "Read and display device option byte.",
}, },
{ {
.name = "options_write", .name = "options_write",
.handler = &stm32x_handle_options_write_command, .handler = stm32x_handle_options_write_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "write device option bytes", .usage = "bank_id ('SWWDG'|'HWWDG') "
"('RSTSTNDBY'|'NORSTSTNDBY') "
"('RSTSTOP'|'NORSTSTOP')",
.help = "Replace bits in device option byte.",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -1229,13 +1247,13 @@ static const struct command_registration stm32x_command_handlers[] = {
struct flash_driver stm32x_flash = { struct flash_driver stm32x_flash = {
.name = "stm32x", .name = "stm32x",
.commands = stm32x_command_handlers, .commands = stm32x_command_handlers,
.flash_bank_command = &stm32x_flash_bank_command, .flash_bank_command = stm32x_flash_bank_command,
.erase = &stm32x_erase, .erase = stm32x_erase,
.protect = &stm32x_protect, .protect = stm32x_protect,
.write = &stm32x_write, .write = stm32x_write,
.probe = &stm32x_probe, .probe = stm32x_probe,
.auto_probe = &stm32x_auto_probe, .auto_probe = stm32x_auto_probe,
.erase_check = &default_flash_mem_blank_check, .erase_check = default_flash_mem_blank_check,
.protect_check = &stm32x_protect_check, .protect_check = stm32x_protect_check,
.info = &stm32x_info, .info = stm32x_info,
}; };

View File

@@ -93,7 +93,10 @@ static int str7x_build_block_list(struct flash_bank *bank)
bank->sectors[num_sectors].offset = mem_layout_str7bank0[i].sector_start; bank->sectors[num_sectors].offset = mem_layout_str7bank0[i].sector_start;
bank->sectors[num_sectors].size = mem_layout_str7bank0[i].sector_size; bank->sectors[num_sectors].size = mem_layout_str7bank0[i].sector_size;
bank->sectors[num_sectors].is_erased = -1; bank->sectors[num_sectors].is_erased = -1;
bank->sectors[num_sectors].is_protected = 1; /* the reset_init handler marks all the sectors unprotected,
* matching hardware after reset; keep the driver in sync
*/
bank->sectors[num_sectors].is_protected = 0;
str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank0[i].sector_bit; str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank0[i].sector_bit;
} }
@@ -102,7 +105,10 @@ static int str7x_build_block_list(struct flash_bank *bank)
bank->sectors[num_sectors].offset = mem_layout_str7bank1[i].sector_start; bank->sectors[num_sectors].offset = mem_layout_str7bank1[i].sector_start;
bank->sectors[num_sectors].size = mem_layout_str7bank1[i].sector_size; bank->sectors[num_sectors].size = mem_layout_str7bank1[i].sector_size;
bank->sectors[num_sectors].is_erased = -1; bank->sectors[num_sectors].is_erased = -1;
bank->sectors[num_sectors].is_protected = 1; /* the reset_init handler marks all the sectors unprotected,
* matching hardware after reset; keep the driver in sync
*/
bank->sectors[num_sectors].is_protected = 0;
str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank1[i].sector_bit; str7x_info->sector_bits[num_sectors++] = mem_layout_str7bank1[i].sector_bit;
} }
@@ -600,6 +606,12 @@ COMMAND_HANDLER(str7x_handle_part_id_command)
static int str7x_info(struct flash_bank *bank, char *buf, int buf_size) static int str7x_info(struct flash_bank *bank, char *buf, int buf_size)
{ {
snprintf(buf, buf_size, "str7x flash driver info"); snprintf(buf, buf_size, "str7x flash driver info");
/* STR7x flash doesn't support sector protection interrogation.
* FLASH_NVWPAR acts as a write only register; its read value
* doesn't reflect the actual protection state of the sectors.
*/
LOG_WARNING("STR7x flash lock information might not be correct "
"due to hardware limitations.");
return ERROR_OK; return ERROR_OK;
} }
@@ -676,7 +688,7 @@ COMMAND_HANDLER(str7x_handle_disable_jtag_command)
static const struct command_registration str7x_exec_command_handlers[] = { static const struct command_registration str7x_exec_command_handlers[] = {
{ {
.name = "disable_jtag", .name = "disable_jtag",
.handler = &str7x_handle_disable_jtag_command, .handler = str7x_handle_disable_jtag_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "disable jtag access", .help = "disable jtag access",
}, },
@@ -695,13 +707,13 @@ static const struct command_registration str7x_command_handlers[] = {
struct flash_driver str7x_flash = { struct flash_driver str7x_flash = {
.name = "str7x", .name = "str7x",
.commands = str7x_command_handlers, .commands = str7x_command_handlers,
.flash_bank_command = &str7x_flash_bank_command, .flash_bank_command = str7x_flash_bank_command,
.erase = &str7x_erase, .erase = str7x_erase,
.protect = &str7x_protect, .protect = str7x_protect,
.write = &str7x_write, .write = str7x_write,
.probe = &str7x_probe, .probe = str7x_probe,
.auto_probe = &str7x_probe, .auto_probe = str7x_probe,
.erase_check = &default_flash_blank_check, .erase_check = default_flash_blank_check,
.protect_check = &str7x_protect_check, .protect_check = str7x_protect_check,
.info = &str7x_info, .info = str7x_info,
}; };

View File

@@ -230,17 +230,9 @@ static int str9x_erase(struct flash_bank *bank, int first, int last)
return ERROR_TARGET_NOT_HALTED; return ERROR_TARGET_NOT_HALTED;
} }
/* Check if we erase whole bank */ /*A slower but stable way of erasing*/
if ((first == 0) && (last == (bank->num_sectors - 1)))
{
/* Optimize to run erase bank command instead of sector */
erase_cmd = 0x80;
}
else
{
/* Erase sector command */ /* Erase sector command */
erase_cmd = 0x20; erase_cmd = 0x20;
}
for (i = first; i <= last; i++) for (i = first; i <= last; i++)
{ {
@@ -296,10 +288,6 @@ static int str9x_erase(struct flash_bank *bank, int first, int last)
LOG_ERROR("error erasing flash bank, status: 0x%x", status); LOG_ERROR("error erasing flash bank, status: 0x%x", status);
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
} }
/* If we ran erase bank command, we are finished */
if (erase_cmd == 0x80)
break;
} }
for (i = first; i <= last; i++) for (i = first; i <= last; i++)
@@ -679,11 +667,12 @@ COMMAND_HANDLER(str9x_handle_flash_config_command)
static const struct command_registration str9x_config_command_handlers[] = { static const struct command_registration str9x_config_command_handlers[] = {
{ {
.name = "disable_jtag", .name = "flash_config",
.handler = &str9x_handle_flash_config_command, .handler = str9x_handle_flash_config_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "configure str9x flash controller", .help = "Configure str9x flash controller, prior to "
.usage = "<bank_id> <BBSR> <NBBSR> <BBADR> <NBBADR>", "programming the flash.",
.usage = "bank_id BBSR NBBSR BBADR NBBADR",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -700,13 +689,13 @@ static const struct command_registration str9x_command_handlers[] = {
struct flash_driver str9x_flash = { struct flash_driver str9x_flash = {
.name = "str9x", .name = "str9x",
.commands = str9x_command_handlers, .commands = str9x_command_handlers,
.flash_bank_command = &str9x_flash_bank_command, .flash_bank_command = str9x_flash_bank_command,
.erase = &str9x_erase, .erase = str9x_erase,
.protect = &str9x_protect, .protect = str9x_protect,
.write = &str9x_write, .write = str9x_write,
.probe = &str9x_probe, .probe = str9x_probe,
.auto_probe = &str9x_probe, .auto_probe = str9x_probe,
.erase_check = &default_flash_blank_check, .erase_check = default_flash_blank_check,
.protect_check = &str9x_protect_check, .protect_check = str9x_protect_check,
.info = &str9x_info, .info = str9x_info,
}; };

View File

@@ -915,6 +915,10 @@ COMMAND_HANDLER(str9xpec_handle_flash_options_write_command)
if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
command_print(CMD_CTX, "str9xpec write options complete.\n"
"INFO: a reset or power cycle is required "
"for the new settings to take effect.");
return ERROR_OK; return ERROR_OK;
} }
@@ -1077,6 +1081,10 @@ COMMAND_HANDLER(str9xpec_handle_flash_unlock_command)
if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS) if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
return ERROR_FLASH_OPERATION_FAILED; return ERROR_FLASH_OPERATION_FAILED;
command_print(CMD_CTX, "str9xpec unlocked.\n"
"INFO: a reset or power cycle is required "
"for the new settings to take effect.");
return ERROR_OK; return ERROR_OK;
} }
@@ -1246,13 +1254,13 @@ static const struct command_registration str9xpec_command_handlers[] = {
struct flash_driver str9xpec_flash = { struct flash_driver str9xpec_flash = {
.name = "str9xpec", .name = "str9xpec",
.commands = str9xpec_command_handlers, .commands = str9xpec_command_handlers,
.flash_bank_command = &str9xpec_flash_bank_command, .flash_bank_command = str9xpec_flash_bank_command,
.erase = &str9xpec_erase, .erase = str9xpec_erase,
.protect = &str9xpec_protect, .protect = str9xpec_protect,
.write = &str9xpec_write, .write = str9xpec_write,
.probe = &str9xpec_probe, .probe = str9xpec_probe,
.auto_probe = &str9xpec_probe, .auto_probe = str9xpec_probe,
.erase_check = &str9xpec_erase_check, .erase_check = str9xpec_erase_check,
.protect_check = &str9xpec_protect_check, .protect_check = str9xpec_protect_check,
.info = &str9xpec_info, .info = str9xpec_info,
}; };

View File

@@ -26,6 +26,11 @@
#include <helper/time_support.h> #include <helper/time_support.h>
#include <target/image.h> #include <target/image.h>
/**
* @file
* Implements Tcl commands used to access NOR flash facilities.
*/
COMMAND_HELPER(flash_command_get_bank, unsigned name_index, COMMAND_HELPER(flash_command_get_bank, unsigned name_index,
struct flash_bank **bank) struct flash_bank **bank)
{ {
@@ -198,14 +203,29 @@ COMMAND_HANDLER(handle_flash_erase_address_command)
int retval; int retval;
int address; int address;
int length; int length;
bool do_pad = false;
struct target *target = get_current_target(CMD_CTX); struct target *target = get_current_target(CMD_CTX);
if (CMD_ARGC != 2) switch (CMD_ARGC) {
case 3:
/* Optionally pad out the address range to block/sector
* boundaries. We can't know if there's data in that part
* of the flash; only do padding if we're told to.
*/
if (strcmp("pad", CMD_ARGV[0]) != 0)
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
do_pad = true;
CMD_ARGC--;
CMD_ARGV++;
/* FALL THROUGH */
case 2:
COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], address); COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], address);
COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], length); COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], length);
break;
default:
return ERROR_COMMAND_SYNTAX_ERROR;
}
if (length <= 0) if (length <= 0)
{ {
command_print(CMD_CTX, "Length must be >0"); command_print(CMD_CTX, "Length must be >0");
@@ -224,7 +244,7 @@ COMMAND_HANDLER(handle_flash_erase_address_command)
struct duration bench; struct duration bench;
duration_start(&bench); duration_start(&bench);
retval = flash_erase_address_range(target, address, length); retval = flash_erase_address_range(target, do_pad, address, length);
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
{ {
@@ -439,7 +459,7 @@ COMMAND_HANDLER(handle_flash_write_image_command)
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
{ {
command_print(CMD_CTX, "wrote %" PRIu32 " byte from file %s " command_print(CMD_CTX, "wrote %" PRIu32 " bytes from file %s "
"in %fs (%0.3f kb/s)", written, CMD_ARGV[0], "in %fs (%0.3f kb/s)", written, CMD_ARGV[0],
duration_elapsed(&bench), duration_kbps(&bench, written)); duration_elapsed(&bench), duration_kbps(&bench, written));
} }
@@ -625,9 +645,9 @@ COMMAND_HANDLER(handle_flash_write_bank_command)
if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK)) if ((ERROR_OK == retval) && (duration_measure(&bench) == ERROR_OK))
{ {
command_print(CMD_CTX, "wrote %zu byte from file %s to flash bank %u" command_print(CMD_CTX, "wrote %ld bytes from file %s to flash bank %u"
" at offset 0x%8.8" PRIx32 " in %fs (%0.3f kb/s)", " at offset 0x%8.8" PRIx32 " in %fs (%0.3f kb/s)",
fileio.size, CMD_ARGV[1], p->bank_number, offset, (long)fileio.size, CMD_ARGV[1], p->bank_number, offset,
duration_elapsed(&bench), duration_kbps(&bench, fileio.size)); duration_elapsed(&bench), duration_kbps(&bench, fileio.size));
} }
@@ -654,89 +674,102 @@ void flash_set_dirty(void)
static const struct command_registration flash_exec_command_handlers[] = { static const struct command_registration flash_exec_command_handlers[] = {
{ {
.name = "probe", .name = "probe",
.handler = &handle_flash_probe_command, .handler = handle_flash_probe_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank>", .usage = "bank_id",
.help = "identify flash bank", .help = "Identify a flash bank.",
}, },
{ {
.name = "info", .name = "info",
.handler = &handle_flash_info_command, .handler = handle_flash_info_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank>", .usage = "bank_id",
.help = "print bank information", .help = "Print information about a flash bank.",
}, },
{ {
.name = "erase_check", .name = "erase_check",
.handler = &handle_flash_erase_check_command, .handler = handle_flash_erase_check_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank>", .usage = "bank_id",
.help = "check erase state of sectors", .help = "Check erase state of all blocks in a "
"flash bank.",
}, },
{ {
.name = "protect_check", .name = "protect_check",
.handler = &handle_flash_protect_check_command, .handler = handle_flash_protect_check_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank>", .usage = "bank_id",
.help = "check protection state of sectors", .help = "Check protection state of all blocks in a "
"flash bank.",
}, },
{ {
.name = "erase_sector", .name = "erase_sector",
.handler = &handle_flash_erase_command, .handler = handle_flash_erase_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank> <first> <last>", .usage = "bank_id first_sector_num last_sector_num",
.help = "erase sectors", .help = "Erase a range of sectors in a flash bank.",
}, },
{ {
.name = "erase_address", .name = "erase_address",
.handler = &handle_flash_erase_address_command, .handler = handle_flash_erase_address_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<address> <length>", .usage = "['pad'] address length",
.help = "erase address range", .help = "Erase flash sectors starting at address and "
"continuing for length bytes. If 'pad' is specified, "
"data outside that range may also be erased: the start "
"address may be decreased, and length increased, so "
"that all of the first and last sectors are erased.",
}, },
{ {
.name = "fillw", .name = "fillw",
.handler = &handle_flash_fill_command, .handler = handle_flash_fill_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<address> <word_pattern> <count>", .usage = "address value n",
.help = "fill with pattern (no autoerase)", .help = "Fill n words with 32-bit value, starting at "
"word address. (No autoerase.)",
}, },
{ {
.name = "fillh", .name = "fillh",
.handler = &handle_flash_fill_command, .handler = handle_flash_fill_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<address> <halfword_pattern> <count>", .usage = "address value n",
.help = "fill with pattern", .help = "Fill n halfwords with 16-bit value, starting at "
"word address. (No autoerase.)",
}, },
{ {
.name = "fillb", .name = "fillb",
.handler = &handle_flash_fill_command, .handler = handle_flash_fill_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<address> <byte_pattern> <count>", .usage = "address value n",
.help = "fill with pattern", .help = "Fill n bytes with 8-bit value, starting at "
"word address. (No autoerase.)",
}, },
{ {
.name = "write_bank", .name = "write_bank",
.handler = &handle_flash_write_bank_command, .handler = handle_flash_write_bank_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank> <file> <offset>", .usage = "bank_id filename offset",
.help = "write binary data", .help = "Write binary data from file to flash bank, "
"starting at specified byte offset from the "
"beginning of the bank.",
}, },
{ {
.name = "write_image", .name = "write_image",
.handler = &handle_flash_write_image_command, .handler = handle_flash_write_image_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "[erase] [unlock] <file> [offset] [type]", .usage = "[erase] [unlock] filename [offset [file_type]]",
.help = "write an image to flash" .help = "Write an image to flash. Optionally first unprotect "
"and/or erase the region to be used. Allow optional "
"offset from beginning of bank (defaults to zero)",
}, },
{ {
.name = "protect", .name = "protect",
.handler = &handle_flash_protect_command, .handler = handle_flash_protect_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<bank> <first> <last> <on | off>", .usage = "bank_id first_sector [last_sector|'last'] "
.help = "set protection of sectors", "('on'|'off')",
.help = "Turn protection on or off for a range of sectors "
"in a given flash bank.",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -891,10 +924,10 @@ COMMAND_HANDLER(handle_flash_init_command)
static const struct command_registration flash_config_command_handlers[] = { static const struct command_registration flash_config_command_handlers[] = {
{ {
.name = "bank", .name = "bank",
.handler = &handle_flash_bank_command, .handler = handle_flash_bank_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.usage = "<name> <driver> <base> <size> " .usage = "bank_id driver_name base_address size_bytes "
"<chip_width> <bus_width> <target> " "chip_width_bytes bus_width_bytes target "
"[driver_options ...]", "[driver_options ...]",
.help = "Define a new bank with the given name, " .help = "Define a new bank with the given name, "
"using the specified NOR flash driver.", "using the specified NOR flash driver.",
@@ -902,20 +935,20 @@ static const struct command_registration flash_config_command_handlers[] = {
{ {
.name = "init", .name = "init",
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.handler = &handle_flash_init_command, .handler = handle_flash_init_command,
.help = "initialize flash devices", .help = "Initialize flash devices.",
}, },
{ {
.name = "banks", .name = "banks",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.handler = &handle_flash_banks_command, .handler = handle_flash_banks_command,
.help = "return readable information about the flash banks", .help = "Display table with information about flash banks.",
}, },
{ {
.name = "list", .name = "list",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.jim_handler = &jim_flash_list, .jim_handler = jim_flash_list,
.help = "returns a list of details about the flash banks", .help = "Returns a list of details about the flash banks.",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@@ -821,19 +821,19 @@ static int tms470_erase_sector(struct flash_bank *bank, int sector)
static const struct command_registration tms470_any_command_handlers[] = { static const struct command_registration tms470_any_command_handlers[] = {
{ {
.name = "flash_keyset", .name = "flash_keyset",
.handler = &tms470_handle_flash_keyset_command, .handler = tms470_handle_flash_keyset_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "tms470 flash_keyset <key0> <key1> <key2> <key3>", .help = "tms470 flash_keyset <key0> <key1> <key2> <key3>",
}, },
{ {
.name = "osc_megahertz", .name = "osc_megahertz",
.handler = &tms470_handle_osc_megahertz_command, .handler = tms470_handle_osc_megahertz_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "tms470 osc_megahertz <MHz>", .help = "tms470 osc_megahertz <MHz>",
}, },
{ {
.name = "plldis", .name = "plldis",
.handler = &tms470_handle_plldis_command, .handler = tms470_handle_plldis_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "tms470 plldis <0/1>", .help = "tms470 plldis <0/1>",
}, },
@@ -1260,13 +1260,13 @@ FLASH_BANK_COMMAND_HANDLER(tms470_flash_bank_command)
struct flash_driver tms470_flash = { struct flash_driver tms470_flash = {
.name = "tms470", .name = "tms470",
.commands = tms470_command_handlers, .commands = tms470_command_handlers,
.flash_bank_command = &tms470_flash_bank_command, .flash_bank_command = tms470_flash_bank_command,
.erase = &tms470_erase, .erase = tms470_erase,
.protect = &tms470_protect, .protect = tms470_protect,
.write = &tms470_write, .write = tms470_write,
.probe = &tms470_probe, .probe = tms470_probe,
.auto_probe = &tms470_auto_probe, .auto_probe = tms470_auto_probe,
.erase_check = &tms470_erase_check, .erase_check = tms470_erase_check,
.protect_check = &tms470_protect_check, .protect_check = tms470_protect_check,
.info = &tms470_info, .info = tms470_info,
}; };

View File

@@ -58,14 +58,14 @@ static const struct command_registration foo_command_handlers[] = {
.name = "bar", .name = "bar",
.handler = &handle_foo_command, .handler = &handle_foo_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.usage = "<address> [enable|disable]", .usage = "address ['enable'|'disable']",
.help = "an example command", .help = "an example command",
}, },
{ {
.name = "baz", .name = "baz",
.handler = &handle_foo_command, .handler = &handle_foo_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.usage = "<address> [enable|disable]", .usage = "address ['enable'|'disable']",
.help = "a sample command", .help = "a sample command",
}, },
{ {
@@ -107,10 +107,10 @@ COMMAND_HANDLER(handle_hello_command)
const struct command_registration hello_command_handlers[] = { const struct command_registration hello_command_handlers[] = {
{ {
.name = "hello", .name = "hello",
.handler = &handle_hello_command, .handler = handle_hello_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "prints a warm welcome", .help = "prints a warm welcome",
.usage = "[<name>]", .usage = "[name]",
}, },
{ {
.name = "foo", .name = "foo",

View File

@@ -108,10 +108,15 @@ static int command_retval_set(Jim_Interp *interp, int retval)
extern struct command_context *global_cmd_ctx; extern struct command_context *global_cmd_ctx;
/* dump a single line to the log for the command.
* Do nothing in case we are not at debug level 3 */
void script_debug(Jim_Interp *interp, const char *name, void script_debug(Jim_Interp *interp, const char *name,
unsigned argc, Jim_Obj *const *argv) unsigned argc, Jim_Obj *const *argv)
{ {
LOG_DEBUG("command - %s", name); if (debug_level < LOG_LVL_DEBUG)
return;
char * dbg = alloc_printf("command - %s", name);
for (unsigned i = 0; i < argc; i++) for (unsigned i = 0; i < argc; i++)
{ {
int len; int len;
@@ -121,8 +126,12 @@ void script_debug(Jim_Interp *interp, const char *name,
if (*w == '#') if (*w == '#')
break; break;
LOG_DEBUG("%s - argv[%d]=%s", name, i, w); char * t = alloc_printf("%s %s", dbg, w);
free (dbg);
dbg = t;
} }
LOG_DEBUG("%s", dbg);
free(dbg);
} }
static void script_command_args_free(const char **words, unsigned nwords) static void script_command_args_free(const char **words, unsigned nwords)
@@ -349,7 +358,7 @@ static int register_command_handler(struct command_context *cmd_ctx,
if (NULL == override_name) if (NULL == override_name)
return JIM_ERR; return JIM_ERR;
retval = Jim_Eval_Named(interp, override_name, __FILE__, __LINE__); retval = Jim_Eval_Named(interp, override_name, __THIS__FILE__ , __LINE__);
free((void *)override_name); free((void *)override_name);
return retval; return retval;
@@ -366,7 +375,10 @@ struct command* register_command(struct command_context *context,
struct command *c = command_find(*head, name); struct command *c = command_find(*head, name);
if (NULL != c) if (NULL != c)
{ {
LOG_ERROR("command '%s' is already registered in '%s' context", /* TODO: originally we treated attempting to register a cmd twice as an error
* Sometimes we need this behaviour, such as with flash banks.
* http://www.mail-archive.com/openocd-development@lists.berlios.de/msg11152.html */
LOG_DEBUG("command '%s' is already registered in '%s' context",
name, parent ? parent->name : "<global>"); name, parent ? parent->name : "<global>");
return c; return c;
} }
@@ -580,6 +592,7 @@ static int run_command(struct command_context *context,
struct command_invocation cmd = { struct command_invocation cmd = {
.ctx = context, .ctx = context,
.current = c,
.name = c->name, .name = c->name,
.argc = num_words - 1, .argc = num_words - 1,
.argv = words + 1, .argv = words + 1,
@@ -933,15 +946,27 @@ static COMMAND_HELPER(command_help_show, struct command *c, unsigned n,
if (is_match && show_help) if (is_match && show_help)
{ {
const char *stage_msg; char *msg;
/* Normal commands are runtime-only; highlight exceptions */
if (c->mode != COMMAND_EXEC) {
const char *stage_msg = "";
switch (c->mode) { switch (c->mode) {
case COMMAND_CONFIG: stage_msg = "CONFIG"; break; case COMMAND_CONFIG:
case COMMAND_EXEC: stage_msg = "EXEC"; break; stage_msg = " (configuration command)";
case COMMAND_ANY: stage_msg = "CONFIG or EXEC"; break; break;
default: stage_msg = "***UNKNOWN***"; break; case COMMAND_ANY:
stage_msg = " (command valid any time)";
break;
default:
stage_msg = " (?mode error?)";
break;
} }
char *msg = alloc_printf("%s%sValid Modes: %s", msg = alloc_printf("%s%s", c->help ? : "", stage_msg);
c->help ? : "", c->help ? " " : "", stage_msg); } else
msg = alloc_printf("%s", c->help ? : "");
if (NULL != msg) if (NULL != msg)
{ {
command_help_show_wrap(msg, n + 3, n + 3); command_help_show_wrap(msg, n + 3, n + 3);
@@ -959,18 +984,45 @@ static COMMAND_HELPER(command_help_show, struct command *c, unsigned n,
COMMAND_HANDLER(handle_help_command) COMMAND_HANDLER(handle_help_command)
{ {
bool full = strcmp(CMD_NAME, "help") == 0; bool full = strcmp(CMD_NAME, "help") == 0;
int retval;
struct command *c = CMD_CTX->commands; struct command *c = CMD_CTX->commands;
char *match = NULL;
const char *match = "";
if (CMD_ARGC == 0) if (CMD_ARGC == 0)
match = ""; match = "";
else if (CMD_ARGC == 1) else if (CMD_ARGC >= 1) {
match = CMD_ARGV[0]; unsigned i;
else
for (i = 0; i < CMD_ARGC; ++i) {
if (NULL != match) {
char *prev = match;
match = alloc_printf("%s %s", match,
CMD_ARGV[i]);
free(prev);
if (NULL == match) {
LOG_ERROR("unable to build "
"search string");
return -ENOMEM;
}
} else {
match = alloc_printf("%s", CMD_ARGV[i]);
if (NULL == match) {
LOG_ERROR("unable to build "
"search string");
return -ENOMEM;
}
}
}
} else
return ERROR_COMMAND_SYNTAX_ERROR; return ERROR_COMMAND_SYNTAX_ERROR;
return CALL_COMMAND_HANDLER(command_help_show_list, c, 0, full, match); retval = CALL_COMMAND_HANDLER(command_help_show_list,
c, 0, full, match);
if (CMD_ARGC >= 1)
free(match);
return retval;
} }
static int command_unknown_find(unsigned argc, Jim_Obj *const *argv, static int command_unknown_find(unsigned argc, Jim_Obj *const *argv,
@@ -1047,6 +1099,7 @@ static int jim_command_mode(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{ {
struct command_context *cmd_ctx = current_command_context(interp); struct command_context *cmd_ctx = current_command_context(interp);
enum command_mode mode; enum command_mode mode;
if (argc > 1) if (argc > 1)
{ {
struct command *c = cmd_ctx->commands; struct command *c = cmd_ctx->commands;
@@ -1183,7 +1236,7 @@ COMMAND_HANDLER(handle_help_add_command)
return help_add_command(CMD_CTX, c, cmd_name, help, usage); return help_add_command(CMD_CTX, c, cmd_name, help, usage);
} }
/* sleep command sleeps for <n> miliseconds /* sleep command sleeps for <n> milliseconds
* this is useful in target startup scripts * this is useful in target startup scripts
*/ */
COMMAND_HANDLER(handle_sleep_command) COMMAND_HANDLER(handle_sleep_command)
@@ -1223,19 +1276,22 @@ static const struct command_registration command_subcommand_handlers[] = {
{ {
.name = "mode", .name = "mode",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.jim_handler = &jim_command_mode, .jim_handler = jim_command_mode,
.usage = "[<name> ...]", .usage = "[command_name ...]",
.help = "Returns the command modes allowed by a command:" .help = "Returns the command modes allowed by a command:"
"'any', 'config', or 'exec'. If no command is" "'any', 'config', or 'exec'. If no command is"
"specified, returns the current command mode.", "specified, returns the current command mode. "
"Returns 'unknown' if an unknown command is given. "
"Command can be multiple tokens.",
}, },
{ {
.name = "type", .name = "type",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.jim_handler = &jim_command_type, .jim_handler = jim_command_type,
.usage = "<name> ...", .usage = "command_name [...]",
.help = "Returns the type of built-in command:" .help = "Returns the type of built-in command:"
"'native', 'simple', 'group', or 'unknown'", "'native', 'simple', 'group', or 'unknown'. "
"Command can be multiple tokens.",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -1243,39 +1299,43 @@ static const struct command_registration command_subcommand_handlers[] = {
static const struct command_registration command_builtin_handlers[] = { static const struct command_registration command_builtin_handlers[] = {
{ {
.name = "add_help_text", .name = "add_help_text",
.handler = &handle_help_add_command, .handler = handle_help_add_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "add new command help text", .help = "Add new command help text; "
.usage = "<command> [...] <help_text>]", "Command can be multiple tokens.",
.usage = "command_name helptext_string",
}, },
{ {
.name = "add_usage_text", .name = "add_usage_text",
.handler = &handle_help_add_command, .handler = handle_help_add_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "add new command usage text", .help = "Add new command usage text; "
.usage = "<command> [...] <usage_text>]", "command can be multiple tokens.",
.usage = "command_name usage_string",
}, },
{ {
.name = "sleep", .name = "sleep",
.handler = &handle_sleep_command, .handler = handle_sleep_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "sleep for n milliseconds. " .help = "Sleep for specified number of milliseconds. "
"\"busy\" will busy wait", "\"busy\" will busy wait instead (avoid this).",
.usage = "<n> [busy]", .usage = "milliseconds ['busy']",
}, },
{ {
.name = "help", .name = "help",
.handler = &handle_help_command, .handler = handle_help_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "show full command help", .help = "Show full command help; "
.usage = "[<command> ...]", "command can be multiple tokens.",
.usage = "[command_name]",
}, },
{ {
.name = "usage", .name = "usage",
.handler = &handle_help_command, .handler = handle_help_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "show basic command usage", .help = "Show basic command usage; "
.usage = "[<command> ...]", "command can be multiple tokens.",
.usage = "[command_name]",
}, },
{ {
.name = "command", .name = "command",
@@ -1310,6 +1370,7 @@ struct command_context* command_init(const char *startup_tcl, Jim_Interp *interp
#endif #endif
context->interp = interp; context->interp = interp;
/* Stick to lowercase for HostOS strings. */
#if defined(_MSC_VER) #if defined(_MSC_VER)
/* WinXX - is generic, the forward /* WinXX - is generic, the forward
* looking problem is this: * looking problem is this:
@@ -1321,7 +1382,7 @@ struct command_context* command_init(const char *startup_tcl, Jim_Interp *interp
HostOs = "winxx"; HostOs = "winxx";
#elif defined(__linux__) #elif defined(__linux__)
HostOs = "linux"; HostOs = "linux";
#elif defined(__DARWIN__) #elif defined(__APPLE__) || defined(__DARWIN__)
HostOs = "darwin"; HostOs = "darwin";
#elif defined(__CYGWIN__) #elif defined(__CYGWIN__)
HostOs = "cygwin"; HostOs = "cygwin";
@@ -1329,8 +1390,10 @@ struct command_context* command_init(const char *startup_tcl, Jim_Interp *interp
HostOs = "mingw32"; HostOs = "mingw32";
#elif defined(__ECOS) #elif defined(__ECOS)
HostOs = "ecos"; HostOs = "ecos";
#elif defined(__FreeBSD__)
HostOs = "freebsd";
#else #else
#warn unrecognized host OS... #warning "Unrecognized host OS..."
HostOs = "other"; HostOs = "other";
#endif #endif
Jim_SetGlobalVariableStr(interp, "ocd_HOSTOS", Jim_SetGlobalVariableStr(interp, "ocd_HOSTOS",

View File

@@ -115,8 +115,10 @@ int parse_config_file(struct command_context *cmd_ctx)
int retval; int retval;
char **cfg; char **cfg;
if (!config_file_names) if (!config_file_names) {
add_config_command ("script openocd.cfg"); command_run_line(cmd_ctx, "script openocd.cfg");
return ERROR_OK;
}
cfg = config_file_names; cfg = config_file_names;

View File

@@ -191,6 +191,7 @@ COMMAND_HANDLER(handle_append_command)
int retval = ERROR_FAIL; int retval = ERROR_FAIL;
FILE *config_file = NULL; FILE *config_file = NULL;
config_file = fopen(CMD_ARGV[0], "a"); config_file = fopen(CMD_ARGV[0], "a");
if (config_file != NULL) if (config_file != NULL)
{ {
@@ -199,7 +200,8 @@ COMMAND_HANDLER(handle_append_command)
unsigned i; unsigned i;
for (i = 1; i < CMD_ARGC; i++) for (i = 1; i < CMD_ARGC; i++)
{ {
if (fwrite(CMD_ARGV[i], 1, strlen(CMD_ARGV[i]), config_file) != strlen(CMD_ARGV[i])) if (fwrite(CMD_ARGV[i], 1, strlen(CMD_ARGV[i]),
config_file) != strlen(CMD_ARGV[i]))
break; break;
if (i != CMD_ARGC - 1) if (i != CMD_ARGC - 1)
{ {
@@ -208,9 +210,8 @@ COMMAND_HANDLER(handle_append_command)
} }
} }
if ((i == CMD_ARGC) && (fwrite("\n", 1, 1, config_file) == 1)) if ((i == CMD_ARGC) && (fwrite("\n", 1, 1, config_file) == 1))
{
retval = ERROR_OK; retval = ERROR_OK;
}
fclose(config_file); fclose(config_file);
} }
@@ -619,76 +620,86 @@ static int zylinjtag_Jim_Command_mac(Jim_Interp *interp, int argc,
static const struct command_registration ioutil_command_handlers[] = { static const struct command_registration ioutil_command_handlers[] = {
{ {
.name = "cat", .name = "cat",
.handler = &handle_cat_command, .handler = handle_cat_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "display file content", .help = "display text file content",
.usage= "<file_name>", .usage= "file_name",
}, },
{ {
.name = "trunc", .name = "trunc",
.handler = &handle_trunc_command, .handler = handle_trunc_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "truncate a file 0 size", .help = "truncate a file to zero length",
.usage= "<file_name>", .usage= "file_name",
}, },
{ {
.name = "cp", .name = "cp",
.handler = &handle_cp_command, .handler = handle_cp_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "copy a file", .help = "copy a file",
.usage = "<src> <dst>", .usage = "src_file_name dst_file_name",
}, },
{ {
.name = "append_file", .name = "append_file",
.handler = &handle_append_command, .handler = handle_append_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "append a variable number of strings to a file", .help = "append a variable number of strings to a file",
.usage= "<file_name> [<string> ...]", .usage= "file_name [string ...]",
}, },
{ {
.name = "meminfo", .name = "meminfo",
.handler = &handle_meminfo_command, .handler = handle_meminfo_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "display available ram memory", .help = "display free heap space",
}, },
{ {
.name = "rm", .name = "rm",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.handler = &handle_rm_command, .handler = handle_rm_command,
.help = "remove a file", .help = "remove a directory or file",
.usage = "<file>", .usage = "file_name",
}, },
/*
* REVISIT shouldn't most, or all, these zylinjtag_*()
* entries be #ifdef ZY1000? If not, why so they have
* those names?
*
* Peek and poke are security holes -- they manipulate
* server-internal addresses.
*/
// jim handlers // jim handlers
{ {
.name = "peek", .name = "peek",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.jim_handler = &zylinjtag_Jim_Command_peek, .jim_handler = zylinjtag_Jim_Command_peek,
.help = "peek at a memory address", .help = "peek at a memory address",
.usage = "<addr>", .usage = "address",
}, },
{ {
.name = "poke", .name = "poke",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.jim_handler = &zylinjtag_Jim_Command_poke, .jim_handler = zylinjtag_Jim_Command_poke,
.help = "poke at a memory address", .help = "poke at a memory address",
.usage = "<addr> <value>", .usage = "address value",
}, },
{ {
.name = "ls", .name = "ls",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.jim_handler = &zylinjtag_Jim_Command_ls, .jim_handler = zylinjtag_Jim_Command_ls,
.help = "show a listing of files", .help = "show a listing of files",
.usage = "<dir>", .usage = "dirname",
}, },
{ {
.name = "mac", .name = "mac",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.jim_handler = &zylinjtag_Jim_Command_mac, .jim_handler = zylinjtag_Jim_Command_mac,
.help = "show MAC address", .help = "show MAC address",
}, },
{ {
.name = "ip", .name = "ip",
.jim_handler = &zylinjtag_Jim_Command_ip, .jim_handler = zylinjtag_Jim_Command_ip,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "show IP address", .help = "show IP address",
}, },

View File

@@ -2217,7 +2217,7 @@ static Jim_Obj *JimStringToLower(Jim_Interp *interp, Jim_Obj *strObjPtr)
memcpy(buf, strObjPtr->bytes, strObjPtr->length + 1); memcpy(buf, strObjPtr->bytes, strObjPtr->length + 1);
for (i = 0; i < strObjPtr->length; i++) for (i = 0; i < strObjPtr->length; i++)
buf[i] = tolower(buf[i]); buf[i] = tolower((unsigned)buf[i]);
return Jim_NewStringObjNoAlloc(interp, buf, strObjPtr->length); return Jim_NewStringObjNoAlloc(interp, buf, strObjPtr->length);
} }
@@ -2233,7 +2233,7 @@ static Jim_Obj *JimStringToUpper(Jim_Interp *interp, Jim_Obj *strObjPtr)
memcpy(buf, strObjPtr->bytes, strObjPtr->length + 1); memcpy(buf, strObjPtr->bytes, strObjPtr->length + 1);
for (i = 0; i < strObjPtr->length; i++) for (i = 0; i < strObjPtr->length; i++)
buf[i] = toupper(buf[i]); buf[i] = toupper((unsigned)buf[i]);
return Jim_NewStringObjNoAlloc(interp, buf, strObjPtr->length); return Jim_NewStringObjNoAlloc(interp, buf, strObjPtr->length);
} }
@@ -2347,7 +2347,7 @@ static Jim_Obj *Jim_FormatString_Inner(Jim_Interp *interp, Jim_Obj *fmtObjPtr,
case '8': case '8':
case '9': case '9':
accum = 0; accum = 0;
while (isdigit(*fmt) && (fmtLen > 0)) { while (isdigit((unsigned)*fmt) && (fmtLen > 0)) {
accum = (accum * 10) + (*fmt - '0'); accum = (accum * 10) + (*fmt - '0');
fmt++; fmtLen--; fmt++; fmtLen--;
} }

View File

@@ -286,13 +286,16 @@ COMMAND_HANDLER(handle_debug_level_command)
if (debug_level >= LOG_LVL_DEBUG && server_use_pipes == 1) if (debug_level >= LOG_LVL_DEBUG && server_use_pipes == 1)
{ {
/* if we are enabling debug info then we need to write to a log file /* if we are enabling debug info then we need to write to a
* otherwise the pipe will get full and cause issues with gdb */ * log file otherwise the pipe will get full and cause issues
* with gdb
*/
FILE* file = fopen("openocd.log", "w"); FILE* file = fopen("openocd.log", "w");
if (file) if (file)
{ {
log_output = file; log_output = file;
LOG_WARNING("enabling log output as we are using pipes"); LOG_WARNING("enabling logfile output because "
"we are using pipes to talk to GDB.");
} }
} }
@@ -319,17 +322,19 @@ COMMAND_HANDLER(handle_log_output_command)
static struct command_registration log_command_handlers[] = { static struct command_registration log_command_handlers[] = {
{ {
.name = "log_output", .name = "log_output",
.handler = &handle_log_output_command, .handler = handle_log_output_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "redirect logging to a file (default: stderr)", .help = "redirect logging to a file (default: stderr)",
.usage = "<file_name>", .usage = "file_name",
}, },
{ {
.name = "debug_level", .name = "debug_level",
.handler = &handle_debug_level_command, .handler = handle_debug_level_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "sets the verbosity level of debugging output", .help = "Sets the verbosity level of debugging output. "
.usage = "<level:0-3>", "0 shows errors only; 1 adds warnings; "
"2 (default) adds other info; 3 adds debugging.",
.usage = "number",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@@ -111,7 +111,12 @@ extern int debug_level;
#define LOG_LEVEL_IS(FOO) ((debug_level) >= (FOO)) #define LOG_LEVEL_IS(FOO) ((debug_level) >= (FOO))
#define LOG_DEBUG(expr ...) \ #define LOG_DEBUG(expr ...) \
((debug_level >= LOG_LVL_DEBUG) ? log_printf_lf (LOG_LVL_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr) , 0 : 0) do { \
if (debug_level >= LOG_LVL_DEBUG) \
log_printf_lf(LOG_LVL_DEBUG, \
__FILE__, __LINE__, __func__, \
expr); \
} while (0)
#define LOG_INFO(expr ...) \ #define LOG_INFO(expr ...) \
log_printf_lf (LOG_LVL_INFO, __FILE__, __LINE__, __FUNCTION__, expr) log_printf_lf (LOG_LVL_INFO, __FILE__, __LINE__, __FUNCTION__, expr)

View File

@@ -74,21 +74,21 @@ static void add_default_dirs(void)
add_script_search_dir(strExePath); add_script_search_dir(strExePath);
} }
/* /*
* Add support for the default (as of 20080121) layout when * Add support for the default (as of 20091118) layout when
* using autotools and cygwin to build native MinGW binary. * using autotools and cygwin/MinGW to build native binary.
* Path separator is converted to UNIX style so that MinGW is * Path separator is converted to UNIX style so that MinGW is
* pleased. * pleased.
* *
* bin/openocd.exe * bin/openocd.exe
* lib/openocd/event/at91eb40a_reset.cfg * share/openocd/scripts/interface/dummy.cfg
* lib/openocd/target/at91eb40a.cfg * share/openocd/scripts/target/at91eb40a.cfg
*/ */
{ {
char strExePath [MAX_PATH]; char strExePath [MAX_PATH];
char *p; char *p;
GetModuleFileName (NULL, strExePath, MAX_PATH); GetModuleFileName (NULL, strExePath, MAX_PATH);
*strrchr(strExePath, '\\') = 0; *strrchr(strExePath, '\\') = 0;
strcat(strExePath, "/../lib/"PACKAGE); strcat(strExePath, "/../share/"PACKAGE"/scripts");
for (p = strExePath; *p; p++) { for (p = strExePath; *p; p++) {
if (*p == '\\') if (*p == '\\')
*p = '/'; *p = '/';
@@ -190,7 +190,7 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[])
if (help_flag) if (help_flag)
{ {
LOG_OUTPUT("Open On-Chip Debugger\n(c) 2005-2008 by Dominic Rath\n\n"); LOG_OUTPUT("Open On-Chip Debugger\nLicensed under GNU GPL v2\n");
LOG_OUTPUT("--help | -h\tdisplay this help\n"); LOG_OUTPUT("--help | -h\tdisplay this help\n");
LOG_OUTPUT("--version | -v\tdisplay OpenOCD version\n"); LOG_OUTPUT("--version | -v\tdisplay OpenOCD version\n");
LOG_OUTPUT("--file | -f\tuse configuration file <name>\n"); LOG_OUTPUT("--file | -f\tuse configuration file <name>\n");

View File

@@ -40,6 +40,12 @@
#define ENOTSUP 134 /* Not supported */ #define ENOTSUP 134 /* Not supported */
#endif #endif
/* for systems that do not support O_BINARY
* linux being one of them */
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifndef HAVE_SYS_TIME_H #ifndef HAVE_SYS_TIME_H
#ifndef _TIMEVAL_DEFINED #ifndef _TIMEVAL_DEFINED

View File

@@ -50,6 +50,8 @@
#ifdef _WIN32 #ifdef _WIN32
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <sys/types.h>
#include <sys/stat.h>
#endif #endif
// --- platform specific headers --- // --- platform specific headers ---
@@ -83,4 +85,9 @@
#include <fcntl.h> #include <fcntl.h>
#endif #endif
#ifndef true
#define true 1
#define false 0
#endif
#endif // SYSTEM_H #endif // SYSTEM_H

View File

@@ -172,6 +172,7 @@ static inline void h_u16_to_be(uint8_t* buf, int val)
#define SCNx32 "x" #define SCNx32 "x"
#define PRIi32 "i" #define PRIi32 "i"
#define PRIu32 "u" #define PRIu32 "u"
#define PRId8 PRId32
typedef CYG_ADDRWORD intptr_t; typedef CYG_ADDRWORD intptr_t;
typedef int64_t intmax_t; typedef int64_t intmax_t;

View File

@@ -530,10 +530,12 @@ int jtag_add_statemove(tap_state_t goal_state)
{ {
tap_state_t cur_state = cmd_queue_cur_state; tap_state_t cur_state = cmd_queue_cur_state;
if (goal_state != cur_state)
{
LOG_DEBUG("cur_state=%s goal_state=%s", LOG_DEBUG("cur_state=%s goal_state=%s",
tap_state_name(cur_state), tap_state_name(cur_state),
tap_state_name(goal_state)); tap_state_name(goal_state));
}
/* If goal is RESET, be paranoid and force that that transition /* If goal is RESET, be paranoid and force that that transition
* (e.g. five TCK cycles, TMS high). Else trust "cur_state". * (e.g. five TCK cycles, TMS high). Else trust "cur_state".
@@ -1621,6 +1623,13 @@ bool jtag_will_verify_capture_ir()
int jtag_power_dropout(int *dropout) int jtag_power_dropout(int *dropout)
{ {
if (jtag == NULL)
{
/* TODO: as the jtag interface is not valid all
* we can do at the moment is exit OpenOCD */
LOG_ERROR("No Valid JTAG Interface Configured.");
exit(-1);
}
return jtag->power_dropout(dropout); return jtag->power_dropout(dropout);
} }

View File

@@ -28,6 +28,9 @@ endif
if FT2232_DRIVER if FT2232_DRIVER
DRIVERFILES += ft2232.c DRIVERFILES += ft2232.c
endif endif
if USB_BLASTER_DRIVER
DRIVERFILES += usb_blaster.c
endif
if AMTJTAGACCEL if AMTJTAGACCEL
DRIVERFILES += amt_jtagaccel.c DRIVERFILES += amt_jtagaccel.c
endif endif

View File

@@ -22,8 +22,6 @@
#endif #endif
#include <jtag/interface.h> #include <jtag/interface.h>
#include <jtag/commands.h>
#if PARPORT_USE_PPDEV == 1 #if PARPORT_USE_PPDEV == 1
#include <linux/parport.h> #include <linux/parport.h>
@@ -41,6 +39,15 @@
#endif #endif
#endif #endif
/**
* @file
* Support the Amontec Chameleon POD with JTAG Accelerator support.
* This is a parallel port JTAG adapter with a CPLD between the
* parallel port and the JTAG connection. VHDL code running in the
* CPLD significantly accelerates JTAG operations compared to the
* bitbanging "Wiggler" style of most parallel port adapters.
*/
/* configuration */ /* configuration */
static uint16_t amt_jtagaccel_port; static uint16_t amt_jtagaccel_port;
@@ -55,13 +62,41 @@ static int rtck_enabled = 0;
#if PARPORT_USE_PPDEV == 1 #if PARPORT_USE_PPDEV == 1
static int device_handle; static int device_handle;
static int addr_mode = IEEE1284_MODE_EPP | IEEE1284_ADDR ; static const int addr_mode = IEEE1284_MODE_EPP | IEEE1284_ADDR;
#define AMT_AW(val) do { ioctl(device_handle, PPSETMODE, &addr_mode); write(device_handle, &val, 1); } while (0)
#define AMT_AR(val) do { ioctl(device_handle, PPSETMODE, &addr_mode); read(device_handle, &val, 1); } while (0)
static int data_mode = IEEE1284_MODE_EPP | IEEE1284_DATA ; /* FIXME do something sane when these ioctl/read/write calls fail. */
#define AMT_DW(val) do { ioctl(device_handle, PPSETMODE, &data_mode); write(device_handle, &val, 1); } while (0)
#define AMT_DR(val) do { ioctl(device_handle, PPSETMODE, &data_mode); read(device_handle, &val, 1); } while (0) #define AMT_AW(val) \
do { \
int __retval; \
\
__retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
__retval = write(device_handle, &val, 1); \
} while (0)
#define AMT_AR(val) \
do { \
int __retval; \
\
__retval = ioctl(device_handle, PPSETMODE, &addr_mode); \
__retval = read(device_handle, &val, 1); \
} while (0)
static const int data_mode = IEEE1284_MODE_EPP | IEEE1284_DATA;
#define AMT_DW(val) \
do { \
int __retval; \
\
__retval = ioctl(device_handle, PPSETMODE, &data_mode); \
__retval = write(device_handle, &val, 1); \
} while (0)
#define AMT_DR(val) \
do { \
int __retval; \
\
__retval = ioctl(device_handle, PPSETMODE, &data_mode); \
__retval = read(device_handle, &val, 1); \
} while (0)
#else #else
@@ -545,15 +580,21 @@ static const struct command_registration amtjtagaccel_command_handlers[] = {
.name = "parport_port", .name = "parport_port",
.handler = &amt_jtagaccel_handle_parport_port_command, .handler = &amt_jtagaccel_handle_parport_port_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "configure the parallel port to use", .help = "configure or display the parallel port to use",
.usage = "<port_num>", .usage = "[port_num]",
}, },
{ {
.name = "parport_port", /**
* @todo Remove this "rtck" command; just use the standard
* mechanism to enable/disable adaptive clocking. First
* implement the standard mechanism and deprecate "rtck";
* after a year or so, it'll be safe to remove this.
*/
.name = "rtck",
.handler = &amt_jtagaccel_handle_rtck_command, .handler = &amt_jtagaccel_handle_rtck_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "enable RTCK", .help = "configure or display RTCK support",
.usage = "<enable|disable>", .usage = "[enable|disable]",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -561,8 +602,9 @@ static const struct command_registration amtjtagaccel_command_handlers[] = {
struct jtag_interface amt_jtagaccel_interface = { struct jtag_interface amt_jtagaccel_interface = {
.name = "amt_jtagaccel", .name = "amt_jtagaccel",
.commands = amtjtagaccel_command_handlers, .commands = amtjtagaccel_command_handlers,
.init = &amt_jtagaccel_init,
.quit = &amt_jtagaccel_quit, .init = amt_jtagaccel_init,
.speed = &amt_jtagaccel_speed, .quit = amt_jtagaccel_quit,
.execute_queue = &amt_jtagaccel_execute_queue, .speed = amt_jtagaccel_speed,
}; .execute_queue = amt_jtagaccel_execute_queue,
};

View File

@@ -514,16 +514,14 @@ static const struct command_registration armjtagew_command_handlers[] = {
struct jtag_interface armjtagew_interface = { struct jtag_interface armjtagew_interface = {
.name = "arm-jtag-ew", .name = "arm-jtag-ew",
.commands = armjtagew_command_handlers, .commands = armjtagew_command_handlers,
.execute_queue = &armjtagew_execute_queue, .execute_queue = armjtagew_execute_queue,
.speed = &armjtagew_speed, .speed = armjtagew_speed,
.khz = &armjtagew_khz, .khz = armjtagew_khz,
.init = armjtagew_init,
.init = &armjtagew_init, .quit = armjtagew_quit,
.quit = &armjtagew_quit, };
};
/***************************************************************************/ /***************************************************************************/
/* ARM-JTAG-EW tap functions */ /* ARM-JTAG-EW tap functions */

View File

@@ -215,7 +215,10 @@ int interface_jtag_add_dr_scan(int in_num_fields, const struct scan_field *in_fi
if (!tap->bypass) if (!tap->bypass)
{ {
struct scan_field * start_field = field; /* keep initial position for assert() */ #ifndef NDEBUG
/* remember initial position for assert() */
struct scan_field *start_field = field;
#endif /* NDEBUG */
for (int j = 0; j < in_num_fields; j++) for (int j = 0; j < in_num_fields; j++)
{ {

View File

@@ -27,13 +27,40 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
/* This code uses information contained in the MPSSE specification which was /**
* @file
* JTAG adapters based on the FT2232 full and high speed USB parts are
* popular low cost JTAG debug solutions. Many FT2232 based JTAG adapters
* are discrete, but development boards may integrate them as alternatives
* to more capable (and expensive) third party JTAG pods. Since JTAG uses
* only one of the two ports on these devices, on integrated boards the
* second port often serves as a USB-to-serial adapter for the target's
* console UART even when the JTAG port is not in use. (Systems which
* support ARM's SWD in addition to JTAG, or instead of it, may use that
* second port for reading SWV trace data.)
*
* FT2232 based JTAG adapters are "dumb" not "smart", because most JTAG
* request/response interactions involve round trips over the USB link.
* A "smart" JTAG adapter has intelligence close to the scan chain, so it
* can for example poll quickly for a status change (usually taking on the
* order of microseconds not milliseconds) before beginning a queued
* transaction which require the previous one to have completed.
*
* There are dozens of adapters of this type, differing in details which
* this driver needs to understand. Those "layout" details are required
* as part of FT2232 driver configuration.
*
* This code uses information contained in the MPSSE specification which was
* found here: * found here:
* http://www.ftdichip.com/Documents/AppNotes/AN2232C-01_MPSSE_Cmnd.pdf * http://www.ftdichip.com/Documents/AppNotes/AN2232C-01_MPSSE_Cmnd.pdf
* Hereafter this is called the "MPSSE Spec". * Hereafter this is called the "MPSSE Spec".
* *
* The datasheet for the ftdichip.com's FT2232D part is here: * The datasheet for the ftdichip.com's FT2232D part is here:
* http://www.ftdichip.com/Documents/DataSheets/DS_FT2232D.pdf * http://www.ftdichip.com/Documents/DataSheets/DS_FT2232D.pdf
*
* Also note the issue with code 0x4b (clock data to TMS) noted in
* http://developer.intra2net.com/mailarchive/html/libftdi/2009/msg00292.html
* which can affect longer JTAG state paths.
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@@ -42,7 +69,6 @@
/* project specific includes */ /* project specific includes */
#include <jtag/interface.h> #include <jtag/interface.h>
#include <jtag/commands.h>
#include <helper/time_support.h> #include <helper/time_support.h>
#if IS_CYGWIN == 1 #if IS_CYGWIN == 1
@@ -2182,6 +2208,11 @@ static int usbjtag_init(void)
} }
else if (strcmp(ft2232_layout, "evb_lm3s811") == 0) else if (strcmp(ft2232_layout, "evb_lm3s811") == 0)
{ {
/* There are multiple revisions of LM3S811 eval boards:
* - Rev B (and older?) boards have no SWO trace support.
* - Rev C boards add ADBUS_6 DBG_ENn and BDBUS_4 SWO_EN;
* they should use the "luminary_icdi" layout instead.
*/
nTRST = 0x0; nTRST = 0x0;
nTRSTnOE = 0x00; nTRSTnOE = 0x00;
nSRST = 0x20; nSRST = 0x20;
@@ -2191,6 +2222,9 @@ static int usbjtag_init(void)
} }
else if (strcmp(ft2232_layout, "luminary_icdi") == 0) else if (strcmp(ft2232_layout, "luminary_icdi") == 0)
{ {
/* Most Luminary eval boards support SWO trace output,
* and should use this "luminary_icdi" layout.
*/
nTRST = 0x0; nTRST = 0x0;
nTRSTnOE = 0x00; nTRSTnOE = 0x00;
nSRST = 0x20; nSRST = 0x20;
@@ -3975,14 +4009,14 @@ static const struct command_registration ft2232_command_handlers[] = {
.handler = &ft2232_handle_device_desc_command, .handler = &ft2232_handle_device_desc_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "set the USB device description of the FTDI FT2232 device", .help = "set the USB device description of the FTDI FT2232 device",
.usage = "<description>", .usage = "description_string",
}, },
{ {
.name = "ft2232_serial", .name = "ft2232_serial",
.handler = &ft2232_handle_serial_command, .handler = &ft2232_handle_serial_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "set the serial number of the FTDI FT2232 device", .help = "set the serial number of the FTDI FT2232 device",
.usage = "<serial#>", .usage = "serial_string",
}, },
{ {
.name = "ft2232_layout", .name = "ft2232_layout",
@@ -3990,21 +4024,21 @@ static const struct command_registration ft2232_command_handlers[] = {
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "set the layout of the FT2232 GPIO signals used " .help = "set the layout of the FT2232 GPIO signals used "
"to control output-enables and reset signals", "to control output-enables and reset signals",
.usage = "<layout>", .usage = "layout_name",
}, },
{ {
.name = "ft2232_vid_pid", .name = "ft2232_vid_pid",
.handler = &ft2232_handle_vid_pid_command, .handler = &ft2232_handle_vid_pid_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "the vendor ID and product ID of the FTDI FT2232 device", .help = "the vendor ID and product ID of the FTDI FT2232 device",
.usage = "<vid> <pid> [...]", .usage = "(vid pid)* ",
}, },
{ {
.name = "ft2232_latency", .name = "ft2232_latency",
.handler = &ft2232_handle_latency_command, .handler = &ft2232_handle_latency_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "set the FT2232 latency timer to a new value", .help = "set the FT2232 latency timer to a new value",
.usage = "<vid> <pid> [...]", .usage = "value",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -4012,10 +4046,11 @@ static const struct command_registration ft2232_command_handlers[] = {
struct jtag_interface ft2232_interface = { struct jtag_interface ft2232_interface = {
.name = "ft2232", .name = "ft2232",
.commands = ft2232_command_handlers, .commands = ft2232_command_handlers,
.init = &ft2232_init,
.quit = &ft2232_quit, .init = ft2232_init,
.speed = &ft2232_speed, .quit = ft2232_quit,
.speed_div = &ft2232_speed_div, .speed = ft2232_speed,
.khz = &ft2232_khz, .speed_div = ft2232_speed_div,
.execute_queue = &ft2232_execute_queue, .khz = ft2232_khz,
}; .execute_queue = ft2232_execute_queue,
};

View File

@@ -565,10 +565,12 @@ COMMAND_HANDLER(gw16012_handle_parport_port_command)
static const struct command_registration gw16012_command_handlers[] = { static const struct command_registration gw16012_command_handlers[] = {
{ {
.name = "parport_port", .name = "parport_port",
.handler = &gw16012_handle_parport_port_command, .handler = gw16012_handle_parport_port_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "configure the parallel port to use", .help = "Display the address of the I/O port (e.g. 0x378) "
.usage = "<port_num>", "or the number of the '/dev/parport' device used. "
"If a parameter is provided, first change that port.",
.usage = "[port_number]",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -576,8 +578,9 @@ static const struct command_registration gw16012_command_handlers[] = {
struct jtag_interface gw16012_interface = { struct jtag_interface gw16012_interface = {
.name = "gw16012", .name = "gw16012",
.commands = gw16012_command_handlers, .commands = gw16012_command_handlers,
.init = &gw16012_init,
.quit = &gw16012_quit, .init = gw16012_init,
.speed = &gw16012_speed, .quit = gw16012_quit,
.execute_queue = &gw16012_execute_queue, .speed = gw16012_speed,
}; .execute_queue = gw16012_execute_queue,
};

View File

@@ -29,6 +29,10 @@
#include <jtag/commands.h> #include <jtag/commands.h>
#include "usb_common.h" #include "usb_common.h"
/* See Segger's public documentation:
* Reference manual for J-Link USB Protocol
* Document RM08001-R6 Date: June 16, 2009
*/
#define VID 0x1366 #define VID 0x1366
#define PID 0x0101 #define PID 0x0101
@@ -646,17 +650,15 @@ static const struct command_registration jlink_command_handlers[] = {
struct jtag_interface jlink_interface = { struct jtag_interface jlink_interface = {
.name = "jlink", .name = "jlink",
.commands = jlink_command_handlers, .commands = jlink_command_handlers,
.execute_queue = &jlink_execute_queue, .execute_queue = jlink_execute_queue,
.speed = &jlink_speed, .speed = jlink_speed,
.speed_div = &jlink_speed_div, .speed_div = jlink_speed_div,
.khz = &jlink_khz, .khz = jlink_khz,
.init = jlink_init,
.init = &jlink_init, .quit = jlink_quit,
.quit = &jlink_quit, };
};
/***************************************************************************/ /***************************************************************************/
/* J-Link tap functions */ /* J-Link tap functions */

View File

@@ -79,8 +79,7 @@ static struct cable cables[] =
/* name tdo trst tms tck tdi srst o_inv i_inv init exit led */ /* name tdo trst tms tck tdi srst o_inv i_inv init exit led */
{ "wiggler", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x80, 0x00 }, { "wiggler", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x80, 0x00 },
{ "wiggler2", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x00, 0x20 }, { "wiggler2", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x01, 0x80, 0x80, 0x00, 0x20 },
{ "wiggler_ntrst_inverted", { "wiggler_ntrst_inverted", 0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x11, 0x80, 0x80, 0x80, 0x00 },
0x80, 0x10, 0x02, 0x04, 0x08, 0x01, 0x11, 0x80, 0x80, 0x80, 0x00 },
{ "old_amt_wiggler", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x11, 0x80, 0x80, 0x80, 0x00 }, { "old_amt_wiggler", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x11, 0x80, 0x80, 0x80, 0x00 },
{ "arm-jtag", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x01, 0x80, 0x80, 0x80, 0x00 }, { "arm-jtag", 0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x01, 0x80, 0x80, 0x80, 0x00 },
{ "chameleon", 0x80, 0x00, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 }, { "chameleon", 0x80, 0x00, 0x04, 0x01, 0x02, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 },
@@ -266,7 +265,6 @@ static int parport_init(void)
struct cable *cur_cable; struct cable *cur_cable;
#if PARPORT_USE_PPDEV == 1 #if PARPORT_USE_PPDEV == 1
char buffer[256]; char buffer[256];
int i = 0;
#endif #endif
cur_cable = cables; cur_cable = cables;
@@ -324,7 +322,8 @@ static int parport_init(void)
LOG_DEBUG("...open"); LOG_DEBUG("...open");
#if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) #if !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__)
i = ioctl(device_handle, PPCLAIM); int i = ioctl(device_handle, PPCLAIM);
if (i < 0) if (i < 0)
{ {
LOG_ERROR("cannot claim device"); LOG_ERROR("cannot claim device");
@@ -425,7 +424,7 @@ COMMAND_HANDLER(parport_handle_parport_port_command)
} }
} }
command_print(CMD_CTX, "parport port = %u", parport_port); command_print(CMD_CTX, "parport port = 0x%" PRIx16 "", parport_port);
return ERROR_OK; return ERROR_OK;
} }
@@ -438,10 +437,13 @@ COMMAND_HANDLER(parport_handle_parport_cable_command)
/* only if the cable name wasn't overwritten by cmdline */ /* only if the cable name wasn't overwritten by cmdline */
if (parport_cable == 0) if (parport_cable == 0)
{ {
/* REVISIT first verify that it's listed in cables[] ... */
parport_cable = malloc(strlen(CMD_ARGV[0]) + sizeof(char)); parport_cable = malloc(strlen(CMD_ARGV[0]) + sizeof(char));
strcpy(parport_cable, CMD_ARGV[0]); strcpy(parport_cable, CMD_ARGV[0]);
} }
/* REVISIT it's probably worth returning the current value ... */
return ERROR_OK; return ERROR_OK;
} }
@@ -485,49 +487,49 @@ COMMAND_HANDLER(parport_handle_parport_toggling_time_command)
static const struct command_registration parport_command_handlers[] = { static const struct command_registration parport_command_handlers[] = {
{ {
.name = "parport_port", .name = "parport_port",
.handler = &parport_handle_parport_port_command, .handler = parport_handle_parport_port_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "either the address of the I/O port " .help = "Display the address of the I/O port (e.g. 0x378) "
"or the number of the '/dev/parport' device", "or the number of the '/dev/parport' device used. "
.usage = "[<port|devname>]", "If a parameter is provided, first change that port.",
.usage = "[port_number]",
}, },
{ {
.name = "parport_cable", .name = "parport_cable",
.handler = &parport_handle_parport_cable_command, .handler = parport_handle_parport_cable_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "the layout of the parallel port cable " .help = "Set the layout of the parallel port cable "
"used to connect to the target", "used to connect to the target.",
.usage = "[<layout>]", /* REVISIT there's no way to list layouts we know ... */
.usage = "[layout]",
}, },
{ {
.name = "parport_write_on_exit", .name = "parport_write_on_exit",
.handler = &parport_handle_write_on_exit_command, .handler = parport_handle_write_on_exit_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "configure the parallel driver to write " .help = "Configure the parallel driver to write "
"a known value to the parallel interface", "a known value to the parallel interface on exit.",
.usage = "[<on|off>]", .usage = "('on'|'off')",
}, },
{ {
.name = "parport_toggling_time", .name = "parport_toggling_time",
.handler = &parport_handle_parport_toggling_time_command, .handler = parport_handle_parport_toggling_time_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "time <ns> it takes for the hardware to toggle TCK", .help = "Displays or assigns how many nanoseconds it "
.usage = "[<ns>]", "takes for the hardware to toggle TCK.",
.usage = "[nanoseconds]",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
struct jtag_interface parport_interface = { struct jtag_interface parport_interface = {
.name = "parport", .name = "parport",
.commands = parport_command_handlers, .commands = parport_command_handlers,
.init = &parport_init, .init = parport_init,
.quit = &parport_quit, .quit = parport_quit,
.khz = parport_khz,
.khz = &parport_khz, .speed_div = parport_speed_div,
.speed_div = &parport_speed_div, .speed = parport_speed,
.speed = &parport_speed, .execute_queue = bitbang_execute_queue,
};
.execute_queue = &bitbang_execute_queue,
};

View File

@@ -17,6 +17,12 @@
* Free Software Foundation, Inc., * * Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
/**
* @file
* Holds driver for PRESTO programmer from ASIX.
* http://tools.asix.net/prg_presto.htm
*/
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "config.h" #include "config.h"
#endif #endif
@@ -742,10 +748,10 @@ COMMAND_HANDLER(presto_handle_serial_command)
static const struct command_registration presto_command_handlers[] = { static const struct command_registration presto_command_handlers[] = {
{ {
.name = "presto_serial", .name = "presto_serial",
.handler = &presto_handle_serial_command, .handler = presto_handle_serial_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "configure serial port", .help = "Configure USB serial number of Presto device.",
.usage = "<devname>", .usage = "serial_string",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -787,14 +793,12 @@ static int presto_jtag_quit(void)
struct jtag_interface presto_interface = { struct jtag_interface presto_interface = {
.name = "presto", .name = "presto",
.commands = presto_command_handlers, .commands = presto_command_handlers,
.execute_queue = &bitq_execute_queue, .execute_queue = bitq_execute_queue,
.speed = &presto_jtag_speed, .speed = presto_jtag_speed,
.khz = &presto_jtag_khz, .khz = presto_jtag_khz,
.speed_div = &presto_jtag_speed_div, .speed_div = presto_jtag_speed_div,
.init = presto_jtag_init,
.init = &presto_jtag_init, .quit = presto_jtag_quit,
.quit = &presto_jtag_quit, };
};

View File

@@ -0,0 +1,589 @@
/***************************************************************************
* Driver for USB-JTAG, Altera USB-Blaster and compatibles *
* Original code from Kolja Waschk's USB-JTAG project *
* (http://www.ixo.de/info/usb_jtag/). *
* Some updates by Anthony Liu (2006). *
* Minor updates and cleanup by Catalin Patulea (2009). *
* *
* Copyright (C) 2009 Catalin Patulea *
* cat@vv.carleton.ca *
* *
* Copyright (C) 2006 Kolja Waschk *
* usbjtag@ixo.de *
* *
* Based on ft2232.c and bitbang.c, *
* Copyright (C) 2004,2006 by Dominic Rath *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
/*
* The following information is originally from Kolja Waschk's USB-JTAG,
* where it was obtained by reverse engineering an Altera USB-Blaster.
* See http://www.ixo.de/info/usb_jtag/ for USB-Blaster block diagram and
* usb_jtag-20080705-1200.zip#usb_jtag/host/openocd for protocol.
*
* The same information is also on the UrJTAG mediawiki, with some additional
* notes on bits marked as "unknown" by usb_jtag.
* (http://sourceforge.net/apps/mediawiki/urjtag/index.php?
* title=Cable_Altera_USB-Blaster)
*
* USB-JTAG, Altera USB-Blaster and compatibles are typically implemented as
* an FTDIChip FT245 followed by a CPLD which handles a two-mode protocol:
*
* _________
* | |
* | AT93C46 |
* |_________|
* __|__________ _________
* | | | |
* USB__| FTDI 245BM |__| EPM7064 |__JTAG (B_TDO,B_TDI,B_TMS,B_TCK)
* |_____________| |_________|
* __|__________ _|___________
* | | | |
* | 6 MHz XTAL | | 24 MHz Osc. |
* |_____________| |_____________|
*
* Protocol details are given in the code below.
*
* It is also possible to emulate this configuration using a single-chip USB
* controller like the Cypress FX2 (again, see usb_jtag for details).
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#if IS_CYGWIN == 1
#include "windows.h"
#undef LOG_ERROR
#endif
/* project specific includes */
#include <jtag/interface.h>
#include <jtag/commands.h>
#include <helper/time_support.h>
/* system includes */
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "bitbang.h"
#if (BUILD_USB_BLASTER_FTD2XX == 1 && BUILD_USB_BLASTER_LIBFTDI == 1)
#error "BUILD_USB_BLASTER_FTD2XX && BUILD_USB_BLASTER_LIBFTDI "
"are mutually exclusive"
#elif (BUILD_USB_BLASTER_FTD2XX != 1 && BUILD_USB_BLASTER_LIBFTDI != 1)
#error "BUILD_USB_BLASTER_FTD2XX || BUILD_USB_BLASTER_LIBFTDI must be chosen"
#endif
/* USB_BLASTER access library includes */
#if BUILD_USB_BLASTER_FTD2XX == 1
#include <ftd2xx.h>
#elif BUILD_USB_BLASTER_LIBFTDI == 1
#include <ftdi.h>
#endif
#include <sys/time.h>
#include <time.h>
static char *usb_blaster_device_desc;
static uint16_t usb_blaster_vid = 0x09fb; /* Altera */
static uint16_t usb_blaster_pid = 0x6001; /* USB-Blaster */
/* last output byte in simple bit banging mode */
static uint8_t out_value;
#if BUILD_USB_BLASTER_FTD2XX == 1
static FT_HANDLE ftdih;
#elif BUILD_USB_BLASTER_LIBFTDI == 1
static struct ftdi_context ftdic;
#endif
static int usb_blaster_buf_write(
uint8_t *buf, int size, uint32_t *bytes_written)
{
#if BUILD_USB_BLASTER_FTD2XX == 1
FT_STATUS status;
DWORD dw_bytes_written;
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size);
#endif
status = FT_Write(ftdih, buf, size, &dw_bytes_written);
if (status != FT_OK)
{
*bytes_written = dw_bytes_written;
LOG_ERROR("FT_Write returned: %lu", status);
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_written = dw_bytes_written;
return ERROR_OK;
#elif BUILD_USB_BLASTER_LIBFTDI == 1
int retval;
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("usb_blaster_buf_write %02X (%d)\n", buf[0], size);
#endif
retval = ftdi_write_data(&ftdic, buf, size);
if (retval < 0)
{
*bytes_written = 0;
LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic));
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_written = retval;
return ERROR_OK;
#endif
}
static int
usb_blaster_buf_read(uint8_t *buf, unsigned size, uint32_t *bytes_read)
{
#if BUILD_USB_BLASTER_FTD2XX == 1
DWORD dw_bytes_read;
FT_STATUS status;
status = FT_Read(ftdih, buf, size, &dw_bytes_read);
if (status != FT_OK)
{
*bytes_read = dw_bytes_read;
LOG_ERROR("FT_Read returned: %lu", status);
return ERROR_JTAG_DEVICE_ERROR;
}
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("usb_blaster_buf_read %02X (%lu)\n", buf[0], dw_bytes_read);
#endif
*bytes_read = dw_bytes_read;
return ERROR_OK;
#elif BUILD_USB_BLASTER_LIBFTDI == 1
int retval;
int timeout = 100;
*bytes_read = 0;
while ((*bytes_read < size) && timeout--)
{
retval = ftdi_read_data(&ftdic, buf + *bytes_read,
size - *bytes_read);
if (retval < 0)
{
*bytes_read = 0;
LOG_ERROR("ftdi_read_data: %s",
ftdi_get_error_string(&ftdic));
return ERROR_JTAG_DEVICE_ERROR;
}
*bytes_read += retval;
}
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("usb_blaster_buf_read %02X (%d)\n", buf[0], *bytes_read);
#endif
return ERROR_OK;
#endif
}
/* The following code doesn't fully utilize the possibilities of the
* USB-Blaster. It writes one byte per JTAG pin state change at a time; it
* doesn't even try to buffer data up to the maximum packet size of 64 bytes.
*
* Actually, the USB-Blaster offers a byte-shift mode to transmit up to 504 data
* bits (bidirectional) in a single USB packet. A header byte has to be sent as
* the first byte in a packet with the following meaning:
*
* Bit 7 (0x80): Must be set to indicate byte-shift mode.
* Bit 6 (0x40): If set, the USB-Blaster will also read data, not just write.
* Bit 5..0: Define the number N of following bytes
*
* All N following bytes will then be clocked out serially on TDI. If Bit 6 was
* set, it will afterwards return N bytes with TDO data read while clocking out
* the TDI data. LSB of the first byte after the header byte will appear first
* on TDI.
*/
/* Simple bit banging mode:
*
* Bit 7 (0x80): Must be zero (see byte-shift mode above)
* Bit 6 (0x40): If set, you will receive a byte indicating the state of TDO
* in return.
* Bit 5 (0x20): Output Enable/LED.
* Bit 4 (0x10): TDI Output.
* Bit 3 (0x08): nCS Output (not used in JTAG mode).
* Bit 2 (0x04): nCE Output (not used in JTAG mode).
* Bit 1 (0x02): TMS Output.
* Bit 0 (0x01): TCK Output.
*
* For transmitting a single data bit, you need to write two bytes. Up to 64
* bytes can be combined in a single USB packet (but this is not done in the
* code below). It isn't possible to read a data without transmitting data.
*/
#define TCK (1 << 0)
#define TMS (1 << 1)
#define NCE (1 << 2)
#define NCS (1 << 3)
#define TDI (1 << 4)
#define LED (1 << 5)
#define READ (1 << 6)
#define SHMODE (1 << 7)
#define OTHERS ((1 << 2) | (1 << 3) | (1 << 5))
#define READ_TDO (1 << 0)
static void usb_blaster_write_data(void)
{
uint32_t bytes_written;
usb_blaster_buf_write(&out_value, 1, &bytes_written);
}
static int usb_blaster_read_data(void)
{
int status;
uint8_t buf[1];
uint32_t bytes_read;
out_value |= READ;
usb_blaster_write_data();
out_value &= ~READ;
status = usb_blaster_buf_read(buf, 1, &bytes_read);
if (status < 0)
return 0;
return !!(buf[0] & READ_TDO);
}
static void usb_blaster_write(int tck, int tms, int tdi)
{
#ifdef _DEBUG_JTAG_IO_
LOG_DEBUG("---- usb_blaster_write(%d,%d,%d)\n", tck, tms, tdi);
#endif
out_value &= ~(TCK | TMS | TDI);
if (tck)
out_value |= TCK;
if (tms)
out_value |= TMS;
if (tdi)
out_value |= TDI;
usb_blaster_write_data();
}
static int usb_blaster_speed(int speed)
{
#if BUILD_USB_BLASTER_FTD2XX == 1
LOG_DEBUG("TODO: usb_blaster_speed() isn't implemented for libftd2xx!");
#elif BUILD_USB_BLASTER_LIBFTDI == 1
LOG_DEBUG("TODO: usb_blaster_speed() isn't optimally implemented!");
/* TODO: libftdi's ftdi_set_baudrate chokes on high rates, use lowlevel
* usb function instead! And additionally allow user to throttle.
*/
if (ftdi_set_baudrate(&ftdic, 3000000 / 4) < 0)
{
LOG_ERROR("Can't set baud rate to max: %s",
ftdi_get_error_string(&ftdic));
return ERROR_JTAG_DEVICE_ERROR;
};
#endif
return ERROR_OK;
}
static void usb_blaster_reset(int trst, int srst)
{
LOG_DEBUG("TODO: usb_blaster_reset(%d,%d) isn't implemented!",
trst, srst);
}
static struct bitbang_interface usb_blaster_bitbang = {
.read = usb_blaster_read_data,
.write = usb_blaster_write,
.reset = usb_blaster_reset,
};
static int usb_blaster_init(void)
{
uint8_t latency_timer;
#if BUILD_USB_BLASTER_FTD2XX == 1
FT_STATUS status;
#endif
#if BUILD_USB_BLASTER_FTD2XX == 1
LOG_DEBUG("'usb_blaster' interface using FTD2XX");
#elif BUILD_USB_BLASTER_LIBFTDI == 1
LOG_DEBUG("'usb_blaster' interface using libftdi");
#endif
#if BUILD_USB_BLASTER_FTD2XX == 1
/* Open by device description */
if (usb_blaster_device_desc == NULL)
{
LOG_WARNING("no usb_blaster device description specified, "
"using default 'USB-Blaster'");
usb_blaster_device_desc = "USB-Blaster";
}
#if IS_WIN32 == 0
/* Add non-standard Vid/Pid to the linux driver */
status = FT_SetVIDPID(usb_blaster_vid, usb_blaster_pid);
if (status != FT_OK)
{
LOG_WARNING("couldn't add %4.4x:%4.4x",
usb_blaster_vid, usb_blaster_pid);
}
#endif
status = FT_OpenEx(usb_blaster_device_desc, FT_OPEN_BY_DESCRIPTION,
&ftdih);
if (status != FT_OK)
{
DWORD num_devices;
LOG_ERROR("unable to open ftdi device: %lu", status);
status = FT_ListDevices(&num_devices, NULL,
FT_LIST_NUMBER_ONLY);
if (status == FT_OK)
{
char **desc_array = malloc(sizeof(char *)
* (num_devices + 1));
unsigned int i;
for (i = 0; i < num_devices; i++)
desc_array[i] = malloc(64);
desc_array[num_devices] = NULL;
status = FT_ListDevices(desc_array, &num_devices,
FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION);
if (status == FT_OK)
{
LOG_ERROR("ListDevices: %lu\n", num_devices);
for (i = 0; i < num_devices; i++)
LOG_ERROR("%i: %s", i, desc_array[i]);
}
for (i = 0; i < num_devices; i++)
free(desc_array[i]);
free(desc_array);
}
else
{
printf("ListDevices: NONE\n");
}
return ERROR_JTAG_INIT_FAILED;
}
status = FT_SetLatencyTimer(ftdih, 2);
if (status != FT_OK)
{
LOG_ERROR("unable to set latency timer: %lu", status);
return ERROR_JTAG_INIT_FAILED;
}
status = FT_GetLatencyTimer(ftdih, &latency_timer);
if (status != FT_OK)
{
LOG_ERROR("unable to get latency timer: %lu", status);
return ERROR_JTAG_INIT_FAILED;
}
LOG_DEBUG("current latency timer: %i", latency_timer);
status = FT_SetBitMode(ftdih, 0x00, 0);
if (status != FT_OK)
{
LOG_ERROR("unable to disable bit i/o mode: %lu", status);
return ERROR_JTAG_INIT_FAILED;
}
#elif BUILD_USB_BLASTER_LIBFTDI == 1
if (ftdi_init(&ftdic) < 0)
return ERROR_JTAG_INIT_FAILED;
/* context, vendor id, product id */
if (ftdi_usb_open(&ftdic, usb_blaster_vid, usb_blaster_pid) < 0)
{
LOG_ERROR("unable to open ftdi device: %s", ftdic.error_str);
return ERROR_JTAG_INIT_FAILED;
}
if (ftdi_usb_reset(&ftdic) < 0)
{
LOG_ERROR("unable to reset ftdi device");
return ERROR_JTAG_INIT_FAILED;
}
if (ftdi_set_latency_timer(&ftdic, 2) < 0)
{
LOG_ERROR("unable to set latency timer");
return ERROR_JTAG_INIT_FAILED;
}
if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0)
{
LOG_ERROR("unable to get latency timer");
return ERROR_JTAG_INIT_FAILED;
}
LOG_DEBUG("current latency timer: %u", latency_timer);
ftdi_disable_bitbang(&ftdic);
#endif
bitbang_interface = &usb_blaster_bitbang;
usb_blaster_speed(jtag_get_speed());
#if 0
#if BUILD_USB_BLASTER_FTD2XX == 1
if ((status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX)) != FT_OK)
{
LOG_ERROR("error purging ftd2xx device: %i", status);
return ERROR_JTAG_INIT_FAILED;
}
#elif BUILD_USB_BLASTER_LIBFTDI == 1
if (ftdi_usb_purge_buffers(&ftdic) < 0)
{
LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str);
return ERROR_JTAG_INIT_FAILED;
}
#endif
#endif
return ERROR_OK;
}
static int usb_blaster_quit(void)
{
#if BUILD_USB_BLASTER_FTD2XX == 1
FT_STATUS status;
status = FT_Close(ftdih);
#elif BUILD_USB_BLASTER_LIBFTDI == 1
ftdi_usb_close(&ftdic);
ftdi_deinit(&ftdic);
#endif
return ERROR_OK;
}
COMMAND_HANDLER(usb_blaster_handle_device_desc_command)
{
if (CMD_ARGC == 1)
usb_blaster_device_desc = strdup(CMD_ARGV[0]);
else
LOG_ERROR("require exactly one argument to "
"usb_blaster_device_desc <description>");
return ERROR_OK;
}
COMMAND_HANDLER(usb_blaster_handle_vid_pid_command)
{
if (CMD_ARGC > 2)
{
LOG_WARNING("ignoring extra IDs in ft2232_vid_pid "
"(maximum is 1 pair)");
CMD_ARGC = 2;
}
if (CMD_ARGC == 2)
{
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], usb_blaster_vid);
COMMAND_PARSE_NUMBER(u16, CMD_ARGV[1], usb_blaster_pid);
}
else
LOG_WARNING("incomplete usb_blaster_vid_pid configuration");
return ERROR_OK;
}
COMMAND_HANDLER(usb_blaster_handle_pin_command)
{
if (CMD_ARGC == 2)
{
const char * const pin_name = CMD_ARGV[0];
uint8_t mask;
unsigned int state;
if (!strcmp(pin_name, "pin6"))
mask = NCE;
else if (!strcmp(pin_name, "pin8"))
mask = NCS;
else
{
LOG_ERROR("%s: pin name must be \"pin6\" or \"pin8\"",
CMD_NAME);
return ERROR_COMMAND_SYNTAX_ERROR;
}
COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], state);
if (state == 0)
{
out_value &= ~mask;
usb_blaster_write_data();
}
else if (state == 1)
{
out_value |= mask;
usb_blaster_write_data();
}
else
{
LOG_ERROR("%s: pin state must be 0 or 1", CMD_NAME);
return ERROR_COMMAND_SYNTAX_ERROR;
}
return ERROR_OK;
}
else
{
LOG_ERROR("%s takes exactly two arguments", CMD_NAME);
return ERROR_COMMAND_SYNTAX_ERROR;
}
}
static const struct command_registration usb_blaster_command_handlers[] = {
{
.name = "usb_blaster_device_desc",
.handler = usb_blaster_handle_device_desc_command,
.mode = COMMAND_CONFIG,
.help = "set the USB device description of the USB-Blaster",
.usage = "description-string",
},
{
.name = "usb_blaster_vid_pid",
.handler = usb_blaster_handle_vid_pid_command,
.mode = COMMAND_CONFIG,
.help = "the vendor ID and product ID of the USB-Blaster",
.usage = "vid pid",
},
{
.name = "usb_blaster",
.handler = usb_blaster_handle_pin_command,
.mode = COMMAND_ANY,
.help = "set pin state for the unused GPIO pins",
.usage = "(pin6|pin8) (0|1)",
},
COMMAND_REGISTRATION_DONE
};
struct jtag_interface usb_blaster_interface = {
.name = "usb_blaster",
.commands = usb_blaster_command_handlers,
.execute_queue = bitbang_execute_queue,
.speed = usb_blaster_speed,
.init = usb_blaster_init,
.quit = usb_blaster_quit,
};

View File

@@ -653,8 +653,9 @@ static void usbprog_jtag_tms_send(struct usbprog_jtag *usbprog_jtag)
struct jtag_interface usbprog_interface = { struct jtag_interface usbprog_interface = {
.name = "usbprog", .name = "usbprog",
.execute_queue = &usbprog_execute_queue,
.speed = &usbprog_speed, .execute_queue = usbprog_execute_queue,
.init = &usbprog_init, .speed = usbprog_speed,
.quit = &usbprog_quit .init = usbprog_init,
}; .quit = usbprog_quit
};

View File

@@ -476,6 +476,17 @@ static int vsllink_init(void)
} }
VSLLINK_USB_TIMEOUT = to_tmp; VSLLINK_USB_TIMEOUT = to_tmp;
/* Some older firmware versions sometimes fail if the
* voltage isn't read first.
*/
vsllink_simple_command(0x01);
result = vsllink_usb_read(vsllink_handle);
if (result != 2)
LOG_WARNING("Fail to get target voltage");
else
LOG_INFO("Target runs at %d mV", vsllink_usb_in_buffer[0]
+ (vsllink_usb_in_buffer[1] << 8));
// connect to vsllink // connect to vsllink
vsllink_connect(); vsllink_connect();
// initialize function pointers // initialize function pointers
@@ -1894,10 +1905,10 @@ struct jtag_interface vsllink_interface = {
.name = "vsllink", .name = "vsllink",
.commands = vsllink_command_handlers, .commands = vsllink_command_handlers,
.init = &vsllink_init, .init = vsllink_init,
.quit = &vsllink_quit, .quit = vsllink_quit,
.khz = &vsllink_khz, .khz = vsllink_khz,
.speed = &vsllink_speed, .speed = vsllink_speed,
.speed_div = &vsllink_speed_div, .speed_div = vsllink_speed_div,
.execute_queue = &vsllink_execute_queue, .execute_queue = vsllink_execute_queue,
}; };

View File

@@ -58,6 +58,9 @@ extern struct jtag_interface ft2232_interface;
#if BUILD_FT2232_LIBFTDI == 1 #if BUILD_FT2232_LIBFTDI == 1
extern struct jtag_interface ft2232_interface; extern struct jtag_interface ft2232_interface;
#endif #endif
#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1
extern struct jtag_interface usb_blaster_interface;
#endif
#if BUILD_AMTJTAGACCEL == 1 #if BUILD_AMTJTAGACCEL == 1
extern struct jtag_interface amt_jtagaccel_interface; extern struct jtag_interface amt_jtagaccel_interface;
#endif #endif
@@ -115,6 +118,9 @@ struct jtag_interface *jtag_interfaces[] = {
#if BUILD_FT2232_LIBFTDI == 1 #if BUILD_FT2232_LIBFTDI == 1
&ft2232_interface, &ft2232_interface,
#endif #endif
#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1
&usb_blaster_interface,
#endif
#if BUILD_AMTJTAGACCEL == 1 #if BUILD_AMTJTAGACCEL == 1
&amt_jtagaccel_interface, &amt_jtagaccel_interface,
#endif #endif

View File

@@ -563,23 +563,22 @@ void jtag_add_reset(int req_tlr_or_trst, int srst);
* Set a global variable to \a state if \a state != TAP_INVALID. * Set a global variable to \a state if \a state != TAP_INVALID.
* *
* Return the value of the global variable. * Return the value of the global variable.
* */
**/
tap_state_t jtag_set_end_state(tap_state_t state); tap_state_t jtag_set_end_state(tap_state_t state);
/** /**
* Function jtag_get_end_state * Function jtag_get_end_state
* *
* Return the value of the global variable for end state * Return the value of the global variable for end state
* */
**/
tap_state_t jtag_get_end_state(void); tap_state_t jtag_get_end_state(void);
void jtag_add_sleep(uint32_t us); void jtag_add_sleep(uint32_t us);
/** /**
* Function jtag_add_stable_clocks * Function jtag_add_clocks
* first checks that the state in which the clocks are to be issued is * first checks that the state in which the clocks are to be issued is
* stable, then queues up clock_count clocks for transmission. * stable, then queues up num_cycles clocks for transmission.
*/ */
void jtag_add_clocks(int num_cycles); void jtag_add_clocks(int num_cycles);

View File

@@ -30,8 +30,18 @@ proc init_reset { mode } {
# documented nor supported except on ZY1000. # documented nor supported except on ZY1000.
proc power_restore {} { proc power_restore {} {
puts "Sensed power restore." puts "Sensed power restore, running reset init and halting GDB."
reset init reset init
# Halt GDB so user can deal with a detected power restore.
#
# After GDB is halted, then output is no longer forwarded
# to the GDB console.
set targets [target names]
foreach t $targets {
# New event script.
$t invoke-event arp_halt_gdb
}
} }
add_help_text power_restore "Overridable procedure run when power restore is detected. Runs 'reset init' by default." add_help_text power_restore "Overridable procedure run when power restore is detected. Runs 'reset init' by default."
@@ -46,9 +56,20 @@ proc power_dropout {} {
# documented nor supported except on ZY1000. # documented nor supported except on ZY1000.
proc srst_deasserted {} { proc srst_deasserted {} {
puts "Sensed nSRST deasserted." puts "Sensed nSRST deasserted, running reset init and halting GDB."
reset init reset init
# Halt GDB so user can deal with a detected reset.
#
# After GDB is halted, then output is no longer forwarded
# to the GDB console.
set targets [target names]
foreach t $targets {
# New event script.
$t invoke-event arp_halt_gdb
}
} }
add_help_text srst_deasserted "Overridable procedure run when srst deassert is detected. Runs 'reset init' by default." add_help_text srst_deasserted "Overridable procedure run when srst deassert is detected. Runs 'reset init' by default."
proc srst_asserted {} { proc srst_asserted {} {

View File

@@ -269,26 +269,39 @@ static int Jim_Command_flush_count(Jim_Interp *interp, int argc, Jim_Obj *const
return JIM_OK; return JIM_OK;
} }
/* REVISIT Just what about these should "move" ... ?
* These registrations, into the main JTAG table?
*
* There's a minor compatibility issue, these all show up twice;
* that's not desirable:
* - jtag drscan ... NOT DOCUMENTED!
* - drscan ...
*
* The "irscan" command (for example) doesn't show twice.
*/
static const struct command_registration jtag_command_handlers_to_move[] = { static const struct command_registration jtag_command_handlers_to_move[] = {
{ {
.name = "drscan", .name = "drscan",
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.jim_handler = &Jim_Command_drscan, .jim_handler = Jim_Command_drscan,
.help = "execute DR scan <device> " .help = "Execute Data Register (DR) scan for one TAP. "
"<num_bits> <value> <num_bits1> <value2> ...", "Other TAPs must be in BYPASS mode.",
.usage = "tap_name [num_bits value]* ['-endstate' state_name]",
}, },
{ {
.name = "flush_count", .name = "flush_count",
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.jim_handler = &Jim_Command_flush_count, .jim_handler = Jim_Command_flush_count,
.help = "returns number of times the JTAG queue has been flushed", .help = "Returns the number of times the JTAG queue "
"has been flushed.",
}, },
{ {
.name = "pathmove", .name = "pathmove",
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.jim_handler = &Jim_Command_pathmove, .jim_handler = Jim_Command_pathmove,
.usage = "<state1>,<state2>,<state3>... ", .usage = "start_state state1 [state2 [state3 ...]]",
.help = "move JTAG to state1 then to state2, state3, etc.", .help = "Move JTAG state machine from current state "
"(start_state) to state1, then state2, state3, etc.",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -610,7 +623,7 @@ static int jim_newtap_cmd(Jim_GetOptInfo *goi)
if (pTap->ir_length != 0) if (pTap->ir_length != 0)
{ {
jtag_tap_init(pTap); jtag_tap_init(pTap);
return ERROR_OK; return JIM_OK;
} }
Jim_SetResult_sprintf(goi->interp, Jim_SetResult_sprintf(goi->interp,
@@ -658,7 +671,8 @@ static void jtag_tap_handle_event(struct jtag_tap *tap, enum jtag_event e)
} }
} }
static int jim_jtag_interface(Jim_Interp *interp, int argc, Jim_Obj *const *argv) static int
jim_jtag_interface(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{ {
Jim_GetOptInfo goi; Jim_GetOptInfo goi;
Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1); Jim_GetOpt_Setup(&goi, interp, argc-1, argv + 1);
@@ -845,73 +859,88 @@ static const struct command_registration jtag_subcommand_handlers[] = {
{ {
.name = "init", .name = "init",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.handler = &handle_jtag_init_command, .handler = handle_jtag_init_command,
.help = "initialize jtag scan chain", .help = "initialize jtag scan chain",
}, },
{ {
.name = "interface", .name = "interface",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.jim_handler = &jim_jtag_interface, .jim_handler = jim_jtag_interface,
.help = "Returns the selected interface", .help = "Returns the name of the currently selected interface.",
}, },
{ {
.name = "arp_init", .name = "arp_init",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.jim_handler = &jim_jtag_arp_init, .jim_handler = jim_jtag_arp_init,
.help = "Validates JTAG scan chain against the list of "
"declared TAPs using just the four standard JTAG "
"signals.",
}, },
{ {
.name = "arp_init-reset", .name = "arp_init-reset",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.jim_handler = &jim_jtag_arp_init_reset, .jim_handler = jim_jtag_arp_init_reset,
.help = "Uses TRST and SRST to try resetting everything on "
"the JTAG scan chain, then performs 'jtag arp_init'."
}, },
{ {
.name = "newtap", .name = "newtap",
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.jim_handler = &jim_jtag_newtap, .jim_handler = jim_jtag_newtap,
.help = "Create a new TAP instance", .help = "Create a new TAP instance named basename.tap_type, "
.usage = "<name> <type> -irlen <count> [-ircapture <count>] " "and appends it to the scan chain.",
"[-irmask <count>] [-enable|-disable]", .usage = "basename tap_type '-irlen' count "
"['-enable'|'-disable'] "
"['-expected_id' number] "
"['-ignore-version'] "
"['-ircapture' number] "
"['-mask' number] ",
}, },
{ {
.name = "tapisenabled", .name = "tapisenabled",
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.jim_handler = &jim_jtag_tap_enabler, .jim_handler = jim_jtag_tap_enabler,
.help = "Returns a integer indicating TAP state (0/1)", .help = "Returns a Tcl boolean (0/1) indicating whether "
.usage = "<name>", "the TAP is enabled (1) or not (0).",
.usage = "tap_name",
}, },
{ {
.name = "tapenable", .name = "tapenable",
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.jim_handler = &jim_jtag_tap_enabler, .jim_handler = jim_jtag_tap_enabler,
.help = "Enable the specified TAP", .help = "Try to enable the specified TAP using the "
.usage = "<name>", "'tap-enable' TAP event.",
.usage = "tap_name",
}, },
{ {
.name = "tapdisable", .name = "tapdisable",
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.jim_handler = &jim_jtag_tap_enabler, .jim_handler = jim_jtag_tap_enabler,
.help = "Enable the specified TAP", .help = "Try to disable the specified TAP using the "
.usage = "<name>", "'tap-disable' TAP event.",
.usage = "tap_name",
}, },
{ {
.name = "configure", .name = "configure",
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.jim_handler = &jim_jtag_configure, .jim_handler = jim_jtag_configure,
.help = "Enable the specified TAP", .help = "Provide a Tcl handler for the specified "
.usage = "<name> [<key> <value> ...]", "TAP event.",
.usage = "tap_name '-event' event_name handler",
}, },
{ {
.name = "cget", .name = "cget",
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.jim_handler = &jim_jtag_configure, .jim_handler = jim_jtag_configure,
.help = "Enable the specified TAP", .help = "Return any Tcl handler for the specified "
.usage = "<name> [<key> <value> ...]", "TAP event.",
.usage = "tap_name '-event' event_name",
}, },
{ {
.name = "names", .name = "names",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.jim_handler = &jim_jtag_names, .jim_handler = jim_jtag_names,
.help = "Returns list of all JTAG tap names", .help = "Returns list of all JTAG tap names.",
}, },
{ {
.chain = jtag_command_handlers_to_move, .chain = jtag_command_handlers_to_move,
@@ -1574,34 +1603,38 @@ COMMAND_HANDLER(handle_tms_sequence_command)
static const struct command_registration jtag_command_handlers[] = { static const struct command_registration jtag_command_handlers[] = {
{ {
.name = "interface", .name = "interface",
.handler = &handle_interface_command, .handler = handle_interface_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "select a JTAG interface", .help = "Select a JTAG interface",
.usage = "<driver_name>", .usage = "driver_name",
}, },
{ {
.name = "interface_list", .name = "interface_list",
.handler = &handle_interface_list_command, .handler = handle_interface_list_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "list all built-in interfaces", .help = "List all built-in interfaces",
}, },
{ {
.name = "jtag_khz", .name = "jtag_khz",
.handler = &handle_jtag_khz_command, .handler = handle_jtag_khz_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "set maximum jtag speed (if supported)", .help = "With an argument, change to the specified maximum "
.usage = "<khz:0=rtck>", "jtag speed. Pass 0 to require adaptive clocking. "
"With or without argument, display current setting.",
.usage = "[khz]",
}, },
{ {
.name = "jtag_rclk", .name = "jtag_rclk",
.handler = &handle_jtag_rclk_command, .handler = handle_jtag_rclk_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "set JTAG speed to RCLK or use fallback speed", .help = "With an argument, change to to use adaptive clocking "
.usage = "<fallback_speed_khz>", "if possible; else to use the fallback speed. "
"With or without argument, display current setting.",
.usage = "[fallback_speed_khz]",
}, },
{ {
.name = "reset_config", .name = "reset_config",
.handler = &handle_reset_config_command, .handler = handle_reset_config_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "configure JTAG reset behavior", .help = "configure JTAG reset behavior",
.usage = "[none|trst_only|srst_only|trst_and_srst] " .usage = "[none|trst_only|srst_only|trst_and_srst] "
@@ -1612,79 +1645,87 @@ static const struct command_registration jtag_command_handlers[] = {
}, },
{ {
.name = "jtag_nsrst_delay", .name = "jtag_nsrst_delay",
.handler = &handle_jtag_nsrst_delay_command, .handler = handle_jtag_nsrst_delay_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "delay after deasserting srst in ms", .help = "delay after deasserting srst in ms",
.usage = "<ms>", .usage = "[milliseconds]",
}, },
{ {
.name = "jtag_ntrst_delay", .name = "jtag_ntrst_delay",
.handler = &handle_jtag_ntrst_delay_command, .handler = handle_jtag_ntrst_delay_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "delay after deasserting trst in ms", .help = "delay after deasserting trst in ms",
.usage = "<ms>" .usage = "[milliseconds]",
}, },
{ {
.name = "jtag_nsrst_assert_width", .name = "jtag_nsrst_assert_width",
.handler = &handle_jtag_nsrst_assert_width_command, .handler = handle_jtag_nsrst_assert_width_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "delay after asserting srst in ms", .help = "delay after asserting srst in ms",
.usage = "<ms>" .usage = "[milliseconds]",
}, },
{ {
.name = "jtag_ntrst_assert_width", .name = "jtag_ntrst_assert_width",
.handler = &handle_jtag_ntrst_assert_width_command, .handler = handle_jtag_ntrst_assert_width_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "delay after asserting trst in ms", .help = "delay after asserting trst in ms",
.usage = "<ms>" .usage = "[milliseconds]",
}, },
{ {
.name = "scan_chain", .name = "scan_chain",
.handler = &handle_scan_chain_command, .handler = handle_scan_chain_command,
.mode = COMMAND_EXEC, .mode = COMMAND_ANY,
.help = "print current scan chain configuration", .help = "print current scan chain configuration",
}, },
{ {
.name = "jtag_reset", .name = "jtag_reset",
.handler = &handle_jtag_reset_command, .handler = handle_jtag_reset_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "toggle reset lines", .help = "Set reset line values. Value '1' is active, "
.usage = "<trst> <srst>", "value '0' is inactive.",
.usage = "trst_active srst_active",
}, },
{ {
.name = "runtest", .name = "runtest",
.handler = &handle_runtest_command, .handler = handle_runtest_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "move to Run-Test/Idle, and execute <num_cycles>", .help = "Move to Run-Test/Idle, and issue TCK for num_cycles.",
.usage = "<num_cycles>" .usage = "num_cycles"
}, },
{ {
.name = "irscan", .name = "irscan",
.handler = &handle_irscan_command, .handler = handle_irscan_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "execute IR scan", .help = "Execute Instruction Register (DR) scan. The "
.usage = "<device> <instr> [dev2] [instr2] ...", "specified opcodes are put into each TAP's IR, "
"and other TAPs are put in BYPASS.",
.usage = "[tap_name instruction]* ['-endstate' state_name]",
}, },
{ {
.name = "verify_ircapture", .name = "verify_ircapture",
.handler = &handle_verify_ircapture_command, .handler = handle_verify_ircapture_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "verify value captured during Capture-IR", .help = "Display or assign flag controlling whether to "
.usage = "<enable | disable>", "verify values captured during Capture-IR.",
.usage = "['enable'|'disable']",
}, },
{ {
.name = "verify_jtag", .name = "verify_jtag",
.handler = &handle_verify_jtag_command, .handler = handle_verify_jtag_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "verify value capture", .help = "Display or assign flag controlling whether to "
.usage = "<enable | disable>", "verify values captured during IR and DR scans.",
.usage = "['enable'|'disable']",
}, },
{ {
.name = "tms_sequence", .name = "tms_sequence",
.handler = &handle_tms_sequence_command, .handler = handle_tms_sequence_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "choose short(default) or long tms_sequence", .help = "Display or change what style TMS sequences to use "
.usage = "<short | long>", "for JTAG state transitions: short (default) or "
"long. Only for working around JTAG bugs.",
/* Specifically for working around DRIVER bugs... */
.usage = "['short'|'long']",
}, },
{ {
.name = "jtag", .name = "jtag",

View File

@@ -50,7 +50,7 @@ static __inline__ void waitQueue(void)
// waitIdle(); // waitIdle();
} }
static void sampleShiftRegister(void) static __inline__ void sampleShiftRegister(void)
{ {
#if 0 #if 0
cyg_uint32 dummy; cyg_uint32 dummy;
@@ -59,8 +59,7 @@ static void sampleShiftRegister(void)
#endif #endif
} }
/* -O3 will inline this for us */ static __inline__ void setCurrentState(enum tap_state state)
static void setCurrentState(enum tap_state state)
{ {
cyg_uint32 a; cyg_uint32 a;
a = state; a = state;

View File

@@ -55,6 +55,11 @@
#include <time.h> #include <time.h>
#ifdef CYGPKG_HAL_NIOS2
#include <cyg/hal/io.h>
#include <cyg/firmwareutil/firmwareutil.h>
#endif
#define ZYLIN_VERSION GIT_ZY1000_VERSION #define ZYLIN_VERSION GIT_ZY1000_VERSION
#define ZYLIN_DATE __DATE__ #define ZYLIN_DATE __DATE__
#define ZYLIN_TIME __TIME__ #define ZYLIN_TIME __TIME__
@@ -127,6 +132,13 @@ static int zy1000_power_dropout(int *dropout)
void zy1000_reset(int trst, int srst) void zy1000_reset(int trst, int srst)
{ {
LOG_DEBUG("zy1000 trst=%d, srst=%d", trst, srst); LOG_DEBUG("zy1000 trst=%d, srst=%d", trst, srst);
/* flush the JTAG FIFO. Not flushing the queue before messing with
* reset has such interesting bugs as causing hard to reproduce
* RCLK bugs as RCLK will stop responding when TRST is asserted
*/
waitIdle();
if (!srst) if (!srst)
{ {
ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x00000001); ZY1000_POKE(ZY1000_JTAG_BASE + 0x14, 0x00000001);
@@ -151,7 +163,6 @@ void zy1000_reset(int trst, int srst)
if (trst||(srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) if (trst||(srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
{ {
waitIdle();
/* we're now in the RESET state until trst is deasserted */ /* we're now in the RESET state until trst is deasserted */
ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_RESET); ZY1000_POKE(ZY1000_JTAG_BASE + 0x20, TAP_RESET);
} else } else
@@ -188,6 +199,9 @@ void zy1000_reset(int trst, int srst)
int zy1000_speed(int speed) int zy1000_speed(int speed)
{ {
/* flush JTAG master FIFO before setting speed */
waitIdle();
if (speed == 0) if (speed == 0)
{ {
/*0 means RCLK*/ /*0 means RCLK*/
@@ -322,30 +336,54 @@ static int jim_zy1000_version(Jim_Interp *interp, int argc, Jim_Obj *const *argv
#ifdef CYGPKG_HAL_NIOS2 #ifdef CYGPKG_HAL_NIOS2
struct info_forward
{
void *data;
struct cyg_upgrade_info *upgraded_file;
};
static void report_info(void *data, const char * format, va_list args)
{
char *s = alloc_vprintf(format, args);
LOG_USER_N("%s", s);
free(s);
}
struct cyg_upgrade_info firmware_info =
{
(cyg_uint8 *)0x84000000,
"/ram/firmware.phi",
"Firmware",
0x0300000,
0x1f00000 -
0x0300000,
"ZylinNiosFirmware\n",
report_info,
};
static int jim_zy1000_writefirmware(Jim_Interp *interp, int argc, Jim_Obj *const *argv) static int jim_zy1000_writefirmware(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{ {
if (argc != 2) if (argc != 2)
return JIM_ERR; return JIM_ERR;
int length; int length;
int stat;
const char *str = Jim_GetString(argv[1], &length); const char *str = Jim_GetString(argv[1], &length);
/* BUG!!!! skip header! */ /* */
void *firmware_address=0x4000000; int tmpFile;
int firmware_length=0x100000; if ((tmpFile = open(firmware_info.file, O_RDWR | O_CREAT | O_TRUNC)) <= 0)
if (length>firmware_length)
return JIM_ERR;
void *err_addr;
if ((stat = flash_erase((void *)firmware_address, firmware_length, (void **)&err_addr)) != 0)
{ {
return JIM_ERR; return JIM_ERR;
} }
bool success;
success = write(tmpFile, str, length) == length;
close(tmpFile);
if (!success)
return JIM_ERR;
if ((stat = flash_program(firmware_address, str, length, (void **)&err_addr)) != 0) if (!cyg_firmware_upgrade(NULL, firmware_info))
return JIM_ERR; return JIM_ERR;
return JIM_OK; return JIM_OK;
@@ -803,29 +841,32 @@ void embeddedice_write_dcc(struct jtag_tap *tap, int reg_addr, uint8_t *buffer,
static const struct command_registration zy1000_commands[] = { static const struct command_registration zy1000_commands[] = {
{ {
.name = "power", .name = "power",
.handler = &handle_power_command, .handler = handle_power_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "turn power switch to target on/off. No arguments - print status.", .help = "Turn power switch to target on/off. "
.usage = "power <on/off>", "With no arguments, prints status.",
.usage = "('on'|'off)",
}, },
{ {
.name = "zy1000_version", .name = "zy1000_version",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.jim_handler = &jim_zy1000_version, .jim_handler = jim_zy1000_version,
.help = "print version info for zy1000", .help = "Print version info for zy1000.",
.usage = "['openocd'|'zy1000'|'date'|'time'|'pcb'|'fpga']",
}, },
{ {
.name = "powerstatus", .name = "powerstatus",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.jim_handler = & zylinjtag_Jim_Command_powerstatus, .jim_handler = zylinjtag_Jim_Command_powerstatus,
.help = "print power status of target", .help = "Returns power status of target",
}, },
#ifdef CYGPKG_HAL_NIOS2 #ifdef CYGPKG_HAL_NIOS2
{ {
.name = "updatezy1000firmware", .name = "updatezy1000firmware",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.jim_handler = &jim_zy1000_writefirmware, .jim_handler = jim_zy1000_writefirmware,
.help = "writes firmware to flash", .help = "writes firmware to flash",
/* .usage = "some_string", */
}, },
#endif #endif
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE

View File

@@ -228,7 +228,8 @@ struct command_context *setup_command_handler(Jim_Interp *interp)
} }
LOG_DEBUG("command registration: complete"); LOG_DEBUG("command registration: complete");
LOG_OUTPUT(OPENOCD_VERSION "\n"); LOG_OUTPUT(OPENOCD_VERSION "\n"
"Licensed under GNU GPL v2\n");
global_cmd_ctx = cmd_ctx; global_cmd_ctx = cmd_ctx;

View File

@@ -89,10 +89,12 @@ COMMAND_HANDLER(handle_pld_device_command)
c->driver = pld_drivers[i]; c->driver = pld_drivers[i];
c->next = NULL; c->next = NULL;
retval = CALL_COMMAND_HANDLER(pld_drivers[i]->pld_device_command, c); retval = CALL_COMMAND_HANDLER(
pld_drivers[i]->pld_device_command, c);
if (ERROR_OK != retval) if (ERROR_OK != retval)
{ {
LOG_ERROR("'%s' driver rejected pld device", CMD_ARGV[0]); LOG_ERROR("'%s' driver rejected pld device",
CMD_ARGV[0]);
free(c); free(c);
return ERROR_OK; return ERROR_OK;
} }
@@ -191,16 +193,16 @@ COMMAND_HANDLER(handle_pld_load_command)
static const struct command_registration pld_exec_command_handlers[] = { static const struct command_registration pld_exec_command_handlers[] = {
{ {
.name = "devices", .name = "devices",
.handler = &handle_pld_devices_command, .handler = handle_pld_devices_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "list configured pld devices", .help = "list configured pld devices",
}, },
{ {
.name = "load", .name = "load",
.handler = &handle_pld_load_command, .handler = handle_pld_load_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "load configuration file into PLD", .help = "load configuration file into PLD",
.usage = "<device#> <file>", .usage = "pld_num filename",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -234,14 +236,14 @@ static const struct command_registration pld_config_command_handlers[] = {
{ {
.name = "device", .name = "device",
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.handler = &handle_pld_device_command, .handler = handle_pld_device_command,
.help = "configure a PLD device", .help = "configure a PLD device",
.usage = "<driver> ...", .usage = "driver_name [driver_args ... ]",
}, },
{ {
.name = "init", .name = "init",
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.handler = &handle_pld_init_command, .handler = handle_pld_init_command,
.help = "initialize PLD devices", .help = "initialize PLD devices",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
@@ -251,7 +253,6 @@ static const struct command_registration pld_command_handler[] = {
.name = "pld", .name = "pld",
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "programmable logic device commands", .help = "programmable logic device commands",
.chain = pld_config_command_handlers, .chain = pld_config_command_handlers,
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE

View File

@@ -237,9 +237,9 @@ static const struct command_registration virtex2_exec_command_handlers[] = {
{ {
.name = "read_stat", .name = "read_stat",
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.handler = &virtex2_handle_read_stat_command, .handler = virtex2_handle_read_stat_command,
.help = "read status register", .help = "read status register",
.usage = "<device_id>", .usage = "pld_num",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@@ -37,6 +37,15 @@
#include <jtag/jtag.h> #include <jtag/jtag.h>
/**
* @file
* GDB server implementation.
*
* This implements the GDB Remote Serial Protocol, over TCP connections,
* giving GDB access to the JTAG or other hardware debugging facilities
* found in most modern embedded processors.
*/
/* private connection data for GDB */ /* private connection data for GDB */
struct gdb_connection struct gdb_connection
{ {
@@ -65,10 +74,10 @@ static struct gdb_connection *current_gdb_connection;
static int gdb_breakpoint_override; static int gdb_breakpoint_override;
static enum breakpoint_type gdb_breakpoint_override_type; static enum breakpoint_type gdb_breakpoint_override_type;
extern int gdb_error(struct connection *connection, int retval); static int gdb_error(struct connection *connection, int retval);
static unsigned short gdb_port = 3333; static unsigned short gdb_port = 3333;
static unsigned short gdb_port_next = 0; static unsigned short gdb_port_next = 0;
static const char *DIGITS = "0123456789abcdef"; static const char DIGITS[16] = "0123456789abcdef";
static void gdb_log_callback(void *priv, const char *file, unsigned line, static void gdb_log_callback(void *priv, const char *file, unsigned line,
const char *function, const char *string); const char *function, const char *string);
@@ -80,15 +89,17 @@ int gdb_actual_connections;
/* set if we are sending a memory map to gdb /* set if we are sending a memory map to gdb
* via qXfer:memory-map:read packet */ * via qXfer:memory-map:read packet */
/* enabled by default*/ /* enabled by default*/
int gdb_use_memory_map = 1; static int gdb_use_memory_map = 1;
/* enabled by default*/ /* enabled by default*/
int gdb_flash_program = 1; static int gdb_flash_program = 1;
/* if set, data aborts cause an error to be reported in memory read packets /* if set, data aborts cause an error to be reported in memory read packets
* see the code in gdb_read_memory_packet() for further explanations */ * see the code in gdb_read_memory_packet() for further explanations.
int gdb_report_data_abort = 0; * Disabled by default.
*/
static int gdb_report_data_abort;
int gdb_last_signal(struct target *target) static int gdb_last_signal(struct target *target)
{ {
switch (target->debug_reason) switch (target->debug_reason)
{ {
@@ -108,7 +119,8 @@ int gdb_last_signal(struct target *target)
} }
} }
int check_pending(struct connection *connection, int timeout_s, int *got_data) static int check_pending(struct connection *connection,
int timeout_s, int *got_data)
{ {
/* a non-blocking socket will block if there is 0 bytes available on the socket, /* a non-blocking socket will block if there is 0 bytes available on the socket,
* but return with as many bytes as are available immediately * but return with as many bytes as are available immediately
@@ -275,14 +287,14 @@ static inline int gdb_get_char_fast(struct connection *connection, int* next_cha
} }
int gdb_get_char(struct connection *connection, int* next_char) static int gdb_get_char(struct connection *connection, int* next_char)
{ {
struct gdb_connection *gdb_con = connection->priv; struct gdb_connection *gdb_con = connection->priv;
return gdb_get_char_fast(connection, next_char, &gdb_con->buf_p, &gdb_con->buf_cnt); return gdb_get_char_fast(connection, next_char, &gdb_con->buf_p, &gdb_con->buf_cnt);
} }
int gdb_putback_char(struct connection *connection, int last_char) static int gdb_putback_char(struct connection *connection, int last_char)
{ {
struct gdb_connection *gdb_con = connection->priv; struct gdb_connection *gdb_con = connection->priv;
@@ -302,7 +314,7 @@ int gdb_putback_char(struct connection *connection, int last_char)
/* The only way we can detect that the socket is closed is the first time /* The only way we can detect that the socket is closed is the first time
* we write to it, we will fail. Subsequent write operations will * we write to it, we will fail. Subsequent write operations will
* succeed. Shudder! */ * succeed. Shudder! */
int gdb_write(struct connection *connection, void *data, int len) static int gdb_write(struct connection *connection, void *data, int len)
{ {
struct gdb_connection *gdb_con = connection->priv; struct gdb_connection *gdb_con = connection->priv;
if (gdb_con->closed) if (gdb_con->closed)
@@ -327,7 +339,8 @@ int gdb_write(struct connection *connection, void *data, int len)
return ERROR_SERVER_REMOTE_CLOSED; return ERROR_SERVER_REMOTE_CLOSED;
} }
int gdb_put_packet_inner(struct connection *connection, char *buffer, int len) static int gdb_put_packet_inner(struct connection *connection,
char *buffer, int len)
{ {
int i; int i;
unsigned char my_checksum = 0; unsigned char my_checksum = 0;
@@ -350,7 +363,8 @@ int gdb_put_packet_inner(struct connection *connection, char *buffer, int len)
int gotdata; int gotdata;
for (;;) for (;;)
{ {
if ((retval = check_pending(connection, 0, &gotdata)) != ERROR_OK) retval = check_pending(connection, 0, &gotdata);
if (retval != ERROR_OK)
return retval; return retval;
if (!gotdata) if (!gotdata)
break; break;
@@ -468,7 +482,7 @@ int gdb_put_packet_inner(struct connection *connection, char *buffer, int len)
return ERROR_OK; return ERROR_OK;
} }
int gdb_put_packet(struct connection *connection, char *buffer, int len) static int gdb_put_packet(struct connection *connection, char *buffer, int len)
{ {
struct gdb_connection *gdb_con = connection->priv; struct gdb_connection *gdb_con = connection->priv;
gdb_con->busy = 1; gdb_con->busy = 1;
@@ -607,7 +621,8 @@ static __inline__ int fetch_packet(struct connection *connection, int *checksum_
return ERROR_OK; return ERROR_OK;
} }
int gdb_get_packet_inner(struct connection *connection, char *buffer, int *len) static int gdb_get_packet_inner(struct connection *connection,
char *buffer, int *len)
{ {
int character; int character;
int retval; int retval;
@@ -682,7 +697,7 @@ int gdb_get_packet_inner(struct connection *connection, char *buffer, int *len)
return ERROR_OK; return ERROR_OK;
} }
int gdb_get_packet(struct connection *connection, char *buffer, int *len) static int gdb_get_packet(struct connection *connection, char *buffer, int *len)
{ {
struct gdb_connection *gdb_con = connection->priv; struct gdb_connection *gdb_con = connection->priv;
gdb_con->busy = 1; gdb_con->busy = 1;
@@ -691,7 +706,7 @@ int gdb_get_packet(struct connection *connection, char *buffer, int *len)
return retval; return retval;
} }
int gdb_output_con(struct connection *connection, const char* line) static int gdb_output_con(struct connection *connection, const char* line)
{ {
char *hex_buffer; char *hex_buffer;
int i, bin_size; int i, bin_size;
@@ -713,7 +728,7 @@ int gdb_output_con(struct connection *connection, const char* line)
return retval; return retval;
} }
int gdb_output(struct command_context *context, const char* line) static int gdb_output(struct command_context *context, const char* line)
{ {
/* this will be dumped to the log and also sent as an O packet if possible */ /* this will be dumped to the log and also sent as an O packet if possible */
LOG_USER_N("%s", line); LOG_USER_N("%s", line);
@@ -758,7 +773,8 @@ static void gdb_frontend_halted(struct target *target, struct connection *connec
} }
} }
int gdb_target_callback_event_handler(struct target *target, enum target_event event, void *priv) static int gdb_target_callback_event_handler(struct target *target,
enum target_event event, void *priv)
{ {
int retval; int retval;
struct connection *connection = priv; struct connection *connection = priv;
@@ -786,7 +802,7 @@ int gdb_target_callback_event_handler(struct target *target, enum target_event e
return ERROR_OK; return ERROR_OK;
} }
int gdb_new_connection(struct connection *connection) static int gdb_new_connection(struct connection *connection)
{ {
struct gdb_connection *gdb_connection = malloc(sizeof(struct gdb_connection)); struct gdb_connection *gdb_connection = malloc(sizeof(struct gdb_connection));
struct gdb_service *gdb_service = connection->service->priv; struct gdb_service *gdb_service = connection->service->priv;
@@ -842,7 +858,7 @@ int gdb_new_connection(struct connection *connection)
return ERROR_OK; return ERROR_OK;
} }
int gdb_connection_closed(struct connection *connection) static int gdb_connection_closed(struct connection *connection)
{ {
struct gdb_service *gdb_service = connection->service->priv; struct gdb_service *gdb_service = connection->service->priv;
struct gdb_connection *gdb_connection = connection->priv; struct gdb_connection *gdb_connection = connection->priv;
@@ -889,14 +905,15 @@ int gdb_connection_closed(struct connection *connection)
return ERROR_OK; return ERROR_OK;
} }
void gdb_send_error(struct connection *connection, uint8_t the_error) static void gdb_send_error(struct connection *connection, uint8_t the_error)
{ {
char err[4]; char err[4];
snprintf(err, 4, "E%2.2X", the_error); snprintf(err, 4, "E%2.2X", the_error);
gdb_put_packet(connection, err, 3); gdb_put_packet(connection, err, 3);
} }
int gdb_last_signal_packet(struct connection *connection, struct target *target, char* packet, int packet_size) static int gdb_last_signal_packet(struct connection *connection,
struct target *target, char* packet, int packet_size)
{ {
char sig_reply[4]; char sig_reply[4];
int signal; int signal;
@@ -926,7 +943,8 @@ static int gdb_reg_pos(struct target *target, int pos, int len)
* The format of reg->value is little endian * The format of reg->value is little endian
* *
*/ */
void gdb_str_to_target(struct target *target, char *tstr, struct reg *reg) static void gdb_str_to_target(struct target *target,
char *tstr, struct reg *reg)
{ {
int i; int i;
@@ -943,7 +961,7 @@ void gdb_str_to_target(struct target *target, char *tstr, struct reg *reg)
} }
} }
static int hextoint(char c) static int hextoint(int c)
{ {
if (c>='0'&&c<='9') if (c>='0'&&c<='9')
{ {
@@ -959,7 +977,8 @@ static int hextoint(char c)
} }
/* copy over in register buffer */ /* copy over in register buffer */
void gdb_target_to_reg(struct target *target, char *tstr, int str_len, uint8_t *bin) static void gdb_target_to_reg(struct target *target,
char *tstr, int str_len, uint8_t *bin)
{ {
if (str_len % 2) if (str_len % 2)
{ {
@@ -978,7 +997,8 @@ void gdb_target_to_reg(struct target *target, char *tstr, int str_len, uint8_t *
} }
} }
int gdb_get_registers_packet(struct connection *connection, struct target *target, char* packet, int packet_size) static int gdb_get_registers_packet(struct connection *connection,
struct target *target, char* packet, int packet_size)
{ {
struct reg **reg_list; struct reg **reg_list;
int reg_list_size; int reg_list_size;
@@ -1028,7 +1048,8 @@ int gdb_get_registers_packet(struct connection *connection, struct target *targe
return ERROR_OK; return ERROR_OK;
} }
int gdb_set_registers_packet(struct connection *connection, struct target *target, char *packet, int packet_size) static int gdb_set_registers_packet(struct connection *connection,
struct target *target, char *packet, int packet_size)
{ {
int i; int i;
struct reg **reg_list; struct reg **reg_list;
@@ -1086,7 +1107,8 @@ int gdb_set_registers_packet(struct connection *connection, struct target *targe
return ERROR_OK; return ERROR_OK;
} }
int gdb_get_register_packet(struct connection *connection, struct target *target, char *packet, int packet_size) static int gdb_get_register_packet(struct connection *connection,
struct target *target, char *packet, int packet_size)
{ {
char *reg_packet; char *reg_packet;
int reg_num = strtoul(packet + 1, NULL, 16); int reg_num = strtoul(packet + 1, NULL, 16);
@@ -1121,7 +1143,8 @@ int gdb_get_register_packet(struct connection *connection, struct target *target
return ERROR_OK; return ERROR_OK;
} }
int gdb_set_register_packet(struct connection *connection, struct target *target, char *packet, int packet_size) static int gdb_set_register_packet(struct connection *connection,
struct target *target, char *packet, int packet_size)
{ {
char *separator; char *separator;
uint8_t *bin_buf; uint8_t *bin_buf;
@@ -1167,7 +1190,7 @@ int gdb_set_register_packet(struct connection *connection, struct target *target
return ERROR_OK; return ERROR_OK;
} }
int gdb_error(struct connection *connection, int retval) static int gdb_error(struct connection *connection, int retval)
{ {
switch (retval) switch (retval)
{ {
@@ -1198,7 +1221,8 @@ int gdb_error(struct connection *connection, int retval)
* *
* 8191 bytes by the looks of it. Why 8191 bytes instead of 8192????? * 8191 bytes by the looks of it. Why 8191 bytes instead of 8192?????
*/ */
int gdb_read_memory_packet(struct connection *connection, struct target *target, char *packet, int packet_size) static int gdb_read_memory_packet(struct connection *connection,
struct target *target, char *packet, int packet_size)
{ {
char *separator; char *separator;
uint32_t addr = 0; uint32_t addr = 0;
@@ -1272,7 +1296,8 @@ int gdb_read_memory_packet(struct connection *connection, struct target *target,
return retval; return retval;
} }
int gdb_write_memory_packet(struct connection *connection, struct target *target, char *packet, int packet_size) static int gdb_write_memory_packet(struct connection *connection,
struct target *target, char *packet, int packet_size)
{ {
char *separator; char *separator;
uint32_t addr = 0; uint32_t addr = 0;
@@ -1329,7 +1354,8 @@ int gdb_write_memory_packet(struct connection *connection, struct target *target
return retval; return retval;
} }
int gdb_write_memory_binary_packet(struct connection *connection, struct target *target, char *packet, int packet_size) static int gdb_write_memory_binary_packet(struct connection *connection,
struct target *target, char *packet, int packet_size)
{ {
char *separator; char *separator;
uint32_t addr = 0; uint32_t addr = 0;
@@ -1377,7 +1403,8 @@ int gdb_write_memory_binary_packet(struct connection *connection, struct target
return ERROR_OK; return ERROR_OK;
} }
int gdb_step_continue_packet(struct connection *connection, struct target *target, char *packet, int packet_size) static int gdb_step_continue_packet(struct connection *connection,
struct target *target, char *packet, int packet_size)
{ {
int current = 0; int current = 0;
uint32_t address = 0x0; uint32_t address = 0x0;
@@ -1410,11 +1437,12 @@ int gdb_step_continue_packet(struct connection *connection, struct target *targe
return retval; return retval;
} }
int gdb_breakpoint_watchpoint_packet(struct connection *connection, struct target *target, char *packet, int packet_size) static int gdb_breakpoint_watchpoint_packet(struct connection *connection,
struct target *target, char *packet, int packet_size)
{ {
int type; int type;
enum breakpoint_type bp_type = BKPT_SOFT /* dummy init to avoid warning */; enum breakpoint_type bp_type = BKPT_SOFT /* dummy init to avoid warning */;
enum watchpoint_rw wp_type; enum watchpoint_rw wp_type = WPT_READ /* dummy init to avoid warning */;
uint32_t address; uint32_t address;
uint32_t size; uint32_t size;
char *separator; char *separator;
@@ -1434,6 +1462,12 @@ int gdb_breakpoint_watchpoint_packet(struct connection *connection, struct targe
wp_type = WPT_READ; wp_type = WPT_READ;
else if (type == 4) /* access watchpoint */ else if (type == 4) /* access watchpoint */
wp_type = WPT_ACCESS; wp_type = WPT_ACCESS;
else
{
LOG_ERROR("invalid gdb watch/breakpoint type(%d), dropping connection", type);
return ERROR_SERVER_REMOTE_CLOSED;
}
if (gdb_breakpoint_override && ((bp_type == BKPT_SOFT)||(bp_type == BKPT_HARD))) if (gdb_breakpoint_override && ((bp_type == BKPT_SOFT)||(bp_type == BKPT_HARD)))
{ {
@@ -1484,7 +1518,7 @@ int gdb_breakpoint_watchpoint_packet(struct connection *connection, struct targe
{ {
if (packet[0] == 'Z') if (packet[0] == 'Z')
{ {
if ((retval = watchpoint_add(target, address, size, type-2, 0, 0xffffffffu)) != ERROR_OK) if ((retval = watchpoint_add(target, address, size, wp_type, 0, 0xffffffffu)) != ERROR_OK)
{ {
if ((retval = gdb_error(connection, retval)) != ERROR_OK) if ((retval = gdb_error(connection, retval)) != ERROR_OK)
return retval; return retval;
@@ -1508,8 +1542,11 @@ int gdb_breakpoint_watchpoint_packet(struct connection *connection, struct targe
return ERROR_OK; return ERROR_OK;
} }
/* print out a string and allocate more space as needed, mainly used for XML at this point */ /* print out a string and allocate more space as needed,
void xml_printf(int *retval, char **xml, int *pos, int *size, const char *fmt, ...) * mainly used for XML at this point
*/
static void xml_printf(int *retval, char **xml, int *pos, int *size,
const char *fmt, ...)
{ {
if (*retval != ERROR_OK) if (*retval != ERROR_OK)
{ {
@@ -1576,22 +1613,6 @@ static int decode_xfer_read(char *buf, char **annex, int *ofs, unsigned int *len
return 0; return 0;
} }
int gdb_calc_blocksize(struct flash_bank *bank)
{
uint32_t i;
uint32_t block_size = 0xffffffff;
/* loop through all sectors and return smallest sector size */
for (i = 0; i < (uint32_t)bank->num_sectors; i++)
{
if (bank->sectors[i].size < block_size)
block_size = bank->sectors[i].size;
}
return block_size;
}
static int compare_bank (const void * a, const void * b) static int compare_bank (const void * a, const void * b)
{ {
struct flash_bank *b1, *b2; struct flash_bank *b1, *b2;
@@ -1610,7 +1631,151 @@ static int compare_bank (const void * a, const void * b)
} }
} }
int gdb_query_packet(struct connection *connection, struct target *target, char *packet, int packet_size) static int gdb_memory_map(struct connection *connection,
struct target *target, char *packet, int packet_size)
{
/* We get away with only specifying flash here. Regions that are not
* specified are treated as if we provided no memory map(if not we
* could detect the holes and mark them as RAM).
* Normally we only execute this code once, but no big deal if we
* have to regenerate it a couple of times.
*/
struct flash_bank *p;
char *xml = NULL;
int size = 0;
int pos = 0;
int retval = ERROR_OK;
struct flash_bank **banks;
int offset;
int length;
char *separator;
uint32_t ram_start = 0;
int i;
/* skip command character */
packet += 23;
offset = strtoul(packet, &separator, 16);
length = strtoul(separator + 1, &separator, 16);
xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n");
/* Sort banks in ascending order. We need to report non-flash
* memory as ram (or rather read/write) by default for GDB, since
* it has no concept of non-cacheable read/write memory (i/o etc).
*
* FIXME Most non-flash addresses are *NOT* RAM! Don't lie.
* Current versions of GDB assume unlisted addresses are RAM...
*/
banks = malloc(sizeof(struct flash_bank *)*flash_get_bank_count());
for (i = 0; i < flash_get_bank_count(); i++) {
p = get_flash_bank_by_num(i);
if (p == NULL) {
free(banks);
retval = ERROR_FAIL;
gdb_send_error(connection, retval);
return retval;
}
banks[i] = p;
}
qsort(banks, flash_get_bank_count(), sizeof(struct flash_bank *),
compare_bank);
for (i = 0; i < flash_get_bank_count(); i++) {
int j;
unsigned sector_size = 0;
uint32_t start, end;
p = banks[i];
start = p->base;
end = p->base + p->size;
if (ram_start < p->base)
xml_printf(&retval, &xml, &pos, &size,
"<memory type=\"ram\" start=\"0x%x\" "
"length=\"0x%x\"/>\n",
ram_start, p->base - ram_start);
/* Report adjacent groups of same-size sectors. So for
* example top boot CFI flash will list an initial region
* with several large sectors (maybe 128KB) and several
* smaller ones at the end (maybe 32KB). STR7 will have
* regions with 8KB, 32KB, and 64KB sectors; etc.
*/
for (j = 0; j < p->num_sectors; j++) {
unsigned group_len;
/* Maybe start a new group of sectors. */
if (sector_size == 0) {
start = p->base + p->sectors[j].offset;
xml_printf(&retval, &xml, &pos, &size,
"<memory type=\"flash\" "
"start=\"0x%x\" ",
start);
sector_size = p->sectors[j].size;
}
/* Does this finish a group of sectors?
* If not, continue an already-started group.
*/
if (j == p->num_sectors -1)
group_len = (p->base + p->size) - start;
else if (p->sectors[j + 1].size != sector_size)
group_len = p->base + p->sectors[j + 1].offset
- start;
else
continue;
xml_printf(&retval, &xml, &pos, &size,
"length=\"0x%x\">\n"
"<property name=\"blocksize\">"
"0x%x</property>\n"
"</memory>\n",
group_len,
sector_size);
sector_size = 0;
}
ram_start = p->base + p->size;
}
if (ram_start != 0)
xml_printf(&retval, &xml, &pos, &size,
"<memory type=\"ram\" start=\"0x%x\" "
"length=\"0x%x\"/>\n",
ram_start, 0-ram_start);
/* ELSE a flash chip could be at the very end of the 32 bit address
* space, in which case ram_start will be precisely 0
*/
free(banks);
banks = NULL;
xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n");
if (retval != ERROR_OK) {
gdb_send_error(connection, retval);
return retval;
}
if (offset + length > pos)
length = pos - offset;
char *t = malloc(length + 1);
t[0] = 'l';
memcpy(t + 1, xml + offset, length);
gdb_put_packet(connection, t, length + 1);
free(t);
free(xml);
return ERROR_OK;
}
static int gdb_query_packet(struct connection *connection,
struct target *target, char *packet, int packet_size)
{ {
struct command_context *cmd_ctx = connection->cmd_ctx; struct command_context *cmd_ctx = connection->cmd_ctx;
struct gdb_connection *gdb_connection = connection->priv; struct gdb_connection *gdb_connection = connection->priv;
@@ -1709,112 +1874,9 @@ int gdb_query_packet(struct connection *connection, struct target *target, char
return ERROR_OK; return ERROR_OK;
} }
else if (strstr(packet, "qXfer:memory-map:read::") && (flash_get_bank_count() > 0)) else if (strstr(packet, "qXfer:memory-map:read::")
{ && (flash_get_bank_count() > 0))
/* We get away with only specifying flash here. Regions that are not return gdb_memory_map(connection, target, packet, packet_size);
* specified are treated as if we provided no memory map(if not we
* could detect the holes and mark them as RAM).
* Normally we only execute this code once, but no big deal if we
* have to regenerate it a couple of times. */
struct flash_bank *p;
char *xml = NULL;
int size = 0;
int pos = 0;
int retval = ERROR_OK;
int offset;
int length;
char *separator;
int blocksize;
/* skip command character */
packet += 23;
offset = strtoul(packet, &separator, 16);
length = strtoul(separator + 1, &separator, 16);
xml_printf(&retval, &xml, &pos, &size, "<memory-map>\n");
/*
sort banks in ascending order, we need to make non-flash memory be ram(or rather
read/write) by default for GDB.
GDB does not have a concept of non-cacheable read/write memory.
*/
struct flash_bank **banks = malloc(sizeof(struct flash_bank *)*flash_get_bank_count());
int i;
for (i = 0; i < flash_get_bank_count(); i++)
{
p = get_flash_bank_by_num(i);
if (p == NULL)
{
free(banks);
retval = ERROR_FAIL;
gdb_send_error(connection, retval);
return retval;
}
banks[i]=p;
}
qsort(banks, flash_get_bank_count(), sizeof(struct flash_bank *), compare_bank);
uint32_t ram_start = 0;
for (i = 0; i < flash_get_bank_count(); i++)
{
p = banks[i];
if (ram_start < p->base)
{
xml_printf(&retval, &xml, &pos, &size, "<memory type=\"ram\" start=\"0x%x\" length=\"0x%x\"/>\n",
ram_start, p->base-ram_start);
}
/* if device has uneven sector sizes, eg. str7, lpc
* we pass the smallest sector size to gdb memory map */
blocksize = gdb_calc_blocksize(p);
xml_printf(&retval, &xml, &pos, &size, "<memory type=\"flash\" start=\"0x%x\" length=\"0x%x\">\n" \
"<property name=\"blocksize\">0x%x</property>\n" \
"</memory>\n", \
p->base, p->size, blocksize);
ram_start = p->base + p->size;
}
if (ram_start != 0)
{
xml_printf(&retval, &xml, &pos, &size, "<memory type=\"ram\" start=\"0x%x\" length=\"0x%x\"/>\n",
ram_start, 0-ram_start);
} else
{
/* a flash chip could be at the very end of the 32 bit address space, in which case
ram_start will be precisely 0 */
}
free(banks);
banks = NULL;
xml_printf(&retval, &xml, &pos, &size, "</memory-map>\n");
if (retval != ERROR_OK)
{
gdb_send_error(connection, retval);
return retval;
}
if (offset + length > pos)
{
length = pos - offset;
}
char *t = malloc(length + 1);
t[0] = 'l';
memcpy(t + 1, xml + offset, length);
gdb_put_packet(connection, t, length + 1);
free(t);
free(xml);
return ERROR_OK;
}
else if (strstr(packet, "qXfer:features:read:")) else if (strstr(packet, "qXfer:features:read:"))
{ {
char *xml = NULL; char *xml = NULL;
@@ -1866,7 +1928,8 @@ int gdb_query_packet(struct connection *connection, struct target *target, char
return ERROR_OK; return ERROR_OK;
} }
int gdb_v_packet(struct connection *connection, struct target *target, char *packet, int packet_size) static int gdb_v_packet(struct connection *connection,
struct target *target, char *packet, int packet_size)
{ {
struct gdb_connection *gdb_connection = connection->priv; struct gdb_connection *gdb_connection = connection->priv;
struct gdb_service *gdb_service = connection->service->priv; struct gdb_service *gdb_service = connection->service->priv;
@@ -1913,9 +1976,19 @@ int gdb_v_packet(struct connection *connection, struct target *target, char *pac
flash_set_dirty(); flash_set_dirty();
/* perform any target specific operations before the erase */ /* perform any target specific operations before the erase */
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_FLASH_ERASE_START); target_call_event_callbacks(gdb_service->target,
result = flash_erase_address_range(gdb_service->target, addr, length); TARGET_EVENT_GDB_FLASH_ERASE_START);
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_FLASH_ERASE_END);
/* vFlashErase:addr,length messages require region start and
* end to be "block" aligned ... if padding is ever needed,
* GDB will have become dangerously confused.
*/
result = flash_erase_address_range(gdb_service->target,
false, addr, length);
/* perform any target specific operations after the erase */
target_call_event_callbacks(gdb_service->target,
TARGET_EVENT_GDB_FLASH_ERASE_END);
/* perform erase */ /* perform erase */
if (result != ERROR_OK) if (result != ERROR_OK)
@@ -2003,11 +2076,12 @@ int gdb_v_packet(struct connection *connection, struct target *target, char *pac
return ERROR_OK; return ERROR_OK;
} }
int gdb_detach(struct connection *connection, struct target *target) static int gdb_detach(struct connection *connection, struct target *target)
{ {
struct gdb_service *gdb_service = connection->service->priv; struct gdb_service *gdb_service = connection->service->priv;
target_call_event_callbacks(gdb_service->target, TARGET_EVENT_GDB_DETACH); target_call_event_callbacks(gdb_service->target,
TARGET_EVENT_GDB_DETACH);
return gdb_put_packet(connection, "OK", 2); return gdb_put_packet(connection, "OK", 2);
} }
@@ -2027,9 +2101,6 @@ static void gdb_log_callback(void *priv, const char *file, unsigned line,
gdb_output_con(connection, string); gdb_output_con(connection, string);
} }
/* Do not allocate this on the stack */
char gdb_packet_buffer[GDB_BUFFER_SIZE];
static void gdb_sig_halted(struct connection *connection) static void gdb_sig_halted(struct connection *connection)
{ {
char sig_reply[4]; char sig_reply[4];
@@ -2038,8 +2109,11 @@ static void gdb_sig_halted(struct connection *connection)
} }
int gdb_input_inner(struct connection *connection) static int gdb_input_inner(struct connection *connection)
{ {
/* Do not allocate this on the stack */
static char gdb_packet_buffer[GDB_BUFFER_SIZE];
struct gdb_service *gdb_service = connection->service->priv; struct gdb_service *gdb_service = connection->service->priv;
struct target *target = gdb_service->target; struct target *target = gdb_service->target;
char *packet = gdb_packet_buffer; char *packet = gdb_packet_buffer;
@@ -2052,10 +2126,9 @@ int gdb_input_inner(struct connection *connection)
do do
{ {
packet_size = GDB_BUFFER_SIZE-1; packet_size = GDB_BUFFER_SIZE-1;
if ((retval = gdb_get_packet(connection, packet, &packet_size)) != ERROR_OK) retval = gdb_get_packet(connection, packet, &packet_size);
{ if (retval != ERROR_OK)
return retval; return retval;
}
/* terminate with zero */ /* terminate with zero */
packet[packet_size] = 0; packet[packet_size] = 0;
@@ -2087,32 +2160,48 @@ int gdb_input_inner(struct connection *connection)
break; break;
case 'q': case 'q':
case 'Q': case 'Q':
retval = gdb_query_packet(connection, target, packet, packet_size); retval = gdb_query_packet(connection,
target, packet,
packet_size);
break; break;
case 'g': case 'g':
retval = gdb_get_registers_packet(connection, target, packet, packet_size); retval = gdb_get_registers_packet(
connection, target,
packet, packet_size);
break; break;
case 'G': case 'G':
retval = gdb_set_registers_packet(connection, target, packet, packet_size); retval = gdb_set_registers_packet(
connection, target,
packet, packet_size);
break; break;
case 'p': case 'p':
retval = gdb_get_register_packet(connection, target, packet, packet_size); retval = gdb_get_register_packet(
connection, target,
packet, packet_size);
break; break;
case 'P': case 'P':
retval = gdb_set_register_packet(connection, target, packet, packet_size); retval = gdb_set_register_packet(
connection, target,
packet, packet_size);
break; break;
case 'm': case 'm':
retval = gdb_read_memory_packet(connection, target, packet, packet_size); retval = gdb_read_memory_packet(
connection, target,
packet, packet_size);
break; break;
case 'M': case 'M':
retval = gdb_write_memory_packet(connection, target, packet, packet_size); retval = gdb_write_memory_packet(
connection, target,
packet, packet_size);
break; break;
case 'z': case 'z':
case 'Z': case 'Z':
retval = gdb_breakpoint_watchpoint_packet(connection, target, packet, packet_size); retval = gdb_breakpoint_watchpoint_packet(connection, target, packet, packet_size);
break; break;
case '?': case '?':
gdb_last_signal_packet(connection, target, packet, packet_size); gdb_last_signal_packet(
connection, target,
packet, packet_size);
break; break;
case 'c': case 'c':
case 's': case 's':
@@ -2123,12 +2212,13 @@ int gdb_input_inner(struct connection *connection)
log_add_callback(gdb_log_callback, connection); log_add_callback(gdb_log_callback, connection);
bool nostep = false; bool nostep = false;
bool already_running = false;
if (target->state == TARGET_RUNNING) if (target->state == TARGET_RUNNING)
{ {
LOG_WARNING("The target is already running. Halt target before stepi/continue."); LOG_WARNING("WARNING! The target is already running. "
retval = target_halt(target); "All changes GDB did to registers will be discarded! "
if (retval == ERROR_OK) "Waiting for target to halt.");
retval = target_wait_state(target, TARGET_HALTED, 100); already_running = true;
} else if (target->state != TARGET_HALTED) } else if (target->state != TARGET_HALTED)
{ {
LOG_WARNING("The target is not in the halted nor running stated, stepi/continue ignored."); LOG_WARNING("The target is not in the halted nor running stated, stepi/continue ignored.");
@@ -2144,7 +2234,7 @@ int gdb_input_inner(struct connection *connection)
} }
gdb_con->sync = false; gdb_con->sync = false;
if ((retval!=ERROR_OK) || nostep) if ((retval!=ERROR_OK) || (!already_running && nostep))
{ {
/* Either the target isn't in the halted state, then we can't /* Either the target isn't in the halted state, then we can't
* step/continue. This might be early setup, etc. * step/continue. This might be early setup, etc.
@@ -2164,6 +2254,9 @@ int gdb_input_inner(struct connection *connection)
*/ */
gdb_con->frontend_state = TARGET_RUNNING; gdb_con->frontend_state = TARGET_RUNNING;
target_call_event_callbacks(target, TARGET_EVENT_GDB_START); target_call_event_callbacks(target, TARGET_EVENT_GDB_START);
if (!already_running)
{
int retval = gdb_step_continue_packet(connection, target, packet, packet_size); int retval = gdb_step_continue_packet(connection, target, packet, packet_size);
if (retval != ERROR_OK) if (retval != ERROR_OK)
{ {
@@ -2172,16 +2265,22 @@ int gdb_input_inner(struct connection *connection)
} }
} }
} }
}
break; break;
case 'v': case 'v':
retval = gdb_v_packet(connection, target, packet, packet_size); retval = gdb_v_packet(
connection, target,
packet, packet_size);
break; break;
case 'D': case 'D':
retval = gdb_detach(connection, target); retval = gdb_detach(connection, target);
extended_protocol = 0; extended_protocol = 0;
break; break;
case 'X': case 'X':
if ((retval = gdb_write_memory_binary_packet(connection, target, packet, packet_size)) != ERROR_OK) retval = gdb_write_memory_binary_packet(
connection, target,
packet, packet_size);
if (retval != ERROR_OK)
return retval; return retval;
break; break;
case 'k': case 'k':
@@ -2236,7 +2335,7 @@ int gdb_input_inner(struct connection *connection)
return ERROR_OK; return ERROR_OK;
} }
int gdb_input(struct connection *connection) static int gdb_input(struct connection *connection)
{ {
int retval = gdb_input_inner(connection); int retval = gdb_input_inner(connection);
struct gdb_connection *gdb_con = connection->priv; struct gdb_connection *gdb_con = connection->priv;
@@ -2272,7 +2371,7 @@ static int gdb_target_start(struct target *target, uint16_t port)
return ERROR_OK; return ERROR_OK;
} }
int gdb_target_add_one(struct target *target) static int gdb_target_add_one(struct target *target)
{ {
if (gdb_port == 0 && server_use_pipes == 0) if (gdb_port == 0 && server_use_pipes == 0)
{ {
@@ -2411,7 +2510,7 @@ COMMAND_HANDLER(handle_gdb_breakpoint_override_command)
static const struct command_registration gdb_command_handlers[] = { static const struct command_registration gdb_command_handlers[] = {
{ {
.name = "gdb_sync", .name = "gdb_sync",
.handler = &handle_gdb_sync_command, .handler = handle_gdb_sync_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "next stepi will return immediately allowing " .help = "next stepi will return immediately allowing "
"GDB to fetch register state without affecting " "GDB to fetch register state without affecting "
@@ -2419,39 +2518,41 @@ static const struct command_registration gdb_command_handlers[] = {
}, },
{ {
.name = "gdb_port", .name = "gdb_port",
.handler = &handle_gdb_port_command, .handler = handle_gdb_port_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "daemon configuration command gdb_port", .help = "Display or specify base port on which to listen "
.usage = "<port>", "for incoming GDB connections. "
"No arguments reports GDB port; zero disables.",
.usage = "[port_num]",
}, },
{ {
.name = "gdb_memory_map", .name = "gdb_memory_map",
.handler = &handle_gdb_memory_map_command, .handler = handle_gdb_memory_map_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "enable or disable memory map", .help = "enable or disable memory map",
.usage = "enable|disable" .usage = "('enable'|'disable')"
}, },
{ {
.name = "gdb_flash_program", .name = "gdb_flash_program",
.handler = &handle_gdb_flash_program_command, .handler = handle_gdb_flash_program_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "enable or disable flash program", .help = "enable or disable flash program",
.usage = "enable|disable" .usage = "('enable'|'disable')"
}, },
{ {
.name = "gdb_report_data_abort", .name = "gdb_report_data_abort",
.handler = &handle_gdb_report_data_abort_command, .handler = handle_gdb_report_data_abort_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "enable or disable reporting data aborts", .help = "enable or disable reporting data aborts",
.usage = "enable|disable" .usage = "('enable'|'disable')"
}, },
{ {
.name = "gdb_breakpoint_override", .name = "gdb_breakpoint_override",
.handler = &handle_gdb_breakpoint_override_command, .handler = handle_gdb_breakpoint_override_command,
.mode = COMMAND_EXEC, .mode = COMMAND_ANY,
.help = "force type of breakpoint " .help = "Display or specify type of breakpoint "
"used by gdb 'break' commands.", "to be used by gdb 'break' commands.",
.usage = "hard|soft|disable", .usage = "('hard'|'soft'|'disable')"
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@@ -36,7 +36,6 @@ struct gdb_service
struct target *target; struct target *target;
}; };
int gdb_target_add_one(struct target *target);
int gdb_target_add_all(struct target *target); int gdb_target_add_all(struct target *target);
int gdb_register_commands(struct command_context *command_context); int gdb_register_commands(struct command_context *command_context);

View File

@@ -118,11 +118,11 @@ static int httpd_Jim_Command_writeform(Jim_Interp *interp, int argc,
// Find length // Find length
const char *data; const char *data;
int actual; int actual;
int retcode; int retcode;
const char *script = alloc_printf(
const char *script = alloc_printf("set dummy_val $httppostdata(%s); set dummy_val", "set dummy_val $httppostdata(%s); set dummy_val",
name); name);
retcode = Jim_Eval_Named(interp, script, __FILE__, __LINE__); retcode = Jim_Eval_Named(interp, script, __FILE__, __LINE__);
free((void *) script); free((void *) script);
if (retcode != JIM_OK) if (retcode != JIM_OK)
@@ -159,20 +159,18 @@ httpd_Jim_Command_formfetch(Jim_Interp *interp,
Jim_WrongNumArgs(interp, 1, argv, "method ?CMD_ARGV ...?"); Jim_WrongNumArgs(interp, 1, argv, "method ?CMD_ARGV ...?");
return JIM_ERR; return JIM_ERR;
} }
char *name = (char*)Jim_GetString(argv[1], NULL); char *name = (char*)Jim_GetString(argv[1], NULL);
const char *script = alloc_printf(
"set dummy_val $httppostdata(%s); set dummy_val",
const char *script = alloc_printf("set dummy_val $httppostdata(%s); set dummy_val",
name); name);
int retcode = Jim_Eval_Named(interp, script, __FILE__, __LINE__); int retcode = Jim_Eval_Named(interp, script, __FILE__, __LINE__);
free((void *) script); free((void *) script);
if (retcode != JIM_OK) if (retcode != JIM_OK)
{
Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
} else else
{
Jim_SetResult(interp, Jim_GetResult(interp)); Jim_SetResult(interp, Jim_GetResult(interp));
}
return JIM_OK; return JIM_OK;
} }
@@ -467,16 +465,16 @@ static struct MHD_Daemon * d;
static const struct command_registration httpd_command_handlers[] = { static const struct command_registration httpd_command_handlers[] = {
{ {
.name = "formfetch", .name = "formfetch",
.jim_handler = &httpd_Jim_Command_formfetch, .jim_handler = httpd_Jim_Command_formfetch,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<parameter_name>", .usage = "parameter_name",
.help = "Reads a posted form value.", .help = "Reads a posted form value.",
}, },
{ {
.name = "writeform", .name = "writeform",
.jim_handler = &httpd_Jim_Command_writeform, .jim_handler = httpd_Jim_Command_writeform,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<parameter_name> <file>", .usage = "parameter_name filename",
.help = "Writes a form value to a file.", .help = "Writes a form value to a file.",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE

View File

@@ -563,9 +563,11 @@ int server_quit(void)
/* tell the server we want to shut down */ /* tell the server we want to shut down */
COMMAND_HANDLER(handle_shutdown_command) COMMAND_HANDLER(handle_shutdown_command)
{ {
LOG_USER("shutdown command invoked");
shutdown_openocd = 1; shutdown_openocd = 1;
return ERROR_COMMAND_CLOSE_CONNECTION; return ERROR_OK;
} }
static const struct command_registration server_command_handlers[] = { static const struct command_registration server_command_handlers[] = {

View File

@@ -88,7 +88,7 @@ static int tcl_input(struct connection *connection)
const char *result; const char *result;
int reslen; int reslen;
struct tcl_connection *tclc; struct tcl_connection *tclc;
char in[256]; unsigned char in[256];
rlen = read_socket(connection->fd, &in, sizeof(in)); rlen = read_socket(connection->fd, &in, sizeof(in));
if (rlen <= 0) { if (rlen <= 0) {
@@ -181,11 +181,12 @@ COMMAND_HANDLER(handle_tcl_port_command)
static const struct command_registration tcl_command_handlers[] = { static const struct command_registration tcl_command_handlers[] = {
{ {
.name = "tcl_port", .name = "tcl_port",
.handler = &handle_tcl_port_command, .handler = handle_tcl_port_command,
.mode = COMMAND_CONFIG, .mode = COMMAND_CONFIG,
.help = "port on which to listen " .help = "Specify port on which to listen "
"for incoming TCL syntax", "for incoming Tcl syntax. "
.usage = "<port>", "No arguments reports Tcl port; zero disables.",
.usage = "[port_num]",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@@ -62,7 +62,6 @@ int telnet_prompt(struct connection *connection)
{ {
struct telnet_connection *t_con = connection->priv; struct telnet_connection *t_con = connection->priv;
telnet_write(connection, "\r", 1); /* the prompt is always placed at the line beginning */
return telnet_write(connection, t_con->prompt, strlen(t_con->prompt)); return telnet_write(connection, t_con->prompt, strlen(t_con->prompt));
} }
@@ -116,10 +115,12 @@ void telnet_log_callback(void *priv, const char *file, unsigned line,
} }
/* clear the command line */ /* clear the command line */
telnet_write(connection, "\r", 1); for (i = strlen(t_con->prompt) + t_con->line_size; i > 0; i -= 16)
telnet_write(connection, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i > 16 ? 16 : i);
for (i = strlen(t_con->prompt) + t_con->line_size; i > 0; i -= 16) for (i = strlen(t_con->prompt) + t_con->line_size; i > 0; i -= 16)
telnet_write(connection, " ", i > 16 ? 16 : i); telnet_write(connection, " ", i > 16 ? 16 : i);
telnet_write(connection, "\r", 1); for (i = strlen(t_con->prompt) + t_con->line_size; i > 0; i -= 16)
telnet_write(connection, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", i > 16 ? 16 : i);
/* output the message */ /* output the message */
telnet_outputline(connection, string); telnet_outputline(connection, string);
@@ -160,6 +161,7 @@ int telnet_new_connection(struct connection *connection)
telnet_write(connection, "\r\n", 2); telnet_write(connection, "\r\n", 2);
} }
telnet_write(connection, "\r", 1); /* the prompt is always placed at the line beginning */
telnet_prompt(connection); telnet_prompt(connection);
/* initialize history */ /* initialize history */
@@ -195,8 +197,8 @@ void telnet_clear_line(struct connection *connection, struct telnet_connection *
int telnet_input(struct connection *connection) int telnet_input(struct connection *connection)
{ {
int bytes_read; int bytes_read;
char buffer[TELNET_BUFFER_SIZE]; unsigned char buffer[TELNET_BUFFER_SIZE];
char *buf_p; unsigned char *buf_p;
struct telnet_connection *t_con = connection->priv; struct telnet_connection *t_con = connection->priv;
struct command_context *command_context = connection->cmd_ctx; struct command_context *command_context = connection->cmd_ctx;
@@ -216,7 +218,7 @@ int telnet_input(struct connection *connection)
switch (t_con->state) switch (t_con->state)
{ {
case TELNET_STATE_DATA: case TELNET_STATE_DATA:
if (*buf_p == '\xff') if (*buf_p == 0xff)
{ {
t_con->state = TELNET_STATE_IAC; t_con->state = TELNET_STATE_IAC;
} }
@@ -331,6 +333,7 @@ int telnet_input(struct connection *connection)
if (retval == ERROR_COMMAND_CLOSE_CONNECTION) if (retval == ERROR_COMMAND_CLOSE_CONNECTION)
return ERROR_SERVER_REMOTE_CLOSED; return ERROR_SERVER_REMOTE_CLOSED;
telnet_write(connection, "\r", 1); /* the prompt is always placed at the line beginning */
retval = telnet_prompt(connection); retval = telnet_prompt(connection);
if (retval == ERROR_SERVER_REMOTE_CLOSED) if (retval == ERROR_SERVER_REMOTE_CLOSED)
return ERROR_SERVER_REMOTE_CLOSED; return ERROR_SERVER_REMOTE_CLOSED;
@@ -395,16 +398,16 @@ int telnet_input(struct connection *connection)
case TELNET_STATE_IAC: case TELNET_STATE_IAC:
switch (*buf_p) switch (*buf_p)
{ {
case '\xfe': case 0xfe:
t_con->state = TELNET_STATE_DONT; t_con->state = TELNET_STATE_DONT;
break; break;
case '\xfd': case 0xfd:
t_con->state = TELNET_STATE_DO; t_con->state = TELNET_STATE_DO;
break; break;
case '\xfc': case 0xfc:
t_con->state = TELNET_STATE_WONT; t_con->state = TELNET_STATE_WONT;
break; break;
case '\xfb': case 0xfb:
t_con->state = TELNET_STATE_WILL; t_con->state = TELNET_STATE_WILL;
break; break;
} }
@@ -619,17 +622,18 @@ COMMAND_HANDLER(handle_exit_command)
static const struct command_registration telnet_command_handlers[] = { static const struct command_registration telnet_command_handlers[] = {
{ {
.name = "exit", .name = "exit",
.handler = &handle_exit_command, .handler = handle_exit_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "exit telnet session", .help = "exit telnet session",
}, },
{ {
.name = "telnet_port", .name = "telnet_port",
.handler = &handle_telnet_port_command, .handler = handle_telnet_port_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "port on which to listen " .help = "Specify port on which to listen "
"for incoming telnet connections", "for incoming telnet connections. "
.usage = "<port>", "No arguments reports telnet port; zero disables.",
.usage = "[port_num]",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@@ -470,7 +470,8 @@ free_all:
#define SVFP_CMD_INC_CNT 1024 #define SVFP_CMD_INC_CNT 1024
static int svf_read_command_from_file(int fd) static int svf_read_command_from_file(int fd)
{ {
char ch, *tmp_buffer = NULL; unsigned char ch;
char *tmp_buffer = NULL;
int cmd_pos = 0, cmd_ok = 0, slash = 0, comment = 0; int cmd_pos = 0, cmd_ok = 0, slash = 0, comment = 0;
while (!cmd_ok && (read(fd, &ch, 1) > 0)) while (!cmd_ok && (read(fd, &ch, 1) > 0))
@@ -499,31 +500,55 @@ static int svf_read_command_from_file(int fd)
case '\r': case '\r':
slash = 0; slash = 0;
comment = 0; comment = 0;
/* Don't save '\r' and '\n' if no data is parsed */
if (!cmd_pos)
break; break;
default: default:
if (!comment) if (!comment)
{ {
if (cmd_pos >= svf_command_buffer_size - 1) /* The parsing code currently expects a space
* before parentheses -- "TDI (123)". Also a
* space afterwards -- "TDI (123) TDO(456)".
* But such spaces are optional... instead of
* parser updates, cope with that by adding the
* spaces as needed.
*
* Ensure there are 3 bytes available, for:
* - current character
* - added space.
* - terminating NUL ('\0')
*/
if ((cmd_pos + 2) >= svf_command_buffer_size)
{ {
tmp_buffer = (char*)malloc(svf_command_buffer_size + SVFP_CMD_INC_CNT); // 1 more byte for '\0' /* REVISIT use realloc(); simpler */
tmp_buffer = malloc(
svf_command_buffer_size
+ SVFP_CMD_INC_CNT);
if (NULL == tmp_buffer) if (NULL == tmp_buffer)
{ {
LOG_ERROR("not enough memory"); LOG_ERROR("not enough memory");
return ERROR_FAIL; return ERROR_FAIL;
} }
if (svf_command_buffer_size > 0) if (svf_command_buffer_size > 0)
{ memcpy(tmp_buffer,
memcpy(tmp_buffer, svf_command_buffer, svf_command_buffer_size); svf_command_buffer,
} svf_command_buffer_size);
if (svf_command_buffer != NULL) if (svf_command_buffer != NULL)
{
free(svf_command_buffer); free(svf_command_buffer);
}
svf_command_buffer = tmp_buffer; svf_command_buffer = tmp_buffer;
svf_command_buffer_size += SVFP_CMD_INC_CNT; svf_command_buffer_size += SVFP_CMD_INC_CNT;
tmp_buffer = NULL; tmp_buffer = NULL;
} }
/* insert a space before '(' */
if ('(' == ch)
svf_command_buffer[cmd_pos++] = ' ';
svf_command_buffer[cmd_pos++] = (char)toupper(ch); svf_command_buffer[cmd_pos++] = (char)toupper(ch);
/* insert a space after ')' */
if (')' == ch)
svf_command_buffer[cmd_pos++] = ' ';
} }
break; break;
} }
@@ -542,25 +567,30 @@ static int svf_read_command_from_file(int fd)
static int svf_parse_cmd_string(char *str, int len, char **argus, int *num_of_argu) static int svf_parse_cmd_string(char *str, int len, char **argus, int *num_of_argu)
{ {
int pos = 0, num = 0, space_found = 1; int pos = 0, num = 0, space_found = 1, in_bracket = 0;
while (pos < len) while (pos < len)
{ {
switch (str[pos]) switch (str[pos])
{ {
case '\n':
case '\r':
case '!': case '!':
case '/': case '/':
LOG_ERROR("fail to parse svf command"); LOG_ERROR("fail to parse svf command");
return ERROR_FAIL; return ERROR_FAIL;
break; case '(':
case ' ': in_bracket = 1;
goto parse_char;
case ')':
in_bracket = 0;
goto parse_char;
default:
parse_char:
if (!in_bracket && isspace((int) str[pos]))
{
space_found = 1; space_found = 1;
str[pos] = '\0'; str[pos] = '\0';
break; }
default: else if (space_found)
if (space_found)
{ {
argus[num++] = &str[pos]; argus[num++] = &str[pos];
space_found = 0; space_found = 0;
@@ -628,6 +658,7 @@ static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_l
return ERROR_FAIL; return ERROR_FAIL;
} }
/* fill from LSB (end of str) to MSB (beginning of str) */
for (i = 0; i < str_hbyte_len; i++) for (i = 0; i < str_hbyte_len; i++)
{ {
ch = 0; ch = 0;
@@ -635,7 +666,13 @@ static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_l
{ {
ch = str[--str_len]; ch = str[--str_len];
if (!isblank(ch)) /* Skip whitespace. The SVF specification (rev E) is
* deficient in terms of basic lexical issues like
* where whitespace is allowed. Long bitstrings may
* require line ends for correctness, since there is
* a hard limit on line length.
*/
if (!isspace(ch))
{ {
if ((ch >= '0') && (ch <= '9')) if ((ch >= '0') && (ch <= '9'))
{ {
@@ -671,11 +708,12 @@ static int svf_copy_hexstring_to_binary(char *str, uint8_t **bin, int orig_bit_l
} }
} }
// consume optional leading '0' characters /* consume optional leading '0' MSBs or whitespace */
while (str_len > 0 && str[str_len - 1] == '0') while (str_len > 0 && ((str[str_len - 1] == '0')
|| isspace((int) str[str_len - 1])))
str_len--; str_len--;
// check valid /* check validity: we must have consumed everything */
if (str_len > 0 || (ch & ~((2 << ((bit_len - 1) % 4)) - 1)) != 0) if (str_len > 0 || (ch & ~((2 << ((bit_len - 1) % 4)) - 1)) != 0)
{ {
LOG_ERROR("value execeeds length"); LOG_ERROR("value execeeds length");
@@ -1460,10 +1498,10 @@ static int svf_run_command(struct command_context *cmd_ctx, char *cmd_str)
static const struct command_registration svf_command_handlers[] = { static const struct command_registration svf_command_handlers[] = {
{ {
.name = "svf", .name = "svf",
.handler = &handle_svf_command, .handler = handle_svf_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "Runs a SVF file.", .help = "Runs a SVF file.",
.usage = "<file>", .usage = "filename ['quiet']",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@@ -64,10 +64,10 @@ static int arm11_step(struct target *target, int current,
static int arm11_check_init(struct arm11_common *arm11) static int arm11_check_init(struct arm11_common *arm11)
{ {
CHECK_RETVAL(arm11_read_DSCR(arm11)); CHECK_RETVAL(arm11_read_DSCR(arm11));
LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
if (!(arm11->dscr & DSCR_HALT_DBG_MODE)) if (!(arm11->dscr & DSCR_HALT_DBG_MODE))
{ {
LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
LOG_DEBUG("Bringing target into debug mode"); LOG_DEBUG("Bringing target into debug mode");
arm11->dscr |= DSCR_HALT_DBG_MODE; arm11->dscr |= DSCR_HALT_DBG_MODE;
@@ -498,12 +498,9 @@ static int arm11_resume(struct target *target, int current,
if (!debug_execution) if (!debug_execution)
target_free_all_working_areas(target); target_free_all_working_areas(target);
/* Set up breakpoints */ /* Should we skip over breakpoints matching the PC? */
if (handle_breakpoints) if (handle_breakpoints) {
{ struct breakpoint *bp;
/* check if one matches PC and step over it if necessary */
struct breakpoint * bp;
for (bp = target->breakpoints; bp; bp = bp->next) for (bp = target->breakpoints; bp; bp = bp->next)
{ {
@@ -514,9 +511,11 @@ static int arm11_resume(struct target *target, int current,
break; break;
} }
} }
}
/* set all breakpoints */ /* activate all breakpoints */
if (true) {
struct breakpoint *bp;
unsigned brp_num = 0; unsigned brp_num = 0;
for (bp = target->breakpoints; bp; bp = bp->next) for (bp = target->breakpoints; bp; bp = bp->next)
@@ -542,7 +541,8 @@ static int arm11_resume(struct target *target, int current,
arm11_sc7_set_vcr(arm11, arm11_vcr); arm11_sc7_set_vcr(arm11, arm11_vcr);
} }
arm11_leave_debug_state(arm11, handle_breakpoints); /* activate all watchpoints and breakpoints */
arm11_leave_debug_state(arm11, true);
arm11_add_IR(arm11, ARM11_RESTART, TAP_IDLE); arm11_add_IR(arm11, ARM11_RESTART, TAP_IDLE);
@@ -953,6 +953,7 @@ static int arm11_write_memory_inner(struct target *target,
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
/* load r0 with buffer address */
/* MRC p14,0,r0,c0,c5,0 */ /* MRC p14,0,r0,c0,c5,0 */
retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address); retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
if (retval != ERROR_OK) if (retval != ERROR_OK)
@@ -975,11 +976,13 @@ static int arm11_write_memory_inner(struct target *target,
for (size_t i = 0; i < count; i++) for (size_t i = 0; i < count; i++)
{ {
/* load r1 from DCC with byte data */
/* MRC p14,0,r1,c0,c5,0 */ /* MRC p14,0,r1,c0,c5,0 */
retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++); retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
/* write r1 to memory */
/* strb r1, [r0], #1 */ /* strb r1, [r0], #1 */
/* strb r1, [r0] */ /* strb r1, [r0] */
retval = arm11_run_instr_no_data1(arm11, retval = arm11_run_instr_no_data1(arm11,
@@ -1002,11 +1005,13 @@ static int arm11_write_memory_inner(struct target *target,
uint16_t value; uint16_t value;
memcpy(&value, buffer + i * sizeof(uint16_t), sizeof(uint16_t)); memcpy(&value, buffer + i * sizeof(uint16_t), sizeof(uint16_t));
/* load r1 from DCC with halfword data */
/* MRC p14,0,r1,c0,c5,0 */ /* MRC p14,0,r1,c0,c5,0 */
retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, value); retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, value);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
/* write r1 to memory */
/* strh r1, [r0], #2 */ /* strh r1, [r0], #2 */
/* strh r1, [r0] */ /* strh r1, [r0] */
retval = arm11_run_instr_no_data1(arm11, retval = arm11_run_instr_no_data1(arm11,
@@ -1021,6 +1026,7 @@ static int arm11_write_memory_inner(struct target *target,
} }
case 4: { case 4: {
/* stream word data through DCC directly to memory */
/* increment: STC p14,c5,[R0],#4 */ /* increment: STC p14,c5,[R0],#4 */
/* no increment: STC p14,c5,[R0]*/ /* no increment: STC p14,c5,[R0]*/
uint32_t instr = !no_increment ? 0xeca05e01 : 0xed805e00; uint32_t instr = !no_increment ? 0xeca05e01 : 0xed805e00;
@@ -1318,17 +1324,20 @@ COMMAND_HANDLER(arm11_handle_vcr)
static const struct command_registration arm11_mw_command_handlers[] = { static const struct command_registration arm11_mw_command_handlers[] = {
{ {
.name = "burst", .name = "burst",
.handler = &arm11_handle_bool_memwrite_burst, .handler = arm11_handle_bool_memwrite_burst,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "Enable/Disable potentially risky fast burst mode" .help = "Display or modify flag controlling potentially "
" (default: enabled)", "risky fast burst mode (default: enabled)",
.usage = "['enable'|'disable']",
}, },
{ {
.name = "error_fatal", .name = "error_fatal",
.handler = &arm11_handle_bool_memwrite_error_fatal, .handler = arm11_handle_bool_memwrite_error_fatal,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "Terminate program if transfer error was found" .help = "Display or modify flag controlling transfer "
"termination on transfer errors"
" (default: enabled)", " (default: enabled)",
.usage = "['enable'|'disable']",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -1338,11 +1347,11 @@ static const struct command_registration arm11_any_command_handlers[] = {
* simulate + breakpoint implementation is broken. * simulate + breakpoint implementation is broken.
* TEMPORARY! NOT DOCUMENTED! */ * TEMPORARY! NOT DOCUMENTED! */
.name = "hardware_step", .name = "hardware_step",
.handler = &arm11_handle_bool_hardware_step, .handler = arm11_handle_bool_hardware_step,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "DEBUG ONLY - Hardware single stepping" .help = "DEBUG ONLY - Hardware single stepping"
" (default: disabled)", " (default: disabled)",
.usage = "(enable|disable)", .usage = "['enable'|'disable']",
}, },
{ {
.name = "memwrite", .name = "memwrite",
@@ -1352,16 +1361,18 @@ static const struct command_registration arm11_any_command_handlers[] = {
}, },
{ {
.name = "step_irq_enable", .name = "step_irq_enable",
.handler = &arm11_handle_bool_step_irq_enable, .handler = arm11_handle_bool_step_irq_enable,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "Enable interrupts while stepping" .help = "Display or modify flag controlling interrupt "
" (default: disabled)", "enable while stepping (default: disabled)",
.usage = "['enable'|'disable']",
}, },
{ {
.name = "vcr", .name = "vcr",
.handler = &arm11_handle_vcr, .handler = arm11_handle_vcr,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.help = "Control (Interrupt) Vector Catch Register", .help = "Display or modify Vector Catch Register",
.usage = "[value]",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };

View File

@@ -854,7 +854,9 @@ int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions
AddressOut = 0; AddressOut = 0;
} }
do /* Timeout here so we don't get stuck. */
int i = 0;
while (1)
{ {
JTAG_DEBUG("SC7 <= c%-3d Data %08x %s", JTAG_DEBUG("SC7 <= c%-3d Data %08x %s",
(unsigned) AddressOut, (unsigned) AddressOut,
@@ -866,10 +868,27 @@ int arm11_sc7_run(struct arm11_common * arm11, struct arm11_sc7_action * actions
CHECK_RETVAL(jtag_execute_queue()); CHECK_RETVAL(jtag_execute_queue());
if (!Ready) /* 'nRW' is 'Ready' on read out */
JTAG_DEBUG("SC7 => !ready"); if (Ready)
break;
long long then = 0;
if (i == 1000)
{
then = timeval_ms();
}
if (i >= 1000)
{
if ((timeval_ms()-then) > 1000)
{
LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
return ERROR_FAIL;
}
}
i++;
} }
while (!Ready); /* 'nRW' is 'Ready' on read out */
if (!nRW) if (!nRW)
JTAG_DEBUG("SC7 => Data %08x", (unsigned) DataIn); JTAG_DEBUG("SC7 => Data %08x", (unsigned) DataIn);

View File

@@ -255,11 +255,21 @@ static int arm720_mmu(struct target *target, int *enabled)
} }
static int arm720_virt2phys(struct target *target, static int arm720_virt2phys(struct target *target,
uint32_t virt, uint32_t *phys) uint32_t virtual, uint32_t *physical)
{ {
/** @todo Implement this! */ int type;
LOG_ERROR("%s: not implemented", __func__); uint32_t cb;
return ERROR_FAIL; int domain;
uint32_t ap;
struct arm720t_common *arm720t = target_to_arm720(target);
uint32_t ret = armv4_5_mmu_translate_va(target, &arm720t->armv4_5_mmu, virtual, &type, &cb, &domain, &ap);
if (type == -1)
{
return ret;
}
*physical = ret;
return ERROR_OK;
} }
static int arm720t_read_memory(struct target *target, static int arm720t_read_memory(struct target *target,
@@ -516,8 +526,10 @@ static const struct command_registration arm720t_exec_command_handlers[] = {
.name = "cp15", .name = "cp15",
.handler = arm720t_handle_cp15_command, .handler = arm720t_handle_cp15_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<opcode> [value]", /* prefer using less error-prone "arm mcr" or "arm mrc" */
.help = "display/modify cp15 register", .help = "display/modify cp15 register using ARM opcode"
" (DEPRECATED)",
.usage = "instruction [value]",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -576,4 +588,5 @@ struct target_type arm720t_target =
.target_create = arm720t_target_create, .target_create = arm720t_target_create,
.init_target = arm720t_init_target, .init_target = arm720t_init_target,
.examine = arm7_9_examine, .examine = arm7_9_examine,
.check_reset = arm7_9_check_reset,
}; };

View File

@@ -2,7 +2,7 @@
* Copyright (C) 2005 by Dominic Rath * * Copyright (C) 2005 by Dominic Rath *
* Dominic.Rath@gmx.de * * Dominic.Rath@gmx.de *
* * * *
* Copyright (C) 2007,2008 Øyvind Harboe * * Copyright (C) 2007-2009 Øyvind Harboe *
* oyvind.harboe@zylin.com * * oyvind.harboe@zylin.com *
* * * *
* Copyright (C) 2008 by Spencer Oliver * * Copyright (C) 2008 by Spencer Oliver *
@@ -11,6 +11,8 @@
* Copyright (C) 2008 by Hongtao Zheng * * Copyright (C) 2008 by Hongtao Zheng *
* hontor@126.com * * hontor@126.com *
* * * *
* Copyright (C) 2009 by David Brownell *
* *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by * * it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
@@ -941,14 +943,16 @@ int arm7_9_poll(struct target *target)
int arm7_9_assert_reset(struct target *target) int arm7_9_assert_reset(struct target *target)
{ {
struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
enum reset_types jtag_reset_config = jtag_get_reset_config();
bool use_event = false;
LOG_DEBUG("target->state: %s", LOG_DEBUG("target->state: %s",
target_state_name(target)); target_state_name(target));
enum reset_types jtag_reset_config = jtag_get_reset_config(); if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT))
if (!(jtag_reset_config & RESET_HAS_SRST)) use_event = true;
{ else if (!(jtag_reset_config & RESET_HAS_SRST)) {
LOG_ERROR("Can't assert SRST"); LOG_ERROR("%s: how to reset?", target_name(target));
return ERROR_FAIL; return ERROR_FAIL;
} }
@@ -963,7 +967,8 @@ int arm7_9_assert_reset(struct target *target)
*/ */
bool srst_asserted = false; bool srst_asserted = false;
if (((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0) if (!use_event
&& !(jtag_reset_config & RESET_SRST_PULLS_TRST)
&& (jtag_reset_config & RESET_SRST_NO_GATING)) && (jtag_reset_config & RESET_SRST_NO_GATING))
{ {
jtag_add_reset(0, 1); jtag_add_reset(0, 1);
@@ -973,48 +978,70 @@ int arm7_9_assert_reset(struct target *target)
if (target->reset_halt) if (target->reset_halt)
{ {
/* /*
* Some targets do not support communication while SRST is asserted. We need to * For targets that don't support communication while SRST is
* set up the reset vector catch here. * asserted, we need to set up the reset vector catch first.
* *
* If TRST is asserted, then these settings will be reset anyway, so setting them * When we use TRST+SRST and that's equivalent to a power-up
* here is harmless. * reset, these settings may well be reset anyway; so setting
* them here won't matter.
*/ */
if (arm7_9->has_vector_catch) if (arm7_9->has_vector_catch)
{ {
/* program vector catch register to catch reset vector */ /* program vector catch register to catch reset */
embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0x1); embeddedice_write_reg(&arm7_9->eice_cache
->reg_list[EICE_VEC_CATCH], 0x1);
/* extra runtest added as issues were found with certain ARM9 cores (maybe more) - AT91SAM9260 and STR9 */ /* extra runtest added as issues were found with
* certain ARM9 cores (maybe more) - AT91SAM9260
* and STR9
*/
jtag_add_runtest(1, jtag_get_end_state()); jtag_add_runtest(1, jtag_get_end_state());
} }
else else
{ {
/* program watchpoint unit to match on reset vector address */ /* program watchpoint unit to match on reset vector
embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_VALUE], 0x0); * address
embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0x3); */
embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0xffffffff); embeddedice_write_reg(&arm7_9->eice_cache
embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], EICE_W_CTRL_ENABLE); ->reg_list[EICE_W0_ADDR_VALUE], 0x0);
embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], ~EICE_W_CTRL_nOPC & 0xff); embeddedice_write_reg(&arm7_9->eice_cache
->reg_list[EICE_W0_ADDR_MASK], 0x3);
embeddedice_write_reg(&arm7_9->eice_cache
->reg_list[EICE_W0_DATA_MASK],
0xffffffff);
embeddedice_write_reg(&arm7_9->eice_cache
->reg_list[EICE_W0_CONTROL_VALUE],
EICE_W_CTRL_ENABLE);
embeddedice_write_reg(&arm7_9->eice_cache
->reg_list[EICE_W0_CONTROL_MASK],
~EICE_W_CTRL_nOPC & 0xff);
} }
} }
/* here we should issue an SRST only, but we may have to assert TRST as well */ if (use_event) {
target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
} else {
/* If we use SRST ... we'd like to issue just SRST, but the
* board or chip may be set up so we have to assert TRST as
* well. On some chips that combination is equivalent to a
* power-up reset, and generally clobbers EICE state.
*/
if (jtag_reset_config & RESET_SRST_PULLS_TRST) if (jtag_reset_config & RESET_SRST_PULLS_TRST)
{
jtag_add_reset(1, 1); jtag_add_reset(1, 1);
} else if (!srst_asserted) else if (!srst_asserted)
{
jtag_add_reset(0, 1); jtag_add_reset(0, 1);
jtag_add_sleep(50000);
} }
target->state = TARGET_RESET; target->state = TARGET_RESET;
jtag_add_sleep(50000);
register_cache_invalidate(arm7_9->armv4_5_common.core_cache); register_cache_invalidate(arm7_9->armv4_5_common.core_cache);
if ((target->reset_halt) && ((jtag_reset_config & RESET_SRST_PULLS_TRST) == 0)) /* REVISIT why isn't standard debug entry logic sufficient?? */
if (target->reset_halt
&& (!(jtag_reset_config & RESET_SRST_PULLS_TRST)
|| use_event))
{ {
/* debug entry was already prepared in arm7_9_assert_reset() */ /* debug entry was prepared above */
target->debug_reason = DBG_REASON_DBGRQ; target->debug_reason = DBG_REASON_DBGRQ;
} }
@@ -2723,6 +2750,29 @@ int arm7_9_examine(struct target *target)
return retval; return retval;
} }
int arm7_9_check_reset(struct target *target)
{
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
if (get_target_reset_nag() && !arm7_9->dcc_downloads)
{
LOG_WARNING("NOTE! DCC downloads have not been enabled, defaulting to slow memory writes. Type 'help dcc'.");
}
if (get_target_reset_nag() && (target->working_area_size == 0))
{
LOG_WARNING("NOTE! Severe performance degradation without working memory enabled.");
}
if (get_target_reset_nag() && !arm7_9->fast_memory_access)
{
LOG_WARNING("NOTE! Severe performance degradation without fast memory access enabled. Type 'help fast'.");
}
return ERROR_OK;
}
COMMAND_HANDLER(handle_arm7_9_dbgrq_command) COMMAND_HANDLER(handle_arm7_9_dbgrq_command)
{ {
struct target *target = get_current_target(CMD_CTX); struct target *target = get_current_target(CMD_CTX);
@@ -2797,6 +2847,12 @@ COMMAND_HANDLER(handle_arm7_9_semihosting_command)
COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting); COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting);
if (!target_was_examined(target))
{
LOG_ERROR("Target not examined yet");
return ERROR_FAIL;
}
if (arm7_9->has_vector_catch) { if (arm7_9->has_vector_catch) {
struct reg *vector_catch = &arm7_9->eice_cache struct reg *vector_catch = &arm7_9->eice_cache
->reg_list[EICE_VEC_CATCH]; ->reg_list[EICE_VEC_CATCH];
@@ -2858,32 +2914,32 @@ int arm7_9_init_arch_info(struct target *target, struct arm7_9_common *arm7_9)
static const struct command_registration arm7_9_any_command_handlers[] = { static const struct command_registration arm7_9_any_command_handlers[] = {
{ {
"dbgrq", "dbgrq",
.handler = &handle_arm7_9_dbgrq_command, .handler = handle_arm7_9_dbgrq_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.usage = "<enable|disable>", .usage = "['enable'|'disable']",
.help = "use EmbeddedICE dbgrq instead of breakpoint " .help = "use EmbeddedICE dbgrq instead of breakpoint "
"for target halt requests", "for target halt requests",
}, },
{ {
"fast_memory_access", "fast_memory_access",
.handler = &handle_arm7_9_fast_memory_access_command, .handler = handle_arm7_9_fast_memory_access_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.usage = "<enable|disable>", .usage = "['enable'|'disable']",
.help = "use fast memory accesses instead of slower " .help = "use fast memory accesses instead of slower "
"but potentially safer accesses", "but potentially safer accesses",
}, },
{ {
"dcc_downloads", "dcc_downloads",
.handler = &handle_arm7_9_dcc_downloads_command, .handler = handle_arm7_9_dcc_downloads_command,
.mode = COMMAND_ANY, .mode = COMMAND_ANY,
.usage = "<enable | disable>", .usage = "['enable'|'disable']",
.help = "use DCC downloads for larger memory writes", .help = "use DCC downloads for larger memory writes",
}, },
{ {
"semihosting", "semihosting",
.handler = &handle_arm7_9_semihosting_command, .handler = handle_arm7_9_semihosting_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<enable | disable>", .usage = "['enable'|'disable']",
.help = "activate support for semihosting operations", .help = "activate support for semihosting operations",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE

View File

@@ -157,5 +157,6 @@ int arm7_9_execute_sys_speed(struct target *target);
int arm7_9_init_arch_info(struct target *target, struct arm7_9_common *arm7_9); int arm7_9_init_arch_info(struct target *target, struct arm7_9_common *arm7_9);
int arm7_9_examine(struct target *target); int arm7_9_examine(struct target *target);
int arm7_9_check_reset(struct target *target);
#endif /* ARM7_9_COMMON_H */ #endif /* ARM7_9_COMMON_H */

View File

@@ -752,4 +752,5 @@ struct target_type arm7tdmi_target =
.target_create = arm7tdmi_target_create, .target_create = arm7tdmi_target_create,
.init_target = arm7tdmi_init_target, .init_target = arm7tdmi_init_target,
.examine = arm7_9_examine, .examine = arm7_9_examine,
.check_reset = arm7_9_check_reset,
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -757,7 +757,7 @@ static int arm926ejs_mmu(struct target *target, int *enabled)
static const struct command_registration arm926ejs_exec_command_handlers[] = { static const struct command_registration arm926ejs_exec_command_handlers[] = {
{ {
.name = "cache_info", .name = "cache_info",
.handler = &arm926ejs_handle_cache_info_command, .handler = arm926ejs_handle_cache_info_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.help = "display information about target caches", .help = "display information about target caches",
@@ -815,6 +815,7 @@ struct target_type arm926ejs_target =
.target_create = arm926ejs_target_create, .target_create = arm926ejs_target_create,
.init_target = arm9tdmi_init_target, .init_target = arm9tdmi_init_target,
.examine = arm7_9_examine, .examine = arm7_9_examine,
.check_reset = arm7_9_check_reset,
.virt2phys = arm926ejs_virt2phys, .virt2phys = arm926ejs_virt2phys,
.mmu = arm926ejs_mmu, .mmu = arm926ejs_mmu,

View File

@@ -68,6 +68,13 @@ static int arm966e_verify_pointer(struct command_context *cmd_ctx,
return ERROR_OK; return ERROR_OK;
} }
/*
* REVISIT: The "read_cp15" and "write_cp15" commands could hook up
* to eventual mrc() and mcr() routines ... the reg_addr values being
* constructed (for CP15 only) from Opcode_1, Opcode_2, and CRn values.
* See section 7.3 of the ARM966E-S TRM.
*/
static int arm966e_read_cp15(struct target *target, int reg_addr, uint32_t *value) static int arm966e_read_cp15(struct target *target, int reg_addr, uint32_t *value)
{ {
int retval = ERROR_OK; int retval = ERROR_OK;
@@ -86,6 +93,9 @@ static int arm966e_read_cp15(struct target *target, int reg_addr, uint32_t *valu
fields[0].tap = jtag_info->tap; fields[0].tap = jtag_info->tap;
fields[0].num_bits = 32; fields[0].num_bits = 32;
/* REVISIT: table 7-2 shows that bits 31-31 need to be
* specified for accessing BIST registers ...
*/
fields[0].out_value = NULL; fields[0].out_value = NULL;
fields[0].in_value = NULL; fields[0].in_value = NULL;
@@ -227,7 +237,7 @@ static const struct command_registration arm966e_exec_command_handlers[] = {
.name = "cp15", .name = "cp15",
.handler = arm966e_handle_cp15_command, .handler = arm966e_handle_cp15_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "<opcode> [value]", .usage = "regnum [value]",
.help = "display/modify cp15 register", .help = "display/modify cp15 register",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
@@ -284,4 +294,5 @@ struct target_type arm966e_target =
.target_create = arm966e_target_create, .target_create = arm966e_target_create,
.init_target = arm9tdmi_init_target, .init_target = arm9tdmi_init_target,
.examine = arm7_9_examine, .examine = arm7_9_examine,
.check_reset = arm7_9_check_reset,
}; };

View File

@@ -834,6 +834,12 @@ COMMAND_HANDLER(handle_arm9tdmi_catch_vectors_command)
struct reg *vector_catch; struct reg *vector_catch;
uint32_t vector_catch_value; uint32_t vector_catch_value;
if (!target_was_examined(target))
{
LOG_ERROR("Target not examined yet");
return ERROR_FAIL;
}
/* it's uncommon, but some ARM7 chips can support this */ /* it's uncommon, but some ARM7 chips can support this */
if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC
|| !arm7_9->has_vector_catch) { || !arm7_9->has_vector_catch) {
@@ -912,7 +918,9 @@ static const struct command_registration arm9tdmi_exec_command_handlers[] = {
.name = "vector_catch", .name = "vector_catch",
.handler = handle_arm9tdmi_catch_vectors_command, .handler = handle_arm9tdmi_catch_vectors_command,
.mode = COMMAND_EXEC, .mode = COMMAND_EXEC,
.usage = "[all|none|reset|undef|swi|pabt|dabt|irq|fiq] ...", .help = "Display, after optionally updating, configuration "
"of vector catch unit.",
.usage = "[all|none|(reset|undef|swi|pabt|dabt|irq|fiq)*]",
}, },
COMMAND_REGISTRATION_DONE COMMAND_REGISTRATION_DONE
}; };
@@ -967,4 +975,5 @@ struct target_type arm9tdmi_target =
.target_create = arm9tdmi_target_create, .target_create = arm9tdmi_target_create,
.init_target = arm9tdmi_init_target, .init_target = arm9tdmi_init_target,
.examine = arm7_9_examine, .examine = arm7_9_examine,
.check_reset = arm7_9_check_reset,
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -23,21 +23,63 @@
#ifndef ARM_ADI_V5_H #ifndef ARM_ADI_V5_H
#define ARM_ADI_V5_H #define ARM_ADI_V5_H
/**
* @file
* This defines formats and data structures used to talk to ADIv5 entities.
* Those include a DAP, different types of Debug Port (DP), and memory mapped
* resources accessed through a MEM-AP.
*/
#include "arm_jtag.h" #include "arm_jtag.h"
#define DAP_IR_DPACC 0xA /* JTAG instructions/registers for JTAG-DP and SWJ-DP */
#define DAP_IR_APACC 0xB #define JTAG_DP_ABORT 0x8
#define JTAG_DP_DPACC 0xA
#define JTAG_DP_APACC 0xB
#define JTAG_DP_IDCODE 0xE
/* three-bit ACK values for DPACC and APACC reads */
#define JTAG_ACK_OK_FAULT 0x2
#define JTAG_ACK_WAIT 0x1
/* three-bit ACK values for SWD access (sent LSB first) */
#define SWD_ACK_OK 0x4
#define SWD_ACK_WAIT 0x2
#define SWD_ACK_FAULT 0x1
#define DPAP_WRITE 0 #define DPAP_WRITE 0
#define DPAP_READ 1 #define DPAP_READ 1
#define DP_ZERO 0
#define DP_CTRL_STAT 0x4
#define DP_SELECT 0x8
#define DP_RDBUFF 0xC
/* A[3:0] for DP registers; A[1:0] are always zero.
* - JTAG accesses all of these via JTAG_DP_DPACC, except for
* IDCODE (JTAG_DP_IDCODE) and ABORT (JTAG_DP_ABORT).
* - SWD accesses these directly, sometimes needing SELECT.CTRLSEL
*/
#define DP_IDCODE 0 /* SWD: read */
#define DP_ABORT 0 /* SWD: write */
#define DP_CTRL_STAT 0x4 /* r/w */
#define DP_WCR 0x4 /* SWD: r/w (mux CTRLSEL) */
#define DP_RESEND 0x8 /* SWD: read */
#define DP_SELECT 0x8 /* JTAG: r/w; SWD: write */
#define DP_RDBUFF 0xC /* read-only */
/* Fields of the DP's AP ABORT register */
#define DAPABORT (1 << 0)
#define STKCMPCLR (1 << 1) /* SWD-only */
#define STKERRCLR (1 << 2) /* SWD-only */
#define WDERRCLR (1 << 3) /* SWD-only */
#define ORUNERRCLR (1 << 4) /* SWD-only */
/* Fields of the DP's CTRL/STAT register */
#define CORUNDETECT (1 << 0) #define CORUNDETECT (1 << 0)
#define SSTICKYORUN (1 << 1) #define SSTICKYORUN (1 << 1)
/* 3:2 - transaction mode (e.g. pushed compare) */
#define SSTICKYCMP (1 << 4)
#define SSTICKYERR (1 << 5) #define SSTICKYERR (1 << 5)
#define READOK (1 << 6) /* SWD-only */
#define WDATAERR (1 << 7) /* SWD-only */
/* 11:8 - mask lanes for pushed compare or verify ops */
/* 21:12 - transaction counter */
#define CDBGRSTREQ (1 << 26) #define CDBGRSTREQ (1 << 26)
#define CDBGRSTACK (1 << 27) #define CDBGRSTACK (1 << 27)
#define CDBGPWRUPREQ (1 << 28) #define CDBGPWRUPREQ (1 << 28)
@@ -45,6 +87,8 @@
#define CSYSPWRUPREQ (1 << 30) #define CSYSPWRUPREQ (1 << 30)
#define CSYSPWRUPACK (1 << 31) #define CSYSPWRUPACK (1 << 31)
/* MEM-AP register addresses */
/* TODO: rename as MEM_AP_REG_* */
#define AP_REG_CSW 0x00 #define AP_REG_CSW 0x00
#define AP_REG_TAR 0x04 #define AP_REG_TAR 0x04
#define AP_REG_DRW 0x0C #define AP_REG_DRW 0x0C
@@ -52,19 +96,26 @@
#define AP_REG_BD1 0x14 #define AP_REG_BD1 0x14
#define AP_REG_BD2 0x18 #define AP_REG_BD2 0x18
#define AP_REG_BD3 0x1C #define AP_REG_BD3 0x1C
#define AP_REG_DBGROMA 0xF8 #define AP_REG_CFG 0xF4 /* big endian? */
#define AP_REG_BASE 0xF8
/* Generic AP register address */
#define AP_REG_IDR 0xFC #define AP_REG_IDR 0xFC
/* Fields of the MEM-AP's CSW register */
#define CSW_8BIT 0 #define CSW_8BIT 0
#define CSW_16BIT 1 #define CSW_16BIT 1
#define CSW_32BIT 2 #define CSW_32BIT 2
#define CSW_ADDRINC_MASK (3 << 4) #define CSW_ADDRINC_MASK (3 << 4)
#define CSW_ADDRINC_OFF 0 #define CSW_ADDRINC_OFF 0
#define CSW_ADDRINC_SINGLE (1 << 4) #define CSW_ADDRINC_SINGLE (1 << 4)
#define CSW_ADDRINC_PACKED (2 << 4) #define CSW_ADDRINC_PACKED (2 << 4)
#define CSW_HPROT (1 << 25) #define CSW_DEVICE_EN (1 << 6)
#define CSW_MASTER_DEBUG (1 << 29) #define CSW_TRIN_PROG (1 << 7)
#define CSW_SPIDEN (1 << 23)
/* 30:24 - implementation-defined! */
#define CSW_HPROT (1 << 25) /* ? */
#define CSW_MASTER_DEBUG (1 << 29) /* ? */
#define CSW_DBGSWENABLE (1 << 31) #define CSW_DBGSWENABLE (1 << 31)
/* transaction mode */ /* transaction mode */
@@ -74,12 +125,14 @@
/* Freerunning transactions with delays and overrun checking */ /* Freerunning transactions with delays and overrun checking */
#define TRANS_MODE_COMPOSITE 2 #define TRANS_MODE_COMPOSITE 2
struct swjdp_reg /**
{ * This represents an ARM Debug Interface (v5) Debug Access Port (DAP).
int addr; * A DAP has two types of component: one Debug Port (DP), which is a
struct arm_jtag *jtag_info; * transport agent; and at least one Access Port (AP), controlling
}; * resource access. Most common is a MEM-AP, for memory access.
*
* @todo Rename "swjdp_common" as "dap". Use of SWJ-DP is optional!
*/
struct swjdp_common struct swjdp_common
{ {
struct arm_jtag *jtag_info; struct arm_jtag *jtag_info;
@@ -102,33 +155,31 @@ struct swjdp_common
}; };
/* Accessor function for currently selected DAP-AP number */ /** Accessor for currently selected DAP-AP number (0..255) */
static inline uint8_t dap_ap_get_select(struct swjdp_common *swjdp) static inline uint8_t dap_ap_get_select(struct swjdp_common *swjdp)
{ {
return (uint8_t)(swjdp ->apsel >> 24); return (uint8_t)(swjdp ->apsel >> 24);
} }
/* Internal functions used in the module, partial transactions, use with caution */ /* AP selection applies to future AP transactions */
int dap_dp_write_reg(struct swjdp_common *swjdp, uint32_t value, uint8_t reg_addr); void dap_ap_select(struct swjdp_common *dap,uint8_t apsel);
/* int swjdp_write_apacc(struct swjdp_common *swjdp, uint32_t value, uint8_t reg_addr); */
int dap_dp_read_reg(struct swjdp_common *swjdp, uint32_t *value, uint8_t reg_addr);
/* int swjdp_read_apacc(struct swjdp_common *swjdp, uint32_t *value, uint8_t reg_addr); */
int dap_setup_accessport(struct swjdp_common *swjdp, uint32_t csw, uint32_t tar);
int dap_ap_select(struct swjdp_common *swjdp,uint8_t apsel);
int dap_ap_write_reg(struct swjdp_common *swjdp, uint32_t addr, uint8_t* out_buf); /* AP transactions ... synchronous given TRANS_MODE_ATOMIC */
int dap_ap_write_reg_u32(struct swjdp_common *swjdp, uint32_t addr, uint32_t value); int dap_setup_accessport(struct swjdp_common *swjdp,
int dap_ap_read_reg(struct swjdp_common *swjdp, uint32_t addr, uint8_t *in_buf); uint32_t csw, uint32_t tar);
int dap_ap_read_reg_u32(struct swjdp_common *swjdp, uint32_t addr, uint32_t *value); int dap_ap_write_reg_u32(struct swjdp_common *swjdp,
uint32_t addr, uint32_t value);
int dap_ap_read_reg_u32(struct swjdp_common *swjdp,
uint32_t addr, uint32_t *value);
/* External interface, partial operations must be completed with swjdp_transaction_endcheck() */ /* Queued JTAG ops must be completed with jtagdp_transaction_endcheck() */
int swjdp_transaction_endcheck(struct swjdp_common *swjdp); int jtagdp_transaction_endcheck(struct swjdp_common *swjdp);
/* MEM-AP memory mapped bus single uint32_t register transfers, without endcheck */ /* Queued MEM-AP memory mapped single word transfers */
int mem_ap_read_u32(struct swjdp_common *swjdp, uint32_t address, uint32_t *value); int mem_ap_read_u32(struct swjdp_common *swjdp, uint32_t address, uint32_t *value);
int mem_ap_write_u32(struct swjdp_common *swjdp, uint32_t address, uint32_t value); int mem_ap_write_u32(struct swjdp_common *swjdp, uint32_t address, uint32_t value);
/* MEM-AP memory mapped bus transfers, single registers, complete transactions */ /* Synchronous MEM-AP memory mapped single word transfers */
int mem_ap_read_atomic_u32(struct swjdp_common *swjdp, int mem_ap_read_atomic_u32(struct swjdp_common *swjdp,
uint32_t address, uint32_t *value); uint32_t address, uint32_t *value);
int mem_ap_write_atomic_u32(struct swjdp_common *swjdp, int mem_ap_write_atomic_u32(struct swjdp_common *swjdp,

View File

@@ -50,6 +50,7 @@
* except as coprocessor 10/11 operations * except as coprocessor 10/11 operations
* * Most ARM instructions through ARMv6 are decoded, but some * * Most ARM instructions through ARMv6 are decoded, but some
* of the post-ARMv4 opcodes may not be handled yet * of the post-ARMv4 opcodes may not be handled yet
* CPS, SDIV, UDIV, LDREX*, STREX*, QASX, ...
* * NEON instructions are not understood (ARMv7-A) * * NEON instructions are not understood (ARMv7-A)
* *
* - Thumb/Thumb2 decoding * - Thumb/Thumb2 decoding
@@ -3247,7 +3248,7 @@ static int t2ev_data_immed(uint32_t opcode, uint32_t address,
case 0x0c: case 0x0c:
/* move constant to top 16 bits of register */ /* move constant to top 16 bits of register */
immed |= (opcode >> 4) & 0xf000; immed |= (opcode >> 4) & 0xf000;
sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rn, immed, immed); sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rd, immed, immed);
return ERROR_OK; return ERROR_OK;
case 0x10: case 0x10:
case 0x12: case 0x12:

View File

@@ -35,6 +35,12 @@
* Implements various ARM DPM operations using architectural debug registers. * Implements various ARM DPM operations using architectural debug registers.
* These routines layer over core-specific communication methods to cope with * These routines layer over core-specific communication methods to cope with
* implementation differences between cores like ARM1136 and Cortex-A8. * implementation differences between cores like ARM1136 and Cortex-A8.
*
* The "Debug Programmers' Model" (DPM) for ARMv6 and ARMv7 is defined by
* Part C (Debug Architecture) of the ARM Architecture Reference Manual,
* ARMv7-A and ARMv7-R edition (ARM DDI 0406B). In OpenOCD, DPM operations
* are abstracted through internal programming interfaces to share code and
* to minimize needless differences in debug behavior between cores.
*/ */
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
@@ -341,7 +347,14 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
if (retval != ERROR_OK) if (retval != ERROR_OK)
goto done; goto done;
/* enable/disable hardware breakpoints */ /* If we're managing hardware breakpoints for this core, enable
* or disable them as requested.
*
* REVISIT We don't yet manage them for ANY cores. Eventually
* we should be able to assume we handle them; but until then,
* cope with the hand-crafted breakpoint code.
*/
if (0) {
for (unsigned i = 0; i < dpm->nbp; i++) { for (unsigned i = 0; i < dpm->nbp; i++) {
struct dpm_bp *dbp = dpm->dbp + i; struct dpm_bp *dbp = dpm->dbp + i;
struct breakpoint *bp = dbp->bp; struct breakpoint *bp = dbp->bp;
@@ -349,6 +362,7 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
retval = dpm_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp, retval = dpm_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp,
bp ? &bp->set : NULL); bp ? &bp->set : NULL);
} }
}
/* enable/disable watchpoints */ /* enable/disable watchpoints */
for (unsigned i = 0; i < dpm->nwp; i++) { for (unsigned i = 0; i < dpm->nwp; i++) {

View File

@@ -2,6 +2,9 @@
* Copyright (C) 2009 by Marvell Technology Group Ltd. * * Copyright (C) 2009 by Marvell Technology Group Ltd. *
* Written by Nicolas Pitre <nico@marvell.com> * * Written by Nicolas Pitre <nico@marvell.com> *
* * * *
* Copyright (C) 2010 by Spencer Oliver *
* spen@spen-soft.co.uk *
* *
* This program is free software; you can redistribute it and/or modify * * This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by * * it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
@@ -40,7 +43,22 @@
#include "arm_semihosting.h" #include "arm_semihosting.h"
#include <helper/binarybuffer.h> #include <helper/binarybuffer.h>
#include <helper/log.h> #include <helper/log.h>
#include <sys/stat.h>
static int open_modeflags[12] = {
O_RDONLY,
O_RDONLY | O_BINARY,
O_RDWR,
O_RDWR | O_BINARY,
O_WRONLY | O_CREAT | O_TRUNC,
O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
O_RDWR | O_CREAT | O_TRUNC,
O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
O_WRONLY | O_CREAT | O_APPEND,
O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
O_RDWR | O_CREAT | O_APPEND,
O_RDWR | O_CREAT | O_APPEND | O_BINARY
};
static int do_semihosting(struct target *target) static int do_semihosting(struct target *target)
{ {
@@ -72,28 +90,21 @@ static int do_semihosting(struct target *target)
uint32_t l = target_buffer_get_u32(target, params+8); uint32_t l = target_buffer_get_u32(target, params+8);
if (l <= 255 && m <= 11) { if (l <= 255 && m <= 11) {
uint8_t fn[256]; uint8_t fn[256];
int mode;
retval = target_read_memory(target, a, 1, l, fn); retval = target_read_memory(target, a, 1, l, fn);
if (retval != ERROR_OK) if (retval != ERROR_OK)
return retval; return retval;
fn[l] = 0; fn[l] = 0;
if (m & 0x2)
mode = O_RDWR;
else if (m & 0xc)
mode = O_WRONLY;
else
mode = O_RDONLY;
if (m >= 8)
mode |= O_CREAT|O_APPEND;
else if (m >= 4)
mode |= O_CREAT|O_TRUNC;
if (strcmp((char *)fn, ":tt") == 0) { if (strcmp((char *)fn, ":tt") == 0) {
if ((mode & 3) == 0) if (m < 4)
result = dup(0); result = dup(STDIN_FILENO);
else else
result = dup(1); result = dup(STDOUT_FILENO);
} else } else {
result = open((char *)fn, mode); /* cygwin requires the permission setting
* otherwise it will fail to reopen a previously
* written file */
result = open((char *)fn, open_modeflags[m], 0644);
}
armv4_5->semihosting_errno = errno; armv4_5->semihosting_errno = errno;
} else { } else {
result = -1; result = -1;
@@ -179,7 +190,7 @@ static int do_semihosting(struct target *target)
} else { } else {
result = read(fd, buf, l); result = read(fd, buf, l);
armv4_5->semihosting_errno = errno; armv4_5->semihosting_errno = errno;
if (result > 0) { if (result >= 0) {
retval = target_write_buffer(target, a, result, buf); retval = target_write_buffer(target, a, result, buf);
if (retval != ERROR_OK) { if (retval != ERROR_OK) {
free(buf); free(buf);
@@ -230,18 +241,14 @@ static int do_semihosting(struct target *target)
return retval; return retval;
else { else {
int fd = target_buffer_get_u32(target, params+0); int fd = target_buffer_get_u32(target, params+0);
off_t cur = lseek(fd, 0, SEEK_CUR); struct stat buf;
if (cur == (off_t)-1) { result = fstat(fd, &buf);
if (result == -1) {
armv4_5->semihosting_errno = errno; armv4_5->semihosting_errno = errno;
result = -1; result = -1;
break; break;
} }
result = lseek(fd, 0, SEEK_END); result = buf.st_size;
armv4_5->semihosting_errno = errno;
if (lseek(fd, cur, SEEK_SET) == (off_t)-1) {
armv4_5->semihosting_errno = errno;
result = -1;
}
} }
break; break;

Some files were not shown because too many files have changed in this diff Show More