From: David B. <dbr...@us...> - 2010-02-22 02:52:30
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via c21c740a895438832ed7e945ee4943da3eb733f9 (commit) via dc342f45f6c8ec02431495863687b3638f1646d5 (commit) via c8ea748dc22660dad934537384d35903dfcc492e (commit) via 3b68a708c2b039d9b091608eccb2206725742a47 (commit) via ecff73043c1ddcc97d4d1ea1c87f251a850b22d4 (commit) via 39cfe6279616a69b858ddd3493d61ed7133ff081 (commit) via a97bb67543eacde38f093610982812f714e7a050 (commit) via 249263d29da11b0ec981c2e0d520cd7dcf08939b (commit) via 1aac72d24339380f6e98c50dec4c96ab30537749 (commit) via a299371a9ec109da3851cb43aed3e9157d095358 (commit) via 27c068c1f82423a2492899d1632caaa6f8261810 (commit) via ce1feaa7322affd3b979c9fe93dd8f7462ea9eca (commit) from b853b9dbc0ba3d68a501d8badc4491f8108cd11b (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit c21c740a895438832ed7e945ee4943da3eb733f9 Author: David Brownell <dbr...@us...> Date: Sun Feb 21 17:19:08 2010 -0800 ft2232 table init cleanup Use labeled initializers in the table of layouts instead of positional ones. This ls cleaner and less error prone, plus it simplifies patches which add members to these structure. Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/jtag/drivers/ft2232.c b/src/jtag/drivers/ft2232.c index 82132d3..5042a22 100644 --- a/src/jtag/drivers/ft2232.c +++ b/src/jtag/drivers/ft2232.c @@ -185,25 +185,84 @@ static void ktlink_blink(void); static const struct ft2232_layout ft2232_layouts[] = { - { "usbjtag", usbjtag_init, usbjtag_reset, NULL }, - { "jtagkey", jtagkey_init, jtagkey_reset, NULL }, - { "jtagkey_prototype_v1", jtagkey_init, jtagkey_reset, NULL }, - { "oocdlink", jtagkey_init, jtagkey_reset, NULL }, - { "signalyzer", usbjtag_init, usbjtag_reset, NULL }, - { "evb_lm3s811", usbjtag_init, usbjtag_reset, NULL }, - { "luminary_icdi", usbjtag_init, usbjtag_reset, NULL }, - { "olimex-jtag", olimex_jtag_init, olimex_jtag_reset, olimex_jtag_blink }, - { "flyswatter", flyswatter_init, flyswatter_reset, flyswatter_jtag_blink }, - { "turtelizer2", turtle_init, turtle_reset, turtle_jtag_blink }, - { "comstick", comstick_init, comstick_reset, NULL }, - { "stm32stick", stm32stick_init, stm32stick_reset, NULL }, - { "axm0432_jtag", axm0432_jtag_init, axm0432_jtag_reset, NULL }, - { "sheevaplug", sheevaplug_init, sheevaplug_reset, NULL }, - { "icebear", icebear_jtag_init, icebear_jtag_reset, NULL }, - { "cortino", cortino_jtag_init, comstick_reset, NULL }, - { "signalyzer-h", signalyzer_h_init, signalyzer_h_reset, signalyzer_h_blink }, - { "ktlink", ktlink_init, ktlink_reset, ktlink_blink }, - { NULL, NULL, NULL, NULL }, + { .name = "usbjtag", + .init = usbjtag_init, + .reset = usbjtag_reset, + }, + { .name = "jtagkey", + .init = jtagkey_init, + .reset = jtagkey_reset, + }, + { .name = "jtagkey_prototype_v1", + .init = jtagkey_init, + .reset = jtagkey_reset, + }, + { .name = "oocdlink", + .init = jtagkey_init, + .reset = jtagkey_reset, + }, + { .name = "signalyzer", + .init = usbjtag_init, + .reset = usbjtag_reset, + }, + { .name = "evb_lm3s811", + .init = usbjtag_init, + .reset = usbjtag_reset, + }, + { .name = "luminary_icdi", + .init = usbjtag_init, + .reset = usbjtag_reset, + }, + { .name = "olimex-jtag", + .init = olimex_jtag_init, + .reset = olimex_jtag_reset, + .blink = olimex_jtag_blink + }, + { .name = "flyswatter", + .init = flyswatter_init, + .reset = flyswatter_reset, + .blink = flyswatter_jtag_blink + }, + { .name = "turtelizer2", + .init = turtle_init, + .reset = turtle_reset, + .blink = turtle_jtag_blink + }, + { .name = "comstick", + .init = comstick_init, + .reset = comstick_reset, + }, + { .name = "stm32stick", + .init = stm32stick_init, + .reset = stm32stick_reset, + }, + { .name = "axm0432_jtag", + .init = axm0432_jtag_init, + .reset = axm0432_jtag_reset, + }, + { .name = "sheevaplug", + .init = sheevaplug_init, + .reset = sheevaplug_reset, + }, + { .name = "icebear", + .init = icebear_jtag_init, + .reset = icebear_jtag_reset, + }, + { .name = "cortino", + .init = cortino_jtag_init, + .reset = comstick_reset, + }, + { .name = "signalyzer-h", + .init = signalyzer_h_init, + .reset = signalyzer_h_reset, + .blink = signalyzer_h_blink + }, + { .name = "ktlink", + .init = ktlink_init, + .reset = ktlink_reset, + .blink = ktlink_blink + }, + { .name = NULL, /* END OF TABLE */ }, }; static uint8_t nTRST, nTRSTnOE, nSRST, nSRSTnOE; commit dc342f45f6c8ec02431495863687b3638f1646d5 Author: David Brownell <dbr...@us...> Date: Sun Feb 21 16:55:17 2010 -0800 Developer's Guide: refresh release procedures Be a closer match to what I've actually done for the past few cycles. In particular, hold off pushing repository updates until after the packages are published, as part of opening the merge window, and mention the utility commands which actually create the archives. Signed-off-by: David Brownell <dbr...@us...> diff --git a/doc/manual/release.txt b/doc/manual/release.txt index 70a22ff..056628e 100644 --- a/doc/manual/release.txt +++ b/doc/manual/release.txt @@ -84,8 +84,8 @@ the minor version will @a also be zero (<code>y = 0, z = 0</code>). After these required numeric components, release version strings may contain tags such as as <em>-rc1</em> or <em>-rc2</em>. These 'rc' tags indicate "release candidate" versions of the package. -Like the major/minor/micro numbers, these tags will be manipulated -by the automated release process. +Like major/minor/micro numbers, these are updated +as part of the release process. The release process includes version number manipulations to the tree being released, ensuring that all numbers are incremented (or rolled @@ -277,22 +277,34 @@ support; the Release Manager isn't the only participant. The following steps should be followed to produce each release: --# Produce final patches to mainline (or a release branch). Nobody - except the RM should be committing anything. - -# Finalize @c NEWS file to describe the changes in the release +-# Produce final patches using a local clone of mainline. Nobody + except the RM should be committing anything. <em>Everyone with commit + privileges needs to know and agree to this in advance!</em> Even the RM + only commits a handful of updates as part of the release process + itself ... to files which are part of the version identification scheme + or release process; and to create the version tag; and then to open the + merge window for the next release cycle. + -# Finalize @c the NEWS file to describe the changes in the release - This file is used to automatically post "blurbs" about the project. - - This material should be produced during the development cycle. - - Add a new item for each @c NEWS-worthy contribution, when committed. + - This material should have been produced during the development cycle, + by adding items for each @c NEWS-worthy contribution, when committed + during the merge window. (One part of closing the merge window, by + opening the RC phase of the release, is the commitment to hold all + further such contributions until the next merge window opens.) + - The RM should make sure nothing important was omitted, as part of + the RC1 cycle. From then on, no more updates to NEWS content should + be needed (except to seed the process for the next release, or maybe + if a significant and longstanding bug is fixed late in the RC phase). -# Bump library version if our API changed (not yet required) -# Update and commit the final package version in @c configure.in: - <code>tools/release/version.sh</code> may help ensure the versions - are named consistently: + (The <code>tools/release/version.sh</code> script might help ensure + the versions are named properly.): -# Remove @c -dev tag. - -# Update the @c -rc tag: + -# Update any @c -rc tag: - If producing the final release from an -rc series, remove it - If producing the first RC in a series, add rc1 - If producing the next RC in a series, bump the rc number - -# Commit that version change. + -# Commit that version change, with a good descriptive comment. -# Create a git tag for the final commit, with a tag name matching the version string in <code>configure.in</code> (including <em>-rcN</em> where relevant): @@ -301,49 +313,92 @@ PACKAGE_VERSION="x.y.z" PACKAGE_TAG="v${PACKAGE_VERSION}" git tag -m "The openocd-${PACKAGE_VERSION} release." "${PACKAGE_TAG}" @endverbatim --# Prepare to resume normal development on mainline (major or minor release) - - Update the version label - - Restore @c -dev version tag. - - For a new minor release cycle, increment the release's minor number - - For a new major release cycle, increment the release's major number - and zero its minor number - - Archive @c NEWS file as "<code>doc/news/NEWS-${PACKAGE_VERSION}</code>". - - Create a new @c NEWS file for the next release - - Commit those changes, and push the commit and the release tag - to mainline. --# Produce the package source archives: - -# <em>Start with a new clone of the source tree</em>, with the - release's tag. This is used only for producing these packages. - -# Checkout the appropriate tag: -<code>git checkout "${PACKAGE_VERSION}"</code> - -# @c bootstrap, @c configure, and @c make the package. - -# Run <code>make distcheck</code> to produce the distribution archives. - -# Run <code>make maintainer-clean</code> verify the repository is empty. - -# Create signature files using @c md5sum, @c sha1sum, etc. --# Publish documentation for the release: - - Allow users to access the documentation for each of our releases. - - Place static copies of the following files on the project website: - - @c NEWS: to provide a blurb for each release - - User's Guide, Developer Manual: to allow easy on-line viewing + -# Do not push those changes to mainline yet; only builds using the + source archives you will be creating should ever be labeled as + official releases (with no "-dev" suffix). Since mainline is a + development tree, these will be pushed later, as part of opening + the merge window for the next release cycle (restoring the "-dev" + suffix for that next release.) Those version and tag updates are + the last ones to be included in the release being made. +-# Produce the release files, using the local clone of the source + tree which holds the release's tag and updated version in + @c configure.in ... this is used only to produce the release, and + all files should already be properly checked out. + -# Run <code>tools/release.sh package</code> to produce the + source archives. This automatically bootstraps and + configures the process. + -# Run <code>tools/release.sh stage</code> to create an @c archives + directory with the release data, including MD5 and SHA1 + checksum files (which are used with Berlios). + -# Sanity check at least one of those archives, by extracting and + configuring its contents, using them to build a copy of OpenOCD, + and verifying that the result prints the correct release version + in its startup banner. (For example, + "configure --enable-ft2232_libftdi --enable-parport" + then "make" and run "src/openocd -v" as a sanity check.) + -# Run <code>make docs</code> to create the + documentation which will be published. -# Upload packages and post announcements of their availability: -# Release packages into files section of project sites: - SF.net: - -# Create a new folder named "${PACKAGE_VERSION}" - -# Select new folder as the target for uploads. - -# Upload files via Web interface into new - -# Set platform types for each archive: + -# Under "Project Admin", use the "File Manager" + -# Create a new folder under "openocd" named "${PACKAGE_VERSION}" + -# Upload the @c NEWS file and mark it as the release notes. + -# Upload the three source archive files, using the Web interface, + into that folder. Verify the upload worked OK by checking the + MD5 and SHA1 checksums computed by SourceForge against the + versions created as part of staging the release. + -# Also upload doc/openocd.pdf (the User's Guide) so the version + matching each release will be easily available. + -# Select each file in the release, and use the property panel + to set its type and select the right release notes. - .tar.bz2: Linux, Mac - .tar.gz: BSD, Solaris, Others - .zip: Windows + - For openocd.pdf just associate it with the right release notes. + -# Create an SF.net project news update. - Berlios: - -# Create the new release for the new version. -# Provide @c NEWS file, as requested. - -# Upload files via FTP to ftp://ftp.berlios.de/incoming/ - -# Edit descriptions for each file. + -# Upload the release files via FTP to ftp://ftp.berlios.de/incoming/ + -# Edit descriptions for each file (one at a time) Note that Berlios + does not automatically checksum files, and it uses a very old + version of the SourceForge code with user interface issues. -# Click button to send E-mail Release Notice. + -# Depending on how paranoid you're feeling today, verify the images by + downloading them from the websites and making sure there are no + differences between the downloaded copies and your originals. + -# Publish User's and Developer's Guides to the project web sites: + -# Use SCP to update the SF.net web site with PDF and HTML for the + User's Guide, and HTML for the developer's guide ... you can + instantiate a shell.sourceforge.net instance and set up symlinks + from your home directory, to simplify this process. + -# (How to update the Berlios web site with the same data?) -# Post announcement e-mail to the openocd-development list. - -# Announce updates on freshmeat.net and other trackers. - -# Submit big updates to news feeds (e.g. Digg, Reddit, etc.). + -# optionally: + -# Post an update on the Berlios blog (if it lets you) + -# Announce updates on freshmeat.net and other trackers. + -# Submit updates to news feeds (e.g. Digg, Reddit, etc.). +-# Resume normal development on mainline, by opening the merge window for + the next major or minor release cycle. (You might want to do this + before all the release bits are fully published.) + - Update the version label in the @c configure.in file: + - Restore @c -dev version tag. + - For a new minor release cycle, increment the release's minor number + - For a new major release cycle, increment the release's major number + and zero its minor number + - Archive @c NEWS file as "<code>doc/news/NEWS-${PACKAGE_VERSION}</code>". + - Create a new @c NEWS file for the next release + - Commit those changes. + - Push all the updates to mainline. + - Last updates for the release, including the release tag (you + will need to "git push --tags"). + - Updates opening the merge window + - At this point, it's OK for commiters to start pushing changes + which have been held off until the next release. (Any bugfixes to + this release will be against a bug-fix release branch starting from + the commit you tagged as this release, not mainline.) + - Announce to the openocd-development list. Ideally, you will also + be able to say who is managing the next release cycle. To start a bug-fix release branch: -# Create a new branch, starting from a major or commit c8ea748dc22660dad934537384d35903dfcc492e Author: David Brownell <dbr...@us...> Date: Sun Feb 21 14:58:16 2010 -0800 ADIv5: relocate memacess_tck cycles When using an AP to access a memory (or a memory-mapped register), some extra TCK (assuming JTAG) cycles should be added to ensure the AP has enugh time to complete that access before trying to collect the response. The previous code was adding these cycles *before* trying to access (read or write) data to that address, not *after*. Fix by putting the delays in the right location. Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 819dd29..d30dd50 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -119,18 +119,6 @@ static int adi_jtag_dp_scan(struct swjdp_common *swjdp, jtag_set_end_state(TAP_IDLE); arm_jtag_set_instr(jtag_info, instr, NULL); - /* Add specified number of tck clocks before accessing memory bus */ - - /* REVISIT these TCK cycles should be *AFTER* updating APACC, since - * they provide more time for the (MEM) AP to complete the read ... - * See "Minimum Response Time" for JTAG-DP, in the ADIv5 spec. - */ - if ((instr == JTAG_DP_APACC) - && ((reg_addr == AP_REG_DRW) - || ((reg_addr & 0xF0) == AP_REG_BD0)) - && (swjdp->memaccess_tck != 0)) - jtag_add_runtest(swjdp->memaccess_tck, jtag_set_end_state(TAP_IDLE)); - /* Scan out a read or write operation using some DP or AP register. * For APACC access with any sticky error flag set, this is discarded. */ @@ -152,6 +140,18 @@ static int adi_jtag_dp_scan(struct swjdp_common *swjdp, jtag_add_dr_scan(2, fields, jtag_get_end_state()); + /* Add specified number of tck clocks after starting memory bus + * access, giving the hardware time to complete the access. + * They provide more time for the (MEM) AP to complete the read ... + * See "Minimum Response Time" for JTAG-DP, in the ADIv5 spec. + */ + if ((instr == JTAG_DP_APACC) + && ((reg_addr == AP_REG_DRW) + || ((reg_addr & 0xF0) == AP_REG_BD0)) + && (swjdp->memaccess_tck != 0)) + jtag_add_runtest(swjdp->memaccess_tck, + jtag_set_end_state(TAP_IDLE)); + return jtag_get_error(); } commit 3b68a708c2b039d9b091608eccb2206725742a47 Author: David Brownell <dbr...@us...> Date: Sun Feb 21 14:56:56 2010 -0800 ADIv5: remove ATOMIC/COMPOSITE interface mode This removes context-sensitivity from the programming interface and makes it possible to know what a block of code does without needing to know the previous history (specifically, the DAP's "trans_mode" setting). The mode was only set to ATOMIC briefly after DAP initialization, making this patch be primarily cleanup; almost everything depends on COMPOSITE. The transactions which shouldn't have been queued were already properly flushing the queue. Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 66b947e..819dd29 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -43,11 +43,16 @@ * is used to access memory mapped resources and is called a MEM-AP. Also a * JTAG-AP is also defined, bridging to JTAG resources; those are uncommon. * - * @todo Remove modality (queued/nonqueued, via DAP trans_mode) from all - * procedure interfaces. Modal programming interfaces are very error prone. - * Procedures should be either queued, or synchronous. Otherwise input - * and output constraints are context-sensitive, and it's hard to know - * what a block of code will do just by reading it. + * This programming interface allows DAP pipelined operations through a + * transaction queue. This primarily affects AP operations (such as using + * a MEM-AP to access memory or registers). If the current transaction has + * not finished by the time the next one must begin, and the ORUNDETECT bit + * is set in the DP_CTRL_STAT register, the SSTICKYORUN status is set and + * further AP operations will fail. There are two basic methods to avoid + * such overrun errors. One involves polling for status instead of using + * transaction piplining. The other involves adding delays to ensure the + * AP has enough time to complete one operation before starting the next + * one. (For JTAG these delays are controlled by memaccess_tck.) */ /* @@ -67,17 +72,6 @@ #include "arm_adi_v5.h" #include <helper/time_support.h> -/* - * Transaction Mode: - * swjdp->trans_mode = TRANS_MODE_COMPOSITE; - * Uses Overrun checking mode and does not do actual JTAG send/receive or transaction - * result checking until swjdp_end_transaction() - * This must be done before using or deallocating any return variables. - * swjdp->trans_mode == TRANS_MODE_ATOMIC - * All reads and writes to the AHB bus are checked for valid completion, and return values - * are immediatley available. -*/ - /* ARM ADI Specification requires at least 10 bits used for TAR autoincrement */ @@ -191,47 +185,32 @@ static int adi_jtag_dp_scan_u32(struct swjdp_common *swjdp, /** * Utility to write AP registers. */ -static int ap_write_check(struct swjdp_common *dap, +static inline int ap_write_check(struct swjdp_common *dap, uint8_t reg_addr, uint8_t *outvalue) { - adi_jtag_dp_scan(dap, JTAG_DP_APACC, reg_addr, DPAP_WRITE, + return adi_jtag_dp_scan(dap, JTAG_DP_APACC, reg_addr, DPAP_WRITE, outvalue, NULL, NULL); - - /* REVISIT except in dap_setup_accessport() almost all call paths - * set up COMPOSITE. Probably worth just inlining the scan... - */ - - /* In TRANS_MODE_ATOMIC all JTAG_DP_APACC transactions wait for - * ack = OK/FAULT and the check CTRL_STAT - */ - if (dap->trans_mode == TRANS_MODE_ATOMIC) - return jtagdp_transaction_endcheck(dap); - - return ERROR_OK; } static int scan_inout_check_u32(struct swjdp_common *swjdp, uint8_t instr, uint8_t reg_addr, uint8_t RnW, uint32_t outvalue, uint32_t *invalue) { + int retval; + /* Issue the read or write */ - adi_jtag_dp_scan_u32(swjdp, instr, reg_addr, RnW, outvalue, NULL, NULL); + retval = adi_jtag_dp_scan_u32(swjdp, instr, reg_addr, + RnW, outvalue, NULL, NULL); + if (retval != ERROR_OK) + return retval; /* For reads, collect posted value; RDBUFF has no other effect. * Assumes read gets acked with OK/FAULT, and CTRL_STAT says "OK". */ if ((RnW == DPAP_READ) && (invalue != NULL)) - adi_jtag_dp_scan_u32(swjdp, JTAG_DP_DPACC, + retval = adi_jtag_dp_scan_u32(swjdp, JTAG_DP_DPACC, DP_RDBUFF, DPAP_READ, 0, invalue, &swjdp->ack); - - /* In TRANS_MODE_ATOMIC all JTAG_DP_APACC transactions wait for - * ack = OK/FAULT and then check CTRL_STAT - */ - if ((instr == JTAG_DP_APACC) - && (swjdp->trans_mode == TRANS_MODE_ATOMIC)) - return jtagdp_transaction_endcheck(swjdp); - - return ERROR_OK; + return retval; } int jtagdp_transaction_endcheck(struct swjdp_common *swjdp) @@ -437,17 +416,13 @@ static int dap_ap_write_reg(struct swjdp_common *swjdp, } /** - * Write an AP register value. - * This is synchronous iff the mode is set to ATOMIC, in which - * case any queued transactions are flushed. + * Asynchronous (queued) AP register write. * * @param swjdp The DAP whose currently selected AP will be written. * @param reg_addr Eight bit AP register address. * @param value Word to be written at reg_addr * - * @return In synchronous mode: ERROR_OK for success, and the register holds - * the specified value; else a fault code. In asynchronous mode, a status - * code reflecting whether the transaction was properly queued. + * @return ERROR_OK if the transaction was properly queued, else a fault code. */ int dap_ap_write_reg_u32(struct swjdp_common *swjdp, uint32_t reg_addr, uint32_t value) @@ -460,17 +435,13 @@ int dap_ap_write_reg_u32(struct swjdp_common *swjdp, } /** - * Read an AP register value. - * This is synchronous iff the mode is set to ATOMIC, in which - * case any queued transactions are flushed. + * Asynchronous (queued) AP register eread. * * @param swjdp The DAP whose currently selected AP will be read. * @param reg_addr Eight bit AP register address. * @param value Points to where the 32-bit (little-endian) word will be stored. * - * @return In synchronous mode: ERROR_OK for success, and *value holds - * the specified value; else a fault code. In asynchronous mode, a status - * code reflecting whether the transaction was properly queued. + * @return ERROR_OK if the transaction was properly queued, else a fault code. */ int dap_ap_read_reg_u32(struct swjdp_common *swjdp, uint32_t reg_addr, uint32_t *value) @@ -486,9 +457,8 @@ int dap_ap_read_reg_u32(struct swjdp_common *swjdp, } /** - * Set up transfer parameters for the currently selected MEM-AP. - * This is synchronous iff the mode is set to ATOMIC, in which - * case any queued transactions are flushed. + * Queue transactions setting up transfer parameters for the + * currently selected MEM-AP. * * Subsequent transfers using registers like AP_REG_DRW or AP_REG_BD2 * initiate data reads or writes using memory or peripheral addresses. @@ -503,9 +473,7 @@ int dap_ap_read_reg_u32(struct swjdp_common *swjdp, * @param tar MEM-AP Transfer Address Register (TAR) to assign. If this * matches the cached address, the register is not changed. * - * @return In synchronous mode: ERROR_OK for success, and the AP is set - * up as requested else a fault code. In asynchronous mode, a status - * code reflecting whether the transaction was properly queued. + * @return ERROR_OK if the transaction was properly queued, else a fault code. */ int dap_setup_accessport(struct swjdp_common *swjdp, uint32_t csw, uint32_t tar) { @@ -550,8 +518,6 @@ int mem_ap_read_u32(struct swjdp_common *swjdp, uint32_t address, { int retval; - swjdp->trans_mode = TRANS_MODE_COMPOSITE; - /* Use banked addressing (REG_BDx) to avoid some link traffic * (updating TAR) when reading several consecutive addresses. */ @@ -603,8 +569,6 @@ int mem_ap_write_u32(struct swjdp_common *swjdp, uint32_t address, { int retval; - swjdp->trans_mode = TRANS_MODE_COMPOSITE; - /* Use banked addressing (REG_BDx) to avoid some link traffic * (updating TAR) when writing several consecutive addresses. */ @@ -652,8 +616,6 @@ int mem_ap_write_buf_u32(struct swjdp_common *swjdp, uint8_t *buffer, int count, uint32_t adr = address; uint8_t* pBuffer = buffer; - swjdp->trans_mode = TRANS_MODE_COMPOSITE; - count >>= 2; wcount = count; @@ -721,8 +683,6 @@ static int mem_ap_write_buf_packed_u16(struct swjdp_common *swjdp, int retval = ERROR_OK; int wcount, blocksize, writecount, i; - swjdp->trans_mode = TRANS_MODE_COMPOSITE; - wcount = count >> 1; while (wcount > 0) @@ -799,8 +759,6 @@ int mem_ap_write_buf_u16(struct swjdp_common *swjdp, uint8_t *buffer, int count, if (count >= 4) return mem_ap_write_buf_packed_u16(swjdp, buffer, count, address); - swjdp->trans_mode = TRANS_MODE_COMPOSITE; - while (count > 0) { dap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address); @@ -823,8 +781,6 @@ static int mem_ap_write_buf_packed_u8(struct swjdp_common *swjdp, int retval = ERROR_OK; int wcount, blocksize, writecount, i; - swjdp->trans_mode = TRANS_MODE_COMPOSITE; - wcount = count; while (wcount > 0) @@ -896,8 +852,6 @@ int mem_ap_write_buf_u8(struct swjdp_common *swjdp, uint8_t *buffer, int count, if (count >= 4) return mem_ap_write_buf_packed_u8(swjdp, buffer, count, address); - swjdp->trans_mode = TRANS_MODE_COMPOSITE; - while (count > 0) { dap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address); @@ -925,8 +879,6 @@ int mem_ap_read_buf_u32(struct swjdp_common *swjdp, uint8_t *buffer, int count, uint32_t adr = address; uint8_t* pBuffer = buffer; - swjdp->trans_mode = TRANS_MODE_COMPOSITE; - count >>= 2; wcount = count; @@ -1009,8 +961,6 @@ static int mem_ap_read_buf_packed_u16(struct swjdp_common *swjdp, int retval = ERROR_OK; int wcount, blocksize, readcount, i; - swjdp->trans_mode = TRANS_MODE_COMPOSITE; - wcount = count >> 1; while (wcount > 0) @@ -1063,8 +1013,6 @@ int mem_ap_read_buf_u16(struct swjdp_common *swjdp, uint8_t *buffer, int count, if (count >= 4) return mem_ap_read_buf_packed_u16(swjdp, buffer, count, address); - swjdp->trans_mode = TRANS_MODE_COMPOSITE; - while (count > 0) { dap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address); @@ -1105,8 +1053,6 @@ static int mem_ap_read_buf_packed_u8(struct swjdp_common *swjdp, int retval = ERROR_OK; int wcount, blocksize, readcount, i; - swjdp->trans_mode = TRANS_MODE_COMPOSITE; - wcount = count; while (wcount > 0) @@ -1156,8 +1102,6 @@ int mem_ap_read_buf_u8(struct swjdp_common *swjdp, uint8_t *buffer, int count, u if (count >= 4) return mem_ap_read_buf_packed_u8(swjdp, buffer, count, address); - swjdp->trans_mode = TRANS_MODE_COMPOSITE; - while (count > 0) { dap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address); @@ -1203,7 +1147,6 @@ int ahbap_debugport_init(struct swjdp_common *swjdp) dap_ap_select(swjdp, 0); /* DP initialization */ - swjdp->trans_mode = TRANS_MODE_ATOMIC; dap_dp_read_reg(swjdp, &dummy, DP_CTRL_STAT); dap_dp_write_reg(swjdp, SSTICKYERR, DP_CTRL_STAT); dap_dp_read_reg(swjdp, &dummy, DP_CTRL_STAT); diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 746f1cb..316701e 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -118,13 +118,6 @@ #define CSW_MASTER_DEBUG (1 << 29) /* ? */ #define CSW_DBGSWENABLE (1 << 31) -/* transaction mode */ -#define TRANS_MODE_NONE 0 -/* Transaction waits for previous to complete */ -#define TRANS_MODE_ATOMIC 1 -/* Freerunning transactions with delays and overrun checking */ -#define TRANS_MODE_COMPOSITE 2 - /** * This represents an ARM Debug Interface (v5) Debug Access Port (DAP). * A DAP has two types of component: one Debug Port (DP), which is a @@ -170,9 +163,8 @@ struct swjdp_common uint32_t ap_tar_value; /* information about current pending SWjDP-AHBAP transaction */ - uint8_t trans_mode; - uint8_t trans_rw; uint8_t ack; + /** * Configures how many extra tck clocks are added after starting a * MEM-AP access before we try to read its status (and/or result). @@ -192,7 +184,7 @@ static inline uint8_t dap_ap_get_select(struct swjdp_common *swjdp) /* AP selection applies to future AP transactions */ void dap_ap_select(struct swjdp_common *dap,uint8_t apsel); -/* AP transactions ... synchronous given TRANS_MODE_ATOMIC */ +/* Queued AP transactions */ int dap_setup_accessport(struct swjdp_common *swjdp, uint32_t csw, uint32_t tar); int dap_ap_write_reg_u32(struct swjdp_common *swjdp, diff --git a/src/target/cortex_m3.c b/src/target/cortex_m3.c index 3dd9468..3ebc34a 100644 --- a/src/target/cortex_m3.c +++ b/src/target/cortex_m3.c @@ -70,8 +70,6 @@ static int cortexm3_dap_read_coreregister_u32(struct swjdp_common *swjdp, mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr); - swjdp->trans_mode = TRANS_MODE_COMPOSITE; - /* mem_ap_write_u32(swjdp, DCB_DCRSR, regnum); */ dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0); dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRSR & 0xC), regnum); @@ -101,8 +99,6 @@ static int cortexm3_dap_write_coreregister_u32(struct swjdp_common *swjdp, mem_ap_read_u32(swjdp, DCB_DCRDR, &dcrdr); - swjdp->trans_mode = TRANS_MODE_COMPOSITE; - /* mem_ap_write_u32(swjdp, DCB_DCRDR, core_regs[i]); */ dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0); dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (DCB_DCRDR & 0xC), value); commit ecff73043c1ddcc97d4d1ea1c87f251a850b22d4 Author: David Brownell <dbr...@us...> Date: Sun Feb 21 14:54:54 2010 -0800 ARM: ADIv5, deadcode cleanup I have no idea what the scan_inout_check() was *expecting* to achieve by issuing a read of the DP_RDBUFF register. But in any case, that code was clearly never being called ("invalue" always NULL) ... so remove it, and the associated comment. Also rename it as ap_write_check(), facilitating a cleanup of its single call site by removing constant parameters. Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index d7afb58..66b947e 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -188,23 +188,24 @@ static int adi_jtag_dp_scan_u32(struct swjdp_common *swjdp, return retval; } -/* scan_inout_check adds one extra inscan for DPAP_READ commands to read variables */ -static int scan_inout_check(struct swjdp_common *swjdp, - uint8_t instr, uint8_t reg_addr, uint8_t RnW, - uint8_t *outvalue, uint8_t *invalue) +/** + * Utility to write AP registers. + */ +static int ap_write_check(struct swjdp_common *dap, + uint8_t reg_addr, uint8_t *outvalue) { - adi_jtag_dp_scan(swjdp, instr, reg_addr, RnW, outvalue, NULL, NULL); + adi_jtag_dp_scan(dap, JTAG_DP_APACC, reg_addr, DPAP_WRITE, + outvalue, NULL, NULL); - if ((RnW == DPAP_READ) && (invalue != NULL)) - adi_jtag_dp_scan(swjdp, JTAG_DP_DPACC, - DP_RDBUFF, DPAP_READ, 0, invalue, &swjdp->ack); + /* REVISIT except in dap_setup_accessport() almost all call paths + * set up COMPOSITE. Probably worth just inlining the scan... + */ /* In TRANS_MODE_ATOMIC all JTAG_DP_APACC transactions wait for * ack = OK/FAULT and the check CTRL_STAT */ - if ((instr == JTAG_DP_APACC) - && (swjdp->trans_mode == TRANS_MODE_ATOMIC)) - return jtagdp_transaction_endcheck(swjdp); + if (dap->trans_mode == TRANS_MODE_ATOMIC) + return jtagdp_transaction_endcheck(dap); return ERROR_OK; } @@ -432,8 +433,7 @@ static int dap_ap_write_reg(struct swjdp_common *swjdp, if (retval != ERROR_OK) return retval; - return scan_inout_check(swjdp, JTAG_DP_APACC, reg_addr, - DPAP_WRITE, out_value_buf, NULL); + return ap_write_check(swjdp, reg_addr, out_value_buf); } /** commit 39cfe6279616a69b858ddd3493d61ed7133ff081 Author: David Brownell <dbr...@us...> Date: Sun Feb 21 14:53:15 2010 -0800 ARM: ADIv5 code shrinkage, cleanup adi_jtag_dp_scan_u32() now wraps adi_jtag_dp_scan(), removing code duplication. Include doxygen for the former. Comment some particularly relevant points. Minor fault handling fixes for both routines: don't register a callback that can't run, or return ERROR_OK after an error. Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 1eff335..d7afb58 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -158,58 +158,34 @@ static int adi_jtag_dp_scan(struct swjdp_common *swjdp, jtag_add_dr_scan(2, fields, jtag_get_end_state()); - return ERROR_OK; + return jtag_get_error(); } -/* Scan out and in from host ordered uint32_t variables */ +/** + * Scan DPACC or APACC out and in from host ordered uint32_t buffers. + * This is exactly like adi_jtag_dp_scan(), except that endianness + * conversions are performed (so the types of invalue and outvalue + * must be different). + */ static int adi_jtag_dp_scan_u32(struct swjdp_common *swjdp, uint8_t instr, uint8_t reg_addr, uint8_t RnW, uint32_t outvalue, uint32_t *invalue, uint8_t *ack) { - struct arm_jtag *jtag_info = swjdp->jtag_info; - struct scan_field fields[2]; uint8_t out_value_buf[4]; - uint8_t out_addr_buf; - - jtag_set_end_state(TAP_IDLE); - arm_jtag_set_instr(jtag_info, instr, NULL); - - /* Add specified number of tck clocks before accessing memory bus */ - - /* REVISIT these TCK cycles should be *AFTER* updating APACC, since - * they provide more time for the (MEM) AP to complete the read ... - */ - if ((instr == JTAG_DP_APACC) - && ((reg_addr == AP_REG_DRW) - || ((reg_addr & 0xF0) == AP_REG_BD0)) - && (swjdp->memaccess_tck != 0)) - jtag_add_runtest(swjdp->memaccess_tck, jtag_set_end_state(TAP_IDLE)); - - fields[0].tap = jtag_info->tap; - fields[0].num_bits = 3; - buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1)); - fields[0].out_value = &out_addr_buf; - fields[0].in_value = ack; + int retval; - fields[1].tap = jtag_info->tap; - fields[1].num_bits = 32; buf_set_u32(out_value_buf, 0, 32, outvalue); - fields[1].out_value = out_value_buf; - fields[1].in_value = NULL; - - if (invalue) - { - fields[1].in_value = (uint8_t *)invalue; - jtag_add_dr_scan(2, fields, jtag_get_end_state()); - jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t) invalue); - } else - { + retval = adi_jtag_dp_scan(swjdp, instr, reg_addr, RnW, + out_value_buf, (uint8_t *)invalue, ack); + if (retval != ERROR_OK) + return retval; - jtag_add_dr_scan(2, fields, jtag_get_end_state()); - } + if (invalue) + jtag_add_callback(arm_le_to_h_u32, + (jtag_callback_data_t) invalue); - return ERROR_OK; + return retval; } /* scan_inout_check adds one extra inscan for DPAP_READ commands to read variables */ commit a97bb67543eacde38f093610982812f714e7a050 Author: David Brownell <dbr...@us...> Date: Sun Feb 21 14:51:19 2010 -0800 ADIv5 clean up AP fault handling Pass up fault codes from various routines, so their callers can clean up after failures, and remove the FIXME comments highlighting those previously goofy code paths. dap_ap_{read,write}_reg_u32() dap_ap_write_reg() mem_ap_{read,write}_u32() mem_ap_{read,write}_atomic_u32() dap_setup_accessport() Make dap_ap_write_reg_u32() just wrap dap_ap_write_reg(), instead of cloning its core code (and broken fault handling). Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 2e3dafb..1eff335 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -450,12 +450,14 @@ static int dap_ap_bankselect(struct swjdp_common *swjdp, uint32_t ap_reg) static int dap_ap_write_reg(struct swjdp_common *swjdp, uint32_t reg_addr, uint8_t *out_value_buf) { - dap_ap_bankselect(swjdp, reg_addr); - scan_inout_check(swjdp, JTAG_DP_APACC, reg_addr, - DPAP_WRITE, out_value_buf, NULL); + int retval; - /* FIXME return fault code from above calls */ - return ERROR_OK; + retval = dap_ap_bankselect(swjdp, reg_addr); + if (retval != ERROR_OK) + return retval; + + return scan_inout_check(swjdp, JTAG_DP_APACC, reg_addr, + DPAP_WRITE, out_value_buf, NULL); } /** @@ -477,12 +479,8 @@ int dap_ap_write_reg_u32(struct swjdp_common *swjdp, uint8_t out_value_buf[4]; buf_set_u32(out_value_buf, 0, 32, value); - dap_ap_bankselect(swjdp, reg_addr); - scan_inout_check(swjdp, JTAG_DP_APACC, reg_addr, - DPAP_WRITE, out_value_buf, NULL); - - /* FIXME return any fault code from above calls */ - return ERROR_OK; + return dap_ap_write_reg(swjdp, + reg_addr, out_value_buf); } /** @@ -501,12 +499,14 @@ int dap_ap_write_reg_u32(struct swjdp_common *swjdp, int dap_ap_read_reg_u32(struct swjdp_common *swjdp, uint32_t reg_addr, uint32_t *value) { - dap_ap_bankselect(swjdp, reg_addr); - scan_inout_check_u32(swjdp, JTAG_DP_APACC, reg_addr, - DPAP_READ, 0, value); + int retval; - /* FIXME return any fault code from above calls */ - return ERROR_OK; + retval = dap_ap_bankselect(swjdp, reg_addr); + if (retval != ERROR_OK) + return retval; + + return scan_inout_check_u32(swjdp, JTAG_DP_APACC, reg_addr, + DPAP_READ, 0, value); } /** @@ -533,19 +533,23 @@ int dap_ap_read_reg_u32(struct swjdp_common *swjdp, */ int dap_setup_accessport(struct swjdp_common *swjdp, uint32_t csw, uint32_t tar) { + int retval; + csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT; if (csw != swjdp->ap_csw_value) { /* LOG_DEBUG("DAP: Set CSW %x",csw); */ - /* FIXME if this call fails, fail this procedure! */ - dap_ap_write_reg_u32(swjdp, AP_REG_CSW, csw); + retval = dap_ap_write_reg_u32(swjdp, AP_REG_CSW, csw); + if (retval != ERROR_OK) + return retval; swjdp->ap_csw_value = csw; } if (tar != swjdp->ap_tar_value) { /* LOG_DEBUG("DAP: Set TAR %x",tar); */ - /* FIXME if this call fails, fail this procedure! */ - dap_ap_write_reg_u32(swjdp, AP_REG_TAR, tar); + retval = dap_ap_write_reg_u32(swjdp, AP_REG_TAR, tar); + if (retval != ERROR_OK) + return retval; swjdp->ap_tar_value = tar; } /* Disable TAR cache when autoincrementing */ @@ -568,17 +572,19 @@ int dap_setup_accessport(struct swjdp_common *swjdp, uint32_t csw, uint32_t tar) int mem_ap_read_u32(struct swjdp_common *swjdp, uint32_t address, uint32_t *value) { + int retval; + swjdp->trans_mode = TRANS_MODE_COMPOSITE; /* Use banked addressing (REG_BDx) to avoid some link traffic * (updating TAR) when reading several consecutive addresses. */ - dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, + retval = dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0); - dap_ap_read_reg_u32(swjdp, AP_REG_BD0 | (address & 0xC), value); + if (retval != ERROR_OK) + return retval; - /* FIXME return any fault code from above calls */ - return ERROR_OK; + return dap_ap_read_reg_u32(swjdp, AP_REG_BD0 | (address & 0xC), value); } /** @@ -596,8 +602,11 @@ int mem_ap_read_u32(struct swjdp_common *swjdp, uint32_t address, int mem_ap_read_atomic_u32(struct swjdp_common *swjdp, uint32_t address, uint32_t *value) { - mem_ap_read_u32(swjdp, address, value); - /* FIXME return any fault code from above call */ + int retval; + + retval = mem_ap_read_u32(swjdp, address, value); + if (retval != ERROR_OK) + return retval; return jtagdp_transaction_endcheck(swjdp); } @@ -616,17 +625,20 @@ int mem_ap_read_atomic_u32(struct swjdp_common *swjdp, uint32_t address, int mem_ap_write_u32(struct swjdp_common *swjdp, uint32_t address, uint32_t value) { + int retval; + swjdp->trans_mode = TRANS_MODE_COMPOSITE; /* Use banked addressing (REG_BDx) to avoid some link traffic * (updating TAR) when writing several consecutive addresses. */ - dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, + retval = dap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0); - dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (address & 0xC), value); + if (retval != ERROR_OK) + return retval; - /* FIXME return any fault code from above calls */ - return ERROR_OK; + return dap_ap_write_reg_u32(swjdp, AP_REG_BD0 | (address & 0xC), + value); } /** @@ -643,8 +655,10 @@ int mem_ap_write_u32(struct swjdp_common *swjdp, uint32_t address, int mem_ap_write_atomic_u32(struct swjdp_common *swjdp, uint32_t address, uint32_t value) { - mem_ap_write_u32(swjdp, address, value); - /* FIXME return any fault code from above call */ + int retval = mem_ap_write_u32(swjdp, address, value); + + if (retval != ERROR_OK) + return retval; return jtagdp_transaction_endcheck(swjdp); } commit 249263d29da11b0ec981c2e0d520cd7dcf08939b Author: David Brownell <dbr...@us...> Date: Sun Feb 21 14:48:04 2010 -0800 ADIv5 clean up AP selection and register caching Handling of AP (and AP register bank) selection, and cached AP registers, is pretty loose ... start tightening it: - It's "AP bank" select support ... there are no DP banks. Rename. + dap_dp_bankselect() becomes dap_ap_bankselect() + "dp_select_value" struct field becomes "ap_bank_value" - Remove duplicate AP cache init paths ... only use dap_ap_select(), and don't make Cortex (A8 or M3) cores roll their own code. - For dap_ap_bankselect(), pass up any fault code from writing the SELECT register. (Nothing yet checks those codes.) - Add various bits of Doxygen Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 94c8ed8..2e3dafb 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -349,7 +349,7 @@ int jtagdp_transaction_endcheck(struct swjdp_common *swjdp) "ap_bank 0x%" PRIx32 ", ap_csw 0x%" PRIx32 ", ap_tar 0x%" PRIx32, - swjdp->dp_select_value, + swjdp->ap_bank_value, swjdp->ap_csw_value, swjdp->ap_tar_value); @@ -419,38 +419,38 @@ static int dap_dp_read_reg(struct swjdp_common *swjdp, */ void dap_ap_select(struct swjdp_common *swjdp,uint8_t apsel) { - uint32_t select; - select = (apsel << 24) & 0xFF000000; + uint32_t select = (apsel << 24) & 0xFF000000; if (select != swjdp->apsel) { swjdp->apsel = select; - /* Switching AP invalidates cached values */ - swjdp->dp_select_value = -1; + /* Switching AP invalidates cached values. + * Values MUST BE UPDATED BEFORE AP ACCESS. + */ + swjdp->ap_bank_value = -1; swjdp->ap_csw_value = -1; swjdp->ap_tar_value = -1; } } -static int dap_dp_bankselect(struct swjdp_common *swjdp, uint32_t ap_reg) +/** Select the AP register bank matching bits 7:4 of ap_reg. */ +static int dap_ap_bankselect(struct swjdp_common *swjdp, uint32_t ap_reg) { - uint32_t select; - select = (ap_reg & 0x000000F0); + uint32_t select = (ap_reg & 0x000000F0); - if (select != swjdp->dp_select_value) + if (select != swjdp->ap_bank_value) { - dap_dp_write_reg(swjdp, select | swjdp->apsel, DP_SELECT); - swjdp->dp_select_value = select; - } - - /* FIXME return any fault code from write() call */ - return ERROR_OK; + swjdp->ap_bank_value = select; + select |= swjdp->apsel; + return dap_dp_write_reg(swjdp, select, DP_SELECT); + } else + return ERROR_OK; } static int dap_ap_write_reg(struct swjdp_common *swjdp, uint32_t reg_addr, uint8_t *out_value_buf) { - dap_dp_bankselect(swjdp, reg_addr); + dap_ap_bankselect(swjdp, reg_addr); scan_inout_check(swjdp, JTAG_DP_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL); @@ -477,7 +477,7 @@ int dap_ap_write_reg_u32(struct swjdp_common *swjdp, uint8_t out_value_buf[4]; buf_set_u32(out_value_buf, 0, 32, value); - dap_dp_bankselect(swjdp, reg_addr); + dap_ap_bankselect(swjdp, reg_addr); scan_inout_check(swjdp, JTAG_DP_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL); @@ -501,7 +501,7 @@ int dap_ap_write_reg_u32(struct swjdp_common *swjdp, int dap_ap_read_reg_u32(struct swjdp_common *swjdp, uint32_t reg_addr, uint32_t *value) { - dap_dp_bankselect(swjdp, reg_addr); + dap_ap_bankselect(swjdp, reg_addr); scan_inout_check_u32(swjdp, JTAG_DP_APACC, reg_addr, DPAP_READ, 0, value); @@ -1206,12 +1206,11 @@ int ahbap_debugport_init(struct swjdp_common *swjdp) /* Default MEM-AP setup. * * REVISIT AP #0 may be an inappropriate default for this. - * Should we probe, or receve a hint from the caller? + * Should we probe, or take a hint from the caller? * Presumably we can ignore the possibility of multiple APs. */ - swjdp->apsel = 0; - swjdp->ap_csw_value = -1; - swjdp->ap_tar_value = -1; + swjdp->apsel = !0; + dap_ap_select(swjdp, 0); /* DP initialization */ swjdp->trans_mode = TRANS_MODE_ATOMIC; diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 759f233..746f1cb 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -138,17 +138,45 @@ struct swjdp_common struct arm_jtag *jtag_info; /* Control config */ uint32_t dp_ctrl_stat; - /* Support for several AP's in one DAP */ + + /** + * Cache for DP_SELECT bits identifying the current AP. A DAP may + * connect to multiple APs, such as one MEM-AP for general access, + * another reserved for accessing debug modules, and a JTAG-DP. + * "-1" indicates no cached value. + */ uint32_t apsel; - /* Register select cache */ - uint32_t dp_select_value; + + /** + * Cache for DP_SELECT bits identifying the current four-word AP + * register bank. This caches AP register addresss bits 7:4; JTAG + * and SWD access primitves pass address bits 3:2; bits 1:0 are zero. + * "-1" indicates no cached value. + */ + uint32_t ap_bank_value; + + /** + * Cache for (MEM-AP) AP_REG_CSW register value. This is written to + * configure an access mode, such as autoincrementing AP_REG_TAR during + * word access. "-1" indicates no cached value. + */ uint32_t ap_csw_value; + + /** + * Cache for (MEM-AP) AP_REG_TAR register value This is written to + * configure the address being read or written + * "-1" indicates no cached value. + */ uint32_t ap_tar_value; + /* information about current pending SWjDP-AHBAP transaction */ uint8_t trans_mode; uint8_t trans_rw; uint8_t ack; - /* extra tck clocks for memory bus access */ + /** + * Configures how many extra tck clocks are added after starting a + * MEM-AP access before we try to read its status (and/or result). + */ uint32_t memaccess_tck; /* Size of TAR autoincrement block, ARM ADI Specification requires at least 10 bits */ uint32_t tar_autoincr_block; diff --git a/src/target/cortex_a8.c b/src/target/cortex_a8.c index 050238c..f4818f8 100644 --- a/src/target/cortex_a8.c +++ b/src/target/cortex_a8.c @@ -53,7 +53,9 @@ static int cortex_a8_dap_write_coreregister_u32(struct target *target, uint32_t value, int regnum); /* * FIXME do topology discovery using the ROM; don't - * assume this is an OMAP3. + * assume this is an OMAP3. Also, allow for multiple ARMv7-A + * cores, with different AP numbering ... don't use a #define + * for these numbers, use per-core armv7a state. */ #define swjdp_memoryap 0 #define swjdp_debugap 1 @@ -1570,9 +1572,7 @@ static int cortex_a8_init_arch_info(struct target *target, cortex_a8->jtag_info.tap = tap; cortex_a8->jtag_info.scann_size = 4; - swjdp->dp_select_value = -1; - swjdp->ap_csw_value = -1; - swjdp->ap_tar_value = -1; + /* Leave (only) generic DAP stuff for debugport_init() */ swjdp->jtag_info = &cortex_a8->jtag_info; swjdp->memaccess_tck = 80; diff --git a/src/target/cortex_m3.c b/src/target/cortex_m3.c index a3b3d42..3dd9468 100644 --- a/src/target/cortex_m3.c +++ b/src/target/cortex_m3.c @@ -1848,12 +1848,11 @@ static int cortex_m3_init_arch_info(struct target *target, cortex_m3->jtag_info.tap = tap; cortex_m3->jtag_info.scann_size = 4; - armv7m->swjdp_info.dp_select_value = -1; - armv7m->swjdp_info.ap_csw_value = -1; - armv7m->swjdp_info.ap_tar_value = -1; + /* Leave (only) generic DAP stuff for debugport_init(); */ armv7m->swjdp_info.jtag_info = &cortex_m3->jtag_info; armv7m->swjdp_info.memaccess_tck = 8; - armv7m->swjdp_info.tar_autoincr_block = (1 << 12); /* Cortex-M3 has 4096 bytes autoincrement range */ + /* Cortex-M3 has 4096 bytes autoincrement range */ + armv7m->swjdp_info.tar_autoincr_block = (1 << 12); /* register arch-specific functions */ armv7m->examine_debug_reason = cortex_m3_examine_debug_reason; commit 1aac72d24339380f6e98c50dec4c96ab30537749 Author: David Brownell <dbr...@us...> Date: Sun Feb 21 14:34:33 2010 -0800 ARM: keep a handle to the PC Keep a handle to the PC in "struct arm", and use it. This register is used a fair amount, so this is a net minor code shrink (other than some line length fixes), but mostly it's to make things more readable. For XScale, fix a dodgy sequence while stepping. It was initializing a variable to a non-NULL value, then updating it to handle the step-over-active-breakpoint case, and then later testing for non-NULL to see if it should reverse that step-over-active logic. It should have done like ARM7/ARM9 does: init to NULL. Signed-off-by: David Brownell <dbr...@us...> diff --git a/src/target/arm.h b/src/target/arm.h index c72b194..6b304e9 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -95,6 +95,9 @@ struct arm { int common_magic; struct reg_cache *core_cache; + /** Handle to the PC; valid in all core modes. */ + struct reg *pc; + /** Handle to the CPSR; valid in all core modes. */ struct reg *cpsr; diff --git a/src/target/arm11.c b/src/target/arm11.c index 678d8ac..51be701 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -451,7 +451,7 @@ static int arm11_halt(struct target *target) static uint32_t arm11_nextpc(struct arm11_common *arm11, int current, uint32_t address) { - void *value = arm11->arm.core_cache->reg_list[15].value; + void *value = arm11->arm.pc->value; if (!current) buf_set_u32(value, 0, 32, address); diff --git a/src/target/arm720t.c b/src/target/arm720t.c index efafa5e..2275935 100644 --- a/src/target/arm720t.c +++ b/src/target/arm720t.c @@ -361,9 +361,9 @@ static int arm720t_soft_reset_halt(struct target *target) armv4_5->cpsr->dirty = 1; /* start fetching from 0x0 */ - buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0); - armv4_5->core_cache->reg_list[15].dirty = 1; - armv4_5->core_cache->reg_list[15].valid = 1; + buf_set_u32(armv4_5->pc->value, 0, 32, 0x0); + armv4_5->pc->dirty = 1; + armv4_5->pc->valid = 1; arm720t_disable_mmu_caches(target, 1, 1, 1); arm720t->armv4_5_mmu.mmu_enabled = 0; diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index 509e91e..2176729 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -1235,9 +1235,9 @@ int arm7_9_soft_reset_halt(struct target *target) armv4_5->cpsr->dirty = 1; /* start fetching from 0x0 */ - buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0); - armv4_5->core_cache->reg_list[15].dirty = 1; - armv4_5->core_cache->reg_list[15].valid = 1; + buf_set_u32(armv4_5->pc->value, 0, 32, 0x0); + armv4_5->pc->dirty = 1; + armv4_5->pc->valid = 1; /* reset registers */ for (i = 0; i <= 14; i++) @@ -1721,9 +1721,10 @@ int arm7_9_restore_context(struct target *target) } /* restore PC */ - LOG_DEBUG("writing PC with value 0x%8.8" PRIx32 "", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)); - arm7_9->write_pc(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)); - armv4_5->core_cache->reg_list[15].dirty = 0; + LOG_DEBUG("writing PC with value 0x%8.8" PRIx32, + buf_get_u32(armv4_5->pc->value, 0, 32)); + arm7_9->write_pc(target, buf_get_u32(armv4_5->pc->value, 0, 32)); + armv4_5->pc->dirty = 0; if (arm7_9->post_restore_context) arm7_9->post_restore_context(target); @@ -1815,15 +1816,17 @@ int arm7_9_resume(struct target *target, int current, uint32_t address, int hand /* current = 1: continue on current pc, otherwise continue at <address> */ if (!current) - buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, address); + buf_set_u32(armv4_5->pc->value, 0, 32, address); uint32_t current_pc; - current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32); + current_pc = buf_get_u32(armv4_5->pc->value, 0, 32); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) { - if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)))) + breakpoint = breakpoint_find(target, + buf_get_u32(armv4_5->pc->value, 0, 32)); + if (breakpoint != NULL) { LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (id: %d)", breakpoint->address, breakpoint->unique_id ); if ((retval = arm7_9_unset_breakpoint(target, breakpoint)) != ERROR_OK) @@ -1881,7 +1884,8 @@ int arm7_9_resume(struct target *target, int current, uint32_t address, int hand } arm7_9_debug_entry(target); - LOG_DEBUG("new PC after step: 0x%8.8" PRIx32 "", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)); + LOG_DEBUG("new PC after step: 0x%8.8" PRIx32, + buf_get_u32(armv4_5->pc->value, 0, 32)); LOG_DEBUG("set breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); if ((retval = arm7_9_set_breakpoint(target, breakpoint)) != ERROR_OK) @@ -1957,7 +1961,7 @@ void arm7_9_enable_eice_step(struct target *target, uint32_t next_pc) struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *armv4_5 = &arm7_9->armv4_5_common; uint32_t current_pc; - current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32); + current_pc = buf_get_u32(armv4_5->pc->value, 0, 32); if (next_pc != current_pc) { @@ -2019,18 +2023,18 @@ int arm7_9_step(struct target *target, int current, uint32_t address, int handle /* current = 1: continue on current pc, otherwise continue at <address> */ if (!current) - buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, address); + buf_set_u32(armv4_5->pc->value, 0, 32, address); - uint32_t current_pc; - current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32); + uint32_t current_pc = buf_get_u32(armv4_5->pc->value, 0, 32); /* the front-end may request us not to handle breakpoints */ if (handle_breakpoints) - if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)))) - if ((retval = arm7_9_unset_breakpoint(target, breakpoint)) != ERROR_OK) - { - return retval; - } + breakpoint = breakpoint_find(target, current_pc); + if (breakpoint != NULL) { + retval = arm7_9_unset_breakpoint(target, breakpoint); + if (retval != ERROR_OK) + return retval; + } target->debug_reason = DBG_REASON_SINGLESTEP; diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c index 16f16b0..530a675 100644 --- a/src/target/arm7tdmi.c +++ b/src/target/arm7tdmi.c @@ -598,7 +598,8 @@ static void arm7tdmi_branch_resume_thumb(struct target *target) /* fetch NOP, LDM in EXECUTE stage (1st cycle) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); /* nothing fetched, LDM in EXECUTE stage (2nd cycle) */ - arm7tdmi_clock_out(jtag_info, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) | 1, NULL, 0); + arm7tdmi_clock_out(jtag_info, + buf_get_u32(armv4_5->pc->value, 0, 32) | 1, NULL, 0); /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */ arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); diff --git a/src/target/arm920t.c b/src/target/arm920t.c index 3e61545..152edcf 100644 --- a/src/target/arm920t.c +++ b/src/target/arm920t.c @@ -777,9 +777,9 @@ int arm920t_soft_reset_halt(struct target *target) armv4_5->cpsr->dirty = 1; /* start fetching from 0x0 */ - buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0); - armv4_5->core_cache->reg_list[15].dirty = 1; - armv4_5->core_cache->reg_list[15].valid = 1; + buf_set_u32(armv4_5->pc->value, 0, 32, 0x0); + armv4_5->pc->dirty = 1; + armv4_5->pc->valid = 1; arm920t_disable_mmu_caches(target, 1, 1, 1); arm920t->armv4_5_mmu.mmu_enabled = 0; diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c index 32ecf72..d811196 100644 --- a/src/target/arm926ejs.c +++ b/src/target/arm926ejs.c @@ -569,9 +569,9 @@ int arm926ejs_soft_reset_halt(struct target *target) armv4_5->cpsr->dirty = 1; /* start fetching from 0x0 */ - buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0); - armv4_5->core_cache->reg_list[15].dirty = 1; - armv4_5->core_cache->reg_list[15].valid = 1; + buf_set_u32(armv4_5->pc->value, 0, 32, 0x0); + armv4_5->pc->dirty = 1; + armv4_5->pc->valid = 1; arm926ejs_disable_mmu_caches(target, 1, 1, 1); arm926ejs->armv4_5_mmu.mmu_enabled = 0; diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c index 761e7cf..77b01b1 100644 --- a/src/target/arm9tdmi.c +++ b/src/target/arm9tdmi.c @@ -677,7 +677,8 @@ static void arm9tdmi_branch_resume_thumb(struct target *target) /* fetch NOP, LDM in EXECUTE stage (1st cycle) */ arm9tdmi_clock_out(jtag_info, ARMV4_5... [truncated message content] |