├── LICENSE ├── README.md ├── dap.c ├── dap.h ├── dap_config.h ├── dap_target.c ├── hal_gpio.h ├── main.c └── raspberry-pi ├── Makefile ├── dap.c ├── dap.h ├── dap_config.h ├── dap_target.c ├── hal_gpio.h └── main.c /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2018, Alex Taradov 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # embedded-swd 2 | Embedded implementation of the SWD interface. This is just an example of implementing 3 | SWD interface in the MCU and programming another MCU using it. 4 | 5 | ### Raspberry Pi Example 6 | 7 | Example for the Raspberry Pi is a complete code that can be compiled into a running 8 | executable (just run 'make'). Root privileges are requred to run the resulting executable, 9 | since it uses direct access to the GPIO controller. 10 | 11 | By default target connections are SWCLK - GPIO2 (pin 3), SWDIO - GPIO3 (pin 5). 12 | This can be adjusted in the dap_config.h file. 13 | 14 | Note that the code will run unmodified on RPi 2B+, for older models you will need 15 | to ajdust BCM_GPIO_BASE definition in the hal_gpio.h file. 16 | 17 | 18 | -------------------------------------------------------------------------------- /dap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /*- Includes ----------------------------------------------------------------*/ 30 | #include 31 | #include 32 | #include 33 | #include "dap_config.h" 34 | #include "dap.h" 35 | 36 | /*- Definitions -------------------------------------------------------------*/ 37 | #define DAP_IDLE_CYCLES 0 38 | #define DAP_RETRY_COUNT 128 39 | #define DAP_SWD_TURNAROUND 1 40 | #define DAP_SWD_DATA_PHASE false 41 | 42 | enum 43 | { 44 | DAP_TRANSFER_APnDP = 1 << 0, 45 | DAP_TRANSFER_RnW = 1 << 1, 46 | DAP_TRANSFER_A2 = 1 << 2, 47 | DAP_TRANSFER_A3 = 1 << 3, 48 | DAP_TRANSFER_MATCH_VALUE = 1 << 4, 49 | DAP_TRANSFER_MATCH_MASK = 1 << 5, 50 | }; 51 | 52 | enum 53 | { 54 | DAP_TRANSFER_INVALID = 0, 55 | DAP_TRANSFER_OK = 1 << 0, 56 | DAP_TRANSFER_WAIT = 1 << 1, 57 | DAP_TRANSFER_FAULT = 1 << 2, 58 | DAP_TRANSFER_ERROR = 1 << 3, 59 | DAP_TRANSFER_MISMATCH = 1 << 4, 60 | }; 61 | 62 | enum 63 | { 64 | SWD_DP_R_IDCODE = 0x00, 65 | SWD_DP_W_ABORT = 0x00, 66 | SWD_DP_R_CTRL_STAT = 0x04, 67 | SWD_DP_W_CTRL_STAT = 0x04, // When CTRLSEL == 0 68 | SWD_DP_W_WCR = 0x04, // When CTRLSEL == 1 69 | SWD_DP_R_RESEND = 0x08, 70 | SWD_DP_W_SELECT = 0x08, 71 | SWD_DP_R_RDBUFF = 0x0c, 72 | }; 73 | 74 | enum 75 | { 76 | SWD_AP_CSW = 0x00 | DAP_TRANSFER_APnDP, 77 | SWD_AP_TAR = 0x04 | DAP_TRANSFER_APnDP, 78 | SWD_AP_DRW = 0x0c | DAP_TRANSFER_APnDP, 79 | 80 | SWD_AP_DB0 = 0x00 | DAP_TRANSFER_APnDP, // 0x10 81 | SWD_AP_DB1 = 0x04 | DAP_TRANSFER_APnDP, // 0x14 82 | SWD_AP_DB2 = 0x08 | DAP_TRANSFER_APnDP, // 0x18 83 | SWD_AP_DB3 = 0x0c | DAP_TRANSFER_APnDP, // 0x1c 84 | 85 | SWD_AP_CFG = 0x04 | DAP_TRANSFER_APnDP, // 0xf4 86 | SWD_AP_BASE = 0x08 | DAP_TRANSFER_APnDP, // 0xf8 87 | SWD_AP_IDR = 0x0c | DAP_TRANSFER_APnDP, // 0xfc 88 | }; 89 | 90 | /*- Implementations ---------------------------------------------------------*/ 91 | 92 | //----------------------------------------------------------------------------- 93 | static inline void dap_delay_loop(void) 94 | { 95 | #ifdef DAP_CONFIG_CLOCK_DELAY 96 | int delay = DAP_CONFIG_CLOCK_DELAY; 97 | 98 | while (--delay) 99 | asm("nop"); 100 | #endif 101 | } 102 | 103 | //----------------------------------------------------------------------------- 104 | static void dap_swd_clock(int cycles) 105 | { 106 | while (cycles--) 107 | { 108 | DAP_CONFIG_SWCLK_clr(); 109 | dap_delay_loop(); 110 | DAP_CONFIG_SWCLK_set(); 111 | dap_delay_loop(); 112 | } 113 | } 114 | 115 | //----------------------------------------------------------------------------- 116 | static void dap_swd_write(uint32_t value, int size) 117 | { 118 | for (int i = 0; i < size; i++) 119 | { 120 | DAP_CONFIG_SWDIO_write(value & 1); 121 | DAP_CONFIG_SWCLK_clr(); 122 | dap_delay_loop(); 123 | DAP_CONFIG_SWCLK_set(); 124 | dap_delay_loop(); 125 | value >>= 1; 126 | } 127 | } 128 | 129 | //----------------------------------------------------------------------------- 130 | static uint32_t dap_swd_read(int size) 131 | { 132 | uint32_t value = 0; 133 | 134 | for (int i = 0; i < size; i++) 135 | { 136 | DAP_CONFIG_SWCLK_clr(); 137 | dap_delay_loop(); 138 | value |= ((uint32_t)DAP_CONFIG_SWDIO_read() << i); 139 | DAP_CONFIG_SWCLK_set(); 140 | dap_delay_loop(); 141 | } 142 | 143 | return value; 144 | } 145 | 146 | //----------------------------------------------------------------------------- 147 | static inline uint32_t dap_parity(uint32_t value) 148 | { 149 | value ^= value >> 16; 150 | value ^= value >> 8; 151 | value ^= value >> 4; 152 | value &= 0x0f; 153 | 154 | return (0x6996 >> value) & 1; 155 | } 156 | 157 | //----------------------------------------------------------------------------- 158 | static int dap_swd_operation(int req, uint32_t *data) 159 | { 160 | uint32_t value; 161 | int ack = 0; 162 | 163 | dap_swd_write(0x81 | (dap_parity(req) << 5) | (req << 1), 8); 164 | 165 | DAP_CONFIG_SWDIO_in(); 166 | 167 | dap_swd_clock(DAP_SWD_TURNAROUND); 168 | 169 | ack = dap_swd_read(3); 170 | 171 | if (DAP_TRANSFER_OK == ack) 172 | { 173 | if (req & DAP_TRANSFER_RnW) 174 | { 175 | value = dap_swd_read(32); 176 | 177 | if (dap_parity(value) != dap_swd_read(1)) 178 | ack = DAP_TRANSFER_ERROR; 179 | 180 | if (data) 181 | *data = value; 182 | 183 | dap_swd_clock(DAP_SWD_TURNAROUND); 184 | 185 | DAP_CONFIG_SWDIO_out(); 186 | } 187 | else 188 | { 189 | dap_swd_clock(DAP_SWD_TURNAROUND); 190 | 191 | DAP_CONFIG_SWDIO_out(); 192 | 193 | dap_swd_write(*data, 32); 194 | dap_swd_write(dap_parity(*data), 1); 195 | } 196 | 197 | DAP_CONFIG_SWDIO_write(0); 198 | dap_swd_clock(DAP_IDLE_CYCLES); 199 | } 200 | 201 | else if (DAP_TRANSFER_WAIT == ack || DAP_TRANSFER_FAULT == ack) 202 | { 203 | if (DAP_SWD_DATA_PHASE && (req & DAP_TRANSFER_RnW)) 204 | dap_swd_clock(32 + 1); 205 | 206 | dap_swd_clock(DAP_SWD_TURNAROUND); 207 | 208 | DAP_CONFIG_SWDIO_out(); 209 | 210 | if (DAP_SWD_DATA_PHASE && (0 == (req & DAP_TRANSFER_RnW))) 211 | { 212 | DAP_CONFIG_SWDIO_write(0); 213 | dap_swd_clock(32 + 1); 214 | } 215 | } 216 | 217 | else 218 | { 219 | dap_swd_clock(DAP_SWD_TURNAROUND + 32 + 1); 220 | } 221 | 222 | DAP_CONFIG_SWDIO_write(1); 223 | 224 | return ack; 225 | } 226 | 227 | //----------------------------------------------------------------------------- 228 | static int dap_swd_transfer_word(int req, uint32_t *data) 229 | { 230 | int ack; 231 | 232 | req &= (DAP_TRANSFER_APnDP | DAP_TRANSFER_RnW | DAP_TRANSFER_A2 | DAP_TRANSFER_A3); 233 | 234 | for (int i = 0; i < DAP_RETRY_COUNT; i++) 235 | { 236 | ack = dap_swd_operation(req, data); 237 | 238 | if (DAP_TRANSFER_WAIT != ack) 239 | break; 240 | } 241 | 242 | return ack; 243 | } 244 | 245 | //----------------------------------------------------------------------------- 246 | static int dap_swd_transfer(int request, uint32_t *data) 247 | { 248 | int ack = DAP_TRANSFER_INVALID; 249 | bool posted_read = false; 250 | bool verify_write = false; 251 | 252 | if (request & DAP_TRANSFER_RnW) 253 | { 254 | if (request & DAP_TRANSFER_APnDP) 255 | { 256 | ack = dap_swd_transfer_word(request, NULL); 257 | 258 | if (ack != DAP_TRANSFER_OK) 259 | return ack; 260 | 261 | posted_read = true; 262 | } 263 | else 264 | { 265 | ack = dap_swd_transfer_word(request, data); 266 | 267 | if (DAP_TRANSFER_OK != ack) 268 | return ack; 269 | } 270 | } 271 | else 272 | { 273 | ack = dap_swd_transfer_word(request, data); 274 | 275 | if (ack != DAP_TRANSFER_OK) 276 | return ack; 277 | 278 | verify_write = true; 279 | } 280 | 281 | if (DAP_TRANSFER_OK == ack) 282 | { 283 | if (posted_read) 284 | ack = dap_swd_transfer_word(SWD_DP_R_RDBUFF | DAP_TRANSFER_RnW, data); 285 | 286 | else if (verify_write) 287 | ack = dap_swd_transfer_word(SWD_DP_R_RDBUFF | DAP_TRANSFER_RnW, NULL); 288 | } 289 | 290 | return ack; 291 | } 292 | 293 | //----------------------------------------------------------------------------- 294 | static void dap_swj_sequence(int size, uint8_t *data) 295 | { 296 | int offset = 0; 297 | 298 | while (size) 299 | { 300 | int sz = (size > 8) ? 8 : size; 301 | 302 | dap_swd_write(data[offset], sz); 303 | 304 | size -= sz; 305 | offset++; 306 | } 307 | } 308 | 309 | //----------------------------------------------------------------------------- 310 | static bool dap_read_reg(uint8_t reg, uint32_t *value) 311 | { 312 | return (DAP_TRANSFER_OK == dap_swd_transfer(reg | DAP_TRANSFER_RnW, value)); 313 | } 314 | 315 | //----------------------------------------------------------------------------- 316 | static bool dap_write_reg(uint8_t reg, uint32_t value) 317 | { 318 | return (DAP_TRANSFER_OK == dap_swd_transfer(reg, &value)); 319 | } 320 | 321 | //----------------------------------------------------------------------------- 322 | void dap_init(void) 323 | { 324 | DAP_CONFIG_SETUP(); 325 | } 326 | 327 | //----------------------------------------------------------------------------- 328 | void dap_connect(void) 329 | { 330 | DAP_CONFIG_CONNECT_SWD(); 331 | } 332 | 333 | //----------------------------------------------------------------------------- 334 | void dap_disconnect(void) 335 | { 336 | DAP_CONFIG_DISCONNECT(); 337 | } 338 | 339 | //----------------------------------------------------------------------------- 340 | uint32_t dap_read_word(uint32_t addr) 341 | { 342 | uint32_t data; 343 | 344 | if (!dap_write_reg(SWD_AP_TAR, addr)) 345 | return 0; 346 | 347 | if (!dap_read_reg(SWD_AP_DRW, &data)) 348 | return 0; 349 | 350 | return data; 351 | } 352 | 353 | //----------------------------------------------------------------------------- 354 | void dap_write_word(uint32_t addr, uint32_t data) 355 | { 356 | dap_write_reg(SWD_AP_TAR, addr); 357 | dap_write_reg(SWD_AP_DRW, data); 358 | } 359 | 360 | //----------------------------------------------------------------------------- 361 | void dap_reset_link(void) 362 | { 363 | uint8_t buf[20]; 364 | uint32_t idcode; 365 | 366 | buf[0] = 0xff; 367 | buf[1] = 0xff; 368 | buf[2] = 0xff; 369 | buf[3] = 0xff; 370 | buf[4] = 0xff; 371 | buf[5] = 0xff; 372 | buf[6] = 0xff; 373 | buf[7] = 0x9e; 374 | buf[8] = 0xe7; 375 | buf[9] = 0xff; 376 | buf[10] = 0xff; 377 | buf[11] = 0xff; 378 | buf[12] = 0xff; 379 | buf[13] = 0xff; 380 | buf[14] = 0xff; 381 | buf[15] = 0xff; 382 | buf[16] = 0x00; 383 | 384 | dap_swj_sequence((7 + 2 + 7 + 1) * 8, buf); 385 | 386 | dap_read_reg(SWD_DP_R_IDCODE, &idcode); 387 | } 388 | 389 | //----------------------------------------------------------------------------- 390 | uint32_t dap_read_idcode(void) 391 | { 392 | uint32_t idcode; 393 | 394 | if (dap_read_reg(SWD_DP_R_IDCODE, &idcode)) 395 | return idcode; 396 | 397 | return 0xffffffff; 398 | } 399 | 400 | //----------------------------------------------------------------------------- 401 | void dap_target_prepare(void) 402 | { 403 | dap_write_reg(SWD_DP_W_ABORT, 0x00000016); 404 | dap_write_reg(SWD_DP_W_SELECT, 0x00000000); 405 | dap_write_reg(SWD_DP_W_CTRL_STAT, 0x50000f00); 406 | dap_write_reg(SWD_AP_CSW, 0x23000052); 407 | } 408 | 409 | -------------------------------------------------------------------------------- /dap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _DAP_H_ 30 | #define _DAP_H_ 31 | 32 | /*- Includes ----------------------------------------------------------------*/ 33 | #include 34 | 35 | /*- Prototypes --------------------------------------------------------------*/ 36 | #define TARGET_ROW_SIZE 256 37 | #define TARGET_PAGE_SIZE 64 38 | 39 | /*- Prototypes --------------------------------------------------------------*/ 40 | void dap_init(void); 41 | void dap_connect(void); 42 | void dap_disconnect(void); 43 | uint32_t dap_read_word(uint32_t addr); 44 | void dap_write_word(uint32_t addr, uint32_t data); 45 | void dap_reset_link(void); 46 | uint32_t dap_read_idcode(void); 47 | void dap_target_prepare(void); 48 | 49 | // Target operations 50 | void dap_target_select(void); 51 | void dap_target_deselect(void); 52 | void dap_target_erase(void); 53 | void dap_target_lock(void); 54 | void dap_target_erase_row(uint32_t addr); 55 | void dap_target_write_page(uint32_t addr, uint8_t *data); 56 | void dap_target_read_page(uint32_t addr, uint8_t *data); 57 | 58 | #endif // _DAP_H_ 59 | 60 | -------------------------------------------------------------------------------- /dap_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _DAP_CONFIG_H_ 30 | #define _DAP_CONFIG_H_ 31 | 32 | /*- Includes ----------------------------------------------------------------*/ 33 | #include "samd21.h" 34 | #include "hal_gpio.h" 35 | 36 | /*- Definitions -------------------------------------------------------------*/ 37 | HAL_GPIO_PIN(SWCLK, B, 0) 38 | HAL_GPIO_PIN(SWDIO, B, 1) 39 | 40 | #define DAP_CONFIG_CLOCK_DELAY 10 41 | 42 | /*- Implementations ---------------------------------------------------------*/ 43 | 44 | //----------------------------------------------------------------------------- 45 | static inline void DAP_CONFIG_SWCLK_write(int value) 46 | { 47 | HAL_GPIO_SWCLK_write(value); 48 | } 49 | 50 | //----------------------------------------------------------------------------- 51 | static inline void DAP_CONFIG_SWDIO_write(int value) 52 | { 53 | HAL_GPIO_SWDIO_write(value); 54 | } 55 | 56 | //----------------------------------------------------------------------------- 57 | static inline int DAP_CONFIG_SWCLK_read(void) 58 | { 59 | return HAL_GPIO_SWCLK_read(); 60 | } 61 | 62 | //----------------------------------------------------------------------------- 63 | static inline int DAP_CONFIG_SWDIO_read(void) 64 | { 65 | return HAL_GPIO_SWDIO_read(); 66 | } 67 | 68 | //----------------------------------------------------------------------------- 69 | static inline void DAP_CONFIG_SWCLK_set(void) 70 | { 71 | HAL_GPIO_SWCLK_set(); 72 | } 73 | 74 | //----------------------------------------------------------------------------- 75 | static inline void DAP_CONFIG_SWCLK_clr(void) 76 | { 77 | HAL_GPIO_SWCLK_clr(); 78 | } 79 | 80 | //----------------------------------------------------------------------------- 81 | static inline void DAP_CONFIG_SWDIO_in(void) 82 | { 83 | HAL_GPIO_SWDIO_in(); 84 | } 85 | 86 | //----------------------------------------------------------------------------- 87 | static inline void DAP_CONFIG_SWDIO_out(void) 88 | { 89 | HAL_GPIO_SWDIO_out(); 90 | } 91 | 92 | //----------------------------------------------------------------------------- 93 | static inline void DAP_CONFIG_SETUP(void) 94 | { 95 | HAL_GPIO_SWCLK_in(); 96 | 97 | HAL_GPIO_SWDIO_in(); 98 | HAL_GPIO_SWDIO_pullup(); 99 | } 100 | 101 | //----------------------------------------------------------------------------- 102 | static inline void DAP_CONFIG_DISCONNECT(void) 103 | { 104 | HAL_GPIO_SWCLK_in(); 105 | HAL_GPIO_SWDIO_in(); 106 | } 107 | 108 | //----------------------------------------------------------------------------- 109 | static inline void DAP_CONFIG_CONNECT_SWD(void) 110 | { 111 | HAL_GPIO_SWDIO_out(); 112 | HAL_GPIO_SWDIO_set(); 113 | 114 | HAL_GPIO_SWCLK_out(); 115 | HAL_GPIO_SWCLK_set(); 116 | } 117 | 118 | #endif // _DAP_CONFIG_H_ 119 | 120 | -------------------------------------------------------------------------------- /dap_target.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /*- Includes ----------------------------------------------------------------*/ 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "dap.h" 36 | 37 | /*- Definitions -------------------------------------------------------------*/ 38 | #define DHCSR 0xe000edf0 39 | #define DEMCR 0xe000edfc 40 | #define AIRCR 0xe000ed0c 41 | 42 | #define DSU_CTRL_STATUS 0x41002100 43 | #define DSU_DID 0x41002118 44 | 45 | #define NVMCTRL_CTRLA 0x41004000 46 | #define NVMCTRL_CTRLB 0x41004004 47 | #define NVMCTRL_PARAM 0x41004008 48 | #define NVMCTRL_INTFLAG 0x41004014 49 | #define NVMCTRL_STATUS 0x41004018 50 | #define NVMCTRL_ADDR 0x4100401c 51 | 52 | #define NVMCTRL_CMD_ER 0xa502 53 | #define NVMCTRL_CMD_WP 0xa504 54 | #define NVMCTRL_CMD_EAR 0xa505 55 | #define NVMCTRL_CMD_WAP 0xa506 56 | #define NVMCTRL_CMD_WL 0xa50f 57 | #define NVMCTRL_CMD_UR 0xa541 58 | #define NVMCTRL_CMD_PBC 0xa544 59 | #define NVMCTRL_CMD_SSB 0xa545 60 | 61 | /*- Implementations ---------------------------------------------------------*/ 62 | 63 | //----------------------------------------------------------------------------- 64 | void dap_target_select(void) 65 | { 66 | // Stop the core 67 | dap_write_word(DHCSR, 0xa05f0003); 68 | dap_write_word(DEMCR, 0x00000001); 69 | dap_write_word(AIRCR, 0x05fa0004); 70 | 71 | // Enable automatic writes 72 | dap_write_word(NVMCTRL_CTRLB, 0); 73 | } 74 | 75 | //----------------------------------------------------------------------------- 76 | void dap_target_deselect(void) 77 | { 78 | dap_write_word(DEMCR, 0x00000000); 79 | dap_write_word(AIRCR, 0x05fa0004); 80 | } 81 | 82 | //----------------------------------------------------------------------------- 83 | void dap_target_erase(void) 84 | { 85 | dap_write_word(DSU_CTRL_STATUS, 0x00001f00); // Clear flags 86 | dap_write_word(DSU_CTRL_STATUS, 0x00000010); // Chip erase 87 | while (0 == (dap_read_word(DSU_CTRL_STATUS) & 0x00000100)); 88 | } 89 | 90 | //----------------------------------------------------------------------------- 91 | void dap_target_lock(void) 92 | { 93 | dap_write_word(NVMCTRL_CTRLA, NVMCTRL_CMD_SSB); // Set Security Bit 94 | } 95 | 96 | //----------------------------------------------------------------------------- 97 | void dap_target_erase_row(uint32_t addr) 98 | { 99 | dap_write_word(NVMCTRL_ADDR, addr >> 1); 100 | 101 | dap_write_word(NVMCTRL_CTRLA, NVMCTRL_CMD_UR); // Unlock Region 102 | while (0 == (dap_read_word(NVMCTRL_INTFLAG) & 1)); 103 | 104 | dap_write_word(NVMCTRL_CTRLA, NVMCTRL_CMD_ER); // Erase Row 105 | while (0 == (dap_read_word(NVMCTRL_INTFLAG) & 1)); 106 | } 107 | 108 | //----------------------------------------------------------------------------- 109 | void dap_target_write_page(uint32_t addr, uint8_t *data) 110 | { 111 | dap_write_word(NVMCTRL_ADDR, addr >> 1); 112 | 113 | dap_write_word(NVMCTRL_CTRLA, NVMCTRL_CMD_UR); // Unlock Region 114 | while (0 == (dap_read_word(NVMCTRL_INTFLAG) & 1)); 115 | 116 | for (int offs = 0; offs < TARGET_PAGE_SIZE; offs += sizeof(uint32_t)) 117 | { 118 | uint32_t value = 119 | ((uint32_t)data[offs + 3] << 24) | ((uint32_t)data[offs + 2] << 16) | 120 | ((uint32_t)data[offs + 1] << 8) | (uint32_t)data[offs]; 121 | 122 | dap_write_word(addr + offs, value); 123 | } 124 | } 125 | 126 | //----------------------------------------------------------------------------- 127 | void dap_target_read_page(uint32_t addr, uint8_t *data) 128 | { 129 | for (int offs = 0; offs < TARGET_PAGE_SIZE; offs += sizeof(uint32_t)) 130 | { 131 | uint32_t value = dap_read_word(addr + offs); 132 | 133 | data[offs + 0] = (value >> 0) & 0xff; 134 | data[offs + 1] = (value >> 8) & 0xff; 135 | data[offs + 2] = (value >> 16) & 0xff; 136 | data[offs + 3] = (value >> 24) & 0xff; 137 | } 138 | } 139 | 140 | -------------------------------------------------------------------------------- /hal_gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _HAL_GPIO_H_ 30 | #define _HAL_GPIO_H_ 31 | 32 | /*- Definitions -------------------------------------------------------------*/ 33 | #define HAL_GPIO_PORTA 0 34 | #define HAL_GPIO_PORTB 1 35 | #define HAL_GPIO_PORTC 2 36 | 37 | #define HAL_GPIO_PMUX_A 0 38 | #define HAL_GPIO_PMUX_B 1 39 | #define HAL_GPIO_PMUX_C 2 40 | #define HAL_GPIO_PMUX_D 3 41 | #define HAL_GPIO_PMUX_E 4 42 | #define HAL_GPIO_PMUX_F 5 43 | #define HAL_GPIO_PMUX_G 6 44 | #define HAL_GPIO_PMUX_H 7 45 | #define HAL_GPIO_PMUX_I 8 46 | 47 | #define HAL_GPIO_PIN(name, port, pin) \ 48 | static inline void HAL_GPIO_##name##_set(void) \ 49 | { \ 50 | PORT->Group[HAL_GPIO_PORT##port].OUTSET.reg = (1 << pin); \ 51 | (void)HAL_GPIO_##name##_set; \ 52 | } \ 53 | \ 54 | static inline void HAL_GPIO_##name##_clr(void) \ 55 | { \ 56 | PORT->Group[HAL_GPIO_PORT##port].OUTCLR.reg = (1 << pin); \ 57 | (void)HAL_GPIO_##name##_clr; \ 58 | } \ 59 | \ 60 | static inline void HAL_GPIO_##name##_toggle(void) \ 61 | { \ 62 | PORT->Group[HAL_GPIO_PORT##port].OUTTGL.reg = (1 << pin); \ 63 | (void)HAL_GPIO_##name##_toggle; \ 64 | } \ 65 | \ 66 | static inline void HAL_GPIO_##name##_write(int value) \ 67 | { \ 68 | if (value) \ 69 | PORT->Group[HAL_GPIO_PORT##port].OUTSET.reg = (1 << pin); \ 70 | else \ 71 | PORT->Group[HAL_GPIO_PORT##port].OUTCLR.reg = (1 << pin); \ 72 | (void)HAL_GPIO_##name##_write; \ 73 | } \ 74 | \ 75 | static inline void HAL_GPIO_##name##_in(void) \ 76 | { \ 77 | PORT->Group[HAL_GPIO_PORT##port].DIRCLR.reg = (1 << pin); \ 78 | PORT->Group[HAL_GPIO_PORT##port].PINCFG[pin].reg |= PORT_PINCFG_INEN; \ 79 | PORT->Group[HAL_GPIO_PORT##port].PINCFG[pin].reg &= ~PORT_PINCFG_PULLEN; \ 80 | (void)HAL_GPIO_##name##_in; \ 81 | } \ 82 | \ 83 | static inline void HAL_GPIO_##name##_out(void) \ 84 | { \ 85 | PORT->Group[HAL_GPIO_PORT##port].DIRSET.reg = (1 << pin); \ 86 | PORT->Group[HAL_GPIO_PORT##port].PINCFG[pin].reg |= PORT_PINCFG_INEN; \ 87 | (void)HAL_GPIO_##name##_out; \ 88 | } \ 89 | \ 90 | static inline void HAL_GPIO_##name##_pullup(void) \ 91 | { \ 92 | PORT->Group[HAL_GPIO_PORT##port].OUTSET.reg = (1 << pin); \ 93 | PORT->Group[HAL_GPIO_PORT##port].PINCFG[pin].reg |= PORT_PINCFG_PULLEN; \ 94 | (void)HAL_GPIO_##name##_pullup; \ 95 | } \ 96 | \ 97 | static inline int HAL_GPIO_##name##_read(void) \ 98 | { \ 99 | return (PORT->Group[HAL_GPIO_PORT##port].IN.reg & (1 << pin)) != 0; \ 100 | (void)HAL_GPIO_##name##_read; \ 101 | } \ 102 | \ 103 | static inline int HAL_GPIO_##name##_state(void) \ 104 | { \ 105 | return (PORT->Group[HAL_GPIO_PORT##port].DIR.reg & (1 << pin)) != 0; \ 106 | (void)HAL_GPIO_##name##_state; \ 107 | } \ 108 | \ 109 | static inline void HAL_GPIO_##name##_pmuxen(int mux) \ 110 | { \ 111 | PORT->Group[HAL_GPIO_PORT##port].PINCFG[pin].reg |= PORT_PINCFG_PMUXEN; \ 112 | if (pin & 1) \ 113 | PORT->Group[HAL_GPIO_PORT##port].PMUX[pin>>1].bit.PMUXO = mux; \ 114 | else \ 115 | PORT->Group[HAL_GPIO_PORT##port].PMUX[pin>>1].bit.PMUXE = mux; \ 116 | (void)HAL_GPIO_##name##_pmuxen; \ 117 | } \ 118 | \ 119 | static inline void HAL_GPIO_##name##_pmuxdis(void) \ 120 | { \ 121 | PORT->Group[HAL_GPIO_PORT##port].PINCFG[pin].reg &= ~PORT_PINCFG_PMUXEN; \ 122 | (void)HAL_GPIO_##name##_pmuxdis; \ 123 | } \ 124 | 125 | #endif // _HAL_GPIO_H_ 126 | 127 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | //----------------------------------------------------------------------------- 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include "samd21.h" 35 | #include "hal_gpio.h" 36 | #include "dap.h" 37 | 38 | //----------------------------------------------------------------------------- 39 | #define PERIOD_FAST 100 40 | #define PERIOD_SLOW 500 41 | 42 | HAL_GPIO_PIN(LED, B, 30) 43 | HAL_GPIO_PIN(BUTTON, A, 15) 44 | HAL_GPIO_PIN(UART_TX, A, 22) 45 | HAL_GPIO_PIN(UART_RX, A, 23) 46 | 47 | //----------------------------------------------------------------------------- 48 | static void uart_init(uint32_t baud) 49 | { 50 | uint64_t br = (uint64_t)65536 * (F_CPU - 16 * baud) / F_CPU; 51 | 52 | HAL_GPIO_UART_TX_out(); 53 | HAL_GPIO_UART_TX_pmuxen(PORT_PMUX_PMUXE_C_Val); 54 | HAL_GPIO_UART_RX_in(); 55 | HAL_GPIO_UART_RX_pmuxen(PORT_PMUX_PMUXE_C_Val); 56 | 57 | PM->APBCMASK.reg |= PM_APBCMASK_SERCOM3; 58 | 59 | GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SERCOM3_GCLK_ID_CORE) | 60 | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0); 61 | 62 | SERCOM3->USART.CTRLA.reg = 63 | SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_MODE_USART_INT_CLK | 64 | SERCOM_USART_CTRLA_RXPO(1/*PAD1*/) | SERCOM_USART_CTRLA_TXPO(0/*PAD0*/); 65 | 66 | SERCOM3->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN | 67 | SERCOM_USART_CTRLB_CHSIZE(0/*8 bits*/); 68 | 69 | SERCOM3->USART.BAUD.reg = (uint16_t)br; 70 | 71 | SERCOM3->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE; 72 | } 73 | 74 | //----------------------------------------------------------------------------- 75 | void uart_putc(char c) 76 | { 77 | while (!(SERCOM3->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_DRE)); 78 | SERCOM3->USART.DATA.reg = c; 79 | } 80 | 81 | //----------------------------------------------------------------------------- 82 | void uart_puts(char *s) 83 | { 84 | while (*s) 85 | uart_putc(*s++); 86 | } 87 | 88 | //----------------------------------------------------------------------------- 89 | void uart_puthex(uint32_t v, int size) 90 | { 91 | char hex[] = "0123456789abcdef"; 92 | 93 | for (int i = 0; i < size; i++) 94 | { 95 | int offs = ((size - 1) - i) * 4; 96 | uart_putc(hex[(v >> offs) & 0xf]); 97 | } 98 | } 99 | 100 | 101 | //----------------------------------------------------------------------------- 102 | static void sys_init(void) 103 | { 104 | // Switch to 8MHz clock (disable prescaler) 105 | SYSCTRL->OSC8M.bit.PRESC = 0; 106 | } 107 | 108 | //----------------------------------------------------------------------------- 109 | static void test_swd(void) 110 | { 111 | dap_init(); 112 | dap_connect(); 113 | dap_reset_link(); 114 | dap_target_prepare(); 115 | dap_target_select(); 116 | 117 | uint32_t id = dap_read_idcode(); 118 | uart_puts("\r\nIDCODE = "); 119 | uart_puthex(id, 8); 120 | 121 | uart_puts("\r\nDSU_DID = "); 122 | uint32_t dsu_did = dap_read_word(0x41002118/*DSU_DID*/); 123 | uart_puthex(dsu_did, 8); 124 | uart_puts("\r\n"); 125 | 126 | uart_puts("Erasing entire device... "); 127 | dap_target_erase(); 128 | uart_puts("done\r\n"); 129 | 130 | 131 | uint32_t addr = 0x8000; 132 | uint8_t page_buf[TARGET_PAGE_SIZE]; 133 | 134 | uart_puts("Erasing a row device... "); 135 | dap_target_erase_row(addr); 136 | uart_puts("done\r\n"); 137 | 138 | for (int i = 0; i < TARGET_PAGE_SIZE; i++) 139 | page_buf[i] = i; 140 | 141 | uart_puts("Writing a page... "); 142 | dap_target_write_page(addr, page_buf); 143 | uart_puts("done\r\n"); 144 | 145 | for (int i = 0; i < TARGET_PAGE_SIZE; i++) // Clear the buffer for readback test 146 | page_buf[i] = 0; 147 | 148 | uart_puts("Reading a page... "); 149 | dap_target_read_page(addr, page_buf); 150 | uart_puts("done\r\n"); 151 | 152 | for (int i = 0; i < TARGET_PAGE_SIZE; i++) 153 | { 154 | if (page_buf[i] != i) 155 | { 156 | uart_puts("\r\nERROR @ "); 157 | uart_puthex(i, 2); 158 | uart_puts("\r\n"); 159 | } 160 | } 161 | 162 | dap_target_deselect(); 163 | 164 | dap_disconnect(); 165 | } 166 | 167 | //----------------------------------------------------------------------------- 168 | int main(void) 169 | { 170 | int cnt = 0; 171 | 172 | sys_init(); 173 | uart_init(115200); 174 | 175 | uart_puts("\r\n--- start ---\r\n"); 176 | 177 | HAL_GPIO_LED_out(); 178 | HAL_GPIO_LED_clr(); 179 | 180 | HAL_GPIO_BUTTON_in(); 181 | HAL_GPIO_BUTTON_pullup(); 182 | 183 | while (1) 184 | { 185 | if (HAL_GPIO_BUTTON_read()) 186 | cnt = 0; 187 | else if (cnt < 5001) 188 | cnt++; 189 | 190 | if (5000 == cnt) 191 | { 192 | uart_puts("Test SWD: "); 193 | test_swd(); 194 | uart_puts("\r\ndone.\r\n"); 195 | } 196 | } 197 | 198 | return 0; 199 | } 200 | -------------------------------------------------------------------------------- /raspberry-pi/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -W -Wall -Wextra -O3 -std=gnu11 2 | CFLAGS += -fno-diagnostics-show-caret 3 | 4 | SRC = \ 5 | main.c \ 6 | dap.c \ 7 | dap_target.c \ 8 | 9 | HDR = \ 10 | hal_gpio.h \ 11 | dap_config.h \ 12 | dap.h \ 13 | 14 | all: $(SRC) $(HDR) 15 | gcc $(CFLAGS) $(SRC) -o dap_test 16 | 17 | 18 | -------------------------------------------------------------------------------- /raspberry-pi/dap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /*- Includes ----------------------------------------------------------------*/ 30 | #include 31 | #include 32 | #include 33 | #include "dap_config.h" 34 | #include "dap.h" 35 | 36 | /*- Definitions -------------------------------------------------------------*/ 37 | #define DAP_IDLE_CYCLES 0 38 | #define DAP_RETRY_COUNT 128 39 | #define DAP_SWD_TURNAROUND 1 40 | #define DAP_SWD_DATA_PHASE false 41 | 42 | enum 43 | { 44 | DAP_TRANSFER_APnDP = 1 << 0, 45 | DAP_TRANSFER_RnW = 1 << 1, 46 | DAP_TRANSFER_A2 = 1 << 2, 47 | DAP_TRANSFER_A3 = 1 << 3, 48 | DAP_TRANSFER_MATCH_VALUE = 1 << 4, 49 | DAP_TRANSFER_MATCH_MASK = 1 << 5, 50 | }; 51 | 52 | enum 53 | { 54 | DAP_TRANSFER_INVALID = 0, 55 | DAP_TRANSFER_OK = 1 << 0, 56 | DAP_TRANSFER_WAIT = 1 << 1, 57 | DAP_TRANSFER_FAULT = 1 << 2, 58 | DAP_TRANSFER_ERROR = 1 << 3, 59 | DAP_TRANSFER_MISMATCH = 1 << 4, 60 | }; 61 | 62 | enum 63 | { 64 | SWD_DP_R_IDCODE = 0x00, 65 | SWD_DP_W_ABORT = 0x00, 66 | SWD_DP_R_CTRL_STAT = 0x04, 67 | SWD_DP_W_CTRL_STAT = 0x04, // When CTRLSEL == 0 68 | SWD_DP_W_WCR = 0x04, // When CTRLSEL == 1 69 | SWD_DP_R_RESEND = 0x08, 70 | SWD_DP_W_SELECT = 0x08, 71 | SWD_DP_R_RDBUFF = 0x0c, 72 | }; 73 | 74 | enum 75 | { 76 | SWD_AP_CSW = 0x00 | DAP_TRANSFER_APnDP, 77 | SWD_AP_TAR = 0x04 | DAP_TRANSFER_APnDP, 78 | SWD_AP_DRW = 0x0c | DAP_TRANSFER_APnDP, 79 | 80 | SWD_AP_DB0 = 0x00 | DAP_TRANSFER_APnDP, // 0x10 81 | SWD_AP_DB1 = 0x04 | DAP_TRANSFER_APnDP, // 0x14 82 | SWD_AP_DB2 = 0x08 | DAP_TRANSFER_APnDP, // 0x18 83 | SWD_AP_DB3 = 0x0c | DAP_TRANSFER_APnDP, // 0x1c 84 | 85 | SWD_AP_CFG = 0x04 | DAP_TRANSFER_APnDP, // 0xf4 86 | SWD_AP_BASE = 0x08 | DAP_TRANSFER_APnDP, // 0xf8 87 | SWD_AP_IDR = 0x0c | DAP_TRANSFER_APnDP, // 0xfc 88 | }; 89 | 90 | /*- Implementations ---------------------------------------------------------*/ 91 | 92 | //----------------------------------------------------------------------------- 93 | static inline void dap_delay_loop(void) 94 | { 95 | #ifdef DAP_CONFIG_CLOCK_DELAY 96 | int delay = DAP_CONFIG_CLOCK_DELAY; 97 | 98 | while (--delay) 99 | asm("nop"); 100 | #endif 101 | } 102 | 103 | //----------------------------------------------------------------------------- 104 | static void dap_swd_clock(int cycles) 105 | { 106 | while (cycles--) 107 | { 108 | DAP_CONFIG_SWCLK_clr(); 109 | dap_delay_loop(); 110 | DAP_CONFIG_SWCLK_set(); 111 | dap_delay_loop(); 112 | } 113 | } 114 | 115 | //----------------------------------------------------------------------------- 116 | static void dap_swd_write(uint32_t value, int size) 117 | { 118 | for (int i = 0; i < size; i++) 119 | { 120 | DAP_CONFIG_SWDIO_write(value & 1); 121 | DAP_CONFIG_SWCLK_clr(); 122 | dap_delay_loop(); 123 | DAP_CONFIG_SWCLK_set(); 124 | dap_delay_loop(); 125 | value >>= 1; 126 | } 127 | } 128 | 129 | //----------------------------------------------------------------------------- 130 | static uint32_t dap_swd_read(int size) 131 | { 132 | uint32_t value = 0; 133 | 134 | for (int i = 0; i < size; i++) 135 | { 136 | DAP_CONFIG_SWCLK_clr(); 137 | dap_delay_loop(); 138 | value |= ((uint32_t)DAP_CONFIG_SWDIO_read() << i); 139 | DAP_CONFIG_SWCLK_set(); 140 | dap_delay_loop(); 141 | } 142 | 143 | return value; 144 | } 145 | 146 | //----------------------------------------------------------------------------- 147 | static inline uint32_t dap_parity(uint32_t value) 148 | { 149 | value ^= value >> 16; 150 | value ^= value >> 8; 151 | value ^= value >> 4; 152 | value &= 0x0f; 153 | 154 | return (0x6996 >> value) & 1; 155 | } 156 | 157 | //----------------------------------------------------------------------------- 158 | static int dap_swd_operation(int req, uint32_t *data) 159 | { 160 | uint32_t value; 161 | int ack = 0; 162 | 163 | dap_swd_write(0x81 | (dap_parity(req) << 5) | (req << 1), 8); 164 | 165 | DAP_CONFIG_SWDIO_in(); 166 | 167 | dap_swd_clock(DAP_SWD_TURNAROUND); 168 | 169 | ack = dap_swd_read(3); 170 | 171 | if (DAP_TRANSFER_OK == ack) 172 | { 173 | if (req & DAP_TRANSFER_RnW) 174 | { 175 | value = dap_swd_read(32); 176 | 177 | if (dap_parity(value) != dap_swd_read(1)) 178 | ack = DAP_TRANSFER_ERROR; 179 | 180 | if (data) 181 | *data = value; 182 | 183 | dap_swd_clock(DAP_SWD_TURNAROUND); 184 | 185 | DAP_CONFIG_SWDIO_out(); 186 | } 187 | else 188 | { 189 | dap_swd_clock(DAP_SWD_TURNAROUND); 190 | 191 | DAP_CONFIG_SWDIO_out(); 192 | 193 | dap_swd_write(*data, 32); 194 | dap_swd_write(dap_parity(*data), 1); 195 | } 196 | 197 | DAP_CONFIG_SWDIO_write(0); 198 | dap_swd_clock(DAP_IDLE_CYCLES); 199 | } 200 | 201 | else if (DAP_TRANSFER_WAIT == ack || DAP_TRANSFER_FAULT == ack) 202 | { 203 | if (DAP_SWD_DATA_PHASE && (req & DAP_TRANSFER_RnW)) 204 | dap_swd_clock(32 + 1); 205 | 206 | dap_swd_clock(DAP_SWD_TURNAROUND); 207 | 208 | DAP_CONFIG_SWDIO_out(); 209 | 210 | if (DAP_SWD_DATA_PHASE && (0 == (req & DAP_TRANSFER_RnW))) 211 | { 212 | DAP_CONFIG_SWDIO_write(0); 213 | dap_swd_clock(32 + 1); 214 | } 215 | } 216 | 217 | else 218 | { 219 | dap_swd_clock(DAP_SWD_TURNAROUND + 32 + 1); 220 | } 221 | 222 | DAP_CONFIG_SWDIO_write(1); 223 | 224 | return ack; 225 | } 226 | 227 | //----------------------------------------------------------------------------- 228 | static int dap_swd_transfer_word(int req, uint32_t *data) 229 | { 230 | int ack; 231 | 232 | req &= (DAP_TRANSFER_APnDP | DAP_TRANSFER_RnW | DAP_TRANSFER_A2 | DAP_TRANSFER_A3); 233 | 234 | for (int i = 0; i < DAP_RETRY_COUNT; i++) 235 | { 236 | ack = dap_swd_operation(req, data); 237 | 238 | if (DAP_TRANSFER_WAIT != ack) 239 | break; 240 | } 241 | 242 | return ack; 243 | } 244 | 245 | //----------------------------------------------------------------------------- 246 | static int dap_swd_transfer(int request, uint32_t *data) 247 | { 248 | int ack = DAP_TRANSFER_INVALID; 249 | bool posted_read = false; 250 | bool verify_write = false; 251 | 252 | if (request & DAP_TRANSFER_RnW) 253 | { 254 | if (request & DAP_TRANSFER_APnDP) 255 | { 256 | ack = dap_swd_transfer_word(request, NULL); 257 | 258 | if (ack != DAP_TRANSFER_OK) 259 | return ack; 260 | 261 | posted_read = true; 262 | } 263 | else 264 | { 265 | ack = dap_swd_transfer_word(request, data); 266 | 267 | if (DAP_TRANSFER_OK != ack) 268 | return ack; 269 | } 270 | } 271 | else 272 | { 273 | ack = dap_swd_transfer_word(request, data); 274 | 275 | if (ack != DAP_TRANSFER_OK) 276 | return ack; 277 | 278 | verify_write = true; 279 | } 280 | 281 | if (DAP_TRANSFER_OK == ack) 282 | { 283 | if (posted_read) 284 | ack = dap_swd_transfer_word(SWD_DP_R_RDBUFF | DAP_TRANSFER_RnW, data); 285 | 286 | else if (verify_write) 287 | ack = dap_swd_transfer_word(SWD_DP_R_RDBUFF | DAP_TRANSFER_RnW, NULL); 288 | } 289 | 290 | return ack; 291 | } 292 | 293 | //----------------------------------------------------------------------------- 294 | static void dap_swj_sequence(int size, uint8_t *data) 295 | { 296 | int offset = 0; 297 | 298 | while (size) 299 | { 300 | int sz = (size > 8) ? 8 : size; 301 | 302 | dap_swd_write(data[offset], sz); 303 | 304 | size -= sz; 305 | offset++; 306 | } 307 | } 308 | 309 | //----------------------------------------------------------------------------- 310 | static bool dap_read_reg(uint8_t reg, uint32_t *value) 311 | { 312 | return (DAP_TRANSFER_OK == dap_swd_transfer(reg | DAP_TRANSFER_RnW, value)); 313 | } 314 | 315 | //----------------------------------------------------------------------------- 316 | static bool dap_write_reg(uint8_t reg, uint32_t value) 317 | { 318 | return (DAP_TRANSFER_OK == dap_swd_transfer(reg, &value)); 319 | } 320 | 321 | //----------------------------------------------------------------------------- 322 | void dap_init(void) 323 | { 324 | DAP_CONFIG_SETUP(); 325 | } 326 | 327 | //----------------------------------------------------------------------------- 328 | void dap_connect(void) 329 | { 330 | DAP_CONFIG_CONNECT_SWD(); 331 | } 332 | 333 | //----------------------------------------------------------------------------- 334 | void dap_disconnect(void) 335 | { 336 | DAP_CONFIG_DISCONNECT(); 337 | } 338 | 339 | //----------------------------------------------------------------------------- 340 | uint32_t dap_read_word(uint32_t addr) 341 | { 342 | uint32_t data; 343 | 344 | if (!dap_write_reg(SWD_AP_TAR, addr)) 345 | return 0; 346 | 347 | if (!dap_read_reg(SWD_AP_DRW, &data)) 348 | return 0; 349 | 350 | return data; 351 | } 352 | 353 | //----------------------------------------------------------------------------- 354 | void dap_write_word(uint32_t addr, uint32_t data) 355 | { 356 | dap_write_reg(SWD_AP_TAR, addr); 357 | dap_write_reg(SWD_AP_DRW, data); 358 | } 359 | 360 | //----------------------------------------------------------------------------- 361 | void dap_reset_link(void) 362 | { 363 | uint8_t buf[20]; 364 | uint32_t idcode; 365 | 366 | buf[0] = 0xff; 367 | buf[1] = 0xff; 368 | buf[2] = 0xff; 369 | buf[3] = 0xff; 370 | buf[4] = 0xff; 371 | buf[5] = 0xff; 372 | buf[6] = 0xff; 373 | buf[7] = 0x9e; 374 | buf[8] = 0xe7; 375 | buf[9] = 0xff; 376 | buf[10] = 0xff; 377 | buf[11] = 0xff; 378 | buf[12] = 0xff; 379 | buf[13] = 0xff; 380 | buf[14] = 0xff; 381 | buf[15] = 0xff; 382 | buf[16] = 0x00; 383 | 384 | dap_swj_sequence((7 + 2 + 7 + 1) * 8, buf); 385 | 386 | dap_read_reg(SWD_DP_R_IDCODE, &idcode); 387 | } 388 | 389 | //----------------------------------------------------------------------------- 390 | uint32_t dap_read_idcode(void) 391 | { 392 | uint32_t idcode; 393 | 394 | if (dap_read_reg(SWD_DP_R_IDCODE, &idcode)) 395 | return idcode; 396 | 397 | return 0xffffffff; 398 | } 399 | 400 | //----------------------------------------------------------------------------- 401 | void dap_target_prepare(void) 402 | { 403 | dap_write_reg(SWD_DP_W_ABORT, 0x00000016); 404 | dap_write_reg(SWD_DP_W_SELECT, 0x00000000); 405 | dap_write_reg(SWD_DP_W_CTRL_STAT, 0x50000f00); 406 | dap_write_reg(SWD_AP_CSW, 0x23000052); 407 | } 408 | 409 | -------------------------------------------------------------------------------- /raspberry-pi/dap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _DAP_H_ 30 | #define _DAP_H_ 31 | 32 | /*- Includes ----------------------------------------------------------------*/ 33 | #include 34 | 35 | /*- Prototypes --------------------------------------------------------------*/ 36 | #define TARGET_ROW_SIZE 256 37 | #define TARGET_PAGE_SIZE 64 38 | #define TARGET_FLASH_SIZE (16*1024) 39 | 40 | /*- Prototypes --------------------------------------------------------------*/ 41 | void dap_init(void); 42 | void dap_connect(void); 43 | void dap_disconnect(void); 44 | uint32_t dap_read_word(uint32_t addr); 45 | void dap_write_word(uint32_t addr, uint32_t data); 46 | void dap_reset_link(void); 47 | uint32_t dap_read_idcode(void); 48 | void dap_target_prepare(void); 49 | 50 | // Target operations 51 | void dap_target_select(void); 52 | void dap_target_deselect(void); 53 | void dap_target_erase(void); 54 | void dap_target_lock(void); 55 | void dap_target_erase_row(uint32_t addr); 56 | void dap_target_write_page(uint32_t addr, uint8_t *data); 57 | void dap_target_read_page(uint32_t addr, uint8_t *data); 58 | 59 | #endif // _DAP_H_ 60 | 61 | -------------------------------------------------------------------------------- /raspberry-pi/dap_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _DAP_CONFIG_H_ 30 | #define _DAP_CONFIG_H_ 31 | 32 | /*- Includes ----------------------------------------------------------------*/ 33 | #include "hal_gpio.h" 34 | 35 | /*- Definitions -------------------------------------------------------------*/ 36 | HAL_GPIO_PIN(SWCLK, 2) 37 | HAL_GPIO_PIN(SWDIO, 3) 38 | 39 | #define DAP_CONFIG_CLOCK_DELAY 500 40 | 41 | /*- Implementations ---------------------------------------------------------*/ 42 | 43 | //----------------------------------------------------------------------------- 44 | static inline void DAP_CONFIG_SWCLK_write(int value) 45 | { 46 | HAL_GPIO_SWCLK_write(value); 47 | } 48 | 49 | //----------------------------------------------------------------------------- 50 | static inline void DAP_CONFIG_SWDIO_write(int value) 51 | { 52 | HAL_GPIO_SWDIO_write(value); 53 | } 54 | 55 | //----------------------------------------------------------------------------- 56 | static inline int DAP_CONFIG_SWCLK_read(void) 57 | { 58 | return HAL_GPIO_SWCLK_read(); 59 | } 60 | 61 | //----------------------------------------------------------------------------- 62 | static inline int DAP_CONFIG_SWDIO_read(void) 63 | { 64 | return HAL_GPIO_SWDIO_read(); 65 | } 66 | 67 | //----------------------------------------------------------------------------- 68 | static inline void DAP_CONFIG_SWCLK_set(void) 69 | { 70 | HAL_GPIO_SWCLK_set(); 71 | } 72 | 73 | //----------------------------------------------------------------------------- 74 | static inline void DAP_CONFIG_SWCLK_clr(void) 75 | { 76 | HAL_GPIO_SWCLK_clr(); 77 | } 78 | 79 | //----------------------------------------------------------------------------- 80 | static inline void DAP_CONFIG_SWDIO_in(void) 81 | { 82 | HAL_GPIO_SWDIO_in(); 83 | } 84 | 85 | //----------------------------------------------------------------------------- 86 | static inline void DAP_CONFIG_SWDIO_out(void) 87 | { 88 | HAL_GPIO_SWDIO_out(); 89 | } 90 | 91 | //----------------------------------------------------------------------------- 92 | static inline void DAP_CONFIG_SETUP(void) 93 | { 94 | HAL_GPIO_SWCLK_in(); 95 | 96 | HAL_GPIO_SWDIO_in(); 97 | HAL_GPIO_SWDIO_pullup(); 98 | } 99 | 100 | //----------------------------------------------------------------------------- 101 | static inline void DAP_CONFIG_DISCONNECT(void) 102 | { 103 | HAL_GPIO_SWCLK_in(); 104 | HAL_GPIO_SWDIO_in(); 105 | } 106 | 107 | //----------------------------------------------------------------------------- 108 | static inline void DAP_CONFIG_CONNECT_SWD(void) 109 | { 110 | HAL_GPIO_SWDIO_out(); 111 | HAL_GPIO_SWDIO_set(); 112 | 113 | HAL_GPIO_SWCLK_out(); 114 | HAL_GPIO_SWCLK_set(); 115 | } 116 | 117 | #endif // _DAP_CONFIG_H_ 118 | 119 | -------------------------------------------------------------------------------- /raspberry-pi/dap_target.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2016, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | /*- Includes ----------------------------------------------------------------*/ 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include "dap.h" 36 | 37 | /*- Definitions -------------------------------------------------------------*/ 38 | #define DHCSR 0xe000edf0 39 | #define DEMCR 0xe000edfc 40 | #define AIRCR 0xe000ed0c 41 | 42 | #define DSU_CTRL_STATUS 0x41002100 43 | #define DSU_DID 0x41002118 44 | 45 | #define NVMCTRL_CTRLA 0x41004000 46 | #define NVMCTRL_CTRLB 0x41004004 47 | #define NVMCTRL_PARAM 0x41004008 48 | #define NVMCTRL_INTFLAG 0x41004014 49 | #define NVMCTRL_STATUS 0x41004018 50 | #define NVMCTRL_ADDR 0x4100401c 51 | 52 | #define NVMCTRL_CMD_ER 0xa502 53 | #define NVMCTRL_CMD_WP 0xa504 54 | #define NVMCTRL_CMD_EAR 0xa505 55 | #define NVMCTRL_CMD_WAP 0xa506 56 | #define NVMCTRL_CMD_WL 0xa50f 57 | #define NVMCTRL_CMD_UR 0xa541 58 | #define NVMCTRL_CMD_PBC 0xa544 59 | #define NVMCTRL_CMD_SSB 0xa545 60 | 61 | /*- Implementations ---------------------------------------------------------*/ 62 | 63 | //----------------------------------------------------------------------------- 64 | void dap_target_select(void) 65 | { 66 | // Stop the core 67 | dap_write_word(DHCSR, 0xa05f0003); 68 | dap_write_word(DEMCR, 0x00000001); 69 | dap_write_word(AIRCR, 0x05fa0004); 70 | 71 | // Enable automatic writes 72 | dap_write_word(NVMCTRL_CTRLB, 0); 73 | } 74 | 75 | //----------------------------------------------------------------------------- 76 | void dap_target_deselect(void) 77 | { 78 | dap_write_word(DEMCR, 0x00000000); 79 | dap_write_word(AIRCR, 0x05fa0004); 80 | } 81 | 82 | //----------------------------------------------------------------------------- 83 | void dap_target_erase(void) 84 | { 85 | dap_write_word(DSU_CTRL_STATUS, 0x00001f00); // Clear flags 86 | dap_write_word(DSU_CTRL_STATUS, 0x00000010); // Chip erase 87 | while (0 == (dap_read_word(DSU_CTRL_STATUS) & 0x00000100)); 88 | } 89 | 90 | //----------------------------------------------------------------------------- 91 | void dap_target_lock(void) 92 | { 93 | dap_write_word(NVMCTRL_CTRLA, NVMCTRL_CMD_SSB); // Set Security Bit 94 | } 95 | 96 | //----------------------------------------------------------------------------- 97 | void dap_target_erase_row(uint32_t addr) 98 | { 99 | dap_write_word(NVMCTRL_ADDR, addr >> 1); 100 | 101 | dap_write_word(NVMCTRL_CTRLA, NVMCTRL_CMD_UR); // Unlock Region 102 | while (0 == (dap_read_word(NVMCTRL_INTFLAG) & 1)); 103 | 104 | dap_write_word(NVMCTRL_CTRLA, NVMCTRL_CMD_ER); // Erase Row 105 | while (0 == (dap_read_word(NVMCTRL_INTFLAG) & 1)); 106 | } 107 | 108 | //----------------------------------------------------------------------------- 109 | void dap_target_write_page(uint32_t addr, uint8_t *data) 110 | { 111 | dap_write_word(NVMCTRL_ADDR, addr >> 1); 112 | 113 | dap_write_word(NVMCTRL_CTRLA, NVMCTRL_CMD_UR); // Unlock Region 114 | while (0 == (dap_read_word(NVMCTRL_INTFLAG) & 1)); 115 | 116 | for (int offs = 0; offs < TARGET_PAGE_SIZE; offs += sizeof(uint32_t)) 117 | { 118 | uint32_t value = 119 | ((uint32_t)data[offs + 3] << 24) | ((uint32_t)data[offs + 2] << 16) | 120 | ((uint32_t)data[offs + 1] << 8) | (uint32_t)data[offs]; 121 | 122 | dap_write_word(addr + offs, value); 123 | } 124 | } 125 | 126 | //----------------------------------------------------------------------------- 127 | void dap_target_read_page(uint32_t addr, uint8_t *data) 128 | { 129 | for (int offs = 0; offs < TARGET_PAGE_SIZE; offs += sizeof(uint32_t)) 130 | { 131 | uint32_t value = dap_read_word(addr + offs); 132 | 133 | data[offs + 0] = (value >> 0) & 0xff; 134 | data[offs + 1] = (value >> 8) & 0xff; 135 | data[offs + 2] = (value >> 16) & 0xff; 136 | data[offs + 3] = (value >> 24) & 0xff; 137 | } 138 | } 139 | 140 | -------------------------------------------------------------------------------- /raspberry-pi/hal_gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #ifndef _HAL_GPIO_H_ 30 | #define _HAL_GPIO_H_ 31 | 32 | /*- Includes ----------------------------------------------------------------*/ 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | /*- Definitions -------------------------------------------------------------*/ 40 | // Note: 0x3f000000 for RPi 2B+ and above, 0x20000000 for older models 41 | #define BCM_GPIO_BASE 0x3f200000 42 | #define BCM_GPIO_SIZE 4096 43 | 44 | enum 45 | { 46 | HAL_GPIO_ALT_0 = 4, 47 | HAL_GPIO_ALT_1 = 5, 48 | HAL_GPIO_ALT_2 = 6, 49 | HAL_GPIO_ALT_3 = 7, 50 | HAL_GPIO_ALT_4 = 3, 51 | HAL_GPIO_ALT_5 = 2, 52 | }; 53 | 54 | /*- Types -------------------------------------------------------------------*/ 55 | typedef struct 56 | { 57 | uint32_t GPFSEL[6]; 58 | uint32_t reserved0; 59 | uint32_t GPSET[2]; 60 | uint32_t reserved1; 61 | uint32_t GPCLR[2]; 62 | uint32_t reserved2; 63 | uint32_t GPLEV[2]; 64 | uint32_t reserved3; 65 | uint32_t GPEDS[2]; 66 | uint32_t reserved4; 67 | uint32_t GPREN[2]; 68 | uint32_t reserved5; 69 | uint32_t GPFEN[2]; 70 | uint32_t reserved6; 71 | uint32_t GPHEN[2]; 72 | uint32_t reserved7; 73 | uint32_t GPLEN[2]; 74 | uint32_t reserved8; 75 | uint32_t GPAREN[2]; 76 | uint32_t reserved9; 77 | uint32_t GPAFEN[2]; 78 | uint32_t reserved10; 79 | uint32_t GPPUD; 80 | uint32_t GPPUDCLK[2]; 81 | } bcm_gpio_t; 82 | 83 | /*- Variables ---------------------------------------------------------------*/ 84 | extern volatile bcm_gpio_t *BCM_GPIO; 85 | 86 | /*- Implementations ---------------------------------------------------------*/ 87 | 88 | //----------------------------------------------------------------------------- 89 | static inline void bcm_gpio_init(void) 90 | { 91 | int fd; 92 | 93 | fd = open("/dev/mem", O_RDWR | O_SYNC); 94 | 95 | if (fd < 0) 96 | err(0, "can't open /dev/mem"); 97 | 98 | BCM_GPIO = (volatile bcm_gpio_t *)mmap(NULL, BCM_GPIO_SIZE, PROT_READ | PROT_WRITE, 99 | MAP_SHARED, fd, BCM_GPIO_BASE); 100 | 101 | close(fd); 102 | 103 | if (MAP_FAILED == BCM_GPIO) 104 | err(0, "mmap() error"); 105 | 106 | (void)bcm_gpio_init; 107 | } 108 | 109 | //----------------------------------------------------------------------------- 110 | static inline void bcm_gpio_close(void) 111 | { 112 | munmap((void *)BCM_GPIO, BCM_GPIO_SIZE); 113 | (void)bcm_gpio_close; 114 | } 115 | 116 | //----------------------------------------------------------------------------- 117 | // Note: The code manipulating GPPUDCLK[0] is not atomic, bad things may happen 118 | // if it is interrupted by some other code manipulating the same registers. 119 | 120 | #define HAL_GPIO_PIN(name, index) \ 121 | _Static_assert(index < 28, "GPIO index must be 0-27"); \ 122 | \ 123 | static inline void HAL_GPIO_##name##_set(void) \ 124 | { \ 125 | BCM_GPIO->GPSET[0] = (1 << index); \ 126 | (void)HAL_GPIO_##name##_set; \ 127 | } \ 128 | \ 129 | static inline void HAL_GPIO_##name##_clr(void) \ 130 | { \ 131 | BCM_GPIO->GPCLR[0] = (1 << index); \ 132 | (void)HAL_GPIO_##name##_clr; \ 133 | } \ 134 | \ 135 | static inline void HAL_GPIO_##name##_toggle(void) \ 136 | { \ 137 | if (BCM_GPIO->GPLEV[0] & (1 << index)) \ 138 | BCM_GPIO->GPCLR[0] = (1 << index); \ 139 | else \ 140 | BCM_GPIO->GPSET[0] = (1 << index); \ 141 | (void)HAL_GPIO_##name##_toggle; \ 142 | } \ 143 | \ 144 | static inline void HAL_GPIO_##name##_write(int value) \ 145 | { \ 146 | if (value) \ 147 | BCM_GPIO->GPSET[0] = (1 << index); \ 148 | else \ 149 | BCM_GPIO->GPCLR[0] = (1 << index); \ 150 | (void)HAL_GPIO_##name##_write; \ 151 | } \ 152 | \ 153 | static inline void HAL_GPIO_##name##_in(void) \ 154 | { \ 155 | int idx = index / 10; \ 156 | int pos = (index % 10) * 3; \ 157 | BCM_GPIO->GPFSEL[idx] &= ~(7 << pos); \ 158 | (void)HAL_GPIO_##name##_in; \ 159 | } \ 160 | \ 161 | static inline void HAL_GPIO_##name##_out(void) \ 162 | { \ 163 | int idx = index / 10; \ 164 | int pos = (index % 10) * 3; \ 165 | BCM_GPIO->GPFSEL[idx] &= ~(7 << pos); \ 166 | BCM_GPIO->GPFSEL[idx] |= (1 << pos); \ 167 | (void)HAL_GPIO_##name##_out; \ 168 | } \ 169 | \ 170 | static inline void HAL_GPIO_##name##_alt(int alt) \ 171 | { \ 172 | int idx = index / 10; \ 173 | int pos = (index % 10) * 3; \ 174 | BCM_GPIO->GPFSEL[idx] &= ~(7 << pos); \ 175 | BCM_GPIO->GPFSEL[idx] |= (alt << pos); \ 176 | (void)HAL_GPIO_##name##_alt; \ 177 | } \ 178 | \ 179 | static inline void HAL_GPIO_##name##_pullup(void) \ 180 | { \ 181 | BCM_GPIO->GPPUD = 2; \ 182 | for (int i = 0; i < 150; i++) asm("nop"); \ 183 | BCM_GPIO->GPPUDCLK[0] |= (1 << index); \ 184 | for (int i = 0; i < 150; i++) asm("nop"); \ 185 | BCM_GPIO->GPPUDCLK[0] &= ~(1 << index); \ 186 | (void)HAL_GPIO_##name##_pullup; \ 187 | } \ 188 | \ 189 | static inline void HAL_GPIO_##name##_pulldown(void) \ 190 | { \ 191 | BCM_GPIO->GPPUD = 1; \ 192 | for (int i = 0; i < 150; i++) asm("nop"); \ 193 | BCM_GPIO->GPPUDCLK[0] |= (1 << index); \ 194 | for (int i = 0; i < 150; i++) asm("nop"); \ 195 | BCM_GPIO->GPPUDCLK[0] &= ~(1 << index); \ 196 | (void)HAL_GPIO_##name##_pulldown; \ 197 | } \ 198 | \ 199 | static inline void HAL_GPIO_##name##_pulloff(void) \ 200 | { \ 201 | BCM_GPIO->GPPUD = 0; \ 202 | for (int i = 0; i < 150; i++) asm("nop"); \ 203 | BCM_GPIO->GPPUDCLK[0] |= (1 << index); \ 204 | for (int i = 0; i < 150; i++) asm("nop"); \ 205 | BCM_GPIO->GPPUDCLK[0] &= ~(1 << index); \ 206 | (void)HAL_GPIO_##name##_pulloff; \ 207 | } \ 208 | \ 209 | static inline int HAL_GPIO_##name##_read(void) \ 210 | { \ 211 | return ((BCM_GPIO->GPLEV[0] & (1 << index)) > 0); \ 212 | (void)HAL_GPIO_##name##_read; \ 213 | } \ 214 | 215 | #endif // _HAL_GPIO_H_ 216 | 217 | -------------------------------------------------------------------------------- /raspberry-pi/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, Alex Taradov 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. The name of the author may not be used to endorse or promote products 14 | * derived from this software without specific prior written permission. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | * POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | //----------------------------------------------------------------------------- 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "hal_gpio.h" 37 | #include "dap.h" 38 | 39 | //----------------------------------------------------------------------------- 40 | volatile bcm_gpio_t *BCM_GPIO; 41 | 42 | //----------------------------------------------------------------------------- 43 | static uint8_t buffer[TARGET_FLASH_SIZE]; 44 | 45 | //----------------------------------------------------------------------------- 46 | static void target_connect(void) 47 | { 48 | dap_init(); 49 | dap_connect(); 50 | dap_reset_link(); 51 | dap_target_prepare(); 52 | dap_target_select(); 53 | } 54 | 55 | //----------------------------------------------------------------------------- 56 | static void target_id(void) 57 | { 58 | uint32_t idcode = dap_read_idcode(); 59 | uint32_t dsu_did = dap_read_word(0x41002118/*DSU_DID*/); 60 | 61 | printf("IDCODE = 0x%08x\n", idcode); 62 | printf("DSU_DID = 0x%08x\n", dsu_did); 63 | 64 | if (idcode != 0x0bc11477) 65 | { 66 | printf("Error: unexpected IDCODE value\n"); 67 | exit(1); 68 | } 69 | } 70 | 71 | //----------------------------------------------------------------------------- 72 | static void target_erase(void) 73 | { 74 | dap_target_erase(); 75 | } 76 | 77 | //----------------------------------------------------------------------------- 78 | static void target_read(char *name) 79 | { 80 | int ptr = 0; 81 | int addr = 0; 82 | int fd, rsize; 83 | 84 | while (ptr < TARGET_FLASH_SIZE) 85 | { 86 | dap_target_read_page(addr, &buffer[ptr]); 87 | 88 | addr += TARGET_PAGE_SIZE; 89 | ptr += TARGET_PAGE_SIZE; 90 | 91 | printf("."); 92 | fflush(stdout); 93 | } 94 | 95 | fd = open(name, O_WRONLY | O_TRUNC | O_CREAT, 0644); 96 | if (fd < 0) 97 | err(1, "open()"); 98 | 99 | rsize = write(fd, buffer, sizeof(buffer)); 100 | if (rsize < 0) 101 | err(1, "write()"); 102 | 103 | close(fd); 104 | } 105 | 106 | //----------------------------------------------------------------------------- 107 | static void target_write(char *name) 108 | { 109 | int ptr = 0; 110 | int addr = 0; 111 | int fd, rsize; 112 | uint8_t tmp[TARGET_PAGE_SIZE]; 113 | 114 | fd = open(name, O_RDONLY); 115 | if (fd < 0) 116 | err(1, "open()"); 117 | 118 | rsize = read(fd, buffer, sizeof(buffer)); 119 | if (rsize < 0) 120 | err(1, "read()"); 121 | 122 | close(fd); 123 | 124 | while (rsize) 125 | { 126 | int size = (rsize < TARGET_PAGE_SIZE) ? rsize : TARGET_PAGE_SIZE; 127 | 128 | memset(tmp, 0xff, sizeof(tmp)); 129 | memcpy(tmp, &buffer[ptr], size); 130 | 131 | dap_target_write_page(addr, tmp); 132 | 133 | rsize -= size; 134 | addr += size; 135 | ptr += size; 136 | 137 | printf("."); 138 | fflush(stdout); 139 | } 140 | } 141 | 142 | //----------------------------------------------------------------------------- 143 | static void target_verify(char *name) 144 | { 145 | int ptr = 0; 146 | int addr = 0; 147 | int fd, rsize; 148 | uint8_t tmp[TARGET_PAGE_SIZE]; 149 | 150 | fd = open(name, O_RDONLY); 151 | if (fd < 0) 152 | err(1, "open()"); 153 | 154 | rsize = read(fd, buffer, sizeof(buffer)); 155 | if (rsize < 0) 156 | err(1, "read()"); 157 | 158 | close(fd); 159 | 160 | while (rsize) 161 | { 162 | int size = (rsize < TARGET_PAGE_SIZE) ? rsize : TARGET_PAGE_SIZE; 163 | 164 | dap_target_read_page(addr, tmp); 165 | 166 | for (int i = 0; i < size; i++) 167 | { 168 | if (tmp[i] != buffer[ptr + i]) 169 | { 170 | printf("Verification failed at 0x%x: expected 0x%02x, got 0x%02x\n", ptr + i, buffer[ptr + i], tmp[i]); 171 | exit(1); 172 | } 173 | } 174 | 175 | rsize -= size; 176 | addr += size; 177 | ptr += size; 178 | 179 | printf("."); 180 | fflush(stdout); 181 | } 182 | } 183 | 184 | //----------------------------------------------------------------------------- 185 | static void target_disconnect(void) 186 | { 187 | dap_target_deselect(); 188 | dap_disconnect(); 189 | } 190 | 191 | //----------------------------------------------------------------------------- 192 | int main(int argc, char *argv[]) 193 | { 194 | bool cmd_erase = false; 195 | bool cmd_read = false; 196 | bool cmd_write = false; 197 | bool cmd_verify = false; 198 | char *file_name; 199 | 200 | if (argc < 2) 201 | { 202 | printf("Usage: dap_test [erase | read | write | verify] [file_name]\n"); 203 | exit(1); 204 | } 205 | 206 | if (0 == strcmp(argv[1], "erase")) 207 | cmd_erase = true; 208 | else if (0 == strcmp(argv[1], "read")) 209 | cmd_read = true; 210 | else if (0 == strcmp(argv[1], "write")) 211 | cmd_write = true; 212 | else if (0 == strcmp(argv[1], "verify")) 213 | cmd_verify = true; 214 | else 215 | { 216 | printf("Error: invalid command '%s'\n", argv[1]); 217 | exit(1); 218 | } 219 | 220 | if ((cmd_read | cmd_write | cmd_verify) && (argc < 3)) 221 | { 222 | printf("Error: file name is expected\n"); 223 | exit(1); 224 | } 225 | 226 | file_name = argv[2]; 227 | 228 | bcm_gpio_init(); 229 | 230 | target_connect(); 231 | target_id(); 232 | 233 | if (cmd_erase) 234 | target_erase(); 235 | 236 | if (cmd_read) 237 | target_read(file_name); 238 | 239 | if (cmd_write) 240 | target_write(file_name); 241 | 242 | if (cmd_verify) 243 | target_verify(file_name); 244 | 245 | target_disconnect(); 246 | 247 | bcm_gpio_close(); 248 | 249 | printf("\n"); 250 | 251 | return 0; 252 | } 253 | 254 | 255 | --------------------------------------------------------------------------------