色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

你真正了解SWD如何下載調(diào)試的么?

要長高 ? 來源:CSDN博主 ? 作者:背包旅行碼農(nóng) ? 2023-12-06 11:20 ? 次閱讀

作為ARM嵌入式工程師下載調(diào)試器都應(yīng)該知道,但你真正了解SWD如何下載調(diào)試的么?ARM 芯片通過什么物理接口和什么方式連接完全取決于芯片Debug子系統(tǒng)的架構(gòu)如何?

你可以從芯片手冊的Debug章節(jié)獲得DAP(Debug Access Port)的信息。我調(diào)試的是NXP公司最新車載芯片S32K3系列的芯片,從S32K3xx Reference Manual中Debug 子系統(tǒng)章節(jié)中得知該芯片的debug和Trace接口基于Arm CoreSight SoC-400的標準。 從Arm CoreSight SoC-400 Technical Reference Manual章節(jié)Debug Access Port中你可以獲取到詳細的信息。這里只做關(guān)鍵內(nèi)容介紹,只介紹涉及的部分。

參考文檔:Arm CoreSight SoC-400 Technical Reference Manual , CoreSight Components Technical Reference Manual , Arm CoreSight Architecture Specification。

從Arm CoreSight SoC-400 Technical Reference Manual中Figure 4-1 Structure of the CoreSight SoC-400 DAP components看出SWD只是接入芯片調(diào)試子系統(tǒng)的一種方式而已。

1663903486186432.png

那么外部調(diào)試工具是怎么通過SWD的方式接入到ARM核內(nèi)部的呢?下面我們詳細介紹一下CoreSight SoC-400 DAP組件架構(gòu)。

DAP是片外調(diào)試工具接入SOC組件的集合。訪問方式是按照ARM?調(diào)試接口架構(gòu)規(guī)范ADIv5.0~ADIv5.2實現(xiàn)。

DAP由以下組件組成:

?DP用于管理與外部調(diào)試器的連接。

?AP訪問片上系統(tǒng)資源。 每種類型的AP可以有多個。

?DAPBUS互連,用于將DP連接到一個或多個AP。

AP提供了非侵入式訪問權(quán)限:

?CoreSight組件下載或者燒錄模型。 通常是通過系統(tǒng)級CoreSight APB總線和APB-AP來完成的。

?內(nèi)存映射的系統(tǒng)組件,通常使用AXI-AP或AHB-AP。

?使用JTAG-AP的舊版JTAG配置的調(diào)試組件。

而且,某些支持CoreSight的處理器直接連接到DAPBUS互連,并實現(xiàn)自己的ADIv5兼容AP。

CoreSight SoC具有單個多功能DP,如下所示:

SWJ-DP 這是一個組合調(diào)試端口,可以通過ADIv5.1定義的JTAG或串行線協(xié)議進行通信。它包含兩個調(diào)試端口SW-DP和JTAG-DP,您可以通過接口時序命令選擇它們,以在調(diào)試端口接口之間切換。

JTAG-DP 兼容DP架構(gòu)版本0。SW-DP兼容DP架構(gòu)版本2和Serial Wire協(xié)議版本2,使SW-DP可以與其他SW-DP或其他實現(xiàn)組件共享連接。

CoreSight SoC中包含的AP端口是:

AXI-AP AXI-AP實現(xiàn)了ADIv5存儲器訪問端口(MEM-AP)架構(gòu),以直接連接到AXI存儲器系統(tǒng)。 您可以使用適當?shù)臉蚪咏M件將其連接到其他內(nèi)存系統(tǒng)。

AHB-AP AHB-AP提供了一個AHB-Lite主站,用于訪問系統(tǒng)AHB總線。 這兼容ADIv5.1中的MEM-AP并且可以執(zhí)行8到32位訪問。

APB-AP APB-AP在AMBA v3.0中提供了一個APB主設(shè)備,用于訪問調(diào)試APB總線。 這兼容具有32位固定傳輸大小的MEM-AP體系結(jié)構(gòu)。

JTAG-AP JTAG-AP提供對片上組件的JTAG訪問,用作JTAG主端口以驅(qū)動ASIC中的JTAG鏈。 這是ADIv5.1中JTAG-AP的實現(xiàn)。

DAPBUS 互連將DP連接到AP。 系統(tǒng)可能不包含某些類型的AP,或者可能包含多個相同類型的AP。

單純看CoreSight SoC-400 DAP組件架構(gòu),感覺會比較空洞,我們結(jié)合一下S32K3XX DAP架構(gòu)圖來看一下。

1663903499758403.png

從芯片的DAP architecture,不難看出S32K3采用的是Arm?CoreSight?架構(gòu)。

你基本可以找到 CoreSight SoC-400和S32K3XX的DAP architecture對應(yīng)關(guān)系:

S32K3XX CoreSight SoC-400

SWJ-DAP <--> Serial Wire JTAG Debug Port (SWJ-DP)

DAPMUX <--> DAPBUS interconnect

AHB_AP <--> AHB Access Port (AHB-AP)

APB-AP <--> APB Access Port (APB-AP)

MDM_AP <--> DAPBUS exported interface

SDA_AP <--> DAPBUS exported interface

SWJ-DP由JTAG-DP和SW-DP的組成。 它選擇JTAG或SWD作為連接機制,并啟用JTAG-DP或SW-DP作為DAP的接口。

JTAG和SWD接口

JTAG接口具有四個強制引腳tck,tms,tdi和tdo,以及一個可選的復(fù)位引腳ntrst。 JTAG-DP和SW-DP還需要獨立的上電復(fù)位npotrst。

SWD接口需要兩個引腳:

?雙向swdio信號

?時鐘swclk,可以從設(shè)備輸入或輸出。

為了使JTAG或SWD共享連接器,必須在SWJ-DP模塊外部進行連接。 特別是,tms必須是雙向引腳,以支持SWD模式下的雙向swdio引腳。

20-Pin ARM Standard JTAG Connector

1663903522710894.png

(From https://www2.keil.com/coresight/coresight-connectors)

它支持用于訪問基于ARM7和ARM9的設(shè)備的JTAG接口。 對于Cortex-Mx設(shè)備,它支持串行線和JTAG接口,以訪問Cortex-Mx設(shè)備上可用的所有SWD,SWV和JTAG信號。

那么是調(diào)試工具是通過什么方式訪問Cortex-Mx內(nèi)部的呢?

參考文檔:ARM? Debug Interface Architecture Specification ADIv5.0 to ADIv5.2

DAP訪問方式是按照ARM?調(diào)試接口架構(gòu)規(guī)范ADIv5.0~ADIv5.2實現(xiàn)。

DAP****結(jié)構(gòu)框圖如下:

來自ARM? Debug Interface Architecture Specification ADIv5.0 to ADIv5.2的Figure A1-2 Structure of the DAP, showing DPv0 JTAG-DP accesses to a generic AP

1663903524417397.png

ADI包括:

Debug Access Port (DAP),DAP外部物理連接 和 DAP與內(nèi)部調(diào)試資源組件的連接。

DAP包含兩個邏輯模塊,Debug Port(DP) 和 Access Port(AP)。DP來連接外部的host,AP來訪問內(nèi)部的調(diào)試組件寄存器:

? Access to the Debug Port (DP) registers. This is provided by Debug Port accesses (DPACC).

? Access to the Access Port (AP) registers. This is provided by Access Port accesses (APACC)

ADIv5標準外部接口支持一下幾種DP:

? The JTAG Debug Port (JTAG-DP)

? The Serial Wire Debug Port (SW-DP)

? The Serial Wire/JTAG Debug Port (SWJ-DP)

內(nèi)部資源接口包含:

AP (MEM-AP or JTAG-AP)

由于我選擇使用的是SW-DP的方式訪問,我這里只對SWD協(xié)議處理流程介紹。

我們下面剖析一下SW-DP報文格式(擔心翻譯有誤,就用英文原文):

Start A single start bit, with value 0b1.

APnDP A single bit, indicating whether the Debug Port or the Access Port Access register is to be accessed. This bit is 0b0 for a DPACC access, or 0b1 for an APACC access.

RnW A single bit, indicating whether the access is a read or a write. This bit is 0b0 for a write access, or 0b1 for a read access.

A[2:3] Two bits, giving the A[3:2] address field for the DP or AP register Address:

? For a DPACC access, the register being addressed depends on the A[3:2] value and, if A[3:2]==0b01, the value that is held in SELECT. DPBANKSEL. For details, see:

— DP architecture version 1 (DPv1) address map on page B2-50

1663903536691891.png

— DP architecture version 2 (DPv2) address map on page B2-51.

1663903545571092.png

? For an APACC access, the register being addressed depends on the A[3:2] value and the value

that is held in SELECT.{APSEL,APBANKSEL}. For details about addressing, see:

— MEM-AP Programmers’ Model on page C2-169 for accesses to a MEM-AP register

1663903552519817.png

— JTAG-AP register summary on page C3-206 for accesses to a JTAG-AP register.

1663903560152462.png

Note

The A[3:2] value is transmitted Least Significant Bit (LSB) first on the wire, which is why it appears as A[2:3] on the diagrams.

Parity A single parity bit for the preceding packet. See Parity on page B4-108.

Stop A single stop bit. In the synchronous SWD protocol, this bit is always 0b0.

Park A single bit. The host must drive the Park bit HIGH to park the line before tristating it for the turnaround period, to ensure that the line is read as HIGH by the target, which is required because the pull-up on the SWD interface is weak. The target reads this bit as 0b1.

Trn Turnaround. See Line turnaround on page B4-107.

Note

All the examples that are given in this chapter show the default turnaround period of one cycle.

ACK[0:2] A three-bit target-to-host response.

1663903569279765.png

WDATA[0:31]

32 bits of write data, from host to target.

RDATA[0:31]

32 bits of read data, from target to host

我們已經(jīng)了解了報文格式,那我們結(jié)合SWD的報文讀寫時序圖來理解。

Successful write operation (OK response)

1663903577467676.png

Successful read operation (OK response)

1663903599297173.png

下面我結(jié)合Successful write operation (OK response)和Structure of the Debug Access Port舉個例子演示一下SWD如何控制DAP。

Every AP or DP access transaction from the debugger includes two address bits, A[3:2]:

? For a DP register access, the address bits A[3:2] and SELECT.DPBANKSEL determine which register is accessed. SELECT is a DP register.

? For an AP register access, SELECT.APSEL selects an AP to access, and the address bits A[3:2] are combined with SELECT.APBANKSEL to determine which AP register is accessed, as summarized in Structure of the Debug Access Port. That is, the two address bits A[3:2] are decoded to select one of the four 32-bit words from the register bank indicated by SELECT.APBANKSEL in the AP indicated by SELECT.APSEL. Bits [1:0] of all AP and DP register addresses are 0b00.

假如我要向AP0寄存器0x14里寫入0xF0000001,調(diào)試工具操作流程如下:

1663903615337573.png

使用DP寄存器向DP的SELECT寄存器寫入:

— SELECT.APSEL to 0x00. APSEL, bits[31:24]

— SELECT.APBANKSEL to 0x1. APBANKSEL, bits[7:4]

APnDP 寫0 表示DP操作,A[3:2]寫0x02表示操作0x08 SELECT 寄存器。寫入0x00000001.

使用AP寄存器向AP0的0x14寄存器寫入:

APnDP 寫1 表示AP操作,由于已經(jīng)向DP的SELECT選擇了APBANKSEL為0x01,A[3:2]寫0x01表示操作0x14 寄存器。寫入0xF0000001. 在這個情況下能訪問0x10~0x1C等4個寄存器。

其他AP操作其實流程一樣。

下面我稍微了解一下MEM-AP.

來自 ARM? Debug Interface Architecture Specification ADIv5.0 to ADIv5.2的Figure C2-1 MEM-AP connecting the DP to debug components

1663903652399406.png

說白了MEM-AP為DAP提供了一種直接訪問系統(tǒng)地址空間的訪問。操作其實和通用AP的訪問一樣。MEM-AP訪問系統(tǒng)地址空間,其實有多了一層間接訪問。我們直接從OpenOCD源碼中看整個過程。

https://sourceforge.net/p/openocd/code/ci/v0.11.0/tree/src/target/cortex_m.c#l2521

struct target_type cortexm_target = {

.name = "cortex_m",

.deprecated_name = "cortex_m3",

.poll = cortex_m_poll,

.arch_state = armv7m_arch_state,

.target_request_data = cortex_m_target_request_data,

.halt = cortex_m_halt,

.resume = cortex_m_resume,

.step = cortex_m_step,

.assert_reset = cortex_m_assert_reset,

.deassert_reset = cortex_m_deassert_reset,

.soft_reset_halt = cortex_m_soft_reset_halt,

.get_gdb_arch = arm_get_gdb_arch,

.get_gdb_reg_list = armv7m_get_gdb_reg_list,

.read_memory = cortex_m_read_memory,

.write_memory = cortex_m_write_memory,

.checksum_memory = armv7m_checksum_memory,

.blank_check_memory = armv7m_blank_check_memory,

.run_algorithm = armv7m_run_algorithm,

.start_algorithm = armv7m_start_algorithm,

.wait_algorithm = armv7m_wait_algorithm,

.add_breakpoint = cortex_m_add_breakpoint,

.remove_breakpoint = cortex_m_remove_breakpoint,

.add_watchpoint = cortex_m_add_watchpoint,

.remove_watchpoint = cortex_m_remove_watchpoint,

.commands = cortex_m_command_handlers,

.target_create = cortex_m_target_create,

.target_jim_configure = adiv5_jim_configure,

.init_target = cortex_m_init_target,

.examine = cortex_m_examine,

.deinit_target = cortex_m_deinit_target,

.profiling = cortex_m_profiling,

};

OpenOCD通過DAP MEM AP的訪問實現(xiàn)Cortex M系統(tǒng)地址空間的訪問。

cortex_m_read_memory和cortex_m_write_memory實現(xiàn)了讀寫操作。看一下這兩個函數(shù)是怎么實現(xiàn)的。

cortex_m_read_memory實現(xiàn)

static int cortex_m_read_memory(struct target *target, target_addr_t address,

uint32_t size, uint32_t count, uint8_t *buffer)

{

struct armv7m_common *armv7m = target_to_armv7m(target);

if (armv7m->arm.is_armv6m) {

/* armv6m does not handle unaligned memory access */

if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))

return ERROR_TARGET_UNALIGNED_ACCESS;

}

return mem_ap_read_buf(armv7m->debug_ap, buffer, size, count, address);

}

int mem_ap_read_buf(struct adiv5_ap *ap,

uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address)

{

return mem_ap_read(ap, buffer, size, count, address, true);

}

/**

* Synchronous read of a block of memory, using a specific access size.

*

* @param ap The MEM-AP to access.

* @param buffer The data buffer to receive the data. No particular alignment is assumed.

* @param size Which access size to use, in bytes. 1, 2 or 4.

* @param count The number of reads to do (in size units, not bytes).

* @param adr Address to be read; it must be readable by the currently selected MEM-AP.

* @param addrinc Whether the target address should be increased after each read or not. This

* should normally be true, except when reading from e.g. a FIFO.

* @return ERROR_OK on success, otherwise an error code.

*/

static int mem_ap_read(struct adiv5_ap *ap, uint8_t *buffer, uint32_t size, uint32_t count,

uint32_t adr, bool addrinc)

{

struct adiv5_dap *dap = ap->dap;

size_t nbytes = size * count;

const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF;

uint32_t csw_size;

uint32_t address = adr;

int retval = ERROR_OK;

/* TI BE-32 Quirks mode:

* Reads on big-endian TMS570 behave strangely differently than writes.

* They read from the physical address requested, but with DRW byte-reversed.

* For example, a byte read from address 0 will place the result in the high bytes of DRW.

* Also, packed 8-bit and 16-bit transfers seem to sometimes return garbage in some bytes,

* so avoid them. */

if (size == 4)

csw_size = CSW_32BIT;

else if (size == 2)

csw_size = CSW_16BIT;

else if (size == 1)

csw_size = CSW_8BIT;

else

return ERROR_TARGET_UNALIGNED_ACCESS;

if (ap->unaligned_access_bad && (adr % size != 0))

return ERROR_TARGET_UNALIGNED_ACCESS;

/* Allocate buffer to hold the sequence of DRW reads that will be made. This is a significant

* over-allocation if packed transfers are going to be used, but determining the real need at

* this point would be messy. */

uint32_t *read_buf = calloc(count, sizeof(uint32_t));

/* Multiplication count * sizeof(uint32_t) may overflow, calloc() is safe */

uint32_t *read_ptr = read_buf;

if (read_buf == NULL) {

LOG_ERROR("Failed to allocate read buffer");

return ERROR_FAIL;

}

/* Queue up all reads. Each read will store the entire DRW word in the read buffer. How many

* useful bytes it contains, and their location in the word, depends on the type of transfer

* and alignment. */

while (nbytes > 0) {

uint32_t this_size = size;

/* Select packed transfer if possible */

if (addrinc && ap->packed_transfers && nbytes >= 4

&& max_tar_block_size(ap->tar_autoincr_block, address) >= 4) {

this_size = 4;

retval = mem_ap_setup_csw(ap, csw_size | CSW_ADDRINC_PACKED);

} else {

retval = mem_ap_setup_csw(ap, csw_size | csw_addrincr);

}

if (retval != ERROR_OK)

break;

retval = mem_ap_setup_tar(ap, address);

if (retval != ERROR_OK)

break;

retval = dap_queue_ap_read(ap, MEM_AP_REG_DRW, read_ptr++);

if (retval != ERROR_OK)

break;

nbytes -= this_size;

if (addrinc)

address += this_size;

mem_ap_update_tar_cache(ap);

}

if (retval == ERROR_OK)

retval = dap_run(dap);

/* Restore state */

address = adr;

nbytes = size * count;

read_ptr = read_buf;

/* If something failed, read TAR to find out how much data was successfully read, so we can

* at least give the caller what we have. */

if (retval != ERROR_OK) {

uint32_t tar;

if (mem_ap_read_tar(ap, &tar) == ERROR_OK) {

/* TAR is incremented after failed transfer on some devices (eg Cortex-M4) */

LOG_ERROR("Failed to read memory at 0x%08"PRIx32, tar);

if (nbytes > tar - address)

nbytes = tar - address;

} else {

LOG_ERROR("Failed to read memory and, additionally, failed to find out where");

nbytes = 0;

}

}

/* Replay loop to populate caller's buffer from the correct word and byte lane */

while (nbytes > 0) {

uint32_t this_size = size;

if (addrinc && ap->packed_transfers && nbytes >= 4

&& max_tar_block_size(ap->tar_autoincr_block, address) >= 4) {

this_size = 4;

}

if (dap->ti_be_32_quirks) {

switch (this_size) {

case 4:

*buffer++ = *read_ptr >> 8 * (3 - (address++ & 3));

*buffer++ = *read_ptr >> 8 * (3 - (address++ & 3));

/* fallthrough */

case 2:

*buffer++ = *read_ptr >> 8 * (3 - (address++ & 3));

/* fallthrough */

case 1:

*buffer++ = *read_ptr >> 8 * (3 - (address++ & 3));

}

} else {

switch (this_size) {

case 4:

*buffer++ = *read_ptr >> 8 * (address++ & 3);

*buffer++ = *read_ptr >> 8 * (address++ & 3);

/* fallthrough */

case 2:

*buffer++ = *read_ptr >> 8 * (address++ & 3);

/* fallthrough */

case 1:

*buffer++ = *read_ptr >> 8 * (address++ & 3);

}

}

read_ptr++;

nbytes -= this_size;

}

free(read_buf);

return retval;

}

static int cortex_m_write_memory(struct target *target, target_addr_t address,

uint32_t size, uint32_t count, const uint8_t *buffer)

{

struct armv7m_common *armv7m = target_to_armv7m(target);

if (armv7m->arm.is_armv6m) {

/* armv6m does not handle unaligned memory access */

if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))

return ERROR_TARGET_UNALIGNED_ACCESS;

}

return mem_ap_write_buf(armv7m->debug_ap, buffer, size, count, address);

}

int mem_ap_write_buf(struct adiv5_ap *ap,

const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address)

{

return mem_ap_write(ap, buffer, size, count, address, true);

}

/**

* Synchronous write of a block of memory, using a specific access size.

*

* @param ap The MEM-AP to access.

* @param buffer The data buffer to write. No particular alignment is assumed.

* @param size Which access size to use, in bytes. 1, 2 or 4.

* @param count The number of writes to do (in size units, not bytes).

* @param address Address to be written; it must be writable by the currently selected MEM-AP.

* @param addrinc Whether the target address should be increased for each write or not. This

* should normally be true, except when writing to e.g. a FIFO.

* @return ERROR_OK on success, otherwise an error code.

*/

static int mem_ap_write(struct adiv5_ap *ap, const uint8_t *buffer, uint32_t size, uint32_t count,

uint32_t address, bool addrinc)

{

struct adiv5_dap *dap = ap->dap;

size_t nbytes = size * count;

const uint32_t csw_addrincr = addrinc ? CSW_ADDRINC_SINGLE : CSW_ADDRINC_OFF;

uint32_t csw_size;

uint32_t addr_xor;

int retval = ERROR_OK;

/* TI BE-32 Quirks mode:

* Writes on big-endian TMS570 behave very strangely. Observed behavior:

* size write address bytes written in order

* 4 TAR ^ 0 (val >> 24), (val >> 16), (val >> 8), (val)

* 2 TAR ^ 2 (val >> 8), (val)

* 1 TAR ^ 3 (val)

* For example, if you attempt to write a single byte to address 0, the processor

* will actually write a byte to address 3.

*

* To make writes of size < 4 work as expected, we xor a value with the address before

* setting the TAP, and we set the TAP after every transfer rather then relying on

* address increment. */

if (size == 4) {

csw_size = CSW_32BIT;

addr_xor = 0;

} else if (size == 2) {

csw_size = CSW_16BIT;

addr_xor = dap->ti_be_32_quirks ? 2 : 0;

} else if (size == 1) {

csw_size = CSW_8BIT;

addr_xor = dap->ti_be_32_quirks ? 3 : 0;

} else {

return ERROR_TARGET_UNALIGNED_ACCESS;

}

if (ap->unaligned_access_bad && (address % size != 0))

return ERROR_TARGET_UNALIGNED_ACCESS;

while (nbytes > 0) {

uint32_t this_size = size;

/* Select packed transfer if possible */

if (addrinc && ap->packed_transfers && nbytes >= 4

&& max_tar_block_size(ap->tar_autoincr_block, address) >= 4) {

this_size = 4;

retval = mem_ap_setup_csw(ap, csw_size | CSW_ADDRINC_PACKED);

} else {

retval = mem_ap_setup_csw(ap, csw_size | csw_addrincr);

}

if (retval != ERROR_OK)

break;

retval = mem_ap_setup_tar(ap, address ^ addr_xor);

if (retval != ERROR_OK)

return retval;

/* How many source bytes each transfer will consume, and their location in the DRW,

* depends on the type of transfer and alignment. See ARM document IHI0031C. */

uint32_t outvalue = 0;

uint32_t drw_byte_idx = address;

if (dap->ti_be_32_quirks) {

switch (this_size) {

case 4:

outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (drw_byte_idx++ & 3) ^ addr_xor);

outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (drw_byte_idx++ & 3) ^ addr_xor);

outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (drw_byte_idx++ & 3) ^ addr_xor);

outvalue |= (uint32_t)*buffer++ << 8 * (3 ^ (drw_byte_idx & 3) ^ addr_xor);

break;

case 2:

outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (drw_byte_idx++ & 3) ^ addr_xor);

outvalue |= (uint32_t)*buffer++ << 8 * (1 ^ (drw_byte_idx & 3) ^ addr_xor);

break;

case 1:

outvalue |= (uint32_t)*buffer++ << 8 * (0 ^ (drw_byte_idx & 3) ^ addr_xor);

break;

}

} else {

switch (this_size) {

case 4:

outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3);

outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3);

/* fallthrough */

case 2:

outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx++ & 3);

/* fallthrough */

case 1:

outvalue |= (uint32_t)*buffer++ << 8 * (drw_byte_idx & 3);

}

}

nbytes -= this_size;

retval = dap_queue_ap_write(ap, MEM_AP_REG_DRW, outvalue);

if (retval != ERROR_OK)

break;

mem_ap_update_tar_cache(ap);

if (addrinc)

address += this_size;

}

/* REVISIT: Might want to have a queued version of this function that does not run. */

if (retval == ERROR_OK)

retval = dap_run(dap);

if (retval != ERROR_OK) {

uint32_t tar;

if (mem_ap_read_tar(ap, &tar) == ERROR_OK)

LOG_ERROR("Failed to write memory at 0x%08"PRIx32, tar);

else

LOG_ERROR("Failed to write memory and, additionally, failed to find out where");

}

return retval;

}

MEM-AP這里我就不畫圖介紹了,對于我來說只要知道MEM-AP是如何幫助DAP訪問到系統(tǒng)地址空間的原理就可以了,大家直接看源碼實現(xiàn)去理解。大家想要知道更多細節(jié)可以參考ADIv5.0~ADIv5.2章節(jié) 7. The Memory Access Port (MEM-AP)

審核編輯:黃飛

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • ARM
    ARM
    +關(guān)注

    關(guān)注

    134

    文章

    9105

    瀏覽量

    367923
  • 調(diào)試器
    +關(guān)注

    關(guān)注

    1

    文章

    305

    瀏覽量

    23763
  • 車載芯片
    +關(guān)注

    關(guān)注

    0

    文章

    75

    瀏覽量

    14751
  • SWD
    SWD
    +關(guān)注

    關(guān)注

    1

    文章

    57

    瀏覽量

    11862
  • 調(diào)試接口
    +關(guān)注

    關(guān)注

    0

    文章

    10

    瀏覽量

    5110
收藏 人收藏

    評論

    相關(guān)推薦

    程序下載接口的區(qū)別----JTAG vs SWD

    簡單來說,下載調(diào)試器是將PC(例如通過USB協(xié)議)發(fā)送的命令轉(zhuǎn)換為MCU(負責MCU內(nèi)部外圍設(shè)備)理解的語言(例如SWD或JTAG協(xié)議)的設(shè)備,加載代碼并精確控制執(zhí)行。
    的頭像 發(fā)表于 09-28 14:44 ?4176次閱讀
    程序<b class='flag-5'>下載</b>接口的區(qū)別----JTAG vs <b class='flag-5'>SWD</b>

    stm32w的下載調(diào)試方式包含了jtage,swd是否支持串口isp下載

    大俠 請支支招吧stm32w的下載調(diào)試方式包含了jtage,swd是否支持串口isp下載
    發(fā)表于 03-28 10:17

    調(diào)試器能用SWD下載,為什么有些調(diào)試器還要帶一個虛擬串口?

    新手請教一下,淘寶買了個stlink能 運行SWD和JTAG,SWD下載。為什么有些其它的調(diào)試器在支持SWD的情況下還要帶一個虛擬串口來
    發(fā)表于 08-07 11:46

    為什么STM32會禁止JTAG調(diào)試功能卻保留SWD下載調(diào)試功能呢

    為什么STM32會禁止JTAG調(diào)試功能卻保留SWD下載調(diào)試功能呢?
    發(fā)表于 11-25 08:56

    SWD和JTAG接口的含義和區(qū)別

    作為嵌入式軟件工程師,下載調(diào)試器都應(yīng)該知道,但真正了解SWD 和 JTAG接口的含義和區(qū)別嗎
    發(fā)表于 12-10 07:24

    STLINK和JLINK使用SWD四線調(diào)試下載STM32的方法

    STLINK和JLINK使用SWD四線調(diào)試下載STM32的方法
    發(fā)表于 01-19 06:48

    如何解決STM32禁用SWD調(diào)試接口后不能下載程序的問題?

    如何解決STM32禁用SWD調(diào)試接口后不能下載程序的問題?
    發(fā)表于 01-27 07:53

    JTAG接口如何轉(zhuǎn)SWD接口_JTAG接口轉(zhuǎn)SWD接口方法

    本文為大家介紹JTAG接口轉(zhuǎn)SWD接口方法,利用此轉(zhuǎn)換方式,可以簡化板載調(diào)試接口(相應(yīng)單片機應(yīng)支持SWD調(diào)試)。
    發(fā)表于 01-11 10:23 ?3.3w次閱讀
    JTAG接口如何轉(zhuǎn)<b class='flag-5'>SWD</b>接口_JTAG接口轉(zhuǎn)<b class='flag-5'>SWD</b>接口方法

    了解這些常用器件封裝和其名字來歷

    了解這些常用器件封裝及其名字來歷
    的頭像 發(fā)表于 01-16 11:06 ?4746次閱讀

    調(diào)試接口SWD和JTAG的區(qū)別

    作者 | strongerHuang 微信公眾號 | strongerHuang 作為嵌入式工程師,下載調(diào)試器都應(yīng)該知道,但真正了解
    的頭像 發(fā)表于 10-27 09:29 ?1.7w次閱讀
    <b class='flag-5'>調(diào)試</b>接口<b class='flag-5'>SWD</b>和JTAG的區(qū)別

    下載調(diào)試接口SWD和JTAG的區(qū)別

    作為嵌入式工程師,下載調(diào)試器都應(yīng)該知道,但真正了解SWD 和 JTAG 接口的含義和區(qū)別嗎
    的頭像 發(fā)表于 11-28 11:44 ?4645次閱讀

    stm32 SWD調(diào)試接口的使用

    SWD 和傳統(tǒng)的調(diào)試方式區(qū)別??? 1. SWD 模式比 JTAG 在高速模式下面更加可靠。 在大數(shù)據(jù)量的情況下面 JTAG 下載程序會失敗, 但是
    發(fā)表于 12-02 17:06 ?27次下載
    stm32 <b class='flag-5'>SWD</b><b class='flag-5'>調(diào)試</b>接口的使用

    解決STM32禁用SWD調(diào)試接口后不能下載程序的問題

    STM32的PA13(SWDIO)、PA14(SWCLK)這兩個引腳為SWD調(diào)試接口,因為STM32默認把這兩個接口當作了下載接口,所以如果程序中有用到這兩個接口的任意一個(比如用來作為普通I/O口
    發(fā)表于 12-02 18:51 ?29次下載
    解決STM32禁用<b class='flag-5'>SWD</b><b class='flag-5'>調(diào)試</b>接口后不能<b class='flag-5'>下載</b>程序的問題

    華大芯片入坑系列-SWD調(diào)試

    華大芯片入坑系列-SWD調(diào)試這兩天調(diào)自制的板子,發(fā)現(xiàn)可以使用離線編程器的SWD模式燒錄,但是Jlink的SWD模式怎么也調(diào)不通,那就無法仿真,很糟心。后來詢問廠家后,說這塊芯片可能不支
    發(fā)表于 01-12 18:47 ?10次下載
    華大芯片入坑系列-<b class='flag-5'>SWD</b><b class='flag-5'>調(diào)試</b>

    這種修復(fù)轉(zhuǎn)爐耳軸軸承位磨損的方法,了解

    這種修復(fù)轉(zhuǎn)爐耳軸軸承位磨損的方法,了解
    發(fā)表于 06-01 15:50 ?0次下載
    主站蜘蛛池模板: 老板吻我下身好爽到高潮| 国产亚洲欧美在线观看三区| 亚洲国产综合久久久无码色伦| 欧美在线看费视频在线| 十八禁啪啦啪漫画| 魔乳 堕乳漫画acg产卵| 久久人妻熟女中文字幕AV蜜芽| 国产亚洲欧美在线中文BT天堂网| 国产h视频在线观看网站免费| 变形金刚7免费观看完整| AV无码九九久久| bt成人社区| WWW国产无套内射久久| gayxxxxgay呻吟受日本| 99久久中文字幕伊人情人| 99re久久精品在线播放| 97精品国产自产在线观看永久| 2019午夜75福利不卡片在线| 中文字幕亚洲欧美日韩2019| 永久免费在线看mv| 最近的2019中文字幕国语| 中文字幕亚洲无线码在线| 2021全国精品卡一卡二| 99久久精品费精品国产| hdxxxx58丝袜连裤袜| qvod激情图片| 嘟嘟嘟在线视频免费观看高清中文| 成人免费视频无遮挡在线看| 俄罗斯15一16处交| 国产精品97久久AV麻豆| 国产永久免费高清在线观看| 精品久久免费视频| 麻豆乱码一卡二卡三卡视频| 暖暖 日本 视频 在线观看免费| 琪琪色在线播放| 日日操夜夜操狠狠操| 午夜福利试看120秒体验区| 亚洲精品久久久无码AV片软件| 亚洲欧美日韩另类精品一区二区三区 | 精品无码乱码AV| 老师的玉足高跟鞋满足我|