X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Ftarget%2Farm_adi_v5.h;h=ec4a179d8c4f2e4d66731d3ff94e4a09e124537b;hb=db6c994642f29b7d47abb4233494a606fbb65369;hp=861a13deea6192b6a139b8149ce6a1a98b1e300e;hpb=f06148612be714f74174bb86fe95f49df07c32fa;p=openocd.git diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 861a13deea..ec4a179d8c 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -118,66 +118,251 @@ #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 * transport agent; and at least one Access Port (AP), controlling * resource access. Most common is a MEM-AP, for memory access. * + * There are two basic DP transports: JTAG, and ARM's low pin-count SWD. + * Accordingly, this interface is responsible for hiding the transport + * differences so upper layer code can largely ignore them. + * + * When the chip is implemented with JTAG-DP or SW-DP, the transport is + * fixed as JTAG or SWD, respectively. Chips incorporating SWJ-DP permit + * a choice made at board design time (by only using the SWD pins), or + * as part of setting up a debug session (if all the dual-role JTAG/SWD + * signals are available). + * * @todo Rename "swjdp_common" as "dap". Use of SWJ-DP is optional! */ struct swjdp_common { + const struct dap_ops *ops; + 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; }; -/* Accessor function for currently selected DAP-AP number */ +/** + * Transport-neutral representation of queued DAP transactions, supporting + * both JTAG and SWD transports. All submitted transactions are logically + * queued, until the queue is executed by run(). Some implementations might + * execute transactions as soon as they're submitted, but no status is made + * availablue until run(). + */ +struct dap_ops { + /** If the DAP transport isn't SWD, it must be JTAG. Upper level + * code may need to care about the difference in some cases. + */ + bool is_swd; + + /** Reads the DAP's IDCODe register. */ + int (*queue_idcode_read)(struct swjdp_common *dap, + uint8_t *ack, uint32_t *data); + + /** DP register read. */ + int (*queue_dp_read)(struct swjdp_common *dap, unsigned reg, + uint32_t *data); + /** DP register write. */ + int (*queue_dp_write)(struct swjdp_common *dap, unsigned reg, + uint32_t data); + + /** AP register read. */ + int (*queue_ap_read)(struct swjdp_common *dap, unsigned reg, + uint32_t *data); + /** AP register write. */ + int (*queue_ap_write)(struct swjdp_common *dap, unsigned reg, + uint32_t data); + /** AP operation abort. */ + int (*queue_ap_abort)(struct swjdp_common *dap, uint8_t *ack); + + /** Executes all queued DAP operations. */ + int (*run)(struct swjdp_common *dap); +}; + +/** + * Queue an IDCODE register read. This is primarily useful for SWD + * transports, where it is required as part of link initialization. + * (For JTAG, this register is read as part of scan chain setup.) + * + * @param dap The DAP used for reading. + * @param ack Pointer to where transaction status will be stored. + * @param data Pointer saying where to store the IDCODE value. + * + * @return ERROR_OK for success, else a fault code. + */ +static inline int dap_queue_idcode_read(struct swjdp_common *dap, + uint8_t *ack, uint32_t *data) +{ + return dap->ops->queue_idcode_read(dap, ack, data); +} + +/** + * Queue a DP register read. + * Note that not all DP registers are readable; also, that JTAG and SWD + * have slight differences in DP register support. + * + * @param dap The DAP used for reading. + * @param reg The two-bit number of the DP register being read. + * @param data Pointer saying where to store the register's value + * (in host endianness). + * + * @return ERROR_OK for success, else a fault code. + */ +static inline int dap_queue_dp_read(struct swjdp_common *dap, + unsigned reg, uint32_t *data) +{ + return dap->ops->queue_dp_read(dap, reg, data); +} + +/** + * Queue a DP register write. + * Note that not all DP registers are writable; also, that JTAG and SWD + * have slight differences in DP register support. + * + * @param dap The DAP used for writing. + * @param reg The two-bit number of the DP register being written. + * @param data Value being written (host endianness) + * + * @return ERROR_OK for success, else a fault code. + */ +static inline int dap_queue_dp_write(struct swjdp_common *dap, + unsigned reg, uint32_t data) +{ + return dap->ops->queue_dp_write(dap, reg, data); +} + +/** + * Queue an AP register read. + * + * @param dap The DAP used for reading. + * @param reg The number of the AP register being read. + * @param data Pointer saying where to store the register's value + * (in host endianness). + * + * @return ERROR_OK for success, else a fault code. + */ +static inline int dap_queue_ap_read(struct swjdp_common *dap, + unsigned reg, uint32_t *data) +{ + return dap->ops->queue_ap_read(dap, reg, data); +} + +/** + * Queue an AP register write. + * + * @param dap The DAP used for writing. + * @param reg The number of the AP register being written. + * @param data Value being written (host endianness) + * + * @return ERROR_OK for success, else a fault code. + */ +static inline int dap_queue_ap_write(struct swjdp_common *dap, + unsigned reg, uint32_t data) +{ + return dap->ops->queue_ap_write(dap, reg, data); +} + +/** + * Queue an AP abort operation. The current AP transaction is aborted, + * including any update of the transaction counter. The AP is left in + * an unknown state (so it must be re-initialized). For use only after + * the AP has reported WAIT status for an extended period. + * + * @param dap The DAP used for writing. + * @param ack Pointer to where transaction status will be stored. + * + * @return ERROR_OK for success, else a fault code. + */ +static inline int dap_queue_ap_abort(struct swjdp_common *dap, uint8_t *ack) +{ + return dap->ops->queue_ap_abort(dap, ack); +} + +/** + * Perform all queued DAP operations, and clear any errors posted in the + * CTRL_STAT register when they are done. Note that if more than one AP + * operation will be queued, one of the first operations in the queue + * should probably enable CORUNDETECT in the CTRL/STAT register. + * + * @param dap The DAP used. + * + * @return ERROR_OK for success, else a fault code. + */ +static inline int dap_run(struct swjdp_common *dap) +{ + return dap->ops->run(dap); +} + +/** Accessor for currently selected DAP-AP number (0..255) */ static inline uint8_t dap_ap_get_select(struct swjdp_common *swjdp) { return (uint8_t)(swjdp ->apsel >> 24); } -/* Queued transactions -- use with care */ +/* AP selection applies to future AP transactions */ +void dap_ap_select(struct swjdp_common *dap,uint8_t apsel); + +/* Queued AP transactions */ int dap_setup_accessport(struct swjdp_common *swjdp, uint32_t csw, uint32_t tar); -int dap_ap_select(struct swjdp_common *swjdp,uint8_t apsel); int dap_ap_write_reg_u32(struct swjdp_common *swjdp, uint32_t addr, uint32_t value); int dap_ap_read_reg_u32(struct swjdp_common *swjdp, uint32_t addr, uint32_t *value); -/* Queued transactions must be completed with swjdp_transaction_endcheck() */ -int swjdp_transaction_endcheck(struct swjdp_common *swjdp); +/* Queued JTAG ops must be completed with jtagdp_transaction_endcheck() */ +int jtagdp_transaction_endcheck(struct swjdp_common *swjdp); -/* MEM-AP memory mapped bus single uint32_t register transfers, without endcheck */ +/* Queued MEM-AP memory mapped single word transfers */ int mem_ap_read_u32(struct swjdp_common *swjdp, uint32_t address, uint32_t *value); int mem_ap_write_u32(struct swjdp_common *swjdp, uint32_t address, uint32_t value); -/* MEM-AP memory mapped bus transfers, single registers, complete transactions */ +/* Synchronous MEM-AP memory mapped single word transfers */ int mem_ap_read_atomic_u32(struct swjdp_common *swjdp, uint32_t address, uint32_t *value); int mem_ap_write_atomic_u32(struct swjdp_common *swjdp, @@ -213,4 +398,12 @@ DAP_COMMAND_HANDLER(dap_memaccess_command); DAP_COMMAND_HANDLER(dap_apsel_command); DAP_COMMAND_HANDLER(dap_apid_command); +struct target; + +/* Put debug link into SWD mode */ +int dap_to_swd(struct target *target); + +/* Put debug link into JTAG mode */ +int dap_to_jtag(struct target *target); + #endif