Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
  • 20 commits
  • 19 files changed
  • 0 comments
  • 2 contributors
Mar 26, 2012
Anton Staaf String: Pick up bug fixes in the string library
There was a bug in the replace method.  This also switches to returning
a const reference to the empty string singleton.
1c339ac
Mar 27, 2012
Cliff L. Biffle DebugAccessPort is now stateful.
Target used to provide a stateful facade over DebugAccessPort, but
I'm trying to limit Target to the functionality that depends on a
specific CPU core.  Since the DebugAccessPort SELECT behavior is
specified by ADIv5, it can safely be hidden inside DebugAccessPort
itself.
d0ff5ca
Anton Staaf FTDI: Move towards supporting more FTDI based programmers
This is the first step towards a more robust programmer enumeration
strategy.  We now use libusb to locate the ftdi chip we will use.
This still just looks up the part by VID:PID which is problematic,
but libusb provides the functionality required to traverse the bus
looking for a specific device based on other parameters.

This commit also adds vid, pid, and interface command line parameters
for controlling which device is selected and which interface port of
the selected device to use.
4957969
Mar 28, 2012
Anton Staaf CommandLine: Get support for parsing hexadecimal integers
VID:PID pairs are usually specified in hexadecimal.  The latest
version of the command line parsing library supports this.
4b73fc4
Anton Staaf IDCode: Don't read the idcode in the SWD driver initialization
This can be done later, there is nothing SWD driver specific about
it.
ad6d2a0
Anton Staaf Formatting: Return MPSSE SWD driver back to it's original style 0d640bb
Anton Staaf Debug: Make debug logging more useful
This adds a few log messages and sets the levels so that they are
more readable.
85589d5
Anton Staaf Timeout: Fix the timeout loop counter to match the debug message meaning 141dd84
Anton Staaf Hack: attempt to get bus blaster working 6eb598b
Anton Staaf Response: Factor out mapping responses to Errors 3c941f9
Anton Staaf Error: Don't include the full Error namespace
This ensures that all uses of the Error enum are prefixed with the
Err namespace qualifier.
a0180cd
Anton Staaf Programmer: Add support for BusBlaster
This change includes new support for selecting a programmer.  The
default programmer is the um232h evaluation board from FTDI since
that was the first board that worked.  Once a programmer has been
selected the vid, pid, and interface can all be overridden from the
command line.

The BusBlaster must have been programmed with the KT-link RTL.
Consiquently, this version should now support the KT-link as well,
but that has not been tested.
a50e5f2
Anton Staaf README: Update docs to discuss Bus Blaster support 28f14f2
Mar 29, 2012
Cliff L. Biffle swd_mpsse: switched binary literals to hex. :-\
I love binary literals, and they're entirely appropriate here.
However, if we want Mac OS X compatibility, we need to compile with
llvm-gcc, which is based on 4.2.1 and doesn't do binary literals.

This *might* be fixed by a full-on move to Clang.  Haven't tested.
442700d
Anton Staaf USB: Remove explicit control of kernel driver attachment
This was not strictly required and is not supported on MacOS.
fc0b465
Anton Staaf Format: Remove tabs that crept in and force spaces to be used in Emacs 28ea3aa
Mar 30, 2012
Anton Staaf ErrorStack: Use newer cleaner version of the error stack library 4464097
Cliff L. Biffle swddude/MPSSE: moved IDCODE read back into driver.
ADIv5 specifies this as part of the SWD initialization, so the
driver is really the right place for it.

Added a big comment to make this more clear in the future.
ee3af00
Cliff L. Biffle swdprobe: gutted! Compiles again.
Of course this doesn't actually work.  It was written for the old
AccessPort abstraction, which no longer exists.  I'm rewriting it
on top of DebugAccessPort and Target.
225a05e
Cliff L. Biffle swdprobe: code to find and traverse ROM tables. 41a8fc8
1  .dir-locals.el
... ... @@ -0,0 +1 @@
  1 +((nil . ((indent-tabs-mode . nil))))
13 README.md
Source Rendered
@@ -41,8 +41,11 @@ boards just begging to be used.
41 41 How Do I Use It?
42 42 ----------------
43 43
44   -You'll need an FTDI FT232H breakout board -- and, of course, a supported
45   -microcontroller with a SWD interface.
  44 +You'll need a supported programmer and, of course, a supported microcontroller
  45 +with a SWD interface. Currently `swddude` supports using the Bus Blaster (v2.5
  46 +programmed with the KT-link compatible CPLD configuration) or any FTDI
  47 +development board with an FT232H or FT2232H chip that has been wired to the SWD
  48 +lines of your microcontroller.
46 49
47 50 Wire up your micro using the configuration described in `swd_mpsse.h`.
48 51
@@ -54,7 +57,7 @@ which we use to convert it into a SWD interface. For best results, build
54 57 After checking out `swddude`, build it like so:
55 58
56 59 $ cd swddude/source
57   - $ make release/swddude
  60 + $ make swddude release
58 61
59 62 This will deposit a `swddude` binary in `swddude/source/release`.
60 63
@@ -64,6 +67,10 @@ binary format -- not ELF, and not Intel hex. Assuming it's in a file called
64 67
65 68 $ swddude -flash firmware.bin -fix_lpc_checksum
66 69
  70 +This will default to the um232h programmer (FTDI's FT232H development board)
  71 +configuration. If you are using a Bus Blaster, you should add
  72 +`-programmer bus_blaster` to the command line above.
  73 +
67 74 That last option, `-fix_lpc_checksum`, adds the vector table checksum expected
68 75 by the NXP LPC series. Without it, your firmware won't run! If some other tool
69 76 has already written the correct checksum into your firmware, you can omit that
2  libs/command_line
... ... @@ -1 +1 @@
1   -Subproject commit 74f97f191bb384d3ef9eb003e5ac14300188e3fa
  1 +Subproject commit 4cd640691a41876d6b0afa717efcc8c1222a4396
2  libs/data
... ... @@ -1 +1 @@
1   -Subproject commit 4a8c375513b791370455037be334d515885e3e90
  1 +Subproject commit 89f79a1a3e7ad82df239843132a1547359f1fb4a
2  libs/error
... ... @@ -1 +1 @@
1   -Subproject commit 770d262bd248ddc827dede449c6d95e3acfbf19c
  1 +Subproject commit e261a8b57f9fb0c21c41394d91b2eae003da3057
2  libs/files
... ... @@ -1 +1 @@
1   -Subproject commit 5b25c27ed4230b101d91b64745565776e09a0c89
  1 +Subproject commit 45174f16388daf0f94f30c45320a197550eb03b4
2  libs/log
... ... @@ -1 +1 @@
1   -Subproject commit 2aa5a77da5e0be72365f7a45e6e45b702a8e0369
  1 +Subproject commit 0f7096d57d788d33269c8705bc1efe90f65d4c5d
2  libs/string
... ... @@ -1 +1 @@
1   -Subproject commit 853748f2749a209632acaf94a3f4b837bfe5115b
  1 +Subproject commit 458306319854dab82cd53ac2baf5966ebec45cb6
2  libs/sys
... ... @@ -1 +1 @@
1   -Subproject commit 563396faf4a4150af95dfe1e470986620b7c999f
  1 +Subproject commit 794534f17a2885ebd80fc0b8468d88c079a335cd
7 source/rptr.h
@@ -89,6 +89,13 @@ template <typename type, typename self> class rptr_base
89 89 }
90 90
91 91 inline self operator++() const { return *this + 1; }
  92 +
  93 + inline self operator-(int d) const
  94 + {
  95 + return self(_bits - d * sizeof(type));
  96 + }
  97 +
  98 + inline self operator--() const { return *this - 1; }
92 99 };
93 100
94 101
15 source/swd.h
@@ -41,24 +41,23 @@ class SWDDriver {
41 41
42 42 /*
43 43 * Initialize the SWD link to the target, per the "Connection and line reset
44   - * sequence" defined by the ARM ADI v5.
  44 + * sequence" defined by the ARM ADI v5. This has two parts:
  45 + * 1. 50 clocks with the SWDIO line held high by the master.
  46 + * 2. A read of the IDCODE register in the DP.
  47 + *
  48 + * Because this function reads IDCODE behind the scenes, it can optionally
  49 + * return it to the application through the pointer argument.
45 50 *
46 51 * If this function returns successfully, it indicates that the interface is
47 52 * functioning, and that an attached microprocessor has responded to us. The
48 53 * state of the target is unknown -- in particular, the contents of the Debug
49 54 * Access Port's SELECT and CTRL/STAT registers are undefined.
50 55 *
51   - * Callers may optionally provide a pointer to a 32-bit variable to receive
52   - * the target Debug Access Port's IDCODE value. This does not identify the
53   - * target itself -- only the implementation of the DAP. If the idcode pointer
54   - * is zero, the IDCODE value won't be saved anywhere, and can be retrieved
55   - * later using a DAP read.
56   - *
57 56 * Return values:
58 57 * Err::success - initialization complete, target responded, IDCODE valid.
59 58 * Err::failure - initialization failed or target failed to respond.
60 59 */
61   - virtual Err::Error initialize(uint32_t *idcode = 0) = 0;
  60 + virtual Err::Error initialize(uint32_t * idcode_out = 0) = 0;
62 61
63 62 /*
64 63 * Asserts the target's reset line continuously until a call to leave_reset.
125 source/swd_dp.cpp
@@ -2,69 +2,116 @@
2 2
3 3 #include "swd.h"
4 4
5   -using namespace Err;
  5 +using Err::Error;
6 6
7   -DebugAccessPort::DebugAccessPort(SWDDriver &swd) : _swd(swd) {}
  7 +/*******************************************************************************
  8 + * DebugAccessPort private implementation
  9 + */
8 10
9   -Error DebugAccessPort::read_idcode(uint32_t *data) {
10   - return _swd.read(kRegIDCODE, true, data);
11   -}
  11 +Error DebugAccessPort::select_ap_bank(uint8_t ap, uint8_t address)
  12 +{
  13 + ARM::word_t sel = (ap << 24) | (address & 0xF0) | (_SELECT & 1);
  14 +
  15 + if (sel != _SELECT) {
  16 + Check(write_select(sel));
  17 + }
12 18
13   -Error DebugAccessPort::write_abort(uint32_t data) {
14   - return _swd.write(kRegABORT, true, data);
  19 + return Err::success;
15 20 }
16 21
17   -Error DebugAccessPort::read_ctrlstat_wcr(uint32_t *data) {
18   - return _swd.read(kRegCTRLSTAT, true, data);
  22 +
  23 +/*******************************************************************************
  24 + * DebugAccessPort public implementation
  25 + */
  26 +
  27 +DebugAccessPort::DebugAccessPort(SWDDriver & swd) :
  28 + _swd(swd),
  29 + _SELECT(-1) {}
  30 +
  31 +Error DebugAccessPort::reset_state()
  32 +{
  33 + Check(write_select(0)); // Reset SELECT and cache.
  34 + Check(write_abort((1 << 1) // Clear STKCMP
  35 + | (1 << 2) // Clear STKERR
  36 + | (1 << 3) // Clear WDERR
  37 + | (1 << 4) // Clear ORUNERR
  38 + ));
  39 + Check(write_ctrlstat((1 << 30) // CSYSPWRUPREQ
  40 + | (1 << 28))); // CDBGPWRUPREQ
  41 + return Err::success;
19 42 }
20 43
21   -Error DebugAccessPort::write_ctrlstat_wcr(uint32_t data) {
22   - return _swd.write(kRegCTRLSTAT, true, data);
  44 +Error DebugAccessPort::read_idcode(ARM::word_t * data)
  45 +{
  46 + return _swd.read(kRegIDCODE, true, data);
23 47 }
24 48
25   -Error DebugAccessPort::write_select(uint32_t data) {
26   - return _swd.write(kRegSELECT, true, data);
  49 +Error DebugAccessPort::write_abort(ARM::word_t data)
  50 +{
  51 + return _swd.write(kRegABORT, true, data);
27 52 }
28 53
29   -Error DebugAccessPort::read_resend(uint32_t *data) {
30   - return _swd.read(kRegRESEND, true, data);
  54 +Error DebugAccessPort::read_ctrlstat(ARM::word_t * data)
  55 +{
  56 + if (_SELECT & 1) Check(write_select(_SELECT & ~1));
  57 +
  58 + return _swd.read(kRegCTRLSTAT, true, data);
31 59 }
32 60
33   -Error DebugAccessPort::read_rdbuff(uint32_t *data) {
34   - return _swd.read(kRegRDBUFF, true, data);
  61 +Error DebugAccessPort::write_ctrlstat(ARM::word_t data)
  62 +{
  63 + if (_SELECT & 1) Check(write_select(_SELECT & ~1));
  64 +
  65 + return _swd.write(kRegCTRLSTAT, true, data);
35 66 }
36 67
37   -Error DebugAccessPort::select_ap_bank(uint8_t ap, uint8_t bank_address) {
38   - return write_select((ap << 24) | (bank_address >> 4));
  68 +Error DebugAccessPort::write_select(ARM::word_t data)
  69 +{
  70 + Check(_swd.write(kRegSELECT, true, data));
  71 +
  72 + _SELECT = data;
  73 + return Err::success;
39 74 }
40 75
41   -Error DebugAccessPort::start_read_ap_in_bank(uint8_t bank_address) {
42   - if (bank_address & 3) return argument_error;
  76 +Error DebugAccessPort::read_resend(ARM::word_t * data)
  77 +{
  78 + return _swd.read(kRegRESEND, true, data);
  79 +}
43 80
44   - return _swd.read((bank_address >> 2) & 3, false, 0);
  81 +Error DebugAccessPort::read_rdbuff(ARM::word_t * data)
  82 +{
  83 + return _swd.read(kRegRDBUFF, true, data);
45 84 }
46 85
47   -Error DebugAccessPort::step_read_ap_in_bank(uint8_t bank_address,
48   - uint32_t *last) {
49   - if (bank_address & 3) return argument_error;
  86 +Error DebugAccessPort::start_read_ap(uint8_t ap_index, uint8_t address)
  87 +{
  88 + if (address & 3) return Err::argument_error;
50 89
51   - return _swd.read((bank_address >> 2) & 3, false, last);
  90 + Check(select_ap_bank(ap_index, address));
  91 +
  92 + return _swd.read((address >> 2) & 3, false, 0);
52 93 }
53 94
54   -Error DebugAccessPort::write_ap_in_bank(uint8_t bank_address, uint32_t data) {
55   - if (bank_address & 3) return argument_error;
  95 +Error DebugAccessPort::step_read_ap(uint8_t ap_index,
  96 + uint8_t address,
  97 + ARM::word_t * last)
  98 +{
  99 + if (address & 3) return Err::argument_error;
  100 +
  101 + Check(select_ap_bank(ap_index, address));
56 102
57   - return _swd.write((bank_address >> 2) & 3, false, data);
  103 + return _swd.read((address >> 2) & 3, false, last);
58 104 }
59 105
60   -Error DebugAccessPort::reset_state() {
61   - Check(write_select(0)); // Reset SELECT.
62   - Check(write_abort((1 << 1) // Clear STKCMP
63   - | (1 << 2) // Clear STKERR
64   - | (1 << 3) // Clear WDERR
65   - | (1 << 4) // Clear ORUNERR
66   - ));
67   - Check(write_ctrlstat_wcr((1 << 30) // CSYSPWRUPREQ
68   - | (1 << 28))); // CDBGPWRUPREQ
69   - return success;
  106 +Error DebugAccessPort::write_ap(uint8_t ap_index,
  107 + uint8_t address,
  108 + ARM::word_t data)
  109 +{
  110 + if (address & 3) return Err::argument_error;
  111 +
  112 + Check(select_ap_bank(ap_index, address));
  113 +
  114 + return _swd.write((address >> 2) & 3, false, data);
70 115 }
  116 +
  117 +
458 source/swd_dp.h
@@ -3,6 +3,8 @@
3 3
4 4 #include "libs/error/error_stack.h"
5 5
  6 +#include "arm.h"
  7 +
6 8 #include <stdint.h>
7 9
8 10 class SWDDriver;
@@ -16,239 +18,235 @@ class SWDDriver;
16 18 * Since the DebugAccessPort provides a strict subset of SWDDriver's
17 19 * functionality (e.g. it can't reset the communications interface or the
18 20 * system), this is important.
  21 + *
  22 + * However, only a single DebugAccessPort should be used per SWDDriver instance,
  23 + * because DebugAccessPort caches state and assumes that it's the only one
  24 + * mutating it.
19 25 */
20   -class DebugAccessPort {
21   - SWDDriver &_swd;
  26 +class DebugAccessPort
  27 +{
  28 + SWDDriver & _swd;
  29 +
  30 + // Caches the current contents of the SELECT DP register.
  31 + ARM::word_t _SELECT;
  32 +
  33 + // Selects the given AP, and the bank to expose the given address.
  34 + Err::Error select_ap_bank(uint8_t ap, uint8_t address);
22 35
23 36 public:
24   - DebugAccessPort(SWDDriver &swd);
25   -
26   - /*
27   - * Debug Access Port registers defined by ADIv5. These are used within the
28   - * DebugAccessPort implementation, and can also be used by other code with
29   - * a SWDDriver directly.
30   - */
31   - enum Register {
32   - kRegABORT = 0x00, // Write-only
33   - kRegIDCODE = 0x00, // Read-only
34   -
35   - kRegCTRLSTAT = 0x01, // Only available when SELECT.CTRLSEL=0
36   - kRegWCR = 0x01, // Only available when SELECT.CTRLSEL=1
37   -
38   - kRegSELECT = 0x02, // Write-only
39   - kRegRESEND = 0x02, // Read-only
40   -
41   - kRegRDBUFF = 0x03, // Read-only
42   - };
43   -
44   -
45   - /*****************************************************************************
46   - * Utilities
47   - */
48   -
49   - /*
50   - * Resets the Debug Access Port to a known state, erasing leftover effects of
51   - * previous sessions:
52   - * - Resets SELECT to reveal the CTRL/STAT register and select the first bank
53   - * of the first AP.
54   - * - Clears the sticky error bits in CTRL/STAT to recover from faults.
55   - * - Switches on power to the debug systems (required before interacting with
56   - * Access Ports).
57   - */
58   - Err::Error reset_state();
59   -
60   -
61   - /*****************************************************************************
62   - * Direct DP register access.
63   - */
64   -
65   - /*
66   - * Reads the contents of the IDCODE register. This register is
67   - * architecturally specified to never return WAIT, so only two return codes
68   - * are possible: Err::success on a successful read, and Err::failure if
69   - * something is wrong.
70   - */
71   - Err::Error read_idcode(uint32_t *);
72   -
73   - /*
74   - * Alters the contents of the ABORT register, used to clear sticky error
75   - * conditions that cause other reads/writes to FAULT.
76   - *
77   - * The ABORT register is architecturally specified to never return WAIT,
78   - * so only two return codes are possible: Err::success on a successful write,
79   - * and Err::failure if something is wrong.
80   - */
81   - Err::Error write_abort(uint32_t);
82   -
83   - /*
84   - * Reads the contents of either the CTRL/STAT or WCR register, depending on
85   - * the value of SELECT.CTRLSEL.
86   - *
87   - * The CTRL/STAT register is architecturally specified to never return WAIT,
88   - * so when SELECT.CTRLSEL=0, only two return codes are possible: Err::success
89   - * on a successful read, and Err::failure if something is wrong.
90   - *
91   - * The WCR register may additionally return Err::try_again.
92   - */
93   - Err::Error read_ctrlstat_wcr(uint32_t *);
94   -
95   - /*
96   - * Alters the contents of either the CTRL/STAT or WCR register, depending on
97   - * the value of SELECT.CTRLSEL.
98   - *
99   - * The CTRL/STAT register is architecturally specified to never return WAIT,
100   - * so when SELECT.CTRLSEL=0, only two return codes are possible: Err::success
101   - * on a successful write, and Err::failure if something is wrong.
102   - *
103   - * The WCR register may additionally return Err::try_again.
104   - */
105   - Err::Error write_ctrlstat_wcr(uint32_t);
106   -
107   - /*
108   - * Alters the contents of the SELECT register, which determines both which
109   - * Access Port bank is visible, and whether the CTRL/STAT or WCR register is
110   - * visible.
111   - *
112   - * May return Err::try_again if an Access Port transaction is in progress.
113   - */
114   - Err::Error write_select(uint32_t);
115   -
116   - /*
117   - * Reads the contents of the RESEND register. May return Err::try_again.
118   - */
119   - Err::Error read_resend(uint32_t *);
120   -
121   - /*
122   - * Reads the contents of the RDBUFF register. RDBUFF contains the results of
123   - * the last successful Access Port read operation. It is a read-once
124   - * register: reading it destroys its contents. May return Err::try_again if
125   - * the Access Port operation is still in progress.
126   - */
127   - Err::Error read_rdbuff(uint32_t *);
128   -
129   -
130   - /*****************************************************************************
131   - * AP register access.
132   - */
133   -
134   - /*
135   - * Selects a particular Access Port and bank. As a side effect, this clears
136   - * the SELECT.CTRLSEL bit, making the Wire Control Register inaccessible and
137   - * revealing the CTRL/STAT register in its place.
138   - *
139   - * The bank is selected by Access Port register address. Access Port register
140   - * addresses are given in the ADIv5 and ARM as 8-bit hexadecimal numbers, e.g.
141   - * 0xF8. The top four bits of this address are the bank number that will be
142   - * written to SELECT. Thus, only the four most-significant bits matter for
143   - * this function.
144   - *
145   - * Return values:
146   - * Err::success - Access Port and bank changed.
147   - * Err::try_again - Access Port transaction in progress, try again.
148   - * Err::failure - communications with interface failed.
149   - */
150   - Err::Error select_ap_bank(uint8_t ap, uint8_t bank_address);
151   -
152   - /*
153   - * Starts a read of one of the four AP registers visible in the current bank.
154   - * (The AP and bank are determined by the most recent write to the SELECT
155   - * register, i.e. through select_ap_bank above.) This function can be used
156   - * together with step_read_ap_in_bank (below) and read_rdbuff (above) to
157   - * chain together several reads from the same AP/bank for higher throughput.
158   - *
159   - * Reads of the AP are asynchronous. Once the read has completed, its result
160   - * will be returned by the next call to step_read_ap_in_bank (below) or
161   - * read_rdbuff (above), whichever comes first.
162   - *
163   - * Until the read is complete, other AP accesses may stall (i.e. return a SWD
164   - * WAIT response, which becomes Err::try_again). Most AP registers can be
165   - * read quickly without stalling; the main exception are the registers in the
166   - * MEM-AP for accessing memory. The MEM-AP provides a TrInProg status bit for
167   - * avoiding this.
168   - *
169   - * The register is selected by Access Port register address. Access Port
170   - * register addresses are given in the ADIv5 and ARM as 8-bit hexadecimal
171   - * numbers, e.g. 0xF8. The top four bits are the bank; the bottom four are
172   - * the byte address of a 32-bit register. (Because it's a 32-bit register,
173   - * the two least significant bits must always be zero.)
174   - *
175   - * Note that the top four bits of the address are ignored by this function!
176   - * The DebugAccessPort assumes that you know what you're doing.
177   - *
178   - * Return values:
179   - * Err::argument_error - least-significant two bits of address not zero.
180   - * Err::success - read operation started.
181   - * Err::try_again - Access Port transaction in progress, try again.
182   - * Err::failure - bad register index or communications with interface failed.
183   - */
184   - Err::Error start_read_ap_in_bank(uint8_t bank_address);
185   -
186   - /*
187   - * Starts a new read of one of the four AP registers visible in the current
188   - * bank, and returns the result of the previous read. (The AP and bank are
189   - * determined by the most recent write to the SELECT register, i.e. through
190   - * select_ap_bank above.) This function can be used
191   - * together with step_read_ap_in_bank (below) and read_rdbuff (above) to
192   - * chain together several reads from the same AP/bank for higher throughput.
193   - *
194   - * Reads of the AP are asynchronous. Once the read
195   - * has completed, its result will be returned by the next call to this
196   - * function or read_rdbuff (above), whichever comes first.
197   - *
198   - * Until the read is complete, other AP accesses may stall (i.e. return a SWD
199   - * WAIT response, which becomes Err::try_again). Most AP registers can be
200   - * read quickly without stalling; the main exception are the registers in the
201   - * MEM-AP for accessing memory. The MEM-AP provides a TrInProg status bit for
202   - * avoiding this.
203   - *
204   - * The register is selected by Access Port register address. Access Port
205   - * register addresses are given in the ADIv5 and ARM as 8-bit hexadecimal
206   - * numbers, e.g. 0xF8. The top four bits are the bank; the bottom four are
207   - * the byte address of a 32-bit register. (Because it's a 32-bit register,
208   - * the two least significant bits must always be zero.)
209   - *
210   - * Note that the top four bits of the address are ignored by this function!
211   - * The DebugAccessPort assumes that you know what you're doing.
212   - *
213   - * Return values:
214   - * Err::argument_error - least-significant two bits of address not zero or
215   - * data pointer is the null pointer.
216   - * Err::success - new read operation started, last results returned.
217   - * Err::try_again - Access Port transaction in progress, try again.
218   - * Err::failure - bad register index or communications with interface failed.
219   - */
220   - Err::Error step_read_ap_in_bank(uint8_t bank_address, uint32_t *data);
221   -
222   - /*
223   - * Writes a new value into one of the four AP registers visible in the current
224   - * bank. (The AP and bank are determined by the most recent write to the
225   - * SELECT register, i.e. through select_ap_bank above.)
226   - *
227   - * Writes to the AP are asynchronous (albeit less so than reads). When this
228   - * function returns, the write operation has been accepted by the Debug Access
229   - * Port on your behalf, but the write itself may not have completed. Until
230   - * it completes, other AP operations may stall (i.e. return a SWD WAIT
231   - * response, which becomes Err::try_again). Most AP registers can be
232   - * written quickly without stalling; the main exception are the registers in
233   - * the MEM-AP for accessing memory. The MEM-AP provides a TrInProg status bit
234   - * for avoiding this.
235   - *
236   - * The register is selected by Access Port register address. Access Port
237   - * register addresses are given in the ADIv5 and ARM as 8-bit hexadecimal
238   - * numbers, e.g. 0xF8. The top four bits are the bank; the bottom four are
239   - * the byte address of a 32-bit register. (Because it's a 32-bit register,
240   - * the two least significant bits must always be zero.)
241   - *
242   - * Note that the top four bits of the address are ignored by this function!
243   - * The DebugAccessPort assumes that you know what you're doing.
244   - *
245   - * Return values:
246   - * Err::argument_error - least-significant two bits of address not zero.
247   - * Err::success - new write operation started.
248   - * Err::try_again - Access Port transaction in progress, try again.
249   - * Err::failure - bad register index or communications with interface failed.
250   - */
251   - Err::Error write_ap_in_bank(uint8_t bank_address, uint32_t data);
  37 + DebugAccessPort(SWDDriver & swd);
  38 +
  39 + /*
  40 + * Debug Access Port registers defined by ADIv5. These are used within the
  41 + * DebugAccessPort implementation, and can also be used by other code with
  42 + * a SWDDriver directly.
  43 + */
  44 + enum Register
  45 + {
  46 + kRegABORT = 0x00, // Write-only
  47 + kRegIDCODE = 0x00, // Read-only
  48 +
  49 + kRegCTRLSTAT = 0x01, // Only available when SELECT.CTRLSEL=0
  50 + kRegWCR = 0x01, // Only available when SELECT.CTRLSEL=1
  51 +
  52 + kRegSELECT = 0x02, // Write-only
  53 + kRegRESEND = 0x02, // Read-only
  54 +
  55 + kRegRDBUFF = 0x03, // Read-only
  56 + };
  57 +
  58 +
  59 + /***************************************************************************
  60 + * Utilities
  61 + */
  62 +
  63 + /*
  64 + * Resets the Debug Access Port to a known state, erasing leftover effects
  65 + * of previous sessions:
  66 + * - Resets SELECT to reveal the CTRL/STAT register and select the first
  67 + * bank of the first AP.
  68 + * - Clears the sticky error bits in CTRL/STAT to recover from faults.
  69 + * - Switches on power to the debug systems (required before interacting
  70 + * with Access Ports).
  71 + */
  72 + Err::Error reset_state();
  73 +
  74 +
  75 + /***************************************************************************
  76 + * Direct DP register access.
  77 + */
  78 +
  79 + /*
  80 + * Reads the contents of the IDCODE register. This register is
  81 + * architecturally specified to never return WAIT, so only two return codes
  82 + * are possible: Err::success on a successful read, and Err::failure if
  83 + * something is wrong.
  84 + */
  85 + Err::Error read_idcode(ARM::word_t *);
  86 +
  87 + /*
  88 + * Alters the contents of the ABORT register, used to clear sticky error
  89 + * conditions that cause other reads/writes to FAULT.
  90 + *
  91 + * The ABORT register is architecturally specified to never return WAIT,
  92 + * so only two return codes are possible: Err::success on a successful
  93 + * write, and Err::failure if something is wrong.
  94 + */
  95 + Err::Error write_abort(ARM::word_t);
  96 +
  97 + /*
  98 + * Reads the contents of the CTRL/STAT register, possibly altering the
  99 + * SELECT register in the process.
  100 + *
  101 + * While CTRL/STAT is architecturally specified to never return WAIT, this
  102 + * method may need to alter SELECT.CTRLSEL to expose CTRL/STAT. SELECT
  103 + * *can* return WAIT. Thus, there are three possible return codes:
  104 + * - Err::success on a successful read.
  105 + * - Err::failure if something is wrong.
  106 + * - Err::try_again if the SELECT register is busy.
  107 + *
  108 + * When this method completes with Err::success, SELECT.CTRLSEL is clear,
  109 + * and subsequent accesses to CTRL/STAT won't return Err::try_again until
  110 + * WCR is accessed.
  111 + */
  112 + Err::Error read_ctrlstat(ARM::word_t *);
  113 +
  114 + /*
  115 + * Alters the contents of the CTRL/STAT register, possibly altering the
  116 + * SELECT register in the process.
  117 + *
  118 + * While CTRL/STAT is architecturally specified to never return WAIT, this
  119 + * method may need to alter SELECT.CTRLSEL to expose CTRL/STAT. SELECT
  120 + * *can* return WAIT. Thus, there are three possible return codes:
  121 + * - Err::success on a successful write.
  122 + * - Err::failure if something is wrong.
  123 + * - Err::try_again if the SELECT register is busy.
  124 + *
  125 + * When this method completes with Err::success, SELECT.CTRLSEL is clear,
  126 + * and subsequent accesses to CTRL/STAT won't return Err::try_again until
  127 + * WCR is accessed.
  128 + */
  129 + Err::Error write_ctrlstat(ARM::word_t);
  130 +
  131 + /*
  132 + * Alters the contents of the SELECT register, which determines both which
  133 + * Access Port bank is visible, and whether the CTRL/STAT or WCR register is
  134 + * visible.
  135 + *
  136 + * May return Err::try_again if an Access Port transaction is in progress.
  137 + */
  138 + Err::Error write_select(ARM::word_t);
  139 +
  140 + /*
  141 + * Reads the contents of the RESEND register. May return Err::try_again.
  142 + */
  143 + Err::Error read_resend(ARM::word_t *);
  144 +
  145 + /*
  146 + * Reads the contents of the RDBUFF register. RDBUFF contains the results
  147 + * of the last successful Access Port read operation. It is a read-once
  148 + * register: reading it destroys its contents. May return Err::try_again if
  149 + * the Access Port operation is still in progress.
  150 + */
  151 + Err::Error read_rdbuff(ARM::word_t *);
  152 +
  153 +
  154 + /***************************************************************************
  155 + * AP register access.
  156 + */
  157 +
  158 + /*
  159 + * Starts a read of an AP register, possibly changing AP and bank to do so.
  160 + * This method can be used together with step_read_ap (below) and
  161 + * read_rdbuff (above) to chain together several reads from the same AP for
  162 + * higher throughput.
  163 + *
  164 + * Reads of the AP are asynchronous. Once the read has completed, its
  165 + * result will be returned by the next call to step_read_ap_in_bank (below)
  166 + * or read_rdbuff (above), whichever comes first.
  167 + *
  168 + * Until the read is complete, other AP accesses may stall (i.e. return a
  169 + * SWD WAIT response, which becomes Err::try_again). Most AP registers can
  170 + * be read quickly without stalling; the main exception are the registers in
  171 + * the MEM-AP for accessing memory. The MEM-AP provides a TrInProg status
  172 + * bit for avoiding this.
  173 + *
  174 + * The register is selected by Access Port register address. Access Port
  175 + * register addresses are given in the ADIv5 and ARM as 8-bit hexadecimal
  176 + * numbers, e.g. 0xF8. The top four bits are the bank; the bottom four are
  177 + * the byte address of a 32-bit register. (Because it's a 32-bit register,
  178 + * the two least significant bits must always be zero.)
  179 + *
  180 + * Return values:
  181 + * Err::argument_error - least-significant two bits of address not zero.
  182 + * Err::success - read operation started.
  183 + * Err::try_again - Access Port transaction in progress, try again.
  184 + * Err::failure - bad register index or failure communicating with
  185 + * interface.
  186 + */
  187 + Err::Error start_read_ap(uint8_t ap_index, uint8_t address);
  188 +
  189 + /*
  190 + * Starts a new read of an AP register, possibly changing banks to do so,
  191 + * and returns the result of the previous read. This method can be used
  192 + * together with start_read_ap and read_rdbuff (above) to
  193 + * chain together several reads from the same AP for higher throughput.
  194 + *
  195 + * Reads of the AP are asynchronous. Once the read has completed, its
  196 + * result will be returned by the next call to this method or read_rdbuff
  197 + * (above), whichever comes first.
  198 + *
  199 + * Until the read is complete, other AP accesses may stall (i.e. return a
  200 + * SWD WAIT response, which becomes Err::try_again). Most AP registers can
  201 + * be read quickly without stalling; the main exception are the registers in
  202 + * the MEM-AP for accessing memory. The MEM-AP provides a TrInProg status
  203 + * bit for avoiding this.
  204 + *
  205 + * The register is selected by Access Port register address. Access Port
  206 + * register addresses are given in the ADIv5 and ARM as 8-bit hexadecimal
  207 + * numbers, e.g. 0xF8. The top four bits are the bank; the bottom four are
  208 + * the byte address of a 32-bit register. (Because it's a 32-bit register,
  209 + * the two least significant bits must always be zero.)
  210 + *
  211 + * Return values:
  212 + * Err::argument_error - least-significant two bits of address not zero or
  213 + * data pointer is the null pointer.
  214 + * Err::success - new read operation started, last results returned.
  215 + * Err::try_again - Access Port transaction in progress, try again.
  216 + * Err::failure - bad register index or failure communicating with
  217 + * interface.
  218 + */
  219 + Err::Error step_read_ap(uint8_t ap_index,
  220 + uint8_t address,
  221 + ARM::word_t * data);
  222 +
  223 + /*
  224 + * Writes a new value into an AP register, possibly changing banks to do
  225 + * so.
  226 + *
  227 + * Writes to the AP are asynchronous (albeit less so than reads). When this
  228 + * function returns, the write operation has been accepted by the Debug
  229 + * Access Port on your behalf, but the write itself may not have completed.
  230 + * Until it completes, other AP operations may stall (i.e. return a SWD
  231 + * WAIT response, which becomes Err::try_again). Most AP registers can be
  232 + * written quickly without stalling; the main exception are the registers in
  233 + * the MEM-AP for accessing memory. The MEM-AP provides a TrInProg status
  234 + * bit for avoiding this.
  235 + *
  236 + * The register is selected by Access Port register address. Access Port
  237 + * register addresses are given in the ADIv5 and ARM as 8-bit hexadecimal
  238 + * numbers, e.g. 0xF8. The top four bits are the bank; the bottom four are
  239 + * the byte address of a 32-bit register. (Because it's a 32-bit register,
  240 + * the two least significant bits must always be zero.)
  241 + *
  242 + * Return values:
  243 + * Err::argument_error - least-significant two bits of address not zero.
  244 + * Err::success - new write operation started.
  245 + * Err::try_again - Access Port transaction in progress, try again.
  246 + * Err::failure - bad register index or failure communicating with
  247 + * interface.
  248 + */
  249 + Err::Error write_ap(uint8_t ap_index, uint8_t address, ARM::word_t data);
252 250 };
253 251
254 252 #endif // SWD_DP_H
722 source/swd_mpsse.cpp
... ... @@ -1,365 +1,477 @@
1   -#include "swd_mpsse.h"
  1 +/*
  2 + * Copyright (c) 2012, Anton Staaf, Cliff L. Biffle
  3 + * All rights reserved.
  4 + *
  5 + * Redistribution and use in source and binary forms, with or without
  6 + * modification, are permitted provided that the following conditions are met:
  7 + * * Redistributions of source code must retain the above copyright
  8 + * notice, this list of conditions and the following disclaimer.
  9 + * * Redistributions in binary form must reproduce the above copyright
  10 + * notice, this list of conditions and the following disclaimer in the
  11 + * documentation and/or other materials provided with the distribution.
  12 + * * Neither the name of the project nor the names of its contributors
  13 + * may be used to endorse or promote products derived from this software
  14 + * without specific prior written permission.
  15 + *
  16 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17 + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19 + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
  20 + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23 + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  25 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26 + */
2 27
  28 +#include "swd_mpsse.h"
3 29 #include "swd_dp.h"
4 30
5 31 #include "libs/error/error_stack.h"
6 32 #include "libs/log/log_default.h"
7 33
8 34 #include <ftdi.h>
9   -
10 35 #include <unistd.h>
11 36
12   -using namespace Err;
13 37 using namespace Log;
14 38
15   -/*******************************************************************************
16   - * MPSSE implementation
17   - */
  39 +using Err::Error;
18 40
19 41 /*
20 42 * Many of the MPSSE commands expect either an 8- or 16-bit count. To get the
21 43 * most out of those bits, it encodes a count N as N-1. These macros produce
22 44 * the individual bytes of the adjusted count.
23 45 */
24   -#define FTH(n) ((((n) - 1) >> 8) & 0xFF) // High 8 bits
25   -#define FTL(n) (((n) - 1) & 0xFF) // Low 8 bits
26   -
27   -namespace { // un-named namespace for implementation bits
28   -
29   -/*
30   - * Maps FT232H I/O pins to SWD signals and protocol states. The mapping
31   - * is fixed for now.
32   - */
33   -enum PinStates {
34   - // RST SWDI SWDO SWDCLK
35   - kStateIdle = 0x9, // 1 0 0 1
36   - kStateResetTarget = 0x1, // 0 0 0 1
37   - kStateResetSWD = 0xB, // 1 0 1 1
38   -};
39   -
40   -/*
41   - * Pin directions for read and write -- used with PinStates above.
42   - */
43   -enum PinDirs {
44   - // RST SWDI SWDO SWDCLK
45   - kDirWrite = 0xB, // 1 0 1 1
46   - kDirRead = 0x9, // 1 0 0 1
47   -};
48   -
  46 +#define FTH(n) ((((n) - 1) >> 8) & 0xff) // High 8 bits
  47 +#define FTL(n) ((((n) - 1) >> 0) & 0xff) // Low 8 bits
49 48
50   -uint8_t const kSWDHeaderStart = 1 << 0;
  49 +uint8_t const swd_header_start = 1 << 0;
51 50
52   -uint8_t const kSWDHeaderAP = 1 << 1;
53   -uint8_t const kSWDHeaderDP = 0 << 1;
  51 +uint8_t const swd_header_ap = 1 << 1;
  52 +uint8_t const swd_header_dp = 0 << 1;
54 53
55   -uint8_t const kSWDHeaderRead = 1 << 2;
56   -uint8_t const kSWDHeaderWrite = 0 << 2;
  54 +uint8_t const swd_header_read = 1 << 2;
  55 +uint8_t const swd_header_write = 0 << 2;
57 56
58   -uint8_t const kSWDHeaderParity = 1 << 5;
59   -uint8_t const kSWDHeaderPark = 1 << 7;
  57 +uint8_t const swd_header_parity = 1 << 5;
60 58
61   -uint8_t swd_request(unsigned address, bool debug_port, bool write) {
62   - bool parity = debug_port ^ write;
  59 +uint8_t const swd_header_park = 1 << 7;
63 60
64   - uint8_t request = kSWDHeaderStart
65   - | (debug_port ? kSWDHeaderDP : kSWDHeaderAP)
66   - | (write ? kSWDHeaderWrite : kSWDHeaderRead)
67   - | ((address & 0x3) << 3)
68   - | kSWDHeaderPark;
  61 +/******************************************************************************/
  62 +uint8 swd_request(int address, bool debug_port, bool write)
  63 +{
  64 + bool parity = debug_port ^ write;
  65 + uint8_t request = (swd_header_start |
  66 + (debug_port ? swd_header_dp : swd_header_ap) |
  67 + (write ? swd_header_write : swd_header_read) |
  68 + ((address & 0x03) << 3) |
  69 + swd_header_park);
69 70
70   - // Incorporate address into parity
71   - switch (address & 0x3) {
72   - case 0:
73   - case 3:
74   - // Even number of ones, no change required.
75   - break;
  71 + switch (address & 0x03)
  72 + {
  73 + case 0:
  74 + case 3:
  75 + break;
76 76
77   - case 1:
78   - case 2:
79   - parity ^= 1;
80   - break;
81   - }
  77 + case 1:
  78 + case 2:
  79 + parity ^= 1;
  80 + break;
  81 + }
82 82
83   - if (parity) request |= kSWDHeaderParity;
  83 + if (parity)
  84 + request |= swd_header_parity;
84 85
85   - return request;
  86 + return request;
86 87 }
  88 +/******************************************************************************/
  89 +bool swd_parity(uint32_t data)
  90 +{
  91 + uint32_t step = data ^ (data >> 16);
87 92
88   -bool swd_parity(uint32_t data) {
89   - uint32_t t = data;
90   - t ^= t >> 16;
91   - t ^= t >> 8;
92   - t ^= t >> 4;
93   - t ^= t >> 2;
94   - t ^= t >> 1;
  93 + step = step ^ (step >> 8);
  94 + step = step ^ (step >> 4);
  95 + step = step ^ (step >> 2);
  96 + step = step ^ (step >> 1);
95 97
96   - return t & 1;
  98 + return (step & 1);
97 99 }
  100 +/******************************************************************************/
  101 +Error mpsse_setup_buffers(ftdi_context * ftdi)
  102 +{
  103 + unsigned read;
  104 + unsigned write;
98 105
99   -Error setup_buffers(ftdi_context *ftdi) {
100   - CheckP(ftdi_usb_purge_buffers(ftdi));
  106 + CheckP(ftdi_usb_purge_buffers(ftdi));
101 107
102   - CheckP(ftdi_read_data_set_chunksize(ftdi, 65536));
103   - CheckP(ftdi_write_data_set_chunksize(ftdi, 65536));
  108 + CheckP(ftdi_read_data_set_chunksize(ftdi, 65536));
  109 + CheckP(ftdi_write_data_set_chunksize(ftdi, 65536));
104 110
105   - uint32_t read, write;
106   - CheckP(ftdi_read_data_get_chunksize(ftdi, &read));
107   - CheckP(ftdi_write_data_get_chunksize(ftdi, &write));
  111 + CheckP(ftdi_read_data_get_chunksize(ftdi, &read));
  112 + CheckP(ftdi_write_data_get_chunksize(ftdi, &write));
108 113
109   - debug(4, "Chunksize (r/w): %u/%u", read, write);
  114 + debug(4, "Chunksize (r/w): %d/%d", read, write);
110 115
111   - return success;
  116 + return Err::success;
112 117 }
  118 +/******************************************************************************/
  119 +Error mpsse_write(ftdi_context * ftdi, uint8_t * buffer, size_t count)
  120 +{
  121 + CheckEQ(ftdi_write_data(ftdi, buffer, count), (int) count);
113 122
114   -Error mpsse_transaction(ftdi_context *ftdi,
115   - uint8_t *command, size_t command_count,
116   - uint8_t *response, size_t response_count,
117   - int timeout) {
118   - size_t count = 0;
119   -
120   - CheckEQ(ftdi_write_data(ftdi, command, command_count), (int) command_count);
121   -
122   - for (int i = 0; i < timeout; ++i) {
123   - count += CheckP(ftdi_read_data(ftdi, response + count,
124   - response_count - count));
125   -
126   - if (count >= response_count) {
127   - debug(5, "MPSSE Response took %d attempts.", i + 1);
128   - return success;
  123 + return Err::success;
  124 +}
  125 +/******************************************************************************/
  126 +Error mpsse_read(ftdi_context * ftdi,
  127 + uint8_t * buffer,
  128 + size_t count,
  129 + int timeout)
  130 +{
  131 + size_t received = 0;
  132 +
  133 + /*
  134 + * This is a crude timeout mechanism. The time that we wait will never
  135 + * be less than the requested number of milliseconds. But it can certainly
  136 + * be more.
  137 + */
  138 + for (int i = 1; i < timeout + 1; ++i)
  139 + {
  140 + received += CheckP(ftdi_read_data(ftdi,
  141 + buffer + received,
  142 + count - received));
  143 +
  144 + if (received >= count)
  145 + {
  146 + debug(5, "MPSSE read took %d attempt%s.", i, i == 1 ? "" : "s");
  147 + return Err::success;
  148 + }
  149 +
  150 + /*
  151 + * The latency timer is set to 1ms, so we wait that long before trying
  152 + * again.
  153 + */
  154 + usleep(1000);
129 155 }
130 156
131   - usleep(1000);
132   - }
  157 + debug(5, "MPSSE read failed after %d attempt%s.",
  158 + timeout, timeout == 1 ? "" : "s");
133 159
134   - return Err::timeout;
  160 + return Err::timeout;
135 161 }
  162 +/******************************************************************************/
  163 +Error mpsse_synchronize(ftdi_context * ftdi)
  164 +{
  165 + uint8_t commands[] = {0xaa};
  166 + uint8_t response[2];
136 167
137   -Error mpsse_synchronize(ftdi_context *ftdi) {
138   - uint8_t commands[] = { 0xAA };
139   - uint8_t response[2];
140   -
141   - Check(mpsse_transaction(ftdi, commands, sizeof(commands),
142   - response, sizeof(response),
143   - 1000));
  168 + Check(mpsse_write(ftdi, commands, sizeof(commands)));
  169 + Check(mpsse_read (ftdi, response, sizeof(response), 1000));
144 170
145   - CheckEQ(response[0], 0xFA);
146   - CheckEQ(response[1], 0xAA);
  171 + CheckEQ(response[0], 0xfa);
  172 + CheckEQ(response[1], 0xaa);
147 173
148   - return success;
  174 + return Err::success;
149 175 }
150   -
151   -Error mpsse_setup(ftdi_context *ftdi) {
152   - Check(setup_buffers(ftdi));
153   - CheckP(ftdi_set_latency_timer(ftdi, 1));
154   -
155   - // Switch into MPSSE mode!
156   - CheckP(ftdi_set_bitmode(ftdi, 0x00, BITMODE_RESET));
157   - CheckP(ftdi_set_bitmode(ftdi, 0x00, BITMODE_MPSSE));
158   -
159   - Check(mpsse_synchronize(ftdi));
160   -
161   - // We run the FT232H at 1MHz by dividing down the 60MHz clock by 60.
162   - uint8_t commands[] = {
163   - DIS_DIV_5,
164   - DIS_ADAPTIVE,
165   - DIS_3_PHASE,
166   -
167   - EN_3_PHASE,
168   - TCK_DIVISOR, FTL(60/2), FTH(60/2),
169   - SET_BITS_LOW, kStateIdle, kDirWrite,
170   - SET_BITS_HIGH, 0, 0,
171   - };
172   -
173   - CheckEQ(ftdi_write_data(ftdi, commands, sizeof(commands)),
174   - sizeof(commands));
175   -
176   - return success;
  176 +/******************************************************************************/
  177 +Error mpsse_setup(MPSSEConfig const & config,
  178 + ftdi_context * ftdi,
  179 + int clock_frequency_hz)
  180 +{
  181 + int divisor = 30000000 / clock_frequency_hz;
  182 + uint8_t commands[] =
  183 + {
  184 + DIS_DIV_5,
  185 + DIS_ADAPTIVE,
  186 + DIS_3_PHASE,
  187 + EN_3_PHASE,
  188 + TCK_DIVISOR, FTL(divisor), FTH(divisor),
  189 + SET_BITS_LOW,
  190 + config.idle_write.low_state,
  191 + config.idle_write.low_direction,
  192 + SET_BITS_HIGH,
  193 + config.idle_write.high_state,
  194 + config.idle_write.high_direction,
  195 + };
  196 +
  197 + Check(mpsse_setup_buffers(ftdi));
  198 +
  199 + CheckP(ftdi_set_latency_timer(ftdi, 1));
  200 +
  201 + CheckP(ftdi_set_bitmode(ftdi, 0x00, BITMODE_RESET));
  202 + CheckP(ftdi_set_bitmode(ftdi, 0x00, BITMODE_MPSSE));
  203 +
  204 + Check(mpsse_synchronize(ftdi));
  205 + Check(mpsse_write(ftdi, commands, sizeof(commands)));
  206 +
  207 + return Err::success;
177 208 }
  209 +/******************************************************************************/
  210 +Error swd_reset(MPSSEConfig const & config, ftdi_context * ftdi)
  211 +{
  212 + uint8_t commands[] =
  213 + {
  214 + /*
  215 + * Pull SWDIO high
  216 + */
  217 + SET_BITS_LOW,
  218 + config.reset_swd.low_state,
  219 + config.reset_swd.low_direction,
  220 + SET_BITS_HIGH,
  221 + config.reset_swd.high_state,
  222 + config.reset_swd.high_direction,
  223 +
  224 + /*
  225 + * Generate 50 clocks (6 bytes + 2 bits)
  226 + */
  227 + CLK_BYTES, FTL(6), FTH(6),
  228 + CLK_BITS, FTL(2),
  229 +
  230 + /*
  231 + * Release SWDIO
  232 + */
  233 + SET_BITS_LOW,
  234 + config.idle_write.low_state,
  235 + config.idle_write.low_direction,
  236 + SET_BITS_HIGH,
  237 + config.idle_write.high_state,
  238 + config.idle_write.high_direction,
  239 +
  240 + CLK_BITS, FTL(1)
  241 + };
  242 +
  243 + Check(mpsse_write(ftdi, commands, sizeof(commands)));
  244 +
  245 + return Err::success;
  246 +}
  247 +/******************************************************************************/
  248 +Error swd_response_to_error(uint8_t response)
  249 +{
  250 + switch (response)
  251 + {
  252 + case 1: return Err::success;
  253 + case 2: return Err::try_again;
  254 + case 4: return Err::failure;
  255 +
  256 + default:
  257 + warning("Received unexpected SWD response %u", response);
  258 + return Err::failure;
  259 + }
  260 +}
  261 +/******************************************************************************/
  262 +MPSSESWDDriver::MPSSESWDDriver(MPSSEConfig const & config,
  263 + ftdi_context * ftdi) :
  264 + _config(config),
  265 + _ftdi(ftdi)
  266 +{
  267 +}
  268 +/******************************************************************************/
  269 +Error MPSSESWDDriver::initialize(uint32_t * idcode_out)
  270 +{
  271 + debug(3, "MPSSESWDDriver::initialize");
178 272
179   -} // un-named namespace for implementation factors
180   -
181   -
182   -/*******************************************************************************
183   - * MPSSESWDDriver class implementation
184   - */
185   -
186   -MPSSESWDDriver::MPSSESWDDriver(ftdi_context *ftdi) : _ftdi(ftdi) {}
187   -
188   -
189   -Error MPSSESWDDriver::initialize(uint32_t *idcode_out) {
190   - Check(mpsse_setup(_ftdi));
191   -
192   - // SWD line reset sequence: 50 bits with SWDIO held high.
193   - uint8_t commands[] = {
194   - SET_BITS_LOW, kStateResetSWD, kDirWrite,
195   - CLK_BYTES, FTL(6), FTH(6), // 48 bits...
196   - CLK_BITS, FTL(2), // ...and two more.
197   - SET_BITS_LOW, kStateIdle, kDirWrite,
198   - CLK_BITS, FTL(1),
199   - };
200   -
201   - CheckEQ(ftdi_write_data(_ftdi, commands, sizeof(commands)),
202   - sizeof(commands));
  273 + Check(mpsse_setup(_config, _ftdi, 1000000));
  274 + Check(swd_reset(_config, _ftdi));
203 275
204   - uint32_t idcode;
205   - Check(read(DebugAccessPort::kRegIDCODE, true, &idcode));
  276 + /*
  277 + * Check the ADIv5 spec before altering the code below. This may seem out
  278 + * of place, but the read of IDCODE is *required* during SWD initialization.
  279 + */
206 280
207   - uint32_t version = idcode >> 28;
208   - uint32_t partno = (idcode >> 12) & 0xFFFF;
209   - uint32_t designer = (idcode >> 1) & 0x7FF;
  281 + uint32_t idcode;
  282 + Check(read(DebugAccessPort::kRegIDCODE, true, &idcode));
210 283
211   - debug(4, "Debug Port IDCODE = %08X", idcode);
212   - debug(4, " Version: %X", version);
213   - debug(4, " Part: %X", partno);
214   - debug(4, " Designer: %X", designer);
  284 + debug(4, "Debug Port IDCODE = %08X", idcode);
  285 + debug(5, "Version: %X", idcode >> 28);
  286 + debug(5, "Part: %X", (idcode >> 12) & 0xFFFF);
  287 + debug(5, "Designer: %X", (idcode >> 1) & 0x7FF);
215 288
216   - if (idcode_out) *idcode_out = idcode;
  289 + if (idcode_out)
  290 + *idcode_out = idcode;
217 291
218   - return success;
  292 + return Err::success;
219 293 }
220   -
221   -
222   -Error MPSSESWDDriver::enter_reset() {
223   - uint8_t commands[] = { SET_BITS_LOW, kStateResetTarget, kDirWrite };
224   -
225   - CheckEQ(ftdi_write_data(_ftdi, commands, sizeof(commands)),
226   - sizeof(commands));
227   -
228   - return success;
  294 +/******************************************************************************/
  295 +Error MPSSESWDDriver::enter_reset()
  296 +{
  297 + uint8_t commands[] =
  298 + {
  299 + SET_BITS_LOW,
  300 + _config.reset_target.low_state,
  301 + _config.reset_target.low_direction,
  302 + SET_BITS_HIGH,
  303 + _config.reset_target.high_state,
  304 + _config.reset_target.high_direction,
  305 + };
  306 +
  307 + debug(3, "MPSSESWDDriver::enter_reset");
  308 +
  309 + Check(mpsse_write(_ftdi, commands, sizeof(commands)));
  310 +
  311 + return Err::success;
229 312 }
230   -
231   -Error MPSSESWDDriver::leave_reset() {
232   - uint8_t commands[] = { SET_BITS_LOW, kStateIdle, kDirWrite };
233   -
234   - CheckEQ(ftdi_write_data(_ftdi, commands, sizeof(commands)),
235   - sizeof(commands));
236   -
237   - return success;
  313 +/******************************************************************************/
  314 +Error MPSSESWDDriver::leave_reset()
  315 +{
  316 + uint8_t commands[] =
  317 + {
  318 + SET_BITS_LOW,
  319 + _config.idle_write.low_state,
  320 + _config.idle_write.low_direction,
  321 + SET_BITS_HIGH,
  322 + _config.idle_write.high_state,
  323 + _config.idle_write.high_direction,
  324 + };
  325 +
  326 + debug(3, "MPSSESWDDriver::leave_reset");
  327 +
  328 + Check(mpsse_write(_ftdi, commands, sizeof(commands)));
  329 +
  330 + return Err::success;
238 331 }
  332 +/******************************************************************************/
  333 +Error MPSSESWDDriver::read(unsigned address, bool debug_port, uint32_t * data)
  334 +{
  335 + debug(3, "MPSSESWDDriver::read(%08X, %d)", address, debug_port);
  336 +
  337 + uint8_t request_commands[] =
  338 + {
  339 + // Write SWD header
  340 + MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_BITMODE, FTL(8),
  341 + swd_request(address, debug_port, false),
  342 + // Turn the bidirectional data line around
  343 + SET_BITS_LOW,
  344 + _config.idle_read.low_state,
  345 + _config.idle_read.low_direction,
  346 + SET_BITS_HIGH,
  347 + _config.idle_read.high_state,
  348 + _config.idle_read.high_direction,
  349 + // And clock out one bit
  350 + CLK_BITS, FTL(1),
  351 + // Now read in the target response
  352 + MPSSE_DO_READ | MPSSE_READ_NEG | MPSSE_LSB | MPSSE_BITMODE, FTL(3),
  353 + };
  354 +
  355 + uint8_t data_commands[] =
  356 + {
  357 + // Then read in the target data
  358 + MPSSE_DO_READ | MPSSE_READ_NEG | MPSSE_LSB, FTL(4), FTH(4),
  359 + // And finally read in the target parity and turn around
  360 + MPSSE_DO_READ | MPSSE_READ_NEG | MPSSE_LSB | MPSSE_BITMODE, FTL(2),
  361 + };
  362 +
  363 + uint8_t cleanup_commands[] =
  364 + {
  365 + // Turn the bidirectional data line back to an output
  366 + SET_BITS_LOW,
  367 + _config.idle_write.low_state,
  368 + _config.idle_write.low_direction,
  369 + SET_BITS_HIGH,
  370 + _config.idle_write.high_state,
  371 + _config.idle_write.high_direction,
  372 + // And clock out one bit
  373 + CLK_BITS, FTL(1),
  374 + };
  375 +
  376 + uint8_t response[6] = {0};
  377 +
  378 + // response[0]: the three-bit response, MSB-justified.
  379 + Check(mpsse_write(_ftdi, request_commands, sizeof(request_commands)));
  380 + Check(mpsse_read(_ftdi, response, 1, 1000));
  381 +
  382 + uint8_t ack = response[0] >> 5;
  383 +
  384 + debug(4, "SWD read got response %u", ack);
  385 +
  386 + if (ack == 0x01)
  387 + {
  388 + uint32_t temp;
  389 +
  390 + // SWD OK
  391 + // Read the data phase.
  392 + // response[4:1]: the 32-bit response word.
  393 + // response[5]: the parity bit in bit 6, turnaround (ignored) in bit 7.
  394 + Check(mpsse_write(_ftdi, data_commands, sizeof(data_commands)));
  395 + Check(mpsse_read(_ftdi, response + 1, sizeof(response) - 1, 1000));
  396 +
  397 + temp = (response[1] << 0 |
  398 + response[2] << 8 |
  399 + response[3] << 16 |
  400 + response[4] << 24);
  401 +
  402 + // Check for parity error.
  403 + CheckEQ((response[5] >> 6) & 1, swd_parity(temp));
  404 +
  405 + if (data)
  406 + *data = temp;
  407 +
  408 + debug(4, "SWD read (%X, %d) = %08X complete with status %d",
  409 + address, debug_port, temp, ack);
  410 + }
239 411
  412 + Check(mpsse_write(_ftdi, cleanup_commands, sizeof(cleanup_commands)));
240 413
241   -Error MPSSESWDDriver::read(unsigned addr, bool debug_port, uint32_t *data) {
242   - debug(4, "MPSSE SWD READ %08X %d", addr, debug_port);
243   -
244   - uint8_t request_commands[] = {
245   - // Send SWD request byte
246   - MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_BITMODE, FTL(8),
247   - swd_request(addr, debug_port, false),
248   -
249   - // Release the bus and clock out a turnaround bit.
250   - SET_BITS_LOW, kStateIdle, kDirRead,
251   - CLK_BITS, FTL(1),
252   -
253   - // Read in the response.
254   - MPSSE_DO_READ | MPSSE_READ_NEG | MPSSE_LSB | MPSSE_BITMODE, FTL(3),
255   - };
256   -
257   - uint8_t data_commands[] = {
258   - // Read in the data and parity fields.
259   - MPSSE_DO_READ | MPSSE_READ_NEG | MPSSE_LSB, FTL(4), FTH(4),
260   - MPSSE_DO_READ | MPSSE_READ_NEG | MPSSE_LSB | MPSSE_BITMODE, FTL(2),
261   - };
262   -
263   - uint8_t cleanup_commands[] = {
264   - // Take the bus back and clock out a turnaround bit.
265   - SET_BITS_LOW, kStateIdle, kDirWrite,
266   - CLK_BITS, FTL(1),
267   - };
268   -
269   -
270   - uint8_t response[6];
271   -
272   - // response[0]: the three-bit response, MSB-justified.
273   - Check(mpsse_transaction(_ftdi, request_commands, sizeof(request_commands),
274   - response, 1,
275   - 1000));
276   - uint8_t ack = response[0] >> 5;
277   -
278   - debug(4, "SWD read got response %u", ack);
279   - if (ack == 0x01) { // SWD OK
280   - // Read the data phase.
281   - // response[4:1]: the 32-bit response word.
282   - // response[5]: the parity bit in bit 6, turnaround (ignored) in bit 7.
283   - Check(mpsse_transaction(_ftdi, data_commands, sizeof(data_commands),
284   - response + 1, sizeof(response) - 1,
285   - 1000));
286   - // Check for parity error.
287   - uint32_t data_temp = response[1]
288   - | response[2] << 8
289   - | response[3] << 16
290   - | response[4] << 24;
291   - uint8_t parity = (response[5] >> 6) & 1;
292   - CheckEQ(parity, swd_parity(data_temp));
293   - debug(4, "SWD read (%X, %d) = %08X complete with status %d",
294   - addr, debug_port, data_temp, ack);
295   - // All is well!
296   - if (data) *data = data_temp;
297   - }
298   -
299   - CheckEQ(ftdi_write_data(_ftdi, cleanup_commands, sizeof(cleanup_commands)),
300   - sizeof(cleanup_commands));
301   -
302   - switch (ack) {
303   - case 1: return success;
304   - case 2: return try_again;
305   - case 4: return failure;
306   -
307   - default:
308   - warning("Received unexpected SWD response %u", ack);
309   - return failure;
310   - }
  414 + return swd_response_to_error(ack);
311 415 }
312   -
313   -Error MPSSESWDDriver::write(unsigned addr, bool debug_port, uint32_t data) {
314   - debug(4, "MPSSE SWD WRITE %08X %d %08X", addr, debug_port, data);
315   -
316   - uint8_t request_commands[] = {
317   - // Write request byte.
318   - MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_BITMODE, FTL(8),
319   - swd_request(addr, debug_port, true),
320   - // Release the bus and clock out a turnaround bit.
321   - SET_BITS_LOW, kStateIdle, kDirRead,
322   - CLK_BITS, FTL(1),
323   -
324   - // Read response.
325   - MPSSE_DO_READ | MPSSE_READ_NEG | MPSSE_LSB | MPSSE_BITMODE, FTL(3),
326   -
327   - // Take the bus back and clock out a turnaround bit.
328   - SET_BITS_LOW, kStateIdle, kDirWrite,
329   - CLK_BITS, FTL(1),
330   - };
331   -
332   - uint8_t data_commands[] = {
333   - // Send the data word.
334   - MPSSE_DO_WRITE | MPSSE_LSB, FTL(4), FTH(4),
335   - (data >> 0) & 0xFF,
336   - (data >> 8) & 0xFF,
337   - (data >> 16) & 0xFF,
338   - (data >> 24) & 0xFF,
339   - // Send the parity bit.
340   - MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_BITMODE, FTL(1),
341   - swd_parity(data) ? 0xFF : 0x00,
342   - };
343   -
344   - uint8_t response[1];
345   - Check(mpsse_transaction(_ftdi, request_commands, sizeof(request_commands),
346   - response, sizeof(response),
347   - 1000));
348   -
349   - uint8_t ack = response[0] >> 5;
350   -
351   - if (ack == 1) { // SWD OK
352   - CheckEQ(ftdi_write_data(_ftdi, data_commands, sizeof(data_commands)),
353   - sizeof(data_commands));
354   - }
355   -
356   - switch (ack) {
357   - case 1: return success;
358   - case 2: return try_again;
359   - case 4: return failure;
360   -
361   - default:
362   - warning("Received unexpected SWD response %u", ack);
363   - return failure;
364   - }
  416 +/******************************************************************************/
  417 +Error MPSSESWDDriver::write(unsigned address, bool debug_port, uint32_t data)
  418 +{
  419 + bool parity = swd_parity(data);
  420 + uint8_t request_commands[] =
  421 + {
  422 + // Write SWD header
  423 + MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_BITMODE, FTL(8),
  424 + swd_request(address, debug_port, true),
  425 + // Turn the bidirectional data line around
  426 + SET_BITS_LOW,
  427 + _config.idle_read.low_state,
  428 + _config.idle_read.low_direction,
  429 + SET_BITS_HIGH,
  430 + _config.idle_read.high_state,
  431 + _config.idle_read.high_direction,
  432 + // And clock out one bit
  433 + CLK_BITS, FTL(1),
  434 + // Now read in the target response
  435 + MPSSE_DO_READ | MPSSE_READ_NEG | MPSSE_LSB | MPSSE_BITMODE, FTL(3),
  436 + // Turn the bidirectional data line back to an output
  437 + SET_BITS_LOW,
  438 + _config.idle_write.low_state,
  439 + _config.idle_write.low_direction,
  440 + SET_BITS_HIGH,
  441 + _config.idle_write.high_state,
  442 + _config.idle_write.high_direction,
  443 + // And clock out one bit
  444 + CLK_BITS, FTL(1),
  445 + };
  446 +
  447 + uint8_t data_commands[] =
  448 + {
  449 + // Write the data
  450 + MPSSE_DO_WRITE | MPSSE_LSB, FTL(4), FTH(4),
  451 + (data >> 0) & 0xff,
  452 + (data >> 8) & 0xff,
  453 + (data >> 16) & 0xff,
  454 + (data >> 24) & 0xff,
  455 + // And finally write the parity bit
  456 + MPSSE_DO_WRITE | MPSSE_LSB | MPSSE_BITMODE, FTL(1),
  457 + parity ? 0xff : 0x00,
  458 + };
  459 +
  460 + debug(3, "MPSSESWDDriver::write(%08X, %d, %08X)",
  461 + address, debug_port, data);
  462 +
  463 + uint8_t response[1] = {0};
  464 +
  465 + Check(mpsse_write(_ftdi, request_commands, sizeof(request_commands)));
  466 + Check(mpsse_read (_ftdi, response, sizeof(response), 1000));
  467 +
  468 + uint8_t ack = response[0] >> 5;
  469 +
  470 + debug(4, "SWD write got response %u", ack);
  471 +
  472 + if (ack == 0x01)
  473 + Check(mpsse_write(_ftdi, data_commands, sizeof(data_commands)));
  474 +
  475 + return swd_response_to_error(ack);
365 476 }
  477 +/******************************************************************************/
67 source/swd_mpsse.h
@@ -6,30 +6,69 @@
6 6 * communication.
7 7 */
8 8
9   -#include "libs/error/error_stack.h"
10   -
11 9 #include "swd.h"
12 10
  11 +#include "libs/error/error_stack.h"
  12 +
13 13 #include <stdint.h>
14 14
15 15 // Forward declaration to avoid importing <ftdi.h>, which pollutes.
16 16 struct ftdi_context;
17 17
18   -class MPSSESWDDriver : public SWDDriver {
19   - ftdi_context *_ftdi;
  18 +struct MPSSEPinConfig
  19 +{
  20 + uint8_t low_state;
  21 + uint8_t low_direction;
  22 + uint8_t high_state;
  23 + uint8_t high_direction;
  24 +};
20 25
21   -public:
22   - MPSSESWDDriver(ftdi_context *);
  26 +struct MPSSEConfig
  27 +{
  28 + uint16_t default_vid;
  29 + uint16_t default_pid;
  30 + int default_interface;
  31 + MPSSEPinConfig idle_read;
  32 + MPSSEPinConfig idle_write;
  33 + MPSSEPinConfig reset_target;
  34 + MPSSEPinConfig reset_swd;
  35 +};
23 36
24   - /*
25   - * See SWDDriver for documentation of these functions.
26   - */
  37 +MPSSEConfig const um232h_config =
  38 +{
  39 + 0x0403, 0x6014, 0,
  40 + {0x09, 0x09, 0x00, 0x00}, //idle read
  41 + {0x09, 0x0b, 0x00, 0x00}, //idle write
  42 + {0x01, 0x0b, 0x00, 0x00}, //reset target
  43 + {0x0b, 0x0b, 0x00, 0x00}, //reset swd
  44 +};
  45 +
  46 +MPSSEConfig const bus_blaster_config =
  47 +{
  48 + 0x0403, 0x6010, 0,
  49 + {0x09, 0x29, 0xb7, 0x58}, //idle read
  50 + {0x09, 0x2b, 0xa7, 0x58}, //idle write
  51 + {0x01, 0x2b, 0xa5, 0x5A}, //reset target
  52 + {0x0b, 0x2b, 0xa7, 0x58}, //reset swd
  53 +};
  54 +
  55 +class MPSSESWDDriver : public SWDDriver
  56 +{
  57 + MPSSEConfig const & _config;