├── CMakeLists.txt ├── Kconfig ├── LICENSE ├── README.md ├── .gitignore ├── cmsis_dap ├── dap_strings.h ├── DAP_queue.h ├── DAP_queue.c ├── debug_cm.h ├── DAP_config.h ├── DAP.h ├── SW_DP.c └── DAP.c └── interface ├── swd_host.h └── swd_host.c /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | idf_component_register( 2 | SRCS 3 | "cmsis_dap/DAP.c" "cmsis_dap/DAP.h" 4 | "cmsis_dap/DAP_queue.c" "cmsis_dap/DAP_queue.h" 5 | "cmsis_dap/DAP_config.h" 6 | "cmsis_dap/dap_strings.h" 7 | "cmsis_dap/debug_cm.h" 8 | "cmsis_dap/SW_DP.c" 9 | "interface/swd_host.c" "interface/swd_host.h" 10 | INCLUDE_DIRS 11 | "cmsis_dap" "interface" 12 | PRIV_REQUIRES 13 | "driver" 14 | ) -------------------------------------------------------------------------------- /Kconfig: -------------------------------------------------------------------------------- 1 | menu "SWD host driver for ESP32" 2 | 3 | config ESP_SWD_CLK_PIN 4 | int "SWD SWCLK Pin" 5 | default 1 6 | help 7 | SWD SWCLK Pin 8 | 9 | config ESP_SWD_IO_PIN 10 | int "SWD IO Pin" 11 | default 2 12 | help 13 | SWD SWDIO Pin 14 | 15 | config ESP_SWD_NRST_PIN 16 | int "SWD Reset Pin" 17 | default 6 18 | help 19 | SWD nRST Pin 20 | 21 | config ESP_SWD_BOOT_PIN 22 | int "Bootloader Pin" 23 | default 11 24 | help 25 | Use this to force target to go into bootloader mode, 26 | in case the original firmware disabled SWD (needed for some new STM32 chips) 27 | 28 | config ESP_SWD_HAS_LED 29 | bool "Enable Status LED support" 30 | default n 31 | help 32 | Toggle status LED support - turn it off to maximise the performance 33 | 34 | config ESP_SWD_LED_PIN 35 | int "SWD LED Pin" 36 | depends on ESP_SWD_HAS_LED 37 | default 3 38 | help 39 | SWD Status LED Pin 40 | 41 | endmenu -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021, Jackson Ming Hu 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SWD Driver for ESP32 2 | 3 | A dirty port of ARM DAPLink 4 | 5 | For ESP32-S2/S3 only, currently tested on ESP32-S2 6 | 7 | ## Usage 8 | 9 | target is a STM32L031K6, writing 8KB of 0x5a to RAM: 10 | 11 | ```c 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | void app_main(void) 19 | { 20 | static const char *TAG = "main"; 21 | ESP_LOGI(TAG, "Lay hou from DAPLink!"); 22 | 23 | swd_init_debug(); 24 | 25 | uint32_t idcode = 0; 26 | uint8_t ret = swd_read_idcode(&idcode); 27 | 28 | ESP_LOGI(TAG, "IDCode readout is: 0x%x, ret: %u", idcode, ret); 29 | 30 | uint8_t *buf = malloc(8192); 31 | memset(buf, 0x5a, 8192); 32 | 33 | int64_t start_ts = esp_timer_get_time(); 34 | ret = swd_write_memory(0x20000000, buf, 8192); 35 | ESP_LOGI(TAG, "Wrote 8KB used %lld us, ret %u", esp_timer_get_time() - start_ts, ret); 36 | } 37 | 38 | ``` 39 | 40 | Log output: 41 | 42 | ``` 43 | I (495) main: Lay hou from DAPLink! 44 | I (505) main: IDCode readout is: 0xbc11477, ret: 1 45 | I (535) main: Wrote 8KB used 24842 us, ret 1 46 | ``` 47 | 48 | ## License 49 | 50 | MIT 51 | 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build system cache 2 | build/ 3 | cmake-build-debug/ 4 | 5 | # VSCode settings 6 | .vscode/ 7 | 8 | # CLion settings 9 | .idea/ 10 | 11 | # ESP-IDF Config 12 | sdkconfig 13 | sdkconfig.old 14 | 15 | # KDevelop 16 | *.kdev4 17 | .kdev4/ 18 | 19 | # Windows thumbnail cache files 20 | Thumbs.db 21 | ehthumbs.db 22 | ehthumbs_vista.db 23 | 24 | # Dump file 25 | *.stackdump 26 | 27 | # Folder config file 28 | [Dd]esktop.ini 29 | 30 | # Recycle Bin used on file shares 31 | $RECYCLE.BIN/ 32 | 33 | # Windows Installer files 34 | *.cab 35 | *.msi 36 | *.msix 37 | *.msm 38 | *.msp 39 | 40 | # Windows shortcuts 41 | *.lnk 42 | 43 | *~ 44 | 45 | # temporary files which can be created if a process still has a handle open of a deleted file 46 | .fuse_hidden* 47 | 48 | # KDE directory preferences 49 | .directory 50 | 51 | # Linux trash folder which might appear on any partition or disk 52 | .Trash-* 53 | 54 | # .nfs files are created when an open file is removed but is still being accessed 55 | .nfs* 56 | .__deepin.db 57 | 58 | # General 59 | .DS_Store 60 | .AppleDouble 61 | .LSOverride 62 | 63 | # Icon must end with two \r 64 | Icon 65 | 66 | # Thumbnails 67 | ._* 68 | 69 | # Files that might appear in the root of a volume 70 | .DocumentRevisions-V100 71 | .fseventsd 72 | .Spotlight-V100 73 | .TemporaryItems 74 | .Trashes 75 | .VolumeIcon.icns 76 | .com.apple.timemachine.donotpresent 77 | 78 | # Directories potentially created on remote AFP share 79 | .AppleDB 80 | .AppleDesktop 81 | Network Trash Folder 82 | Temporary Items 83 | .apdisk 84 | 85 | -------------------------------------------------------------------------------- /cmsis_dap/dap_strings.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file dap_strings.h 3 | * 4 | * DAPLink Interface Firmware 5 | * Copyright (c) 2019, ARM Limited, All Rights Reserved 6 | * SPDX-License-Identifier: Apache-2.0 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 9 | * not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 16 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | */ 20 | 21 | #include 22 | 23 | /** Get Vendor ID string. 24 | \param str Pointer to buffer to store the string. 25 | \return String length. 26 | */ 27 | static inline uint8_t DAP_GetVendorString (char *str) { 28 | (void)str; 29 | return (0U); 30 | } 31 | 32 | /** Get Product ID string. 33 | \param str Pointer to buffer to store the string. 34 | \return String length. 35 | */ 36 | static inline uint8_t DAP_GetProductString (char *str) { 37 | (void)str; 38 | return (0U); 39 | } 40 | 41 | /** Get Serial Number string. 42 | \param str Pointer to buffer to store the string. 43 | \return String length. 44 | */ 45 | static inline uint8_t DAP_GetSerNumString (char *str) { 46 | char data[7] = { 0 }; 47 | esp_efuse_mac_get_default((uint8_t *)data); 48 | uint8_t length = (uint8_t)strlen(data) + 1; 49 | memcpy(str, data, sizeof(data)); 50 | return length; 51 | } 52 | 53 | /** Get firmware version string. 54 | \param str Pointer to buffer to store the string. 55 | \return String length. 56 | */ 57 | static inline uint8_t DAP_ProductFirmwareVerString (char *str) { 58 | const char * data = "2.0.0"; 59 | uint8_t length = (uint8_t)strlen(data) + 1; 60 | memcpy(str, data, length); 61 | return length; 62 | } 63 | -------------------------------------------------------------------------------- /cmsis_dap/DAP_queue.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file DAP_queue.h 3 | * @brief DAP processing queue 4 | * 5 | * DAPLink Interface Firmware 6 | * Copyright (c) 2019, ARM Limited, All Rights Reserved 7 | * SPDX-License-Identifier: Apache-2.0 8 | * 9 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 10 | * not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 17 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | */ 21 | 22 | #ifndef DAP_QUEUE_H 23 | #define DAP_QUEUE_H 24 | 25 | #include "DAP_config.h" 26 | #include "DAP.h" 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | #define FREE_COUNT_INIT (DAP_PACKET_COUNT) 33 | #define SEND_COUNT_INIT 0 34 | 35 | typedef struct _DAP_queue { 36 | uint8_t USB_Request [DAP_PACKET_COUNT][DAP_PACKET_SIZE]; // Request Buffer 37 | uint16_t resp_size[DAP_PACKET_COUNT]; //track the return response size 38 | uint32_t free_count; 39 | uint32_t send_count; 40 | uint32_t recv_idx; 41 | uint32_t send_idx; 42 | } DAP_queue; 43 | 44 | void DAP_queue_init(DAP_queue * queue); 45 | 46 | /* 47 | * Get the a buffer from the DAP_queue where the response to the request is stored 48 | * Parameters: queue - DAP queue, buf = return the buffer location, len = return the len of the response 49 | * Return Value: TRUE - Success, FALSE - Error 50 | */ 51 | bool DAP_queue_get_send_buf(DAP_queue * queue, uint8_t ** buf, int * len); 52 | 53 | /* 54 | * Execute a request and store result to the DAP_queue 55 | * Parameters: queue - DAP queue, reqbuf = buffer with DAP request, len = of the request buffer, retbuf = buffer to peek on the result of the DAP operation 56 | * Return Value: TRUE - Success, FALSE - Error 57 | */ 58 | bool DAP_queue_execute_buf(DAP_queue * queue, const uint8_t *reqbuf, int len, uint8_t ** retbuf); 59 | 60 | #ifdef __cplusplus 61 | } 62 | #endif 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /cmsis_dap/DAP_queue.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file DAP_queue.c 3 | * @brief DAP processing queue 4 | * 5 | * DAPLink Interface Firmware 6 | * Copyright (c) 2019, ARM Limited, All Rights Reserved 7 | * SPDX-License-Identifier: Apache-2.0 8 | * 9 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 10 | * not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 17 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | */ 21 | 22 | #include 23 | #include 24 | #include "DAP_queue.h" 25 | 26 | void DAP_queue_init(DAP_queue * queue) 27 | { 28 | queue->recv_idx = 0; 29 | queue->send_idx = 0; 30 | queue->free_count = FREE_COUNT_INIT; 31 | queue->send_count = SEND_COUNT_INIT; 32 | } 33 | 34 | /* 35 | * Get the a buffer from the DAP_queue where the response to the request is stored 36 | * Parameters: queue - DAP queue, buf = return the buffer location, len = return the len of the response 37 | * Return Value: TRUE - Success, FALSE - Error 38 | */ 39 | 40 | bool DAP_queue_get_send_buf(DAP_queue * queue, uint8_t ** buf, int * len) 41 | { 42 | if (queue->send_count) { 43 | queue->send_count--; 44 | *buf = queue->USB_Request[queue->send_idx]; 45 | *len = queue->resp_size[queue->send_idx]; 46 | queue->send_idx = (queue->send_idx + 1) % DAP_PACKET_COUNT; 47 | queue->free_count++; 48 | return (true); 49 | } 50 | return (false); 51 | } 52 | 53 | /* 54 | * Execute a request and store result to the DAP_queue 55 | * Parameters: queue - DAP queue, reqbuf = buffer with DAP request, len = of the request buffer, retbuf = buffer to peek on the result of the DAP operation 56 | * Return Value: TRUE - Success, FALSE - Error 57 | */ 58 | 59 | 60 | bool DAP_queue_execute_buf(DAP_queue * queue, const uint8_t *reqbuf, int len, uint8_t ** retbuf) 61 | { 62 | uint32_t rsize; 63 | if (queue->free_count > 0) { 64 | if (len > DAP_PACKET_SIZE) { 65 | len = DAP_PACKET_SIZE; 66 | } 67 | queue->free_count--; 68 | memcpy(queue->USB_Request[queue->recv_idx], reqbuf, len); 69 | rsize = DAP_ExecuteCommand(reqbuf, queue->USB_Request[queue->recv_idx]); 70 | queue->resp_size[queue->recv_idx] = rsize & 0xFFFF; //get the response size 71 | *retbuf = queue->USB_Request[queue->recv_idx]; 72 | queue->recv_idx = (queue->recv_idx + 1) % DAP_PACKET_COUNT; 73 | queue->send_count++; 74 | return (true); 75 | } 76 | return (false); 77 | } 78 | -------------------------------------------------------------------------------- /interface/swd_host.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file swd_host.h 3 | * @brief Host driver for accessing the DAP 4 | * 5 | * DAPLink Interface Firmware 6 | * Copyright (c) 2009-2019, ARM Limited, All Rights Reserved 7 | * Copyright 2019, Cypress Semiconductor Corporation 8 | * or a subsidiary of Cypress Semiconductor Corporation. 9 | * SPDX-License-Identifier: Apache-2.0 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 12 | * not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 19 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | 24 | #pragma once 25 | 26 | #include "debug_cm.h" 27 | 28 | #ifdef __cplusplus 29 | extern "C" { 30 | #endif 31 | 32 | typedef enum { 33 | CONNECT_NORMAL, 34 | CONNECT_UNDER_RESET, 35 | } SWD_CONNECT_TYPE; 36 | 37 | typedef enum { 38 | FLASHALGO_RETURN_BOOL, 39 | FLASHALGO_RETURN_POINTER, 40 | FLASHALGO_RETURN_VALUE, 41 | } flash_algo_return_t; 42 | 43 | typedef struct __attribute__((__packed__)) { 44 | uint32_t breakpoint; 45 | uint32_t static_base; 46 | uint32_t stack_pointer; 47 | } program_syscall_t; 48 | 49 | uint8_t swd_init(void); 50 | uint8_t swd_off(void); 51 | uint8_t swd_init_debug(void); 52 | uint8_t swd_clear_errors(void); 53 | uint8_t swd_read_dp(uint8_t adr, uint32_t *val); 54 | uint8_t swd_write_dp(uint8_t adr, uint32_t val); 55 | uint8_t swd_read_ap(uint32_t adr, uint32_t *val); 56 | uint8_t swd_write_ap(uint32_t adr, uint32_t val); 57 | uint8_t swd_read_word(uint32_t addr, uint32_t *val); 58 | uint8_t swd_write_word(uint32_t addr, uint32_t val); 59 | uint8_t swd_read_byte(uint32_t addr, uint8_t *val); 60 | uint8_t swd_write_byte(uint32_t addr, uint8_t val); 61 | uint8_t swd_read_memory(uint32_t address, uint8_t *data, uint32_t size); 62 | uint8_t swd_write_memory(uint32_t address, uint8_t *data, uint32_t size); 63 | uint8_t swd_read_core_register(uint32_t n, uint32_t *val); 64 | uint8_t swd_write_core_register(uint32_t n, uint32_t val); 65 | uint8_t swd_flash_syscall_exec(const program_syscall_t *sys_call, uint32_t entry, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, flash_algo_return_t return_type, uint32_t *ret_out); 66 | uint8_t swd_flash_syscall_exec_async(const program_syscall_t *sys_call, uint32_t entry, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4); 67 | uint8_t swd_flash_syscall_wait_result(flash_algo_return_t return_type, uint32_t *ret_out); 68 | uint8_t swd_transfer_retry(uint32_t req, uint32_t *data); 69 | uint8_t swd_halt_target(); 70 | uint8_t swd_wait_until_halted(void); 71 | void int2array(uint8_t *res, uint32_t data, uint8_t len); 72 | void swd_set_reset_connect(SWD_CONNECT_TYPE type); 73 | void swd_set_soft_reset(uint32_t soft_reset_type); 74 | uint8_t swd_read_idcode(uint32_t *id); 75 | void swd_trigger_nrst(); 76 | uint8_t JTAG2SWD(void); 77 | 78 | #ifdef __cplusplus 79 | } 80 | #endif 81 | -------------------------------------------------------------------------------- /cmsis_dap/debug_cm.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file debug_cm.h 3 | * @brief Access to ARM DAP (Cortex-M) using CMSIS-DAP protocol 4 | * 5 | * DAPLink Interface Firmware 6 | * Copyright (c) 2009-2016, ARM Limited, All Rights Reserved 7 | * SPDX-License-Identifier: Apache-2.0 8 | * 9 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 10 | * not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 17 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | */ 21 | 22 | #ifndef DEBUG_CM_H 23 | #define DEBUG_CM_H 24 | 25 | #include "DAP.h" 26 | 27 | // SWD register access 28 | #define SWD_REG_AP (1) 29 | #define SWD_REG_DP (0) 30 | #define SWD_REG_R (1<<1) 31 | #define SWD_REG_W (0<<1) 32 | #define SWD_REG_ADR(a) (a & 0x0c) 33 | 34 | // Abort Register definitions 35 | #define DAPABORT 0x00000001 // DAP Abort 36 | #define STKCMPCLR 0x00000002 // Clear STICKYCMP Flag (SW Only) 37 | #define STKERRCLR 0x00000004 // Clear STICKYERR Flag (SW Only) 38 | #define WDERRCLR 0x00000008 // Clear WDATAERR Flag (SW Only) 39 | #define ORUNERRCLR 0x00000010 // Clear STICKYORUN Flag (SW Only) 40 | 41 | // Debug Control and Status definitions 42 | #define ORUNDETECT 0x00000001 // Overrun Detect 43 | #define STICKYORUN 0x00000002 // Sticky Overrun 44 | #define TRNMODE 0x0000000C // Transfer Mode Mask 45 | #define TRNNORMAL 0x00000000 // Transfer Mode: Normal 46 | #define TRNVERIFY 0x00000004 // Transfer Mode: Pushed Verify 47 | #define TRNCOMPARE 0x00000008 // Transfer Mode: Pushed Compare 48 | #define STICKYCMP 0x00000010 // Sticky Compare 49 | #define STICKYERR 0x00000020 // Sticky Error 50 | #define READOK 0x00000040 // Read OK (SW Only) 51 | #define WDATAERR 0x00000080 // Write Data Error (SW Only) 52 | #define MASKLANE 0x00000F00 // Mask Lane Mask 53 | #define MASKLANE0 0x00000100 // Mask Lane 0 54 | #define MASKLANE1 0x00000200 // Mask Lane 1 55 | #define MASKLANE2 0x00000400 // Mask Lane 2 56 | #define MASKLANE3 0x00000800 // Mask Lane 3 57 | #define TRNCNT 0x001FF000 // Transaction Counter Mask 58 | #define CDBGRSTREQ 0x04000000 // Debug Reset Request 59 | #define CDBGRSTACK 0x08000000 // Debug Reset Acknowledge 60 | #define CDBGPWRUPREQ 0x10000000 // Debug Power-up Request 61 | #define CDBGPWRUPACK 0x20000000 // Debug Power-up Acknowledge 62 | #define CSYSPWRUPREQ 0x40000000 // System Power-up Request 63 | #define CSYSPWRUPACK 0x80000000 // System Power-up Acknowledge 64 | 65 | // Debug Select Register definitions 66 | #define CTRLSEL 0x00000001 // CTRLSEL (SW Only) 67 | #define APBANKSEL 0x000000F0 // APBANKSEL Mask 68 | #define APSEL 0xFF000000 // APSEL Mask 69 | 70 | // Access Port Register Addresses 71 | #define AP_CSW 0x00 // Control and Status Word 72 | #define AP_TAR 0x04 // Transfer Address 73 | #define AP_DRW 0x0C // Data Read/Write 74 | #define AP_BD0 0x10 // Banked Data 0 75 | #define AP_BD1 0x14 // Banked Data 1 76 | #define AP_BD2 0x18 // Banked Data 2 77 | #define AP_BD3 0x1C // Banked Data 3 78 | #define AP_ROM 0xF8 // Debug ROM Address 79 | #define AP_IDR 0xFC // Identification Register 80 | 81 | // AP Control and Status Word definitions 82 | #define CSW_SIZE 0x00000007 // Access Size: Selection Mask 83 | #define CSW_SIZE8 0x00000000 // Access Size: 8-bit 84 | #define CSW_SIZE16 0x00000001 // Access Size: 16-bit 85 | #define CSW_SIZE32 0x00000002 // Access Size: 32-bit 86 | #define CSW_ADDRINC 0x00000030 // Auto Address Increment Mask 87 | #define CSW_NADDRINC 0x00000000 // No Address Increment 88 | #define CSW_SADDRINC 0x00000010 // Single Address Increment 89 | #define CSW_PADDRINC 0x00000020 // Packed Address Increment 90 | #define CSW_DBGSTAT 0x00000040 // Debug Status 91 | #define CSW_TINPROG 0x00000080 // Transfer in progress 92 | #define CSW_HPROT 0x02000000 // User/Privilege Control 93 | #define CSW_MSTRTYPE 0x20000000 // Master Type Mask 94 | #define CSW_MSTRCORE 0x00000000 // Master Type: Core 95 | #define CSW_MSTRDBG 0x20000000 // Master Type: Debug 96 | #define CSW_RESERVED 0x01000000 // Reserved Value 97 | 98 | // Core Debug Register Address Offsets 99 | #define DBG_OFS 0x0DF0 // Debug Register Offset inside NVIC 100 | #define DBG_HCSR_OFS 0x00 // Debug Halting Control & Status Register 101 | #define DBG_CRSR_OFS 0x04 // Debug Core Register Selector Register 102 | #define DBG_CRDR_OFS 0x08 // Debug Core Register Data Register 103 | #define DBG_EMCR_OFS 0x0C // Debug Exception & Monitor Control Register 104 | 105 | // Core Debug Register Addresses 106 | #define DBG_HCSR (DBG_Addr + DBG_HCSR_OFS) 107 | #define DBG_CRSR (DBG_Addr + DBG_CRSR_OFS) 108 | #define DBG_CRDR (DBG_Addr + DBG_CRDR_OFS) 109 | #define DBG_EMCR (DBG_Addr + DBG_EMCR_OFS) 110 | 111 | // Debug Halting Control and Status Register definitions 112 | #define C_DEBUGEN 0x00000001 // Debug Enable 113 | #define C_HALT 0x00000002 // Halt 114 | #define C_STEP 0x00000004 // Step 115 | #define C_MASKINTS 0x00000008 // Mask Interrupts 116 | #define C_SNAPSTALL 0x00000020 // Snap Stall 117 | #define S_REGRDY 0x00010000 // Register R/W Ready Flag 118 | #define S_HALT 0x00020000 // Halt Flag 119 | #define S_SLEEP 0x00040000 // Sleep Flag 120 | #define S_LOCKUP 0x00080000 // Lockup Flag 121 | #define S_RETIRE_ST 0x01000000 // Sticky Retire Flag 122 | #define S_RESET_ST 0x02000000 // Sticky Reset Flag 123 | #define DBGKEY 0xA05F0000 // Debug Key 124 | 125 | // Debug Exception and Monitor Control Register definitions 126 | #define VC_CORERESET 0x00000001 // Reset Vector Catch 127 | #define VC_MMERR 0x00000010 // Debug Trap on MMU Fault 128 | #define VC_NOCPERR 0x00000020 // Debug Trap on No Coprocessor Fault 129 | #define VC_CHKERR 0x00000040 // Debug Trap on Checking Error Fault 130 | #define VC_STATERR 0x00000080 // Debug Trap on State Error Fault 131 | #define VC_BUSERR 0x00000100 // Debug Trap on Bus Error Fault 132 | #define VC_INTERR 0x00000200 // Debug Trap on Interrupt Error Fault 133 | #define VC_HARDERR 0x00000400 // Debug Trap on Hard Fault 134 | #define MON_EN 0x00010000 // Monitor Enable 135 | #define MON_PEND 0x00020000 // Monitor Pend 136 | #define MON_STEP 0x00040000 // Monitor Step 137 | #define MON_REQ 0x00080000 // Monitor Request 138 | #define TRCENA 0x01000000 // Trace Enable (DWT, ITM, ETM, TPIU) 139 | 140 | // NVIC: Interrupt Controller Type Register 141 | #define NVIC_ICT (NVIC_Addr + 0x0004) 142 | #define INTLINESNUM 0x0000001F // Interrupt Line Numbers 143 | 144 | // NVIC: CPUID Base Register 145 | #define NVIC_CPUID (NVIC_Addr + 0x0D00) 146 | #define CPUID_PARTNO 0x0000FFF0 // Part Number Mask 147 | #define CPUID_REVISION 0x0000000F // Revision Mask 148 | #define CPUID_VARIANT 0x00F00000 // Variant Mask 149 | 150 | // NVIC: Application Interrupt/Reset Control Register 151 | #define NVIC_AIRCR (NVIC_Addr + 0x0D0C) 152 | #define VECTRESET 0x00000001 // Reset Cortex-M (except Debug) 153 | #define VECTCLRACTIVE 0x00000002 // Clear Active Vector Bit 154 | #define SYSRESETREQ 0x00000004 // Reset System (except Debug) 155 | #define VECTKEY 0x05FA0000 // Write Key 156 | 157 | // NVIC: Debug Fault Status Register 158 | #define NVIC_DFSR (NVIC_Addr + 0x0D30) 159 | #define HALTED 0x00000001 // Halt Flag 160 | #define BKPT 0x00000002 // BKPT Flag 161 | #define DWTTRAP 0x00000004 // DWT Match 162 | #define VCATCH 0x00000008 // Vector Catch Flag 163 | #define EXTERNAL 0x00000010 // External Debug Request 164 | 165 | // Data Watchpoint and Trace unit 166 | #define DWT_PCSR 0xe000101c // DWT PC Sampling Register 167 | 168 | #endif 169 | -------------------------------------------------------------------------------- /cmsis_dap/DAP_config.h: -------------------------------------------------------------------------------- 1 | /** 2 | * DAPLink on ESP32-S2 3 | * HAL Wrapper 4 | * 5 | * By Jackson Mong Hu 6 | * License: MIT 7 | * 8 | */ 9 | 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #if defined(CONFIG_IDF_TARGET_ESP32S2) 18 | #define CPU_CLOCK CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ * 1000000 ///< Specifies the CPU Clock in Hz 19 | #elif defined(CONFIG_IDF_TARGET_ESP32S3) 20 | #define CPU_CLOCK CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ * 1000000 ///< Specifies the CPU Clock in Hz 21 | #endif 22 | #define DAP_SWD 1 ///< SWD Mode: 1 = available, 0 = not available 23 | #define DAP_JTAG 0 ///< JTAG Mode: 1 = available, 0 = not available. 24 | #define DAP_JTAG_DEV_CNT 0 ///< Maximum number of JTAG devices on scan chain 25 | #define DAP_DEFAULT_PORT 1 ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG. 26 | #define DAP_DEFAULT_SWJ_CLOCK 50000000 ///< Default SWD/JTAG clock frequency in Hz. 27 | #define IO_PORT_WRITE_CYCLES 2 ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0 28 | 29 | /// Maximum Package Size for Command and Response data. 30 | /// This configuration settings is used to optimized the communication performance with the 31 | /// debugger and depends on the USB peripheral. Change setting to 1024 for High-Speed USB. 32 | #define DAP_PACKET_SIZE 64 ///< USB: 64 = Full-Speed, 1024 = High-Speed. 33 | 34 | /// Maximum Package Buffers for Command and Response data. 35 | /// This configuration settings is used to optimized the communication performance with the 36 | /// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the 37 | /// setting can be reduced (valid range is 1 .. 255). Change setting to 4 for High-Speed USB. 38 | #define DAP_PACKET_COUNT 4 ///< Buffers: 64 = Full-Speed, 4 = High-Speed. 39 | 40 | /// Indicate that UART Serial Wire Output (SWO) trace is available. 41 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 42 | #define SWO_UART 0 ///< SWO UART: 1 = available, 0 = not available 43 | 44 | /// Maximum SWO UART Baudrate 45 | #define SWO_UART_MAX_BAUDRATE 10000000U ///< SWO UART Maximum Baudrate in Hz 46 | 47 | /// Indicate that Manchester Serial Wire Output (SWO) trace is available. 48 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 49 | #define SWO_MANCHESTER 0 ///< SWO Manchester: 1 = available, 0 = not available 50 | 51 | /// SWO Trace Buffer Size. 52 | #define SWO_BUFFER_SIZE 4096U ///< SWO Trace Buffer Size in bytes (must be 2^n) 53 | 54 | /// SWO Streaming Trace. 55 | #define SWO_STREAM 0 ///< SWO Streaming Trace: 1 = available, 0 = not available. 56 | 57 | /// Clock frequency of the Test Domain Timer. Timer value is returned with \ref TIMESTAMP_GET. 58 | #define TIMESTAMP_CLOCK 80000000U ///< Timestamp clock in Hz (0 = timestamps not supported). 59 | 60 | 61 | /// Debug Unit is connected to fixed Target Device. 62 | /// The Debug Unit may be part of an evaluation board and always connected to a fixed 63 | /// known device. In this case a Device Vendor and Device Name string is stored which 64 | /// may be used by the debugger or IDE to configure device parameters. 65 | #define TARGET_DEVICE_FIXED 0 ///< Target Device: 1 = known, 0 = unknown; 66 | 67 | #if TARGET_DEVICE_FIXED 68 | #define TARGET_DEVICE_VENDOR "" ///< String indicating the Silicon Vendor 69 | #define TARGET_DEVICE_NAME "" ///< String indicating the Target Device 70 | #endif 71 | 72 | #ifndef CONFIG_ESP_SWD_CLK_PIN 73 | #define PIN_SWCLK 1 74 | #else 75 | #define PIN_SWCLK CONFIG_ESP_SWD_CLK_PIN 76 | #endif 77 | 78 | #ifndef CONFIG_ESP_SWD_IO_PIN 79 | #define PIN_SWDIO 2 80 | #else 81 | #define PIN_SWDIO CONFIG_ESP_SWD_IO_PIN 82 | #endif 83 | 84 | #ifndef CONFIG_ESP_SWD_NRST_PIN 85 | #define PIN_nRST 6 86 | #else 87 | #define PIN_nRST CONFIG_ESP_SWD_NRST_PIN 88 | #endif 89 | 90 | #ifndef CONFIG_ESP_SWD_LED_PIN 91 | #define PIN_LED 3 92 | #else 93 | #define PIN_SWDIO CONFIG_ESP_SWD_LED_PIN 94 | #endif 95 | 96 | 97 | static inline void PORT_JTAG_SETUP(void) 98 | { 99 | (void)0; // Not supported 100 | } 101 | 102 | static inline void PORT_SWD_SETUP(void) 103 | { 104 | // Set SWCLK HIGH, pull-up only 105 | gpio_ll_output_enable(&GPIO, PIN_SWCLK); 106 | gpio_ll_od_disable(&GPIO, PIN_SWCLK); 107 | gpio_ll_set_level(&GPIO, PIN_SWCLK, 1); 108 | gpio_ll_pulldown_dis(&GPIO, PIN_SWCLK); 109 | gpio_ll_pullup_en(&GPIO, PIN_SWCLK); 110 | gpio_ll_pin_filter_disable(&GPIO, PIN_SWCLK); 111 | 112 | 113 | // Set SWDIO HIGH, pull-up only 114 | gpio_ll_output_enable(&GPIO, PIN_SWDIO); 115 | gpio_ll_od_disable(&GPIO, PIN_SWDIO); 116 | gpio_ll_set_level(&GPIO, PIN_SWDIO, 1); 117 | gpio_ll_pulldown_dis(&GPIO, PIN_SWDIO); 118 | gpio_ll_pullup_en(&GPIO, PIN_SWDIO); 119 | gpio_ll_pin_filter_disable(&GPIO, PIN_SWDIO); 120 | 121 | // Set RESET HIGH, pull-up only 122 | gpio_ll_output_enable(&GPIO, PIN_nRST); 123 | gpio_ll_od_disable(&GPIO, PIN_nRST); 124 | gpio_ll_set_level(&GPIO, PIN_nRST, 1); 125 | gpio_ll_pulldown_dis(&GPIO, PIN_nRST); 126 | gpio_ll_pullup_en(&GPIO, PIN_nRST); 127 | } 128 | 129 | static inline void PORT_OFF(void) 130 | { 131 | gpio_ll_output_disable(&GPIO, PIN_SWCLK); 132 | gpio_ll_output_disable(&GPIO, PIN_SWDIO); 133 | gpio_ll_output_disable(&GPIO, PIN_nRST); 134 | gpio_ll_input_enable(&GPIO, PIN_SWCLK); 135 | gpio_ll_input_enable(&GPIO, PIN_SWDIO); 136 | gpio_ll_input_enable(&GPIO, PIN_nRST); 137 | } 138 | 139 | static __always_inline uint32_t PIN_SWCLK_TCK_IN(void) 140 | { 141 | return (GPIO.out & (1 << PIN_SWCLK)) == 0 ? 0 : 1; 142 | } 143 | 144 | static __always_inline void PIN_SWCLK_TCK_SET(void) 145 | { 146 | GPIO.out_w1ts = (1 << PIN_SWCLK); 147 | } 148 | 149 | static __always_inline void PIN_SWCLK_TCK_CLR(void) 150 | { 151 | GPIO.out_w1tc = (1 << PIN_SWCLK); 152 | } 153 | 154 | static __always_inline uint32_t PIN_SWDIO_TMS_IN(void) 155 | { 156 | return (GPIO.out & (1 << PIN_SWDIO)) == 0 ? 0 : 1; 157 | } 158 | 159 | static __always_inline void PIN_SWDIO_TMS_SET(void) 160 | { 161 | GPIO.out_w1ts = (1 << PIN_SWDIO); 162 | } 163 | 164 | static __always_inline void PIN_SWDIO_TMS_CLR(void) 165 | { 166 | GPIO.out_w1tc = (1 << PIN_SWDIO); 167 | } 168 | 169 | static __always_inline uint32_t PIN_SWDIO_IN(void) 170 | { 171 | return (GPIO.in & (1 << PIN_SWDIO)) == 0 ? 0 : 1; 172 | } 173 | 174 | static __always_inline void PIN_SWDIO_OUT(uint32_t bit) 175 | { 176 | if (bit & 1) { 177 | GPIO.out_w1ts = (1 << PIN_SWDIO); 178 | } else { 179 | GPIO.out_w1tc = (1 << PIN_SWDIO); 180 | } 181 | } 182 | 183 | static __always_inline void PIN_SWDIO_OUT_ENABLE(void) 184 | { 185 | GPIO.enable_w1ts = (1 << PIN_SWDIO); 186 | PIN_INPUT_DISABLE(GPIO_PIN_MUX_REG[PIN_SWDIO]); 187 | } 188 | 189 | static __always_inline void PIN_SWDIO_OUT_DISABLE(void) 190 | { 191 | GPIO.enable_w1tc = (1 << PIN_SWDIO); 192 | PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[PIN_SWDIO]); 193 | } 194 | 195 | static __always_inline uint32_t PIN_TDI_IN(void) 196 | { 197 | return (0); // Not available 198 | } 199 | 200 | static __always_inline void PIN_TDI_OUT(uint32_t bit) 201 | { 202 | ; // Not available 203 | } 204 | 205 | static __always_inline uint32_t PIN_TDO_IN(void) 206 | { 207 | return (0); // Not available 208 | } 209 | 210 | static __always_inline uint32_t PIN_nTRST_IN(void) 211 | { 212 | return (0); // Not available 213 | } 214 | 215 | static __always_inline void PIN_nTRST_OUT(uint32_t bit) 216 | { 217 | ; // Not available 218 | } 219 | 220 | static __always_inline uint32_t PIN_nRESET_IN(void) 221 | { 222 | return (GPIO.out & (1 << PIN_nRST)) == 0 ? 0 : 1; 223 | } 224 | 225 | static __always_inline void PIN_nRESET_OUT(uint32_t bit) 226 | { 227 | if (bit & 1) { 228 | GPIO.out_w1ts = (1 << PIN_nRST); 229 | } else { 230 | GPIO.out_w1tc = (1 << PIN_nRST); 231 | } 232 | } 233 | 234 | #include "../../../esp_timer/private_include/esp_timer_impl.h" 235 | 236 | static __always_inline uint32_t TIMESTAMP_GET() 237 | { 238 | return esp_timer_impl_get_counter_reg(); 239 | } 240 | 241 | static inline void DAP_SETUP(void) 242 | { 243 | PORT_SWD_SETUP(); // Or maybe no need to set up again?? 244 | 245 | #ifdef ESP_SWD_HAS_LED 246 | gpio_ll_output_enable(&GPIO, PIN_LED); 247 | gpio_ll_input_disable(&GPIO, PIN_LED); 248 | gpio_ll_od_disable(&GPIO, PIN_LED); 249 | gpio_ll_pullup_en(&GPIO, PIN_LED); 250 | gpio_ll_pulldown_dis(&GPIO, PIN_LED); 251 | #endif 252 | } 253 | 254 | static inline uint32_t RESET_TARGET(void) 255 | { 256 | return 0; // No need 257 | } 258 | 259 | static inline void LED_CONNECTED_OUT(uint32_t bit) 260 | { 261 | #ifdef CONFIG_ESP_SWD_HAS_LED 262 | if (bit & 1) { 263 | GPIO.out_w1ts = (1 << PIN_LED); 264 | } else { 265 | GPIO.out_w1tc = (1 << PIN_LED); 266 | } 267 | #endif 268 | } 269 | 270 | static inline void LED_RUNNING_OUT(uint32_t bit) 271 | { 272 | #ifdef CONFIG_ESP_SWD_HAS_LED 273 | (void) 0; // Not supported? 274 | #endif 275 | } 276 | 277 | //************************************************************************************************** -------------------------------------------------------------------------------- /cmsis_dap/DAP.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2020 ARM Limited. All rights reserved. 3 | * Copyright 2019, Cypress Semiconductor Corporation 4 | * or a subsidiary of Cypress Semiconductor Corporation. 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the License); you may 9 | * not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 16 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | * ---------------------------------------------------------------------- 21 | * 22 | * $Date: 26. November 2019 23 | * $Revision: V2.0.0 24 | * 25 | * Project: CMSIS-DAP Include 26 | * Title: DAP.h Definitions 27 | * 28 | *---------------------------------------------------------------------------*/ 29 | 30 | #ifndef __DAP_H__ 31 | #define __DAP_H__ 32 | 33 | 34 | // DAP Firmware Version 35 | #ifdef DAP_FW_V1 36 | #define DAP_FW_VER "1.2.0" 37 | #else 38 | #define DAP_FW_VER "2.0.0" 39 | #endif 40 | 41 | // DAP Command IDs 42 | #define ID_DAP_Info 0x00U 43 | #define ID_DAP_HostStatus 0x01U 44 | #define ID_DAP_Connect 0x02U 45 | #define ID_DAP_Disconnect 0x03U 46 | #define ID_DAP_TransferConfigure 0x04U 47 | #define ID_DAP_Transfer 0x05U 48 | #define ID_DAP_TransferBlock 0x06U 49 | #define ID_DAP_TransferAbort 0x07U 50 | #define ID_DAP_WriteABORT 0x08U 51 | #define ID_DAP_Delay 0x09U 52 | #define ID_DAP_ResetTarget 0x0AU 53 | #define ID_DAP_SWJ_Pins 0x10U 54 | #define ID_DAP_SWJ_Clock 0x11U 55 | #define ID_DAP_SWJ_Sequence 0x12U 56 | #define ID_DAP_SWD_Configure 0x13U 57 | #define ID_DAP_SWD_Sequence 0x1DU 58 | #define ID_DAP_JTAG_Sequence 0x14U 59 | #define ID_DAP_JTAG_Configure 0x15U 60 | #define ID_DAP_JTAG_IDCODE 0x16U 61 | #define ID_DAP_SWO_Transport 0x17U 62 | #define ID_DAP_SWO_Mode 0x18U 63 | #define ID_DAP_SWO_Baudrate 0x19U 64 | #define ID_DAP_SWO_Control 0x1AU 65 | #define ID_DAP_SWO_Status 0x1BU 66 | #define ID_DAP_SWO_ExtendedStatus 0x1EU 67 | #define ID_DAP_SWO_Data 0x1CU 68 | 69 | #define ID_DAP_QueueCommands 0x7EU 70 | #define ID_DAP_ExecuteCommands 0x7FU 71 | 72 | // DAP Vendor Command IDs 73 | #define ID_DAP_Vendor0 0x80U 74 | #define ID_DAP_Vendor1 0x81U 75 | #define ID_DAP_Vendor2 0x82U 76 | #define ID_DAP_Vendor3 0x83U 77 | #define ID_DAP_Vendor4 0x84U 78 | #define ID_DAP_Vendor5 0x85U 79 | #define ID_DAP_Vendor6 0x86U 80 | #define ID_DAP_Vendor7 0x87U 81 | #define ID_DAP_Vendor8 0x88U 82 | #define ID_DAP_Vendor9 0x89U 83 | #define ID_DAP_Vendor10 0x8AU 84 | #define ID_DAP_Vendor11 0x8BU 85 | #define ID_DAP_Vendor12 0x8CU 86 | #define ID_DAP_Vendor13 0x8DU 87 | #define ID_DAP_Vendor14 0x8EU 88 | #define ID_DAP_Vendor15 0x8FU 89 | #define ID_DAP_Vendor16 0x90U 90 | #define ID_DAP_Vendor17 0x91U 91 | #define ID_DAP_Vendor18 0x92U 92 | #define ID_DAP_Vendor19 0x93U 93 | #define ID_DAP_Vendor20 0x94U 94 | #define ID_DAP_Vendor21 0x95U 95 | #define ID_DAP_Vendor22 0x96U 96 | #define ID_DAP_Vendor23 0x97U 97 | #define ID_DAP_Vendor24 0x98U 98 | #define ID_DAP_Vendor25 0x99U 99 | #define ID_DAP_Vendor26 0x9AU 100 | #define ID_DAP_Vendor27 0x9BU 101 | #define ID_DAP_Vendor28 0x9CU 102 | #define ID_DAP_Vendor29 0x9DU 103 | #define ID_DAP_Vendor30 0x9EU 104 | #define ID_DAP_Vendor31 0x9FU 105 | 106 | // DAP Extended range of Vendor Command IDs 107 | 108 | #define ID_DAP_VendorExFirst 0xA0U 109 | #define ID_DAP_VendorExLast 0xFEU 110 | 111 | #define ID_DAP_Invalid 0xFFU 112 | 113 | // DAP Status Code 114 | #define DAP_OK 0U 115 | #define DAP_ERROR 0xFFU 116 | 117 | // DAP ID 118 | #define DAP_ID_VENDOR 1U 119 | #define DAP_ID_PRODUCT 2U 120 | #define DAP_ID_SER_NUM 3U 121 | #define DAP_ID_CMSIS_DAP_VER 4U 122 | #define DAP_ID_FW_VER 4U // Deprecated alias of DAP_ID_CMSIS_DAP_VER for backwards compatibility. 123 | #define DAP_ID_DEVICE_VENDOR 5U 124 | #define DAP_ID_DEVICE_NAME 6U 125 | #define DAP_ID_PRODUCT_FW_VER 7U 126 | #define DAP_ID_CAPABILITIES 0xF0U 127 | #define DAP_ID_TIMESTAMP_CLOCK 0xF1U 128 | #define DAP_ID_SWO_BUFFER_SIZE 0xFDU 129 | #define DAP_ID_PACKET_COUNT 0xFEU 130 | #define DAP_ID_PACKET_SIZE 0xFFU 131 | 132 | // DAP Host Status 133 | #define DAP_DEBUGGER_CONNECTED 0U 134 | #define DAP_TARGET_RUNNING 1U 135 | 136 | // DAP Port 137 | #define DAP_PORT_AUTODETECT 0U // Autodetect Port 138 | #define DAP_PORT_DISABLED 0U // Port Disabled (I/O pins in High-Z) 139 | #define DAP_PORT_SWD 1U // SWD Port (SWCLK, SWDIO) + nRESET 140 | #define DAP_PORT_JTAG 2U // JTAG Port (TCK, TMS, TDI, TDO, nTRST) + nRESET 141 | 142 | // DAP SWJ Pins 143 | #define DAP_SWJ_SWCLK_TCK 0 // SWCLK/TCK 144 | #define DAP_SWJ_SWDIO_TMS 1 // SWDIO/TMS 145 | #define DAP_SWJ_TDI 2 // TDI 146 | #define DAP_SWJ_TDO 3 // TDO 147 | #define DAP_SWJ_nTRST 5 // nTRST 148 | #define DAP_SWJ_nRESET 7 // nRESET 149 | 150 | // DAP Transfer Request 151 | #define DAP_TRANSFER_APnDP (1U<<0) 152 | #define DAP_TRANSFER_RnW (1U<<1) 153 | #define DAP_TRANSFER_A2 (1U<<2) 154 | #define DAP_TRANSFER_A3 (1U<<3) 155 | #define DAP_TRANSFER_MATCH_VALUE (1U<<4) 156 | #define DAP_TRANSFER_MATCH_MASK (1U<<5) 157 | #define DAP_TRANSFER_TIMESTAMP (1U<<7) 158 | 159 | // DAP Transfer Response 160 | #define DAP_TRANSFER_OK (1U<<0) 161 | #define DAP_TRANSFER_WAIT (1U<<1) 162 | #define DAP_TRANSFER_FAULT (1U<<2) 163 | #define DAP_TRANSFER_ERROR (1U<<3) 164 | #define DAP_TRANSFER_MISMATCH (1U<<4) 165 | 166 | // DAP SWO Trace Mode 167 | #define DAP_SWO_OFF 0U 168 | #define DAP_SWO_UART 1U 169 | #define DAP_SWO_MANCHESTER 2U 170 | 171 | // DAP SWO Trace Status 172 | #define DAP_SWO_CAPTURE_ACTIVE (1U<<0) 173 | #define DAP_SWO_CAPTURE_PAUSED (1U<<1) 174 | #define DAP_SWO_STREAM_ERROR (1U<<6) 175 | #define DAP_SWO_BUFFER_OVERRUN (1U<<7) 176 | 177 | 178 | // Debug Port Register Addresses 179 | #define DP_IDCODE 0x00U // IDCODE Register (SW Read only) 180 | #define DP_ABORT 0x00U // Abort Register (SW Write only) 181 | #define DP_CTRL_STAT 0x04U // Control & Status 182 | #define DP_WCR 0x04U // Wire Control Register (SW Only) 183 | #define DP_SELECT 0x08U // Select Register (JTAG R/W & SW W) 184 | #define DP_RESEND 0x08U // Resend (SW Read Only) 185 | #define DP_RDBUFF 0x0CU // Read Buffer (Read Only) 186 | 187 | // JTAG IR Codes 188 | #define JTAG_ABORT 0x08U 189 | #define JTAG_DPACC 0x0AU 190 | #define JTAG_APACC 0x0BU 191 | #define JTAG_IDCODE 0x0EU 192 | #define JTAG_BYPASS 0x0FU 193 | 194 | // JTAG Sequence Info 195 | #define JTAG_SEQUENCE_TCK 0x3FU // TCK count 196 | #define JTAG_SEQUENCE_TMS 0x40U // TMS value 197 | #define JTAG_SEQUENCE_TDO 0x80U // TDO capture 198 | 199 | // SWD Sequence Info 200 | #define SWD_SEQUENCE_CLK 0x3FU // SWCLK count 201 | #define SWD_SEQUENCE_DIN 0x80U // SWDIO capture 202 | 203 | 204 | #include 205 | #include 206 | 207 | // DAP Data structure 208 | typedef struct { 209 | uint8_t debug_port; // Debug Port 210 | uint8_t fast_clock; // Fast Clock Flag 211 | uint8_t padding[2]; 212 | uint32_t clock_delay; // Clock Delay 213 | uint32_t timestamp; // Last captured Timestamp 214 | struct { // Transfer Configuration 215 | uint8_t idle_cycles; // Idle cycles after transfer 216 | uint8_t padding[3]; 217 | uint16_t retry_count; // Number of retries after WAIT response 218 | uint16_t match_retry; // Number of retries if read value does not match 219 | uint32_t match_mask; // Match Mask 220 | } transfer; 221 | #if (DAP_SWD != 0) 222 | struct { // SWD Configuration 223 | uint8_t turnaround; // Turnaround period 224 | uint8_t data_phase; // Always generate Data Phase 225 | } swd_conf; 226 | #endif 227 | #if (DAP_JTAG != 0) 228 | struct { // JTAG Device Chain 229 | uint8_t count; // Number of devices 230 | uint8_t index; // Device index (device at TDO has index 0) 231 | #if (DAP_JTAG_DEV_CNT != 0) 232 | uint8_t ir_length[DAP_JTAG_DEV_CNT]; // IR Length in bits 233 | uint16_t ir_before[DAP_JTAG_DEV_CNT]; // Bits before IR 234 | uint16_t ir_after [DAP_JTAG_DEV_CNT]; // Bits after IR 235 | #endif 236 | } jtag_dev; 237 | #endif 238 | } DAP_Data_t; 239 | 240 | extern DAP_Data_t DAP_Data; // DAP Data 241 | extern volatile uint8_t DAP_TransferAbort; // Transfer Abort Flag 242 | 243 | 244 | #ifdef __cplusplus 245 | extern "C" 246 | { 247 | #endif 248 | 249 | // Functions 250 | extern void SWJ_Sequence (uint32_t count, const uint8_t *data); 251 | extern void SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi); 252 | extern void JTAG_Sequence (uint32_t info, const uint8_t *tdi, uint8_t *tdo); 253 | extern void JTAG_IR (uint32_t ir); 254 | extern uint32_t JTAG_ReadIDCode (void); 255 | extern void JTAG_WriteAbort (uint32_t data); 256 | extern uint8_t JTAG_Transfer (uint32_t request, uint32_t *data); 257 | extern uint8_t SWD_Transfer (uint32_t request, uint32_t *data); 258 | 259 | extern void Delayms (uint32_t delay); 260 | 261 | extern uint32_t SWO_Transport (const uint8_t *request, uint8_t *response); 262 | extern uint32_t SWO_Mode (const uint8_t *request, uint8_t *response); 263 | extern uint32_t SWO_Baudrate (const uint8_t *request, uint8_t *response); 264 | extern uint32_t SWO_Control (const uint8_t *request, uint8_t *response); 265 | extern uint32_t SWO_Status (uint8_t *response); 266 | extern uint32_t SWO_ExtendedStatus (const uint8_t *request, uint8_t *response); 267 | extern uint32_t SWO_Data (const uint8_t *request, uint8_t *response); 268 | 269 | extern void SWO_QueueTransfer (uint8_t *buf, uint32_t num); 270 | extern void SWO_AbortTransfer (void); 271 | extern void SWO_TransferComplete (void); 272 | 273 | extern uint32_t UART_SWO_Mode (uint32_t enable); 274 | extern uint32_t UART_SWO_Baudrate (uint32_t baudrate); 275 | extern uint32_t UART_SWO_Control (uint32_t active); 276 | extern void UART_SWO_Capture (uint8_t *buf, uint32_t num); 277 | extern uint32_t UART_SWO_GetCount (void); 278 | 279 | extern uint32_t Manchester_SWO_Mode (uint32_t enable); 280 | extern uint32_t Manchester_SWO_Baudrate (uint32_t baudrate); 281 | extern uint32_t Manchester_SWO_Control (uint32_t active); 282 | extern void Manchester_SWO_Capture (uint8_t *buf, uint32_t num); 283 | extern uint32_t Manchester_SWO_GetCount (void); 284 | 285 | extern uint32_t DAP_ProcessVendorCommand (const uint8_t *request, uint8_t *response); 286 | extern uint32_t DAP_ProcessCommand (const uint8_t *request, uint8_t *response); 287 | extern uint32_t DAP_ExecuteCommand (const uint8_t *request, uint8_t *response); 288 | 289 | extern void DAP_Setup (void); 290 | 291 | // Configurable delay for clock generation 292 | #ifndef DELAY_SLOW_CYCLES 293 | #define DELAY_SLOW_CYCLES 10U // Number of cycles for one iteration 294 | #endif 295 | 296 | static __inline__ __attribute__((__always_inline__)) void PIN_DELAY_SLOW (uint32_t delay) { 297 | while (--delay); 298 | } 299 | 300 | 301 | // Fixed delay for fast clock generation 302 | #ifndef DELAY_FAST_CYCLES 303 | #define DELAY_FAST_CYCLES 0 // Number of cycles: 0..3 304 | #endif 305 | static __inline__ __attribute__((__always_inline__)) void PIN_DELAY_FAST (void) { 306 | #if (DELAY_FAST_CYCLES >= 1U) 307 | __asm__ __volatile__("nop;"); 308 | #endif 309 | #if (DELAY_FAST_CYCLES >= 2U) 310 | __NOP(); 311 | #endif 312 | #if (DELAY_FAST_CYCLES >= 3U) 313 | __NOP(); 314 | #endif 315 | } 316 | 317 | #ifdef __cplusplus 318 | } 319 | #endif 320 | 321 | 322 | #endif /* __DAP_H__ */ 323 | -------------------------------------------------------------------------------- /cmsis_dap/SW_DP.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2017 ARM Limited. All rights reserved. 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the License); you may 7 | * not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 14 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * ---------------------------------------------------------------------- 19 | * 20 | * $Date: 1. December 2017 21 | * $Revision: V2.0.0 22 | * 23 | * Project: CMSIS-DAP Source 24 | * Title: SW_DP.c CMSIS-DAP SW DP I/O 25 | * 26 | *---------------------------------------------------------------------------*/ 27 | 28 | #include 29 | #include "DAP_config.h" 30 | #include "DAP.h" 31 | 32 | // SW Macros 33 | 34 | #define PIN_SWCLK_SET PIN_SWCLK_TCK_SET 35 | #define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR 36 | 37 | #define SW_CLOCK_CYCLE() \ 38 | PIN_SWCLK_CLR(); \ 39 | PIN_DELAY(); \ 40 | PIN_SWCLK_SET(); \ 41 | PIN_DELAY() 42 | 43 | #define SW_WRITE_BIT(bit) \ 44 | PIN_SWDIO_OUT(bit); \ 45 | PIN_SWCLK_CLR(); \ 46 | PIN_DELAY(); \ 47 | PIN_SWCLK_SET(); \ 48 | PIN_DELAY() 49 | 50 | #define SW_READ_BIT(bit) \ 51 | PIN_SWCLK_CLR(); \ 52 | PIN_DELAY(); \ 53 | bit = PIN_SWDIO_IN(); \ 54 | PIN_SWCLK_SET(); \ 55 | PIN_DELAY() 56 | 57 | #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) 58 | 59 | 60 | // Generate SWJ Sequence 61 | // count: sequence bit count 62 | // data: pointer to sequence bit data 63 | // return: none 64 | #if ((DAP_SWD != 0) || (DAP_JTAG != 0)) 65 | void IRAM_ATTR SWJ_Sequence (uint32_t count, const uint8_t *data) { 66 | uint32_t val; 67 | uint32_t n; 68 | 69 | val = 0U; 70 | n = 0U; 71 | while (count--) { 72 | if (n == 0U) { 73 | val = *data++; 74 | n = 8U; 75 | } 76 | if (val & 1U) { 77 | PIN_SWDIO_TMS_SET(); 78 | } else { 79 | PIN_SWDIO_TMS_CLR(); 80 | } 81 | SW_CLOCK_CYCLE(); 82 | val >>= 1; 83 | n--; 84 | } 85 | } 86 | #endif 87 | 88 | 89 | // Generate SWD Sequence 90 | // info: sequence information 91 | // swdo: pointer to SWDIO generated data 92 | // swdi: pointer to SWDIO captured data 93 | // return: none 94 | #if (DAP_SWD != 0) 95 | void IRAM_ATTR SWD_Sequence (uint32_t info, const uint8_t *swdo, uint8_t *swdi) { 96 | uint32_t val; 97 | uint32_t bit; 98 | uint32_t n, k; 99 | 100 | n = info & SWD_SEQUENCE_CLK; 101 | if (n == 0U) { 102 | n = 64U; 103 | } 104 | 105 | if (info & SWD_SEQUENCE_DIN) { 106 | while (n) { 107 | val = 0U; 108 | for (k = 8U; k && n; k--, n--) { 109 | SW_READ_BIT(bit); 110 | val >>= 1; 111 | val |= bit << 7; 112 | } 113 | val >>= k; 114 | *swdi++ = (uint8_t)val; 115 | } 116 | } else { 117 | while (n) { 118 | val = *swdo++; 119 | for (k = 8U; k && n; k--, n--) { 120 | SW_WRITE_BIT(val); 121 | val >>= 1; 122 | } 123 | } 124 | } 125 | } 126 | #endif 127 | 128 | 129 | #if (DAP_SWD != 0) 130 | 131 | 132 | // SWD Transfer I/O 133 | // request: A[3:2] RnW APnDP 134 | // data: DATA[31:0] 135 | // return: ACK[2:0] 136 | #define SWD_TransferFunction(speed) /**/ \ 137 | static inline __attribute__((always_inline)) uint8_t SWD_Transfer##speed (uint32_t request, uint32_t *data) { \ 138 | uint32_t ack; \ 139 | uint32_t bit; \ 140 | uint32_t val; \ 141 | uint32_t parity; \ 142 | \ 143 | uint32_t n; \ 144 | \ 145 | /* Packet Request */ \ 146 | parity = 0U; \ 147 | SW_WRITE_BIT(1U); /* Start Bit */ \ 148 | bit = request >> 0; \ 149 | SW_WRITE_BIT(bit); /* APnDP Bit */ \ 150 | parity += bit; \ 151 | bit = request >> 1; \ 152 | SW_WRITE_BIT(bit); /* RnW Bit */ \ 153 | parity += bit; \ 154 | bit = request >> 2; \ 155 | SW_WRITE_BIT(bit); /* A2 Bit */ \ 156 | parity += bit; \ 157 | bit = request >> 3; \ 158 | SW_WRITE_BIT(bit); /* A3 Bit */ \ 159 | parity += bit; \ 160 | SW_WRITE_BIT(parity); /* Parity Bit */ \ 161 | SW_WRITE_BIT(0U); /* Stop Bit */ \ 162 | SW_WRITE_BIT(1U); /* Park Bit */ \ 163 | \ 164 | /* Turnaround */ \ 165 | PIN_SWDIO_OUT_DISABLE(); \ 166 | for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ 167 | SW_CLOCK_CYCLE(); \ 168 | } \ 169 | \ 170 | /* Acknowledge response */ \ 171 | SW_READ_BIT(bit); \ 172 | ack = bit << 0; \ 173 | SW_READ_BIT(bit); \ 174 | ack |= bit << 1; \ 175 | SW_READ_BIT(bit); \ 176 | ack |= bit << 2; \ 177 | \ 178 | if (ack == DAP_TRANSFER_OK) { /* OK response */ \ 179 | /* Data transfer */ \ 180 | if (request & DAP_TRANSFER_RnW) { \ 181 | /* Read data */ \ 182 | val = 0U; \ 183 | parity = 0U; \ 184 | for (n = 32U; n; n--) { \ 185 | SW_READ_BIT(bit); /* Read RDATA[0:31] */ \ 186 | parity += bit; \ 187 | val >>= 1; \ 188 | val |= bit << 31; \ 189 | } \ 190 | SW_READ_BIT(bit); /* Read Parity */ \ 191 | if ((parity ^ bit) & 1U) { \ 192 | ack = DAP_TRANSFER_ERROR; \ 193 | } \ 194 | if (data) { *data = val; } \ 195 | /* Turnaround */ \ 196 | for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ 197 | SW_CLOCK_CYCLE(); \ 198 | } \ 199 | PIN_SWDIO_OUT_ENABLE(); \ 200 | } else { \ 201 | /* Turnaround */ \ 202 | for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ 203 | SW_CLOCK_CYCLE(); \ 204 | } \ 205 | PIN_SWDIO_OUT_ENABLE(); \ 206 | /* Write data */ \ 207 | val = *data; \ 208 | parity = 0U; \ 209 | for (n = 32U; n; n--) { \ 210 | SW_WRITE_BIT(val); /* Write WDATA[0:31] */ \ 211 | parity += val; \ 212 | val >>= 1; \ 213 | } \ 214 | SW_WRITE_BIT(parity); /* Write Parity Bit */ \ 215 | } \ 216 | /* Capture Timestamp */ \ 217 | if (request & DAP_TRANSFER_TIMESTAMP) { \ 218 | DAP_Data.timestamp = TIMESTAMP_GET(); \ 219 | } \ 220 | /* Idle cycles */ \ 221 | n = DAP_Data.transfer.idle_cycles; \ 222 | if (n) { \ 223 | PIN_SWDIO_OUT(0U); \ 224 | for (; n; n--) { \ 225 | SW_CLOCK_CYCLE(); \ 226 | } \ 227 | } \ 228 | PIN_SWDIO_OUT(1U); \ 229 | return ((uint8_t)ack); \ 230 | } \ 231 | \ 232 | if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { \ 233 | /* WAIT or FAULT response */ \ 234 | if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) != 0U)) { \ 235 | for (n = 32U+1U; n; n--) { \ 236 | SW_CLOCK_CYCLE(); /* Dummy Read RDATA[0:31] + Parity */ \ 237 | } \ 238 | } \ 239 | /* Turnaround */ \ 240 | for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ 241 | SW_CLOCK_CYCLE(); \ 242 | } \ 243 | PIN_SWDIO_OUT_ENABLE(); \ 244 | if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) == 0U)) { \ 245 | PIN_SWDIO_OUT(0U); \ 246 | for (n = 32U+1U; n; n--) { \ 247 | SW_CLOCK_CYCLE(); /* Dummy Write WDATA[0:31] + Parity */ \ 248 | } \ 249 | } \ 250 | PIN_SWDIO_OUT(1U); \ 251 | return ((uint8_t)ack); \ 252 | } \ 253 | \ 254 | /* Protocol error */ \ 255 | for (n = DAP_Data.swd_conf.turnaround + 32U + 1U; n; n--) { \ 256 | SW_CLOCK_CYCLE(); /* Back off data phase */ \ 257 | } \ 258 | PIN_SWDIO_OUT_ENABLE(); \ 259 | PIN_SWDIO_OUT(1U); \ 260 | return ((uint8_t)ack); \ 261 | } 262 | 263 | 264 | #undef PIN_DELAY 265 | #define PIN_DELAY() PIN_DELAY_FAST() 266 | SWD_TransferFunction(Fast) 267 | 268 | #undef PIN_DELAY 269 | #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) 270 | SWD_TransferFunction(Slow) 271 | 272 | 273 | // SWD Transfer I/O 274 | // request: A[3:2] RnW APnDP 275 | // data: DATA[31:0] 276 | // return: ACK[2:0] 277 | uint8_t IRAM_ATTR SWD_Transfer(uint32_t request, uint32_t *data) { 278 | if (DAP_Data.fast_clock) { 279 | return SWD_TransferFast(request, data); 280 | } else { 281 | return SWD_TransferSlow(request, data); 282 | } 283 | } 284 | 285 | 286 | #endif /* (DAP_SWD != 0) */ 287 | -------------------------------------------------------------------------------- /interface/swd_host.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @file swd_host.c 3 | * @brief Implementation of swd_host.h 4 | * 5 | * DAPLink Interface Firmware 6 | * Copyright (c) 2009-2019, ARM Limited, All Rights Reserved 7 | * Copyright 2019, Cypress Semiconductor Corporation 8 | * or a subsidiary of Cypress Semiconductor Corporation. 9 | * SPDX-License-Identifier: Apache-2.0 10 | * 11 | * Licensed under the Apache License, Version 2.0 (the "License"); you may 12 | * not use this file except in compliance with the License. 13 | * You may obtain a copy of the License at 14 | * 15 | * http://www.apache.org/licenses/LICENSE-2.0 16 | * 17 | * Unless required by applicable law or agreed to in writing, software 18 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 19 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 | * See the License for the specific language governing permissions and 21 | * limitations under the License. 22 | */ 23 | 24 | #include 25 | #include 26 | 27 | #include "swd_host.h" 28 | #include "debug_cm.h" 29 | #include "DAP_config.h" 30 | #include "DAP.h" 31 | 32 | 33 | #include 34 | #define DAP_TAG "swd" 35 | 36 | 37 | // Probably not 1024 38 | #ifndef TARGET_AUTO_INCREMENT_PAGE_SIZE 39 | #define TARGET_AUTO_INCREMENT_PAGE_SIZE (1024) 40 | #endif 41 | 42 | // Default NVIC and Core debug base addresses 43 | // TODO: Read these addresses from ROM. 44 | #define NVIC_Addr (0xe000e000) 45 | #define DBG_Addr (0xe000edf0) 46 | 47 | // AP CSW register, base value 48 | #define CSW_VALUE (CSW_RESERVED | CSW_MSTRDBG | CSW_HPROT | CSW_DBGSTAT | CSW_SADDRINC) 49 | 50 | #define DCRDR 0xE000EDF8 51 | #define DCRSR 0xE000EDF4 52 | #define DHCSR 0xE000EDF0 53 | #define REGWnR (1 << 16) 54 | 55 | #define MAX_SWD_RETRY 100//10 56 | #define MAX_TIMEOUT UINT32_MAX // Timeout for syscalls on target 57 | 58 | // Use the CMSIS-Core definition if available. 59 | #if !defined(SCB_AIRCR_PRIGROUP_Pos) 60 | #define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */ 61 | #define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */ 62 | #endif 63 | 64 | typedef struct { 65 | uint32_t select; 66 | uint32_t csw; 67 | } DAP_STATE; 68 | 69 | typedef struct { 70 | uint32_t r[16]; 71 | uint32_t xpsr; 72 | } DEBUG_STATE; 73 | 74 | static SWD_CONNECT_TYPE reset_connect = CONNECT_NORMAL; 75 | 76 | static DAP_STATE dap_state; 77 | static uint32_t soft_reset = SYSRESETREQ; 78 | 79 | static uint32_t swd_get_apsel(uint32_t adr) 80 | { 81 | uint32_t apsel = 0; // target_get_apsel(); 82 | if (!apsel) 83 | return adr & 0xff000000; 84 | else 85 | return apsel; 86 | } 87 | 88 | void swd_set_reset_connect(SWD_CONNECT_TYPE type) 89 | { 90 | reset_connect = type; 91 | } 92 | 93 | void IRAM_ATTR int2array(uint8_t *res, uint32_t data, uint8_t len) 94 | { 95 | uint8_t i = 0; 96 | 97 | for (i = 0; i < len; i++) { 98 | res[i] = (data >> 8 * i) & 0xff; 99 | } 100 | } 101 | 102 | uint8_t IRAM_ATTR swd_transfer_retry(uint32_t req, uint32_t *data) 103 | { 104 | uint8_t i, ack; 105 | 106 | for (i = 0; i < MAX_SWD_RETRY; i++) { 107 | ack = SWD_Transfer(req, data); 108 | 109 | // if ack != WAIT 110 | if (ack != DAP_TRANSFER_WAIT) { 111 | return ack; 112 | } 113 | } 114 | 115 | return ack; 116 | } 117 | 118 | void swd_set_soft_reset(uint32_t soft_reset_type) 119 | { 120 | soft_reset = soft_reset_type; 121 | } 122 | 123 | uint8_t swd_init(void) 124 | { 125 | //TODO - DAP_Setup puts GPIO pins in a hi-z state which can 126 | // cause problems on re-init. This needs to be investigated 127 | // and fixed. 128 | DAP_Setup(); 129 | PORT_SWD_SETUP(); 130 | return 1; 131 | } 132 | 133 | uint8_t swd_off(void) 134 | { 135 | gpio_set_level(CONFIG_ESP_SWD_BOOT_PIN, 1); 136 | vTaskDelay(pdMS_TO_TICKS(20)); 137 | PIN_nRESET_OUT(0); 138 | vTaskDelay(pdMS_TO_TICKS(350)); 139 | PIN_nRESET_OUT(1); 140 | vTaskDelay(pdMS_TO_TICKS(100));; 141 | 142 | gpio_reset_pin(CONFIG_ESP_SWD_BOOT_PIN); 143 | gpio_reset_pin(PIN_SWCLK); 144 | gpio_reset_pin(PIN_SWDIO); 145 | gpio_reset_pin(PIN_nRST); 146 | 147 | return 1; 148 | } 149 | 150 | uint8_t IRAM_ATTR swd_clear_errors(void) 151 | { 152 | if (!swd_write_dp(DP_ABORT, STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR)) { 153 | return 0; 154 | } 155 | return 1; 156 | } 157 | 158 | // Read debug port register. 159 | uint8_t IRAM_ATTR swd_read_dp(uint8_t adr, uint32_t *val) 160 | { 161 | uint32_t tmp_in; 162 | uint8_t tmp_out[4]; 163 | uint8_t ack; 164 | uint32_t tmp; 165 | tmp_in = SWD_REG_DP | SWD_REG_R | SWD_REG_ADR(adr); 166 | ack = swd_transfer_retry(tmp_in, (uint32_t *)tmp_out); 167 | *val = 0; 168 | tmp = tmp_out[3]; 169 | *val |= (tmp << 24); 170 | tmp = tmp_out[2]; 171 | *val |= (tmp << 16); 172 | tmp = tmp_out[1]; 173 | *val |= (tmp << 8); 174 | tmp = tmp_out[0]; 175 | *val |= (tmp << 0); 176 | return (ack == 0x01); 177 | } 178 | 179 | // Write debug port register 180 | uint8_t IRAM_ATTR swd_write_dp(uint8_t adr, uint32_t val) 181 | { 182 | uint32_t req; 183 | uint8_t data[4]; 184 | uint8_t ack; 185 | 186 | //check if the right bank is already selected 187 | if ((adr == DP_SELECT) && (dap_state.select == val)) { 188 | return 1; 189 | } 190 | 191 | req = SWD_REG_DP | SWD_REG_W | SWD_REG_ADR(adr); 192 | int2array(data, val, 4); 193 | ack = swd_transfer_retry(req, (uint32_t *)data); 194 | if ((ack == DAP_TRANSFER_OK) && (adr == DP_SELECT)) { 195 | dap_state.select = val; 196 | } 197 | 198 | return (ack == 0x01); 199 | } 200 | 201 | // Read access port register. 202 | uint8_t IRAM_ATTR swd_read_ap(uint32_t adr, uint32_t *val) 203 | { 204 | uint8_t tmp_in, ack; 205 | uint8_t tmp_out[4]; 206 | uint32_t tmp; 207 | uint32_t apsel = swd_get_apsel(adr); 208 | uint32_t bank_sel = adr & APBANKSEL; 209 | 210 | if (!swd_write_dp(DP_SELECT, apsel | bank_sel)) { 211 | return 0; 212 | } 213 | 214 | tmp_in = SWD_REG_AP | SWD_REG_R | SWD_REG_ADR(adr); 215 | // first dummy read 216 | swd_transfer_retry(tmp_in, (uint32_t *)tmp_out); 217 | ack = swd_transfer_retry(tmp_in, (uint32_t *)tmp_out); 218 | *val = 0; 219 | tmp = tmp_out[3]; 220 | *val |= (tmp << 24); 221 | tmp = tmp_out[2]; 222 | *val |= (tmp << 16); 223 | tmp = tmp_out[1]; 224 | *val |= (tmp << 8); 225 | tmp = tmp_out[0]; 226 | *val |= (tmp << 0); 227 | return (ack == 0x01); 228 | } 229 | 230 | // Write access port register 231 | uint8_t IRAM_ATTR swd_write_ap(uint32_t adr, uint32_t val) 232 | { 233 | uint8_t data[4]; 234 | uint8_t req, ack; 235 | uint32_t apsel = swd_get_apsel(adr); 236 | uint32_t bank_sel = adr & APBANKSEL; 237 | 238 | if (!swd_write_dp(DP_SELECT, apsel | bank_sel)) { 239 | return 0; 240 | } 241 | 242 | switch (adr) { 243 | case AP_CSW: 244 | if (dap_state.csw == val) { 245 | return 1; 246 | } 247 | 248 | dap_state.csw = val; 249 | break; 250 | 251 | default: 252 | break; 253 | } 254 | 255 | req = SWD_REG_AP | SWD_REG_W | SWD_REG_ADR(adr); 256 | int2array(data, val, 4); 257 | 258 | if (swd_transfer_retry(req, (uint32_t *)data) != 0x01) { 259 | return 0; 260 | } 261 | 262 | req = SWD_REG_DP | SWD_REG_R | SWD_REG_ADR(DP_RDBUFF); 263 | ack = swd_transfer_retry(req, NULL); 264 | return (ack == 0x01); 265 | } 266 | 267 | 268 | // Write 32-bit word aligned values to target memory using address auto-increment. 269 | // size is in bytes. 270 | static IRAM_ATTR uint8_t swd_write_block(uint32_t address, uint8_t *data, uint32_t size) 271 | { 272 | uint8_t tmp_in[4], req; 273 | uint32_t size_in_words; 274 | uint32_t i, ack; 275 | 276 | if (size == 0) { 277 | return 0; 278 | } 279 | 280 | size_in_words = size / 4; 281 | 282 | // CSW register 283 | if (!swd_write_ap(AP_CSW, CSW_VALUE | CSW_SIZE32)) { 284 | return 0; 285 | } 286 | 287 | // TAR write 288 | req = SWD_REG_AP | SWD_REG_W | (1 << 2); 289 | int2array(tmp_in, address, 4); 290 | 291 | if (swd_transfer_retry(req, (uint32_t *)tmp_in) != 0x01) { 292 | return 0; 293 | } 294 | 295 | // DRW write 296 | req = SWD_REG_AP | SWD_REG_W | (3 << 2); 297 | 298 | for (i = 0; i < size_in_words; i++) { 299 | if (swd_transfer_retry(req, (uint32_t *)data) != 0x01) { 300 | return 0; 301 | } 302 | 303 | data += 4; 304 | } 305 | 306 | // dummy read 307 | req = SWD_REG_DP | SWD_REG_R | SWD_REG_ADR(DP_RDBUFF); 308 | ack = swd_transfer_retry(req, NULL); 309 | return (ack == 0x01); 310 | } 311 | 312 | // Read 32-bit word aligned values from target memory using address auto-increment. 313 | // size is in bytes. 314 | static uint8_t IRAM_ATTR swd_read_block(uint32_t address, uint8_t *data, uint32_t size) 315 | { 316 | uint8_t tmp_in[4], req, ack; 317 | uint32_t size_in_words; 318 | uint32_t i; 319 | 320 | if (size == 0) { 321 | return 0; 322 | } 323 | 324 | size_in_words = size / 4; 325 | 326 | if (!swd_write_ap(AP_CSW, CSW_VALUE | CSW_SIZE32)) { 327 | return 0; 328 | } 329 | 330 | // TAR write 331 | req = SWD_REG_AP | SWD_REG_W | AP_TAR; 332 | int2array(tmp_in, address, 4); 333 | 334 | if (swd_transfer_retry(req, (uint32_t *)tmp_in) != DAP_TRANSFER_OK) { 335 | return 0; 336 | } 337 | 338 | // read data 339 | req = SWD_REG_AP | SWD_REG_R | AP_DRW; 340 | 341 | // initiate first read, data comes back in next read 342 | if (swd_transfer_retry(req, NULL) != 0x01) { 343 | return 0; 344 | } 345 | 346 | for (i = 0; i < (size_in_words - 1); i++) { 347 | if (swd_transfer_retry(req, (uint32_t *)data) != DAP_TRANSFER_OK) { 348 | return 0; 349 | } 350 | 351 | data += 4; 352 | } 353 | 354 | // read last word 355 | req = SWD_REG_DP | SWD_REG_R | SWD_REG_ADR(DP_RDBUFF); 356 | ack = swd_transfer_retry(req, (uint32_t *)data); 357 | return (ack == 0x01); 358 | } 359 | 360 | // Read target memory. 361 | static uint8_t IRAM_ATTR swd_read_data(uint32_t addr, uint32_t *val) 362 | { 363 | uint8_t tmp_in[4]; 364 | uint8_t tmp_out[4]; 365 | uint8_t req, ack; 366 | uint32_t tmp; 367 | // put addr in TAR register 368 | int2array(tmp_in, addr, 4); 369 | req = SWD_REG_AP | SWD_REG_W | (1 << 2); 370 | 371 | if (swd_transfer_retry(req, (uint32_t *)tmp_in) != 0x01) { 372 | return 0; 373 | } 374 | 375 | // read data 376 | req = SWD_REG_AP | SWD_REG_R | (3 << 2); 377 | 378 | if (swd_transfer_retry(req, (uint32_t *)tmp_out) != 0x01) { 379 | return 0; 380 | } 381 | 382 | // dummy read 383 | req = SWD_REG_DP | SWD_REG_R | SWD_REG_ADR(DP_RDBUFF); 384 | ack = swd_transfer_retry(req, (uint32_t *)tmp_out); 385 | *val = 0; 386 | tmp = tmp_out[3]; 387 | *val |= (tmp << 24); 388 | tmp = tmp_out[2]; 389 | *val |= (tmp << 16); 390 | tmp = tmp_out[1]; 391 | *val |= (tmp << 8); 392 | tmp = tmp_out[0]; 393 | *val |= (tmp << 0); 394 | return (ack == 0x01); 395 | } 396 | 397 | // Write target memory. 398 | static uint8_t IRAM_ATTR swd_write_data(uint32_t address, uint32_t data) 399 | { 400 | uint8_t tmp_in[4]; 401 | uint8_t req, ack; 402 | // put addr in TAR register 403 | int2array(tmp_in, address, 4); 404 | req = SWD_REG_AP | SWD_REG_W | (1 << 2); 405 | 406 | if (swd_transfer_retry(req, (uint32_t *)tmp_in) != 0x01) { 407 | return 0; 408 | } 409 | 410 | // write data 411 | int2array(tmp_in, data, 4); 412 | req = SWD_REG_AP | SWD_REG_W | (3 << 2); 413 | 414 | if (swd_transfer_retry(req, (uint32_t *)tmp_in) != 0x01) { 415 | return 0; 416 | } 417 | 418 | // dummy read 419 | req = SWD_REG_DP | SWD_REG_R | SWD_REG_ADR(DP_RDBUFF); 420 | ack = swd_transfer_retry(req, NULL); 421 | return (ack == 0x01) ? 1 : 0; 422 | } 423 | 424 | // Read 32-bit word from target memory. 425 | uint8_t IRAM_ATTR swd_read_word(uint32_t addr, uint32_t *val) 426 | { 427 | if (!swd_write_ap(AP_CSW, CSW_VALUE | CSW_SIZE32)) { 428 | return 0; 429 | } 430 | 431 | if (!swd_read_data(addr, val)) { 432 | return 0; 433 | } 434 | 435 | return 1; 436 | } 437 | 438 | // Write 32-bit word to target memory. 439 | uint8_t IRAM_ATTR swd_write_word(uint32_t addr, uint32_t val) 440 | { 441 | if (!swd_write_ap(AP_CSW, CSW_VALUE | CSW_SIZE32)) { 442 | return 0; 443 | } 444 | 445 | if (!swd_write_data(addr, val)) { 446 | return 0; 447 | } 448 | 449 | return 1; 450 | } 451 | 452 | // Read 8-bit byte from target memory. 453 | uint8_t IRAM_ATTR swd_read_byte(uint32_t addr, uint8_t *val) 454 | { 455 | uint32_t tmp; 456 | 457 | if (!swd_write_ap(AP_CSW, CSW_VALUE | CSW_SIZE8)) { 458 | return 0; 459 | } 460 | 461 | if (!swd_read_data(addr, &tmp)) { 462 | return 0; 463 | } 464 | 465 | *val = (uint8_t)(tmp >> ((addr & 0x03) << 3)); 466 | return 1; 467 | } 468 | 469 | // Write 8-bit byte to target memory. 470 | uint8_t IRAM_ATTR swd_write_byte(uint32_t addr, uint8_t val) 471 | { 472 | uint32_t tmp; 473 | 474 | if (!swd_write_ap(AP_CSW, CSW_VALUE | CSW_SIZE8)) { 475 | return 0; 476 | } 477 | 478 | tmp = val << ((addr & 0x03) << 3); 479 | 480 | if (!swd_write_data(addr, tmp)) { 481 | return 0; 482 | } 483 | 484 | return 1; 485 | } 486 | 487 | // Read unaligned data from target memory. 488 | // size is in bytes. 489 | uint8_t IRAM_ATTR swd_read_memory(uint32_t address, uint8_t *data, uint32_t size) 490 | { 491 | uint32_t n; 492 | 493 | // Read bytes until word aligned 494 | while ((size > 0) && (address & 0x3)) { 495 | if (!swd_read_byte(address, data)) { 496 | return 0; 497 | } 498 | 499 | address++; 500 | data++; 501 | size--; 502 | } 503 | 504 | // Read word aligned blocks 505 | while (size > 3) { 506 | // Limit to auto increment page size 507 | n = TARGET_AUTO_INCREMENT_PAGE_SIZE - (address & (TARGET_AUTO_INCREMENT_PAGE_SIZE - 1)); 508 | 509 | if (size < n) { 510 | n = size & 0xFFFFFFFC; // Only count complete words remaining 511 | } 512 | 513 | if (!swd_read_block(address, data, n)) { 514 | return 0; 515 | } 516 | 517 | address += n; 518 | data += n; 519 | size -= n; 520 | } 521 | 522 | // Read remaining bytes 523 | while (size > 0) { 524 | if (!swd_read_byte(address, data)) { 525 | return 0; 526 | } 527 | 528 | address++; 529 | data++; 530 | size--; 531 | } 532 | 533 | return 1; 534 | } 535 | 536 | // Write unaligned data to target memory. 537 | // size is in bytes. 538 | uint8_t IRAM_ATTR swd_write_memory(uint32_t address, uint8_t *data, uint32_t size) 539 | { 540 | uint32_t n = 0; 541 | 542 | // Write bytes until word aligned 543 | while ((size > 0) && (address & 0x3)) { 544 | if (!swd_write_byte(address, *data)) { 545 | return 0; 546 | } 547 | 548 | address++; 549 | data++; 550 | size--; 551 | } 552 | 553 | // Write word aligned blocks 554 | while (size > 3) { 555 | // Limit to auto increment page size 556 | n = TARGET_AUTO_INCREMENT_PAGE_SIZE - (address & (TARGET_AUTO_INCREMENT_PAGE_SIZE - 1)); 557 | 558 | if (size < n) { 559 | n = size & 0xFFFFFFFC; // Only count complete words remaining 560 | } 561 | 562 | if (!swd_write_block(address, data, n)) { 563 | return 0; 564 | } 565 | 566 | address += n; 567 | data += n; 568 | size -= n; 569 | } 570 | 571 | // Write remaining bytes 572 | while (size > 0) { 573 | if (!swd_write_byte(address, *data)) { 574 | return 0; 575 | } 576 | 577 | address++; 578 | data++; 579 | size--; 580 | } 581 | 582 | return 1; 583 | } 584 | 585 | // Execute system call. 586 | static uint8_t IRAM_ATTR swd_write_debug_state(DEBUG_STATE *state) 587 | { 588 | uint32_t i, status; 589 | 590 | if (!swd_write_dp(DP_SELECT, 0)) { 591 | return 0; 592 | } 593 | 594 | // R0, R1, R2, R3 595 | for (i = 0; i < 4; i++) { 596 | if (!swd_write_core_register(i, state->r[i])) { 597 | ESP_LOGE(DAP_TAG, "Failed to set R0-3"); 598 | return 0; 599 | } 600 | } 601 | 602 | // R9 603 | if (!swd_write_core_register(9, state->r[9])) { 604 | ESP_LOGE(DAP_TAG, "Failed to set R9"); 605 | return 0; 606 | } 607 | 608 | // R13, R14, R15 609 | for (i = 13; i < 16; i++) { 610 | if (!swd_write_core_register(i, state->r[i])) { 611 | ESP_LOGE(DAP_TAG, "Failed to set R13-15"); 612 | return 0; 613 | } 614 | } 615 | 616 | // xPSR 617 | if (!swd_write_core_register(16, state->xpsr)) { 618 | ESP_LOGE(DAP_TAG, "Failed to set xPSR"); 619 | return 0; 620 | } 621 | 622 | if (!swd_write_word(DBG_HCSR, DBGKEY | C_DEBUGEN | C_MASKINTS | C_HALT)) { 623 | ESP_LOGE(DAP_TAG, "Failed to set halt"); 624 | return 0; 625 | } 626 | 627 | if (!swd_write_word(DBG_HCSR, DBGKEY | C_DEBUGEN | C_MASKINTS)) { 628 | ESP_LOGE(DAP_TAG, "Failed to set unhalt"); 629 | return 0; 630 | } 631 | 632 | // check status 633 | if (!swd_read_dp(DP_CTRL_STAT, &status)) { 634 | ESP_LOGE(DAP_TAG, "Failed to check status"); 635 | return 0; 636 | } 637 | 638 | if (status & (STICKYERR | WDATAERR)) { 639 | ESP_LOGE(DAP_TAG, "Status has error"); 640 | return 0; 641 | } 642 | 643 | return 1; 644 | } 645 | 646 | uint8_t IRAM_ATTR swd_read_core_register(uint32_t n, uint32_t *val) 647 | { 648 | int i = 0, timeout = 100; 649 | 650 | if (!swd_write_word(DCRSR, n)) { 651 | return 0; 652 | } 653 | 654 | // wait for S_REGRDY 655 | for (i = 0; i < timeout; i++) { 656 | if (!swd_read_word(DHCSR, val)) { 657 | return 0; 658 | } 659 | 660 | if (*val & S_REGRDY) { 661 | break; 662 | } 663 | } 664 | 665 | if (i == timeout) { 666 | ESP_LOGE(DAP_TAG, "Timeout"); 667 | return 0; 668 | } 669 | 670 | if (!swd_read_word(DCRDR, val)) { 671 | return 0; 672 | } 673 | 674 | return 1; 675 | } 676 | 677 | uint8_t IRAM_ATTR swd_write_core_register(uint32_t n, uint32_t val) 678 | { 679 | int i = 0, timeout = 100; 680 | 681 | if (!swd_write_word(DCRDR, val)) { 682 | return 0; 683 | } 684 | 685 | if (!swd_write_word(DCRSR, n | REGWnR)) { 686 | return 0; 687 | } 688 | 689 | // wait for S_REGRDY 690 | for (i = 0; i < timeout; i++) { 691 | if (!swd_read_word(DHCSR, &val)) { 692 | return 0; 693 | } 694 | 695 | if (val & S_REGRDY) { 696 | return 1; 697 | } 698 | } 699 | 700 | ESP_LOGE(DAP_TAG, "Core timeout"); 701 | return 0; 702 | } 703 | 704 | uint8_t IRAM_ATTR swd_wait_until_halted(void) 705 | { 706 | // Wait for target to stop 707 | uint32_t val, i, timeout = MAX_TIMEOUT; 708 | 709 | for (i = 0; i < timeout; i++) { 710 | vTaskDelay(1); 711 | if (!swd_read_word(DBG_HCSR, &val)) { 712 | return 0; 713 | } 714 | 715 | if (val & S_HALT) { 716 | return 1; 717 | } 718 | } 719 | 720 | return 0; 721 | } 722 | 723 | uint8_t IRAM_ATTR swd_flash_syscall_exec(const program_syscall_t *sys_call, uint32_t entry, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, flash_algo_return_t return_type, uint32_t *ret_out) 724 | { 725 | DEBUG_STATE state = {{0}, 0}; 726 | // Call flash algorithm function on target and wait for result. 727 | state.r[0] = arg1; // R0: Argument 1 728 | state.r[1] = arg2; // R1: Argument 2 729 | state.r[2] = arg3; // R2: Argument 3 730 | state.r[3] = arg4; // R3: Argument 4 731 | state.r[9] = sys_call->static_base; // SB: Static Base 732 | state.r[13] = sys_call->stack_pointer; // SP: Stack Pointer 733 | state.r[14] = sys_call->breakpoint; // LR: Exit Point 734 | state.r[15] = entry; // PC: Entry Point 735 | state.xpsr = 0x01000000; // xPSR: T = 1, ISR = 0 736 | 737 | if (!swd_write_debug_state(&state)) { 738 | ESP_LOGE(DAP_TAG, "Failed to set state"); 739 | return 0; 740 | } 741 | 742 | if (!swd_wait_until_halted()) { 743 | ESP_LOGE(DAP_TAG, "Failed to halt"); 744 | return 0; 745 | } 746 | 747 | if (!swd_read_core_register(0, &state.r[0])) { 748 | ESP_LOGE(DAP_TAG, "Failed to read register"); 749 | return 0; 750 | } 751 | 752 | //remove the C_MASKINTS 753 | if (!swd_write_word(DBG_HCSR, DBGKEY | C_DEBUGEN | C_HALT)) { 754 | ESP_LOGE(DAP_TAG, "Failed to halt again"); 755 | return 0; 756 | } 757 | 758 | if (return_type == FLASHALGO_RETURN_POINTER) { 759 | // Flash verify functions return pointer to byte following the buffer if successful. 760 | if (state.r[0] != (arg1 + arg2)) { 761 | return 0; 762 | } 763 | } else if (return_type == FLASHALGO_RETURN_VALUE) { 764 | if (ret_out != NULL) { 765 | *ret_out = state.r[0]; 766 | } 767 | } else { 768 | // ESP_LOGW(DAP_TAG, "R0 = %d", state.r[0]); 769 | // 770 | // uint32_t r1 = 0; 771 | // swd_read_core_register(1, &r1); 772 | // 773 | // uint32_t r2 = 0; 774 | // swd_read_core_register(2, &r2); 775 | // 776 | // uint32_t r15 = 0; 777 | // swd_read_core_register(15, &r15); 778 | // ESP_LOGW(DAP_TAG, "R1 = 0x%x, R2 = 0x%x, R15 (PC) = 0x%x", r1, r2, r15); 779 | 780 | if (state.r[0] != 0) { 781 | uint32_t r1 = 0; 782 | swd_read_core_register(1, &r1); 783 | 784 | uint32_t r2 = 0; 785 | swd_read_core_register(2, &r2); 786 | 787 | uint32_t r15 = 0; 788 | swd_read_core_register(15, &r15); 789 | ESP_LOGW(DAP_TAG, "R1 = 0x%lx, R2 = 0x%lx, R15 (PC) = 0x%lx", r1, r2, r15); 790 | 791 | return 0; 792 | } 793 | } 794 | 795 | return 1; 796 | } 797 | 798 | // SWD Reset 799 | static uint8_t IRAM_ATTR swd_reset(void) 800 | { 801 | uint8_t tmp_in[8]; 802 | uint8_t i = 0; 803 | 804 | for (i = 0; i < 8; i++) { 805 | tmp_in[i] = 0xff; 806 | } 807 | 808 | SWJ_Sequence(51, tmp_in); 809 | return 1; 810 | } 811 | 812 | // SWD Switch 813 | static uint8_t IRAM_ATTR swd_switch(uint16_t val) 814 | { 815 | uint8_t tmp_in[2]; 816 | tmp_in[0] = val & 0xff; 817 | tmp_in[1] = (val >> 8) & 0xff; 818 | SWJ_Sequence(16, tmp_in); 819 | return 1; 820 | } 821 | 822 | 823 | // SWD Read ID 824 | uint8_t IRAM_ATTR swd_read_idcode(uint32_t *id) 825 | { 826 | uint8_t tmp_in[1]; 827 | uint8_t tmp_out[4]; 828 | tmp_in[0] = 0x00; 829 | SWJ_Sequence(8, tmp_in); 830 | 831 | if (swd_read_dp(0, (uint32_t *)tmp_out) != 0x01) { 832 | return 0; 833 | } 834 | 835 | *id = (tmp_out[3] << 24) | (tmp_out[2] << 16) | (tmp_out[1] << 8) | tmp_out[0]; 836 | return 1; 837 | } 838 | 839 | 840 | uint8_t IRAM_ATTR JTAG2SWD() 841 | { 842 | uint32_t tmp = 0; 843 | 844 | if (!swd_reset()) { 845 | return 0; 846 | } 847 | 848 | if (!swd_switch(0xE79E)) { 849 | return 0; 850 | } 851 | 852 | if (!swd_reset()) { 853 | return 0; 854 | } 855 | 856 | if (!swd_read_idcode(&tmp)) { 857 | ESP_LOGE(DAP_TAG, "Set transit fail"); 858 | return 0; 859 | } 860 | 861 | return 1; 862 | } 863 | 864 | 865 | 866 | uint8_t swd_init_debug(void) 867 | { 868 | uint32_t tmp = 0; 869 | int i = 0; 870 | int timeout = 100; 871 | // init dap state with fake values 872 | dap_state.select = 0xffffffff; 873 | dap_state.csw = 0xffffffff; 874 | 875 | #if CONFIG_ESP_SWD_BOOT_PIN != -1 876 | gpio_config_t boot_pin_cfg = {}; 877 | boot_pin_cfg.intr_type = GPIO_INTR_DISABLE; 878 | boot_pin_cfg.mode = GPIO_MODE_OUTPUT; 879 | boot_pin_cfg.pull_down_en = GPIO_PULLDOWN_ENABLE; 880 | boot_pin_cfg.pull_up_en = GPIO_PULLUP_DISABLE; 881 | boot_pin_cfg.pin_bit_mask = (1 << CONFIG_ESP_SWD_BOOT_PIN); 882 | gpio_config(&boot_pin_cfg); 883 | 884 | ESP_LOGI(DAP_TAG, "Asserting BOOT0 pin"); 885 | gpio_set_level(CONFIG_ESP_SWD_BOOT_PIN, 1); 886 | vTaskDelay(pdMS_TO_TICKS(20)); 887 | #endif 888 | 889 | int8_t retries = 4; 890 | int8_t do_abort = 0; 891 | do { 892 | if (do_abort) { 893 | //do an abort on stale target, then reset the device 894 | swd_write_dp(DP_ABORT, DAPABORT); 895 | PIN_nRESET_OUT(0); 896 | vTaskDelay(pdMS_TO_TICKS(20)); 897 | PIN_nRESET_OUT(1); 898 | vTaskDelay(pdMS_TO_TICKS(20)); 899 | do_abort = 0; 900 | } 901 | swd_init(); 902 | 903 | if (!JTAG2SWD()) { 904 | ESP_LOGE(DAP_TAG, "JTAG2SWD fail"); 905 | do_abort = 1; 906 | continue; 907 | } 908 | 909 | if (!swd_clear_errors()) { 910 | ESP_LOGE(DAP_TAG, "Clear error fail"); 911 | do_abort = 1; 912 | continue; 913 | } 914 | 915 | if (!swd_write_dp(DP_SELECT, 0)) { 916 | ESP_LOGE(DAP_TAG, "SELECT DP fail"); 917 | do_abort = 1; 918 | continue; 919 | 920 | } 921 | 922 | // Power up 923 | if (!swd_write_dp(DP_CTRL_STAT, CSYSPWRUPREQ | CDBGPWRUPREQ)) { 924 | ESP_LOGE(DAP_TAG, "Power up fail"); 925 | do_abort = 1; 926 | continue; 927 | } 928 | 929 | for (i = 0; i < timeout; i++) { 930 | if (!swd_read_dp(DP_CTRL_STAT, &tmp)) { 931 | ESP_LOGE(DAP_TAG, "DP_CTRL_STAT fail"); 932 | do_abort = 1; 933 | break; 934 | } 935 | if ((tmp & (CDBGPWRUPACK | CSYSPWRUPACK)) == (CDBGPWRUPACK | CSYSPWRUPACK)) { 936 | // Break from loop if powerup is complete 937 | break; 938 | } 939 | } 940 | if ((i == timeout) || (do_abort == 1)) { 941 | // Unable to powerup DP 942 | ESP_LOGE(DAP_TAG, "Unable to powerup DP"); 943 | do_abort = 1; 944 | continue; 945 | } 946 | 947 | if (!swd_write_dp(DP_CTRL_STAT, CSYSPWRUPREQ | CDBGPWRUPREQ | TRNNORMAL | MASKLANE)) { 948 | ESP_LOGE(DAP_TAG, "Set transit fail"); 949 | do_abort = 1; 950 | continue; 951 | } 952 | 953 | if (!swd_write_dp(DP_SELECT, 0)) { 954 | ESP_LOGE(DAP_TAG, "Unselect DP fail"); 955 | do_abort = 1; 956 | continue; 957 | } 958 | 959 | return 1; 960 | 961 | } while (--retries > 0); 962 | 963 | return 0; 964 | } 965 | 966 | uint8_t IRAM_ATTR swd_halt_target() 967 | { 968 | if (!swd_write_word(DBG_HCSR, DBGKEY | C_DEBUGEN | C_HALT)) { 969 | return 0; 970 | } 971 | 972 | return 1; 973 | } 974 | 975 | void swd_trigger_nrst() 976 | { 977 | gpio_set_level(CONFIG_ESP_SWD_BOOT_PIN, 0); 978 | vTaskDelay(pdMS_TO_TICKS(20)); 979 | PIN_nRESET_OUT(0); 980 | vTaskDelay(pdMS_TO_TICKS(350)); 981 | PIN_nRESET_OUT(1); 982 | vTaskDelay(pdMS_TO_TICKS(100)); 983 | } 984 | 985 | uint8_t swd_flash_syscall_exec_async(const program_syscall_t *sys_call, uint32_t entry, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4) 986 | { 987 | DEBUG_STATE state = {{0}, 0}; 988 | // Call flash algorithm function on target and wait for result. 989 | state.r[0] = arg1; // R0: Argument 1 990 | state.r[1] = arg2; // R1: Argument 2 991 | state.r[2] = arg3; // R2: Argument 3 992 | state.r[3] = arg4; // R3: Argument 4 993 | state.r[9] = sys_call->static_base; // SB: Static Base 994 | state.r[13] = sys_call->stack_pointer; // SP: Stack Pointer 995 | state.r[14] = sys_call->breakpoint; // LR: Exit Point 996 | state.r[15] = entry; // PC: Entry Point 997 | state.xpsr = 0x01000000; // xPSR: T = 1, ISR = 0 998 | 999 | if (!swd_write_debug_state(&state)) { 1000 | ESP_LOGE(DAP_TAG, "Failed to set state"); 1001 | return 0; 1002 | } 1003 | 1004 | return 1; 1005 | } 1006 | 1007 | uint8_t swd_flash_syscall_wait_result(flash_algo_return_t return_type, uint32_t *ret_out) 1008 | { 1009 | DEBUG_STATE state = {{0}, 0}; 1010 | if (!swd_wait_until_halted()) { 1011 | ESP_LOGE(DAP_TAG, "Failed to halt"); 1012 | return 0; 1013 | } 1014 | 1015 | if (!swd_read_core_register(0, &state.r[0])) { 1016 | ESP_LOGE(DAP_TAG, "Failed to read register"); 1017 | return 0; 1018 | } 1019 | 1020 | //remove the C_MASKINTS 1021 | if (!swd_write_word(DBG_HCSR, DBGKEY | C_DEBUGEN | C_HALT)) { 1022 | ESP_LOGE(DAP_TAG, "Failed to halt again"); 1023 | return 0; 1024 | } 1025 | 1026 | if (return_type == FLASHALGO_RETURN_POINTER) { 1027 | // Flash verify functions return pointer to byte following the buffer if successful. 1028 | ESP_LOGE(DAP_TAG, "Async exec doesn't support POINTER return type"); 1029 | return 0; 1030 | } else if (return_type == FLASHALGO_RETURN_VALUE) { 1031 | if (ret_out != NULL) { 1032 | *ret_out = state.r[0]; 1033 | } 1034 | } else { 1035 | if (state.r[0] != 0) { 1036 | uint32_t r1 = 0; 1037 | swd_read_core_register(1, &r1); 1038 | 1039 | uint32_t r2 = 0; 1040 | swd_read_core_register(2, &r2); 1041 | 1042 | uint32_t r15 = 0; 1043 | swd_read_core_register(15, &r15); 1044 | ESP_LOGW(DAP_TAG, "R1 = 0x%lx, R2 = 0x%lx, R15 (PC) = 0x%lx", r1, r2, r15); 1045 | 1046 | return 0; 1047 | } 1048 | } 1049 | 1050 | return 1; 1051 | } 1052 | 1053 | -------------------------------------------------------------------------------- /cmsis_dap/DAP.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013-2020 ARM Limited. All rights reserved. 3 | * Copyright 2019, Cypress Semiconductor Corporation 4 | * or a subsidiary of Cypress Semiconductor Corporation. 5 | * 6 | * SPDX-License-Identifier: Apache-2.0 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the License); you may 9 | * not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an AS IS BASIS, WITHOUT 16 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | * ---------------------------------------------------------------------- 21 | * 22 | * $Date: 1. December 2017 23 | * $Revision: V2.0.0 24 | * 25 | * Project: CMSIS-DAP Source 26 | * Title: DAP.c CMSIS-DAP Commands 27 | * 28 | *---------------------------------------------------------------------------*/ 29 | 30 | #include 31 | #include "DAP_config.h" 32 | #include "DAP.h" 33 | #include "dap_strings.h" 34 | 35 | 36 | #if (DAP_PACKET_SIZE < 64U) 37 | #error "Minimum Packet Size is 64!" 38 | #endif 39 | #if (DAP_PACKET_SIZE > 32768U) 40 | #error "Maximum Packet Size is 32768!" 41 | #endif 42 | #if (DAP_PACKET_COUNT < 1U) 43 | #error "Minimum Packet Count is 1!" 44 | #endif 45 | #if (DAP_PACKET_COUNT > 255U) 46 | #error "Maximum Packet Count is 255!" 47 | #endif 48 | 49 | 50 | // Clock Macros 51 | 52 | #define MAX_SWJ_CLOCK(delay_cycles) \ 53 | ((CPU_CLOCK/2U) / (IO_PORT_WRITE_CYCLES + delay_cycles)) 54 | 55 | #define CLOCK_DELAY(swj_clock) \ 56 | (((CPU_CLOCK/2U) / swj_clock) - IO_PORT_WRITE_CYCLES) 57 | 58 | 59 | DAP_Data_t DAP_Data; // DAP Data 60 | volatile uint8_t DAP_TransferAbort; // Transfer Abort Flag 61 | 62 | 63 | static const char DAP_FW_Ver [] = DAP_FW_VER; 64 | 65 | #if TARGET_DEVICE_FIXED 66 | static const char TargetDeviceVendor [] = TARGET_DEVICE_VENDOR; 67 | static const char TargetDeviceName [] = TARGET_DEVICE_NAME; 68 | #endif 69 | 70 | 71 | // Get DAP Information 72 | // id: info identifier 73 | // info: pointer to info data 74 | // return: number of bytes in info data 75 | static uint8_t DAP_Info(uint8_t id, uint8_t *info) { 76 | uint8_t length = 0U; 77 | 78 | switch (id) { 79 | case DAP_ID_VENDOR: 80 | length = DAP_GetVendorString((char *)info); 81 | break; 82 | case DAP_ID_PRODUCT: 83 | length = DAP_GetProductString((char *)info); 84 | break; 85 | case DAP_ID_SER_NUM: 86 | length = DAP_GetSerNumString((char *)info); 87 | break; 88 | case DAP_ID_CMSIS_DAP_VER: 89 | length = (uint8_t)sizeof(DAP_FW_Ver); 90 | memcpy(info, DAP_FW_Ver, length); 91 | break; 92 | case DAP_ID_DEVICE_VENDOR: 93 | #if TARGET_DEVICE_FIXED 94 | length = (uint8_t)sizeof(TargetDeviceVendor); 95 | memcpy(info, TargetDeviceVendor, length); 96 | #endif 97 | break; 98 | case DAP_ID_DEVICE_NAME: 99 | #if TARGET_DEVICE_FIXED 100 | length = (uint8_t)sizeof(TargetDeviceName); 101 | memcpy(info, TargetDeviceName, length); 102 | #endif 103 | break; 104 | case DAP_ID_PRODUCT_FW_VER: 105 | length = DAP_ProductFirmwareVerString((char *)info); 106 | break; 107 | case DAP_ID_CAPABILITIES: 108 | info[0] = ((DAP_SWD != 0) ? (1U << 0) : 0U) | 109 | ((DAP_JTAG != 0) ? (1U << 1) : 0U) | 110 | ((SWO_UART != 0) ? (1U << 2) : 0U) | 111 | ((SWO_MANCHESTER != 0) ? (1U << 3) : 0U) | 112 | /* Atomic Commands */ (1U << 4) | 113 | ((TIMESTAMP_CLOCK != 0U) ? (1U << 5) : 0U) | 114 | ((SWO_STREAM != 0U) ? (1U << 6) : 0U); 115 | length = 1U; 116 | break; 117 | case DAP_ID_TIMESTAMP_CLOCK: 118 | #if (TIMESTAMP_CLOCK != 0U) 119 | info[0] = (uint8_t)(TIMESTAMP_CLOCK >> 0); 120 | info[1] = (uint8_t)(TIMESTAMP_CLOCK >> 8); 121 | info[2] = (uint8_t)(TIMESTAMP_CLOCK >> 16); 122 | info[3] = (uint8_t)(TIMESTAMP_CLOCK >> 24); 123 | length = 4U; 124 | #endif 125 | break; 126 | case DAP_ID_SWO_BUFFER_SIZE: 127 | #if ((SWO_UART != 0) || (SWO_MANCHESTER != 0)) 128 | info[0] = (uint8_t)(SWO_BUFFER_SIZE >> 0); 129 | info[1] = (uint8_t)(SWO_BUFFER_SIZE >> 8); 130 | info[2] = (uint8_t)(SWO_BUFFER_SIZE >> 16); 131 | info[3] = (uint8_t)(SWO_BUFFER_SIZE >> 24); 132 | length = 4U; 133 | #endif 134 | break; 135 | case DAP_ID_PACKET_SIZE: 136 | info[0] = (uint8_t)(DAP_PACKET_SIZE >> 0); 137 | info[1] = (uint8_t)(DAP_PACKET_SIZE >> 8); 138 | length = 2U; 139 | break; 140 | case DAP_ID_PACKET_COUNT: 141 | info[0] = DAP_PACKET_COUNT; 142 | length = 1U; 143 | break; 144 | default: 145 | break; 146 | } 147 | 148 | return (length); 149 | } 150 | 151 | 152 | // Delay for specified time 153 | // delay: delay time in ms 154 | void Delayms(uint32_t delay) { 155 | delay *= ((CPU_CLOCK/1000U) + (DELAY_SLOW_CYCLES-1U)) / DELAY_SLOW_CYCLES; 156 | PIN_DELAY_SLOW(delay); 157 | } 158 | 159 | 160 | // Process Delay command and prepare response 161 | // request: pointer to request data 162 | // response: pointer to response data 163 | // return: number of bytes in response (lower 16 bits) 164 | // number of bytes in request (upper 16 bits) 165 | static uint32_t DAP_Delay(const uint8_t *request, uint8_t *response) { 166 | uint32_t delay; 167 | 168 | delay = (uint32_t)(*(request+0)) | 169 | (uint32_t)(*(request+1) << 8); 170 | delay *= ((CPU_CLOCK/1000000U) + (DELAY_SLOW_CYCLES-1U)) / DELAY_SLOW_CYCLES; 171 | 172 | PIN_DELAY_SLOW(delay); 173 | 174 | *response = DAP_OK; 175 | return ((2U << 16) | 1U); 176 | } 177 | 178 | 179 | // Process Host Status command and prepare response 180 | // request: pointer to request data 181 | // response: pointer to response data 182 | // return: number of bytes in response (lower 16 bits) 183 | // number of bytes in request (upper 16 bits) 184 | static uint32_t DAP_HostStatus(const uint8_t *request, uint8_t *response) { 185 | 186 | switch (*request) { 187 | case DAP_DEBUGGER_CONNECTED: 188 | LED_CONNECTED_OUT((*(request+1) & 1U)); 189 | break; 190 | case DAP_TARGET_RUNNING: 191 | LED_RUNNING_OUT((*(request+1) & 1U)); 192 | break; 193 | default: 194 | *response = DAP_ERROR; 195 | return ((2U << 16) | 1U); 196 | } 197 | 198 | *response = DAP_OK; 199 | return ((2U << 16) | 1U); 200 | } 201 | 202 | 203 | // Process Connect command and prepare response 204 | // request: pointer to request data 205 | // response: pointer to response data 206 | // return: number of bytes in response (lower 16 bits) 207 | // number of bytes in request (upper 16 bits) 208 | static uint32_t DAP_Connect(const uint8_t *request, uint8_t *response) { 209 | uint32_t port; 210 | 211 | if (*request == DAP_PORT_AUTODETECT) { 212 | port = DAP_DEFAULT_PORT; 213 | } else { 214 | port = *request; 215 | } 216 | 217 | switch (port) { 218 | #if (DAP_SWD != 0) 219 | case DAP_PORT_SWD: 220 | DAP_Data.debug_port = DAP_PORT_SWD; 221 | PORT_SWD_SETUP(); 222 | break; 223 | #endif 224 | #if (DAP_JTAG != 0) 225 | case DAP_PORT_JTAG: 226 | DAP_Data.debug_port = DAP_PORT_JTAG; 227 | PORT_JTAG_SETUP(); 228 | break; 229 | #endif 230 | default: 231 | port = DAP_PORT_DISABLED; 232 | break; 233 | } 234 | 235 | *response = (uint8_t)port; 236 | return ((1U << 16) | 1U); 237 | } 238 | 239 | 240 | // Process Disconnect command and prepare response 241 | // response: pointer to response data 242 | // return: number of bytes in response 243 | static uint32_t DAP_Disconnect(uint8_t *response) { 244 | 245 | DAP_Data.debug_port = DAP_PORT_DISABLED; 246 | PORT_OFF(); 247 | 248 | *response = DAP_OK; 249 | return (1U); 250 | } 251 | 252 | 253 | // Process Reset Target command and prepare response 254 | // response: pointer to response data 255 | // return: number of bytes in response 256 | static uint32_t DAP_ResetTarget(uint8_t *response) { 257 | 258 | *(response+1) = RESET_TARGET(); 259 | *(response+0) = DAP_OK; 260 | return (2U); 261 | } 262 | 263 | 264 | // Process SWJ Pins command and prepare response 265 | // request: pointer to request data 266 | // response: pointer to response data 267 | // return: number of bytes in response (lower 16 bits) 268 | // number of bytes in request (upper 16 bits) 269 | static uint32_t DAP_SWJ_Pins(const uint8_t *request, uint8_t *response) { 270 | #if ((DAP_SWD != 0) || (DAP_JTAG != 0)) 271 | uint32_t value; 272 | uint32_t select; 273 | uint32_t wait; 274 | uint32_t timestamp; 275 | 276 | value = (uint32_t) *(request+0); 277 | select = (uint32_t) *(request+1); 278 | wait = (uint32_t)(*(request+2) << 0) | 279 | (uint32_t)(*(request+3) << 8) | 280 | (uint32_t)(*(request+4) << 16) | 281 | (uint32_t)(*(request+5) << 24); 282 | 283 | if ((select & (1U << DAP_SWJ_SWCLK_TCK)) != 0U) { 284 | if ((value & (1U << DAP_SWJ_SWCLK_TCK)) != 0U) { 285 | PIN_SWCLK_TCK_SET(); 286 | } else { 287 | PIN_SWCLK_TCK_CLR(); 288 | } 289 | } 290 | if ((select & (1U << DAP_SWJ_SWDIO_TMS)) != 0U) { 291 | if ((value & (1U << DAP_SWJ_SWDIO_TMS)) != 0U) { 292 | PIN_SWDIO_TMS_SET(); 293 | } else { 294 | PIN_SWDIO_TMS_CLR(); 295 | } 296 | } 297 | if ((select & (1U << DAP_SWJ_TDI)) != 0U) { 298 | PIN_TDI_OUT(value >> DAP_SWJ_TDI); 299 | } 300 | if ((select & (1U << DAP_SWJ_nTRST)) != 0U) { 301 | PIN_nTRST_OUT(value >> DAP_SWJ_nTRST); 302 | } 303 | if ((select & (1U << DAP_SWJ_nRESET)) != 0U){ 304 | PIN_nRESET_OUT(value >> DAP_SWJ_nRESET); 305 | } 306 | 307 | if (wait != 0U) { 308 | #if (TIMESTAMP_CLOCK != 0U) 309 | if (wait > 3000000U) { 310 | wait = 3000000U; 311 | } 312 | #if (TIMESTAMP_CLOCK >= 1000000U) 313 | wait *= TIMESTAMP_CLOCK / 1000000U; 314 | #else 315 | wait /= 1000000U / TIMESTAMP_CLOCK; 316 | #endif 317 | #else 318 | wait = 1U; 319 | #endif 320 | timestamp = TIMESTAMP_GET(); 321 | do { 322 | if ((select & (1U << DAP_SWJ_SWCLK_TCK)) != 0U) { 323 | if ((value >> DAP_SWJ_SWCLK_TCK) ^ PIN_SWCLK_TCK_IN()) { 324 | continue; 325 | } 326 | } 327 | if ((select & (1U << DAP_SWJ_SWDIO_TMS)) != 0U) { 328 | if ((value >> DAP_SWJ_SWDIO_TMS) ^ PIN_SWDIO_TMS_IN()) { 329 | continue; 330 | } 331 | } 332 | if ((select & (1U << DAP_SWJ_TDI)) != 0U) { 333 | if ((value >> DAP_SWJ_TDI) ^ PIN_TDI_IN()) { 334 | continue; 335 | } 336 | } 337 | if ((select & (1U << DAP_SWJ_nTRST)) != 0U) { 338 | if ((value >> DAP_SWJ_nTRST) ^ PIN_nTRST_IN()) { 339 | continue; 340 | } 341 | } 342 | if ((select & (1U << DAP_SWJ_nRESET)) != 0U) { 343 | if ((value >> DAP_SWJ_nRESET) ^ PIN_nRESET_IN()) { 344 | continue; 345 | } 346 | } 347 | break; 348 | } while ((TIMESTAMP_GET() - timestamp) < wait); 349 | } 350 | 351 | value = (PIN_SWCLK_TCK_IN() << DAP_SWJ_SWCLK_TCK) | 352 | (PIN_SWDIO_TMS_IN() << DAP_SWJ_SWDIO_TMS) | 353 | (PIN_TDI_IN() << DAP_SWJ_TDI) | 354 | (PIN_TDO_IN() << DAP_SWJ_TDO) | 355 | (PIN_nTRST_IN() << DAP_SWJ_nTRST) | 356 | (PIN_nRESET_IN() << DAP_SWJ_nRESET); 357 | 358 | *response = (uint8_t)value; 359 | #else 360 | *response = 0U; 361 | #endif 362 | 363 | return ((6U << 16) | 1U); 364 | } 365 | 366 | 367 | // Process SWJ Clock command and prepare response 368 | // request: pointer to request data 369 | // response: pointer to response data 370 | // return: number of bytes in response (lower 16 bits) 371 | // number of bytes in request (upper 16 bits) 372 | static uint32_t DAP_SWJ_Clock(const uint8_t *request, uint8_t *response) { 373 | #if ((DAP_SWD != 0) || (DAP_JTAG != 0)) 374 | uint32_t clock; 375 | uint32_t delay; 376 | 377 | clock = (uint32_t)(*(request+0) << 0) | 378 | (uint32_t)(*(request+1) << 8) | 379 | (uint32_t)(*(request+2) << 16) | 380 | (uint32_t)(*(request+3) << 24); 381 | 382 | if (clock == 0U) { 383 | *response = DAP_ERROR; 384 | return ((4U << 16) | 1U); 385 | } 386 | 387 | if (clock >= MAX_SWJ_CLOCK(DELAY_FAST_CYCLES)) { 388 | DAP_Data.fast_clock = 1U; 389 | DAP_Data.clock_delay = 1U; 390 | } else { 391 | DAP_Data.fast_clock = 0U; 392 | 393 | delay = ((CPU_CLOCK/2U) + (clock - 1U)) / clock; 394 | if (delay > IO_PORT_WRITE_CYCLES) { 395 | delay -= IO_PORT_WRITE_CYCLES; 396 | delay = (delay + (DELAY_SLOW_CYCLES - 1U)) / DELAY_SLOW_CYCLES; 397 | } else { 398 | delay = 1U; 399 | } 400 | 401 | DAP_Data.clock_delay = delay; 402 | } 403 | 404 | *response = DAP_OK; 405 | #else 406 | *response = DAP_ERROR; 407 | #endif 408 | 409 | return ((4U << 16) | 1U); 410 | } 411 | 412 | 413 | // Process SWJ Sequence command and prepare response 414 | // request: pointer to request data 415 | // response: pointer to response data 416 | // return: number of bytes in response (lower 16 bits) 417 | // number of bytes in request (upper 16 bits) 418 | static uint32_t DAP_SWJ_Sequence(const uint8_t *request, uint8_t *response) { 419 | uint32_t count; 420 | 421 | count = *request++; 422 | if (count == 0U) { 423 | count = 256U; 424 | } 425 | 426 | #if ((DAP_SWD != 0) || (DAP_JTAG != 0)) 427 | SWJ_Sequence(count, request); 428 | *response = DAP_OK; 429 | #else 430 | *response = DAP_ERROR; 431 | #endif 432 | 433 | count = (count + 7U) >> 3; 434 | 435 | return (((count + 1U) << 16) | 1U); 436 | } 437 | 438 | 439 | // Process SWD Configure command and prepare response 440 | // request: pointer to request data 441 | // response: pointer to response data 442 | // return: number of bytes in response (lower 16 bits) 443 | // number of bytes in request (upper 16 bits) 444 | static uint32_t DAP_SWD_Configure(const uint8_t *request, uint8_t *response) { 445 | #if (DAP_SWD != 0) 446 | uint8_t value; 447 | 448 | value = *request; 449 | DAP_Data.swd_conf.turnaround = (value & 0x03U) + 1U; 450 | DAP_Data.swd_conf.data_phase = (value & 0x04U) ? 1U : 0U; 451 | 452 | *response = DAP_OK; 453 | #else 454 | *response = DAP_ERROR; 455 | #endif 456 | 457 | return ((1U << 16) | 1U); 458 | } 459 | 460 | 461 | // Process SWD Sequence command and prepare response 462 | // request: pointer to request data 463 | // response: pointer to response data 464 | // return: number of bytes in response (lower 16 bits) 465 | // number of bytes in request (upper 16 bits) 466 | static uint32_t DAP_SWD_Sequence(const uint8_t *request, uint8_t *response) { 467 | uint32_t sequence_info; 468 | uint32_t sequence_count; 469 | uint32_t request_count; 470 | uint32_t response_count; 471 | uint32_t count; 472 | 473 | #if (DAP_SWD != 0) 474 | *response++ = DAP_OK; 475 | #else 476 | *response++ = DAP_ERROR; 477 | #endif 478 | request_count = 1U; 479 | response_count = 1U; 480 | 481 | sequence_count = *request++; 482 | while (sequence_count--) { 483 | sequence_info = *request++; 484 | count = sequence_info & SWD_SEQUENCE_CLK; 485 | if (count == 0U) { 486 | count = 64U; 487 | } 488 | count = (count + 7U) / 8U; 489 | #if (DAP_SWD != 0) 490 | if ((sequence_info & SWD_SEQUENCE_DIN) != 0U) { 491 | PIN_SWDIO_OUT_DISABLE(); 492 | } else { 493 | PIN_SWDIO_OUT_ENABLE(); 494 | } 495 | SWD_Sequence(sequence_info, request, response); 496 | if (sequence_count == 0U) { 497 | PIN_SWDIO_OUT_ENABLE(); 498 | } 499 | #endif 500 | if ((sequence_info & SWD_SEQUENCE_DIN) != 0U) { 501 | request_count++; 502 | #if (DAP_SWD != 0) 503 | response += count; 504 | response_count += count; 505 | #endif 506 | } else { 507 | request += count; 508 | request_count += count + 1U; 509 | } 510 | } 511 | 512 | return ((request_count << 16) | response_count); 513 | } 514 | 515 | 516 | // Process JTAG Sequence command and prepare response 517 | // request: pointer to request data 518 | // response: pointer to response data 519 | // return: number of bytes in response (lower 16 bits) 520 | // number of bytes in request (upper 16 bits) 521 | static uint32_t DAP_JTAG_Sequence(const uint8_t *request, uint8_t *response) { 522 | uint32_t sequence_info; 523 | uint32_t sequence_count; 524 | uint32_t request_count; 525 | uint32_t response_count; 526 | uint32_t count; 527 | 528 | #if (DAP_JTAG != 0) 529 | *response++ = DAP_OK; 530 | #else 531 | *response++ = DAP_ERROR; 532 | #endif 533 | request_count = 1U; 534 | response_count = 1U; 535 | 536 | sequence_count = *request++; 537 | while (sequence_count--) { 538 | sequence_info = *request++; 539 | count = sequence_info & JTAG_SEQUENCE_TCK; 540 | if (count == 0U) { 541 | count = 64U; 542 | } 543 | count = (count + 7U) / 8U; 544 | #if (DAP_JTAG != 0) 545 | JTAG_Sequence(sequence_info, request, response); 546 | #endif 547 | request += count; 548 | request_count += count + 1U; 549 | #if (DAP_JTAG != 0) 550 | if ((sequence_info & JTAG_SEQUENCE_TDO) != 0U) { 551 | response += count; 552 | response_count += count; 553 | } 554 | #endif 555 | } 556 | 557 | return ((request_count << 16) | response_count); 558 | } 559 | 560 | 561 | // Process JTAG Configure command and prepare response 562 | // request: pointer to request data 563 | // response: pointer to response data 564 | // return: number of bytes in response (lower 16 bits) 565 | // number of bytes in request (upper 16 bits) 566 | static uint32_t DAP_JTAG_Configure(const uint8_t *request, uint8_t *response) { 567 | uint32_t count; 568 | #if (DAP_JTAG != 0) 569 | uint32_t length; 570 | uint32_t bits; 571 | uint32_t n; 572 | 573 | count = *request++; 574 | DAP_Data.jtag_dev.count = (uint8_t)count; 575 | 576 | bits = 0U; 577 | for (n = 0U; n < count; n++) { 578 | length = *request++; 579 | DAP_Data.jtag_dev.ir_length[n] = (uint8_t)length; 580 | DAP_Data.jtag_dev.ir_before[n] = (uint16_t)bits; 581 | bits += length; 582 | } 583 | for (n = 0U; n < count; n++) { 584 | bits -= DAP_Data.jtag_dev.ir_length[n]; 585 | DAP_Data.jtag_dev.ir_after[n] = (uint16_t)bits; 586 | } 587 | 588 | *response = DAP_OK; 589 | #else 590 | count = *request; 591 | *response = DAP_ERROR; 592 | #endif 593 | 594 | return (((count + 1U) << 16) | 1U); 595 | } 596 | 597 | 598 | // Process JTAG IDCODE command and prepare response 599 | // request: pointer to request data 600 | // response: pointer to response data 601 | // return: number of bytes in response (lower 16 bits) 602 | // number of bytes in request (upper 16 bits) 603 | static uint32_t DAP_JTAG_IDCode(const uint8_t *request, uint8_t *response) { 604 | #if (DAP_JTAG != 0) 605 | uint32_t data; 606 | 607 | if (DAP_Data.debug_port != DAP_PORT_JTAG) { 608 | goto id_error; 609 | } 610 | 611 | // Device index (JTAP TAP) 612 | DAP_Data.jtag_dev.index = *request; 613 | if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) { 614 | goto id_error; 615 | } 616 | 617 | // Select JTAG chain 618 | JTAG_IR(JTAG_IDCODE); 619 | 620 | // Read IDCODE register 621 | data = JTAG_ReadIDCode(); 622 | 623 | // Store Data 624 | *(response+0) = DAP_OK; 625 | *(response+1) = (uint8_t)(data >> 0); 626 | *(response+2) = (uint8_t)(data >> 8); 627 | *(response+3) = (uint8_t)(data >> 16); 628 | *(response+4) = (uint8_t)(data >> 24); 629 | 630 | return ((1U << 16) | 5U); 631 | 632 | id_error: 633 | #endif 634 | *response = DAP_ERROR; 635 | return ((1U << 16) | 1U); 636 | } 637 | 638 | 639 | // Process Transfer Configure command and prepare response 640 | // request: pointer to request data 641 | // response: pointer to response data 642 | // return: number of bytes in response (lower 16 bits) 643 | // number of bytes in request (upper 16 bits) 644 | static uint32_t DAP_TransferConfigure(const uint8_t *request, uint8_t *response) { 645 | 646 | DAP_Data.transfer.idle_cycles = *(request+0); 647 | DAP_Data.transfer.retry_count = (uint16_t) *(request+1) | 648 | (uint16_t)(*(request+2) << 8); 649 | DAP_Data.transfer.match_retry = (uint16_t) *(request+3) | 650 | (uint16_t)(*(request+4) << 8); 651 | 652 | *response = DAP_OK; 653 | return ((5U << 16) | 1U); 654 | } 655 | 656 | 657 | // Process SWD Transfer command and prepare response 658 | // request: pointer to request data 659 | // response: pointer to response data 660 | // return: number of bytes in response (lower 16 bits) 661 | // number of bytes in request (upper 16 bits) 662 | #if (DAP_SWD != 0) 663 | static uint32_t DAP_SWD_Transfer(const uint8_t *request, uint8_t *response) { 664 | const 665 | uint8_t *request_head; 666 | uint32_t request_count; 667 | uint32_t request_value; 668 | uint8_t *response_head; 669 | uint32_t response_count; 670 | uint32_t response_value; 671 | uint32_t post_read; 672 | uint32_t check_write; 673 | uint32_t match_value; 674 | uint32_t match_retry; 675 | uint32_t retry; 676 | uint32_t data; 677 | #if (TIMESTAMP_CLOCK != 0U) 678 | uint32_t timestamp; 679 | #endif 680 | 681 | request_head = request; 682 | 683 | response_count = 0U; 684 | response_value = 0U; 685 | response_head = response; 686 | response += 2; 687 | 688 | DAP_TransferAbort = 0U; 689 | 690 | post_read = 0U; 691 | check_write = 0U; 692 | 693 | request++; // Ignore DAP index 694 | 695 | request_count = *request++; 696 | 697 | for (; request_count != 0U; request_count--) { 698 | request_value = *request++; 699 | if ((request_value & DAP_TRANSFER_RnW) != 0U) { 700 | // Read register 701 | if (post_read) { 702 | // Read was posted before 703 | retry = DAP_Data.transfer.retry_count; 704 | if ((request_value & (DAP_TRANSFER_APnDP | DAP_TRANSFER_MATCH_VALUE)) == DAP_TRANSFER_APnDP) { 705 | // Read previous AP data and post next AP read 706 | do { 707 | response_value = SWD_Transfer(request_value, &data); 708 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 709 | } else { 710 | // Read previous AP data 711 | do { 712 | response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); 713 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 714 | post_read = 0U; 715 | } 716 | if (response_value != DAP_TRANSFER_OK) { 717 | break; 718 | } 719 | // Store previous AP data 720 | *response++ = (uint8_t) data; 721 | *response++ = (uint8_t)(data >> 8); 722 | *response++ = (uint8_t)(data >> 16); 723 | *response++ = (uint8_t)(data >> 24); 724 | #if (TIMESTAMP_CLOCK != 0U) 725 | if (post_read) { 726 | // Store Timestamp of next AP read 727 | if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) { 728 | timestamp = DAP_Data.timestamp; 729 | *response++ = (uint8_t) timestamp; 730 | *response++ = (uint8_t)(timestamp >> 8); 731 | *response++ = (uint8_t)(timestamp >> 16); 732 | *response++ = (uint8_t)(timestamp >> 24); 733 | } 734 | } 735 | #endif 736 | } 737 | if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) { 738 | // Read with value match 739 | match_value = (uint32_t)(*(request+0) << 0) | 740 | (uint32_t)(*(request+1) << 8) | 741 | (uint32_t)(*(request+2) << 16) | 742 | (uint32_t)(*(request+3) << 24); 743 | request += 4; 744 | match_retry = DAP_Data.transfer.match_retry; 745 | if ((request_value & DAP_TRANSFER_APnDP) != 0U) { 746 | // Post AP read 747 | retry = DAP_Data.transfer.retry_count; 748 | do { 749 | response_value = SWD_Transfer(request_value, NULL); 750 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 751 | if (response_value != DAP_TRANSFER_OK) { 752 | break; 753 | } 754 | } 755 | do { 756 | // Read register until its value matches or retry counter expires 757 | retry = DAP_Data.transfer.retry_count; 758 | do { 759 | response_value = SWD_Transfer(request_value, &data); 760 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 761 | if (response_value != DAP_TRANSFER_OK) { 762 | break; 763 | } 764 | } while (((data & DAP_Data.transfer.match_mask) != match_value) && match_retry-- && !DAP_TransferAbort); 765 | if ((data & DAP_Data.transfer.match_mask) != match_value) { 766 | response_value |= DAP_TRANSFER_MISMATCH; 767 | } 768 | if (response_value != DAP_TRANSFER_OK) { 769 | break; 770 | } 771 | } else { 772 | // Normal read 773 | retry = DAP_Data.transfer.retry_count; 774 | if ((request_value & DAP_TRANSFER_APnDP) != 0U) { 775 | // Read AP register 776 | if (post_read == 0U) { 777 | // Post AP read 778 | do { 779 | response_value = SWD_Transfer(request_value, NULL); 780 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 781 | if (response_value != DAP_TRANSFER_OK) { 782 | break; 783 | } 784 | #if (TIMESTAMP_CLOCK != 0U) 785 | // Store Timestamp 786 | if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) { 787 | timestamp = DAP_Data.timestamp; 788 | *response++ = (uint8_t) timestamp; 789 | *response++ = (uint8_t)(timestamp >> 8); 790 | *response++ = (uint8_t)(timestamp >> 16); 791 | *response++ = (uint8_t)(timestamp >> 24); 792 | } 793 | #endif 794 | post_read = 1U; 795 | } 796 | } else { 797 | // Read DP register 798 | do { 799 | response_value = SWD_Transfer(request_value, &data); 800 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 801 | if (response_value != DAP_TRANSFER_OK) { 802 | break; 803 | } 804 | #if (TIMESTAMP_CLOCK != 0U) 805 | // Store Timestamp 806 | if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) { 807 | timestamp = DAP_Data.timestamp; 808 | *response++ = (uint8_t) timestamp; 809 | *response++ = (uint8_t)(timestamp >> 8); 810 | *response++ = (uint8_t)(timestamp >> 16); 811 | *response++ = (uint8_t)(timestamp >> 24); 812 | } 813 | #endif 814 | // Store data 815 | *response++ = (uint8_t) data; 816 | *response++ = (uint8_t)(data >> 8); 817 | *response++ = (uint8_t)(data >> 16); 818 | *response++ = (uint8_t)(data >> 24); 819 | } 820 | } 821 | check_write = 0U; 822 | } else { 823 | // Write register 824 | if (post_read) { 825 | // Read previous data 826 | retry = DAP_Data.transfer.retry_count; 827 | do { 828 | response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); 829 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 830 | if (response_value != DAP_TRANSFER_OK) { 831 | break; 832 | } 833 | // Store previous data 834 | *response++ = (uint8_t) data; 835 | *response++ = (uint8_t)(data >> 8); 836 | *response++ = (uint8_t)(data >> 16); 837 | *response++ = (uint8_t)(data >> 24); 838 | post_read = 0U; 839 | } 840 | // Load data 841 | data = (uint32_t)(*(request+0) << 0) | 842 | (uint32_t)(*(request+1) << 8) | 843 | (uint32_t)(*(request+2) << 16) | 844 | (uint32_t)(*(request+3) << 24); 845 | request += 4; 846 | if ((request_value & DAP_TRANSFER_MATCH_MASK) != 0U) { 847 | // Write match mask 848 | DAP_Data.transfer.match_mask = data; 849 | response_value = DAP_TRANSFER_OK; 850 | } else { 851 | // Write DP/AP register 852 | retry = DAP_Data.transfer.retry_count; 853 | do { 854 | response_value = SWD_Transfer(request_value, &data); 855 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 856 | if (response_value != DAP_TRANSFER_OK) { 857 | break; 858 | } 859 | #if (TIMESTAMP_CLOCK != 0U) 860 | // Store Timestamp 861 | if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) { 862 | timestamp = DAP_Data.timestamp; 863 | *response++ = (uint8_t) timestamp; 864 | *response++ = (uint8_t)(timestamp >> 8); 865 | *response++ = (uint8_t)(timestamp >> 16); 866 | *response++ = (uint8_t)(timestamp >> 24); 867 | } 868 | #endif 869 | check_write = 1U; 870 | } 871 | } 872 | response_count++; 873 | if (DAP_TransferAbort) { 874 | break; 875 | } 876 | } 877 | 878 | for (; request_count != 0U; request_count--) { 879 | // Process canceled requests 880 | request_value = *request++; 881 | if ((request_value & DAP_TRANSFER_RnW) != 0U) { 882 | // Read register 883 | if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) { 884 | // Read with value match 885 | request += 4; 886 | } 887 | } else { 888 | // Write register 889 | request += 4; 890 | } 891 | } 892 | 893 | if (response_value == DAP_TRANSFER_OK) { 894 | if (post_read) { 895 | // Read previous data 896 | retry = DAP_Data.transfer.retry_count; 897 | do { 898 | response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); 899 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 900 | if (response_value != DAP_TRANSFER_OK) { 901 | goto end; 902 | } 903 | // Store previous data 904 | *response++ = (uint8_t) data; 905 | *response++ = (uint8_t)(data >> 8); 906 | *response++ = (uint8_t)(data >> 16); 907 | *response++ = (uint8_t)(data >> 24); 908 | } else if (check_write) { 909 | // Check last write 910 | retry = DAP_Data.transfer.retry_count; 911 | do { 912 | response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); 913 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 914 | } 915 | } 916 | 917 | end: 918 | *(response_head+0) = (uint8_t)response_count; 919 | *(response_head+1) = (uint8_t)response_value; 920 | 921 | return (((uint32_t)(request - request_head) << 16) | (uint32_t)(response - response_head)); 922 | } 923 | #endif 924 | 925 | 926 | // Process JTAG Transfer command and prepare response 927 | // request: pointer to request data 928 | // response: pointer to response data 929 | // return: number of bytes in response (lower 16 bits) 930 | // number of bytes in request (upper 16 bits) 931 | #if (DAP_JTAG != 0) 932 | static uint32_t DAP_JTAG_Transfer(const uint8_t *request, uint8_t *response) { 933 | const 934 | uint8_t *request_head; 935 | uint32_t request_count; 936 | uint32_t request_value; 937 | uint32_t request_ir; 938 | uint8_t *response_head; 939 | uint32_t response_count; 940 | uint32_t response_value; 941 | uint32_t post_read; 942 | uint32_t match_value; 943 | uint32_t match_retry; 944 | uint32_t retry; 945 | uint32_t data; 946 | uint32_t ir; 947 | #if (TIMESTAMP_CLOCK != 0U) 948 | uint32_t timestamp; 949 | #endif 950 | 951 | request_head = request; 952 | 953 | response_count = 0U; 954 | response_value = 0U; 955 | response_head = response; 956 | response += 2; 957 | 958 | DAP_TransferAbort = 0U; 959 | 960 | ir = 0U; 961 | post_read = 0U; 962 | 963 | // Device index (JTAP TAP) 964 | DAP_Data.jtag_dev.index = *request++; 965 | if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) { 966 | goto end; 967 | } 968 | 969 | request_count = *request++; 970 | 971 | for (; request_count != 0U; request_count--) { 972 | request_value = *request++; 973 | request_ir = (request_value & DAP_TRANSFER_APnDP) ? JTAG_APACC : JTAG_DPACC; 974 | if ((request_value & DAP_TRANSFER_RnW) != 0U) { 975 | // Read register 976 | if (post_read) { 977 | // Read was posted before 978 | retry = DAP_Data.transfer.retry_count; 979 | if ((ir == request_ir) && ((request_value & DAP_TRANSFER_MATCH_VALUE) == 0U)) { 980 | // Read previous data and post next read 981 | do { 982 | response_value = JTAG_Transfer(request_value, &data); 983 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 984 | } else { 985 | // Select JTAG chain 986 | if (ir != JTAG_DPACC) { 987 | ir = JTAG_DPACC; 988 | JTAG_IR(ir); 989 | } 990 | // Read previous data 991 | do { 992 | response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); 993 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 994 | post_read = 0U; 995 | } 996 | if (response_value != DAP_TRANSFER_OK) { 997 | break; 998 | } 999 | // Store previous data 1000 | *response++ = (uint8_t) data; 1001 | *response++ = (uint8_t)(data >> 8); 1002 | *response++ = (uint8_t)(data >> 16); 1003 | *response++ = (uint8_t)(data >> 24); 1004 | #if (TIMESTAMP_CLOCK != 0U) 1005 | if (post_read) { 1006 | // Store Timestamp of next AP read 1007 | if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) { 1008 | timestamp = DAP_Data.timestamp; 1009 | *response++ = (uint8_t) timestamp; 1010 | *response++ = (uint8_t)(timestamp >> 8); 1011 | *response++ = (uint8_t)(timestamp >> 16); 1012 | *response++ = (uint8_t)(timestamp >> 24); 1013 | } 1014 | } 1015 | #endif 1016 | } 1017 | if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) { 1018 | // Read with value match 1019 | match_value = (uint32_t)(*(request+0) << 0) | 1020 | (uint32_t)(*(request+1) << 8) | 1021 | (uint32_t)(*(request+2) << 16) | 1022 | (uint32_t)(*(request+3) << 24); 1023 | request += 4; 1024 | match_retry = DAP_Data.transfer.match_retry; 1025 | // Select JTAG chain 1026 | if (ir != request_ir) { 1027 | ir = request_ir; 1028 | JTAG_IR(ir); 1029 | } 1030 | // Post DP/AP read 1031 | retry = DAP_Data.transfer.retry_count; 1032 | do { 1033 | response_value = JTAG_Transfer(request_value, NULL); 1034 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1035 | if (response_value != DAP_TRANSFER_OK) { 1036 | break; 1037 | } 1038 | do { 1039 | // Read register until its value matches or retry counter expires 1040 | retry = DAP_Data.transfer.retry_count; 1041 | do { 1042 | response_value = JTAG_Transfer(request_value, &data); 1043 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1044 | if (response_value != DAP_TRANSFER_OK) { 1045 | break; 1046 | } 1047 | } while (((data & DAP_Data.transfer.match_mask) != match_value) && match_retry-- && !DAP_TransferAbort); 1048 | if ((data & DAP_Data.transfer.match_mask) != match_value) { 1049 | response_value |= DAP_TRANSFER_MISMATCH; 1050 | } 1051 | if (response_value != DAP_TRANSFER_OK) { 1052 | break; 1053 | } 1054 | } else { 1055 | // Normal read 1056 | if (post_read == 0U) { 1057 | // Select JTAG chain 1058 | if (ir != request_ir) { 1059 | ir = request_ir; 1060 | JTAG_IR(ir); 1061 | } 1062 | // Post DP/AP read 1063 | retry = DAP_Data.transfer.retry_count; 1064 | do { 1065 | response_value = JTAG_Transfer(request_value, NULL); 1066 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1067 | if (response_value != DAP_TRANSFER_OK) { 1068 | break; 1069 | } 1070 | #if (TIMESTAMP_CLOCK != 0U) 1071 | // Store Timestamp 1072 | if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) { 1073 | timestamp = DAP_Data.timestamp; 1074 | *response++ = (uint8_t) timestamp; 1075 | *response++ = (uint8_t)(timestamp >> 8); 1076 | *response++ = (uint8_t)(timestamp >> 16); 1077 | *response++ = (uint8_t)(timestamp >> 24); 1078 | } 1079 | #endif 1080 | post_read = 1U; 1081 | } 1082 | } 1083 | } else { 1084 | // Write register 1085 | if (post_read) { 1086 | // Select JTAG chain 1087 | if (ir != JTAG_DPACC) { 1088 | ir = JTAG_DPACC; 1089 | JTAG_IR(ir); 1090 | } 1091 | // Read previous data 1092 | retry = DAP_Data.transfer.retry_count; 1093 | do { 1094 | response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); 1095 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1096 | if (response_value != DAP_TRANSFER_OK) { 1097 | break; 1098 | } 1099 | // Store previous data 1100 | *response++ = (uint8_t) data; 1101 | *response++ = (uint8_t)(data >> 8); 1102 | *response++ = (uint8_t)(data >> 16); 1103 | *response++ = (uint8_t)(data >> 24); 1104 | post_read = 0U; 1105 | } 1106 | // Load data 1107 | data = (uint32_t)(*(request+0) << 0) | 1108 | (uint32_t)(*(request+1) << 8) | 1109 | (uint32_t)(*(request+2) << 16) | 1110 | (uint32_t)(*(request+3) << 24); 1111 | request += 4; 1112 | if ((request_value & DAP_TRANSFER_MATCH_MASK) != 0U) { 1113 | // Write match mask 1114 | DAP_Data.transfer.match_mask = data; 1115 | response_value = DAP_TRANSFER_OK; 1116 | } else { 1117 | // Select JTAG chain 1118 | if (ir != request_ir) { 1119 | ir = request_ir; 1120 | JTAG_IR(ir); 1121 | } 1122 | // Write DP/AP register 1123 | retry = DAP_Data.transfer.retry_count; 1124 | do { 1125 | response_value = JTAG_Transfer(request_value, &data); 1126 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1127 | if (response_value != DAP_TRANSFER_OK) { 1128 | break; 1129 | } 1130 | #if (TIMESTAMP_CLOCK != 0U) 1131 | // Store Timestamp 1132 | if ((request_value & DAP_TRANSFER_TIMESTAMP) != 0U) { 1133 | timestamp = DAP_Data.timestamp; 1134 | *response++ = (uint8_t) timestamp; 1135 | *response++ = (uint8_t)(timestamp >> 8); 1136 | *response++ = (uint8_t)(timestamp >> 16); 1137 | *response++ = (uint8_t)(timestamp >> 24); 1138 | } 1139 | #endif 1140 | } 1141 | } 1142 | response_count++; 1143 | if (DAP_TransferAbort) { 1144 | break; 1145 | } 1146 | } 1147 | 1148 | for (; request_count != 0U; request_count--) { 1149 | // Process canceled requests 1150 | request_value = *request++; 1151 | if ((request_value & DAP_TRANSFER_RnW) != 0U) { 1152 | // Read register 1153 | if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) { 1154 | // Read with value match 1155 | request += 4; 1156 | } 1157 | } else { 1158 | // Write register 1159 | request += 4; 1160 | } 1161 | } 1162 | 1163 | if (response_value == DAP_TRANSFER_OK) { 1164 | // Select JTAG chain 1165 | if (ir != JTAG_DPACC) { 1166 | ir = JTAG_DPACC; 1167 | JTAG_IR(ir); 1168 | } 1169 | if (post_read) { 1170 | // Read previous data 1171 | retry = DAP_Data.transfer.retry_count; 1172 | do { 1173 | response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); 1174 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1175 | if (response_value != DAP_TRANSFER_OK) { 1176 | goto end; 1177 | } 1178 | // Store previous data 1179 | *response++ = (uint8_t) data; 1180 | *response++ = (uint8_t)(data >> 8); 1181 | *response++ = (uint8_t)(data >> 16); 1182 | *response++ = (uint8_t)(data >> 24); 1183 | } else { 1184 | // Check last write 1185 | retry = DAP_Data.transfer.retry_count; 1186 | do { 1187 | response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); 1188 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1189 | } 1190 | } 1191 | 1192 | end: 1193 | *(response_head+0) = (uint8_t)response_count; 1194 | *(response_head+1) = (uint8_t)response_value; 1195 | 1196 | return (((uint32_t)(request - request_head) << 16) | (uint32_t)(response - response_head)); 1197 | } 1198 | #endif 1199 | 1200 | 1201 | // Process Dummy Transfer command and prepare response 1202 | // request: pointer to request data 1203 | // response: pointer to response data 1204 | // return: number of bytes in response (lower 16 bits) 1205 | // number of bytes in request (upper 16 bits) 1206 | static uint32_t DAP_Dummy_Transfer(const uint8_t *request, uint8_t *response) { 1207 | const 1208 | uint8_t *request_head; 1209 | uint32_t request_count; 1210 | uint32_t request_value; 1211 | 1212 | request_head = request; 1213 | 1214 | request++; // Ignore DAP index 1215 | 1216 | request_count = *request++; 1217 | 1218 | for (; request_count != 0U; request_count--) { 1219 | // Process dummy requests 1220 | request_value = *request++; 1221 | if ((request_value & DAP_TRANSFER_RnW) != 0U) { 1222 | // Read register 1223 | if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) { 1224 | // Read with value match 1225 | request += 4; 1226 | } 1227 | } else { 1228 | // Write register 1229 | request += 4; 1230 | } 1231 | } 1232 | 1233 | *(response+0) = 0U; // Response count 1234 | *(response+1) = 0U; // Response value 1235 | 1236 | return (((uint32_t)(request - request_head) << 16) | 2U); 1237 | } 1238 | 1239 | 1240 | // Process Transfer command and prepare response 1241 | // request: pointer to request data 1242 | // response: pointer to response data 1243 | // return: number of bytes in response (lower 16 bits) 1244 | // number of bytes in request (upper 16 bits) 1245 | static uint32_t DAP_Transfer(const uint8_t *request, uint8_t *response) { 1246 | uint32_t num; 1247 | 1248 | switch (DAP_Data.debug_port) { 1249 | #if (DAP_SWD != 0) 1250 | case DAP_PORT_SWD: 1251 | num = DAP_SWD_Transfer(request, response); 1252 | break; 1253 | #endif 1254 | #if (DAP_JTAG != 0) 1255 | case DAP_PORT_JTAG: 1256 | num = DAP_JTAG_Transfer(request, response); 1257 | break; 1258 | #endif 1259 | default: 1260 | num = DAP_Dummy_Transfer(request, response); 1261 | break; 1262 | } 1263 | 1264 | return (num); 1265 | } 1266 | 1267 | 1268 | // Process SWD Transfer Block command and prepare response 1269 | // request: pointer to request data 1270 | // response: pointer to response data 1271 | // return: number of bytes in response 1272 | #if (DAP_SWD != 0) 1273 | static uint32_t DAP_SWD_TransferBlock(const uint8_t *request, uint8_t *response) { 1274 | uint32_t request_count; 1275 | uint32_t request_value; 1276 | uint32_t response_count; 1277 | uint32_t response_value; 1278 | uint8_t *response_head; 1279 | uint32_t retry; 1280 | uint32_t data; 1281 | 1282 | response_count = 0U; 1283 | response_value = 0U; 1284 | response_head = response; 1285 | response += 3; 1286 | 1287 | DAP_TransferAbort = 0U; 1288 | 1289 | request++; // Ignore DAP index 1290 | 1291 | request_count = (uint32_t)(*(request+0) << 0) | 1292 | (uint32_t)(*(request+1) << 8); 1293 | request += 2; 1294 | if (request_count == 0U) { 1295 | goto end; 1296 | } 1297 | 1298 | request_value = *request++; 1299 | if ((request_value & DAP_TRANSFER_RnW) != 0U) { 1300 | // Read register block 1301 | if ((request_value & DAP_TRANSFER_APnDP) != 0U) { 1302 | // Post AP read 1303 | retry = DAP_Data.transfer.retry_count; 1304 | do { 1305 | response_value = SWD_Transfer(request_value, NULL); 1306 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1307 | if (response_value != DAP_TRANSFER_OK) { 1308 | goto end; 1309 | } 1310 | } 1311 | while (request_count--) { 1312 | // Read DP/AP register 1313 | if ((request_count == 0U) && ((request_value & DAP_TRANSFER_APnDP) != 0U)) { 1314 | // Last AP read 1315 | request_value = DP_RDBUFF | DAP_TRANSFER_RnW; 1316 | } 1317 | retry = DAP_Data.transfer.retry_count; 1318 | do { 1319 | response_value = SWD_Transfer(request_value, &data); 1320 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1321 | if (response_value != DAP_TRANSFER_OK) { 1322 | goto end; 1323 | } 1324 | // Store data 1325 | *response++ = (uint8_t) data; 1326 | *response++ = (uint8_t)(data >> 8); 1327 | *response++ = (uint8_t)(data >> 16); 1328 | *response++ = (uint8_t)(data >> 24); 1329 | response_count++; 1330 | } 1331 | } else { 1332 | // Write register block 1333 | while (request_count--) { 1334 | // Load data 1335 | data = (uint32_t)(*(request+0) << 0) | 1336 | (uint32_t)(*(request+1) << 8) | 1337 | (uint32_t)(*(request+2) << 16) | 1338 | (uint32_t)(*(request+3) << 24); 1339 | request += 4; 1340 | // Write DP/AP register 1341 | retry = DAP_Data.transfer.retry_count; 1342 | do { 1343 | response_value = SWD_Transfer(request_value, &data); 1344 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1345 | if (response_value != DAP_TRANSFER_OK) { 1346 | goto end; 1347 | } 1348 | response_count++; 1349 | } 1350 | // Check last write 1351 | retry = DAP_Data.transfer.retry_count; 1352 | do { 1353 | response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); 1354 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1355 | } 1356 | 1357 | end: 1358 | *(response_head+0) = (uint8_t)(response_count >> 0); 1359 | *(response_head+1) = (uint8_t)(response_count >> 8); 1360 | *(response_head+2) = (uint8_t) response_value; 1361 | 1362 | return ((uint32_t)(response - response_head)); 1363 | } 1364 | #endif 1365 | 1366 | 1367 | // Process JTAG Transfer Block command and prepare response 1368 | // request: pointer to request data 1369 | // response: pointer to response data 1370 | // return: number of bytes in response 1371 | #if (DAP_JTAG != 0) 1372 | static uint32_t DAP_JTAG_TransferBlock(const uint8_t *request, uint8_t *response) { 1373 | uint32_t request_count; 1374 | uint32_t request_value; 1375 | uint32_t response_count; 1376 | uint32_t response_value; 1377 | uint8_t *response_head; 1378 | uint32_t retry; 1379 | uint32_t data; 1380 | uint32_t ir; 1381 | 1382 | response_count = 0U; 1383 | response_value = 0U; 1384 | response_head = response; 1385 | response += 3; 1386 | 1387 | DAP_TransferAbort = 0U; 1388 | 1389 | // Device index (JTAP TAP) 1390 | DAP_Data.jtag_dev.index = *request++; 1391 | if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) { 1392 | goto end; 1393 | } 1394 | 1395 | request_count = (uint32_t)(*(request+0) << 0) | 1396 | (uint32_t)(*(request+1) << 8); 1397 | request += 2; 1398 | if (request_count == 0U) { 1399 | goto end; 1400 | } 1401 | 1402 | request_value = *request++; 1403 | 1404 | // Select JTAG chain 1405 | ir = (request_value & DAP_TRANSFER_APnDP) ? JTAG_APACC : JTAG_DPACC; 1406 | JTAG_IR(ir); 1407 | 1408 | if ((request_value & DAP_TRANSFER_RnW) != 0U) { 1409 | // Post read 1410 | retry = DAP_Data.transfer.retry_count; 1411 | do { 1412 | response_value = JTAG_Transfer(request_value, NULL); 1413 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1414 | if (response_value != DAP_TRANSFER_OK) { 1415 | goto end; 1416 | } 1417 | // Read register block 1418 | while (request_count--) { 1419 | // Read DP/AP register 1420 | if (request_count == 0U) { 1421 | // Last read 1422 | if (ir != JTAG_DPACC) { 1423 | JTAG_IR(JTAG_DPACC); 1424 | } 1425 | request_value = DP_RDBUFF | DAP_TRANSFER_RnW; 1426 | } 1427 | retry = DAP_Data.transfer.retry_count; 1428 | do { 1429 | response_value = JTAG_Transfer(request_value, &data); 1430 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1431 | if (response_value != DAP_TRANSFER_OK) { 1432 | goto end; 1433 | } 1434 | // Store data 1435 | *response++ = (uint8_t) data; 1436 | *response++ = (uint8_t)(data >> 8); 1437 | *response++ = (uint8_t)(data >> 16); 1438 | *response++ = (uint8_t)(data >> 24); 1439 | response_count++; 1440 | } 1441 | } else { 1442 | // Write register block 1443 | while (request_count--) { 1444 | // Load data 1445 | data = (uint32_t)(*(request+0) << 0) | 1446 | (uint32_t)(*(request+1) << 8) | 1447 | (uint32_t)(*(request+2) << 16) | 1448 | (uint32_t)(*(request+3) << 24); 1449 | request += 4; 1450 | // Write DP/AP register 1451 | retry = DAP_Data.transfer.retry_count; 1452 | do { 1453 | response_value = JTAG_Transfer(request_value, &data); 1454 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1455 | if (response_value != DAP_TRANSFER_OK) { 1456 | goto end; 1457 | } 1458 | response_count++; 1459 | } 1460 | // Check last write 1461 | if (ir != JTAG_DPACC) { 1462 | JTAG_IR(JTAG_DPACC); 1463 | } 1464 | retry = DAP_Data.transfer.retry_count; 1465 | do { 1466 | response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); 1467 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1468 | } 1469 | 1470 | end: 1471 | *(response_head+0) = (uint8_t)(response_count >> 0); 1472 | *(response_head+1) = (uint8_t)(response_count >> 8); 1473 | *(response_head+2) = (uint8_t) response_value; 1474 | 1475 | return ((uint32_t)(response - response_head)); 1476 | } 1477 | #endif 1478 | 1479 | 1480 | // Process Transfer Block command and prepare response 1481 | // request: pointer to request data 1482 | // response: pointer to response data 1483 | // return: number of bytes in response (lower 16 bits) 1484 | // number of bytes in request (upper 16 bits) 1485 | static uint32_t DAP_TransferBlock(const uint8_t *request, uint8_t *response) { 1486 | uint32_t num; 1487 | 1488 | switch (DAP_Data.debug_port) { 1489 | #if (DAP_SWD != 0) 1490 | case DAP_PORT_SWD: 1491 | num = DAP_SWD_TransferBlock (request, response); 1492 | break; 1493 | #endif 1494 | #if (DAP_JTAG != 0) 1495 | case DAP_PORT_JTAG: 1496 | num = DAP_JTAG_TransferBlock(request, response); 1497 | break; 1498 | #endif 1499 | default: 1500 | *(response+0) = 0U; // Response count [7:0] 1501 | *(response+1) = 0U; // Response count[15:8] 1502 | *(response+2) = 0U; // Response value 1503 | num = 3U; 1504 | break; 1505 | } 1506 | 1507 | if ((*(request+3) & DAP_TRANSFER_RnW) != 0U) { 1508 | // Read register block 1509 | num |= 4U << 16; 1510 | } else { 1511 | // Write register block 1512 | num |= (4U + (((uint32_t)(*(request+1)) | (uint32_t)(*(request+2) << 8)) * 4)) << 16; 1513 | } 1514 | 1515 | return (num); 1516 | } 1517 | 1518 | 1519 | // Process SWD Write ABORT command and prepare response 1520 | // request: pointer to request data 1521 | // response: pointer to response data 1522 | // return: number of bytes in response 1523 | #if (DAP_SWD != 0) 1524 | static uint32_t DAP_SWD_WriteAbort(const uint8_t *request, uint8_t *response) { 1525 | uint32_t data; 1526 | 1527 | // Load data (Ignore DAP index) 1528 | data = (uint32_t)(*(request+1) << 0) | 1529 | (uint32_t)(*(request+2) << 8) | 1530 | (uint32_t)(*(request+3) << 16) | 1531 | (uint32_t)(*(request+4) << 24); 1532 | 1533 | // Write Abort register 1534 | SWD_Transfer(DP_ABORT, &data); 1535 | 1536 | *response = DAP_OK; 1537 | return (1U); 1538 | } 1539 | #endif 1540 | 1541 | 1542 | // Process JTAG Write ABORT command and prepare response 1543 | // request: pointer to request data 1544 | // response: pointer to response data 1545 | // return: number of bytes in response 1546 | #if (DAP_JTAG != 0) 1547 | static uint32_t DAP_JTAG_WriteAbort(const uint8_t *request, uint8_t *response) { 1548 | uint32_t data; 1549 | 1550 | // Device index (JTAP TAP) 1551 | DAP_Data.jtag_dev.index = *request; 1552 | if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) { 1553 | *response = DAP_ERROR; 1554 | return (1U); 1555 | } 1556 | 1557 | // Select JTAG chain 1558 | JTAG_IR(JTAG_ABORT); 1559 | 1560 | // Load data 1561 | data = (uint32_t)(*(request+1) << 0) | 1562 | (uint32_t)(*(request+2) << 8) | 1563 | (uint32_t)(*(request+3) << 16) | 1564 | (uint32_t)(*(request+4) << 24); 1565 | 1566 | // Write Abort register 1567 | JTAG_WriteAbort(data); 1568 | 1569 | *response = DAP_OK; 1570 | return (1U); 1571 | } 1572 | #endif 1573 | 1574 | 1575 | // Process Write ABORT command and prepare response 1576 | // request: pointer to request data 1577 | // response: pointer to response data 1578 | // return: number of bytes in response (lower 16 bits) 1579 | // number of bytes in request (upper 16 bits) 1580 | static uint32_t DAP_WriteAbort(const uint8_t *request, uint8_t *response) { 1581 | uint32_t num; 1582 | 1583 | switch (DAP_Data.debug_port) { 1584 | #if (DAP_SWD != 0) 1585 | case DAP_PORT_SWD: 1586 | num = DAP_SWD_WriteAbort (request, response); 1587 | break; 1588 | #endif 1589 | #if (DAP_JTAG != 0) 1590 | case DAP_PORT_JTAG: 1591 | num = DAP_JTAG_WriteAbort(request, response); 1592 | break; 1593 | #endif 1594 | default: 1595 | *response = DAP_ERROR; 1596 | num = 1U; 1597 | break; 1598 | } 1599 | return ((5U << 16) | num); 1600 | } 1601 | 1602 | 1603 | // Process DAP Vendor command request and prepare response 1604 | // Default function (can be overridden) 1605 | // request: pointer to request data 1606 | // response: pointer to response data 1607 | // return: number of bytes in response (lower 16 bits) 1608 | // number of bytes in request (upper 16 bits) 1609 | uint32_t DAP_ProcessVendorCommand(const uint8_t *request, uint8_t *response) { 1610 | (void)request; 1611 | *response = ID_DAP_Invalid; 1612 | return ((1U << 16) | 1U); 1613 | } 1614 | 1615 | // Process DAP Vendor extended command request and prepare response 1616 | // Default function (can be overridden) 1617 | // request: pointer to request data 1618 | // response: pointer to response data 1619 | // return: number of bytes in response (lower 16 bits) 1620 | // number of bytes in request (upper 16 bits) 1621 | uint32_t DAP_ProcessVendorCommandEx(const uint8_t *request, uint8_t *response) { 1622 | *response = ID_DAP_Invalid; 1623 | return ((1U << 16) | 1U); 1624 | } 1625 | 1626 | // Process DAP command request and prepare response 1627 | // request: pointer to request data 1628 | // response: pointer to response data 1629 | // return: number of bytes in response (lower 16 bits) 1630 | // number of bytes in request (upper 16 bits) 1631 | uint32_t DAP_ProcessCommand(const uint8_t *request, uint8_t *response) { 1632 | uint32_t num; 1633 | 1634 | if ((*request >= ID_DAP_Vendor0) && (*request <= ID_DAP_Vendor31)) { 1635 | return DAP_ProcessVendorCommand(request, response); 1636 | } 1637 | 1638 | if ((*request >= ID_DAP_VendorExFirst) && (*request <= ID_DAP_VendorExLast)) { 1639 | return DAP_ProcessVendorCommandEx(request, response); 1640 | } 1641 | 1642 | *response++ = *request; 1643 | 1644 | switch (*request++) { 1645 | case ID_DAP_Info: 1646 | num = DAP_Info(*request, response+1); 1647 | *response = (uint8_t)num; 1648 | return ((2U << 16) + 2U + num); 1649 | 1650 | case ID_DAP_HostStatus: 1651 | num = DAP_HostStatus(request, response); 1652 | break; 1653 | 1654 | case ID_DAP_Connect: 1655 | num = DAP_Connect(request, response); 1656 | break; 1657 | case ID_DAP_Disconnect: 1658 | num = DAP_Disconnect(response); 1659 | break; 1660 | 1661 | case ID_DAP_Delay: 1662 | num = DAP_Delay(request, response); 1663 | break; 1664 | 1665 | case ID_DAP_ResetTarget: 1666 | num = DAP_ResetTarget(response); 1667 | break; 1668 | 1669 | case ID_DAP_SWJ_Pins: 1670 | num = DAP_SWJ_Pins(request, response); 1671 | break; 1672 | case ID_DAP_SWJ_Clock: 1673 | num = DAP_SWJ_Clock(request, response); 1674 | break; 1675 | case ID_DAP_SWJ_Sequence: 1676 | num = DAP_SWJ_Sequence(request, response); 1677 | break; 1678 | 1679 | case ID_DAP_SWD_Configure: 1680 | num = DAP_SWD_Configure(request, response); 1681 | break; 1682 | case ID_DAP_SWD_Sequence: 1683 | num = DAP_SWD_Sequence(request, response); 1684 | break; 1685 | 1686 | case ID_DAP_JTAG_Sequence: 1687 | num = DAP_JTAG_Sequence(request, response); 1688 | break; 1689 | case ID_DAP_JTAG_Configure: 1690 | num = DAP_JTAG_Configure(request, response); 1691 | break; 1692 | case ID_DAP_JTAG_IDCODE: 1693 | num = DAP_JTAG_IDCode(request, response); 1694 | break; 1695 | 1696 | case ID_DAP_TransferConfigure: 1697 | num = DAP_TransferConfigure(request, response); 1698 | break; 1699 | case ID_DAP_Transfer: 1700 | num = DAP_Transfer(request, response); 1701 | break; 1702 | case ID_DAP_TransferBlock: 1703 | num = DAP_TransferBlock(request, response); 1704 | break; 1705 | 1706 | case ID_DAP_WriteABORT: 1707 | num = DAP_WriteAbort(request, response); 1708 | break; 1709 | 1710 | #if ((SWO_UART != 0) || (SWO_MANCHESTER != 0)) 1711 | case ID_DAP_SWO_Transport: 1712 | num = SWO_Transport(request, response); 1713 | break; 1714 | case ID_DAP_SWO_Mode: 1715 | num = SWO_Mode(request, response); 1716 | break; 1717 | case ID_DAP_SWO_Baudrate: 1718 | num = SWO_Baudrate(request, response); 1719 | break; 1720 | case ID_DAP_SWO_Control: 1721 | num = SWO_Control(request, response); 1722 | break; 1723 | case ID_DAP_SWO_Status: 1724 | num = SWO_Status(response); 1725 | break; 1726 | case ID_DAP_SWO_ExtendedStatus: 1727 | num = SWO_ExtendedStatus(request, response); 1728 | break; 1729 | case ID_DAP_SWO_Data: 1730 | num = SWO_Data(request, response); 1731 | break; 1732 | #endif 1733 | 1734 | default: 1735 | *(response-1) = ID_DAP_Invalid; 1736 | return ((1U << 16) | 1U); 1737 | } 1738 | 1739 | return ((1U << 16) + 1U + num); 1740 | } 1741 | 1742 | 1743 | // Execute DAP command (process request and prepare response) 1744 | // request: pointer to request data 1745 | // response: pointer to response data 1746 | // return: number of bytes in response (lower 16 bits) 1747 | // number of bytes in request (upper 16 bits) 1748 | uint32_t DAP_ExecuteCommand(const uint8_t *request, uint8_t *response) { 1749 | uint32_t cnt, num, n; 1750 | 1751 | if (*request == ID_DAP_ExecuteCommands) { 1752 | *response++ = *request++; 1753 | cnt = *request++; 1754 | *response++ = (uint8_t)cnt; 1755 | num = (2U << 16) | 2U; 1756 | while (cnt--) { 1757 | n = DAP_ProcessCommand(request, response); 1758 | num += n; 1759 | request += (uint16_t)(n >> 16); 1760 | response += (uint16_t) n; 1761 | } 1762 | return (num); 1763 | } 1764 | 1765 | return DAP_ProcessCommand(request, response); 1766 | } 1767 | 1768 | 1769 | #include 1770 | #define DAP_TAG "swd" 1771 | 1772 | // Setup DAP 1773 | void DAP_Setup(void) { 1774 | 1775 | // Default settings 1776 | DAP_Data.debug_port = 0U; 1777 | DAP_Data.transfer.idle_cycles = 0U; 1778 | DAP_Data.transfer.retry_count = 100U; 1779 | DAP_Data.transfer.match_retry = 0U; 1780 | DAP_Data.transfer.match_mask = 0x00000000U; 1781 | #if (DAP_SWD != 0) 1782 | DAP_Data.swd_conf.turnaround = 1U; 1783 | DAP_Data.swd_conf.data_phase = 0U; 1784 | #endif 1785 | #if (DAP_JTAG != 0) 1786 | DAP_Data.jtag_dev.count = 0U; 1787 | #endif 1788 | 1789 | if (DAP_DEFAULT_SWJ_CLOCK >= MAX_SWJ_CLOCK(DELAY_FAST_CYCLES)) { 1790 | DAP_Data.fast_clock = 1U; 1791 | DAP_Data.clock_delay = 1U; 1792 | } else { 1793 | DAP_Data.fast_clock = 0U; 1794 | 1795 | uint32_t delay = ((CPU_CLOCK/2U) + (DAP_DEFAULT_SWJ_CLOCK - 1U)) / DAP_DEFAULT_SWJ_CLOCK; 1796 | if (delay > IO_PORT_WRITE_CYCLES) { 1797 | delay -= IO_PORT_WRITE_CYCLES; 1798 | delay = (delay + (DELAY_SLOW_CYCLES - 1U)) / DELAY_SLOW_CYCLES; 1799 | } else { 1800 | delay = 1U; 1801 | } 1802 | 1803 | DAP_Data.clock_delay = delay; 1804 | 1805 | ESP_LOGD(DAP_TAG, "Delay: %lu, delay cycle: %u, MAX_SWJ_CLOCK: %u", delay, ((CPU_CLOCK/2U) + (DAP_DEFAULT_SWJ_CLOCK - 1U)) / DAP_DEFAULT_SWJ_CLOCK, MAX_SWJ_CLOCK(DELAY_FAST_CYCLES)); 1806 | } 1807 | 1808 | DAP_SETUP(); // Device specific setup 1809 | } 1810 | --------------------------------------------------------------------------------