├── .gitignore ├── DAP.cpp ├── DAP.h ├── DAP_config.h ├── JTAG_DP.cpp ├── LICENSE ├── README.md ├── SW_DP.cpp ├── arduino-cmsis-dap.ino ├── board.cpp ├── board.h ├── dap_vendor_command.cpp ├── debug_cm.h ├── gpio.h ├── read_uid.h ├── semihost.cpp ├── semihost.h ├── target_reset.h ├── target_struct.h ├── tasks.h └── uart.h /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *~ 3 | -------------------------------------------------------------------------------- /DAP.cpp: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP Interface Firmware 2 | * Copyright (c) 2009-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include "DAP_config.h" 19 | #include "DAP.h" 20 | #include "semihost.h" 21 | 22 | 23 | #define DAP_FW_VER "1.0" // Firmware Version 24 | 25 | 26 | #if (DAP_PACKET_SIZE < 64) 27 | #error "Minimum Packet Size is 64" 28 | #endif 29 | #if (DAP_PACKET_SIZE > 32768) 30 | #error "Maximum Packet Size is 32768" 31 | #endif 32 | #if (DAP_PACKET_COUNT < 1) 33 | #error "Minimum Packet Count is 1" 34 | #endif 35 | #if (DAP_PACKET_COUNT > 255) 36 | #error "Maximum Packet Count is 255" 37 | #endif 38 | 39 | 40 | // Clock Macros 41 | 42 | #define MAX_SWJ_CLOCK(delay_cycles) \ 43 | (CPU_CLOCK/2 / (IO_PORT_WRITE_CYCLES + delay_cycles)) 44 | 45 | #define CLOCK_DELAY(swj_clock) \ 46 | ((CPU_CLOCK/2 / swj_clock) - IO_PORT_WRITE_CYCLES) 47 | 48 | 49 | DAP_Data_t DAP_Data; // DAP Data 50 | volatile uint8_t DAP_TransferAbort; // Trasfer Abort Flag 51 | 52 | 53 | #ifdef DAP_VENDOR 54 | const char DAP_Vendor [] = DAP_VENDOR; 55 | #endif 56 | #ifdef DAP_PRODUCT 57 | const char DAP_Product[] = DAP_PRODUCT; 58 | #endif 59 | #ifdef DAP_SER_NUM 60 | const char DAP_SerNum [] = DAP_SER_NUM; 61 | #endif 62 | const char DAP_FW_Ver [] = DAP_FW_VER; 63 | 64 | #if TARGET_DEVICE_FIXED 65 | const char TargetDeviceVendor [] = TARGET_DEVICE_VENDOR; 66 | const char TargetDeviceName [] = TARGET_DEVICE_NAME; 67 | #endif 68 | 69 | 70 | // Get DAP Information 71 | // id: info identifier 72 | // info: pointer to info data 73 | // return: number of bytes in info data 74 | static uint8_t DAP_Info(uint8_t id, uint8_t *info) { 75 | uint8_t length = 0; 76 | 77 | switch (id) { 78 | case DAP_ID_VENDOR: 79 | #ifdef DAP_VENDOR 80 | memcpy(info, DAP_Vendor, sizeof(DAP_Vendor)); 81 | length = sizeof(DAP_Vendor); 82 | #endif 83 | break; 84 | case DAP_ID_PRODUCT: 85 | #ifdef DAP_PRODUCT 86 | memcpy(info, DAP_Product, sizeof(DAP_Product)); 87 | length = sizeof(DAP_Product); 88 | #endif 89 | break; 90 | case DAP_ID_SER_NUM: 91 | #ifdef DAP_SER_NUM 92 | memcpy(info, DAP_SerNum, sizeof(DAP_SerNum)); 93 | length = sizeof(DAP_SerNum); 94 | #endif 95 | break; 96 | case DAP_ID_FW_VER: 97 | memcpy(info, DAP_FW_Ver, sizeof(DAP_FW_Ver)); 98 | length = sizeof(DAP_FW_Ver); 99 | break; 100 | case DAP_ID_DEVICE_VENDOR: 101 | #if TARGET_DEVICE_FIXED 102 | memcpy(info, TargetDeviceVendor, sizeof(TargetDeviceVendor)); 103 | length = sizeof(TargetDeviceVendor); 104 | #endif 105 | break; 106 | case DAP_ID_DEVICE_NAME: 107 | #if TARGET_DEVICE_FIXED 108 | memcpy(info, TargetDeviceName, sizeof(TargetDeviceName)); 109 | length = sizeof(TargetDeviceName); 110 | #endif 111 | break; 112 | case DAP_ID_CAPABILITIES: 113 | info[0] = ((DAP_SWD != 0) ? (1 << 0) : 0) | 114 | ((DAP_JTAG != 0) ? (1 << 1) : 0); 115 | length = 1; 116 | break; 117 | case DAP_ID_PACKET_SIZE: 118 | info[0] = (uint8_t)(DAP_PACKET_SIZE >> 0); 119 | info[1] = (uint8_t)(DAP_PACKET_SIZE >> 8); 120 | length = 2; 121 | break; 122 | case DAP_ID_PACKET_COUNT: 123 | info[0] = DAP_PACKET_COUNT; 124 | length = 1; 125 | break; 126 | } 127 | 128 | return (length); 129 | } 130 | 131 | 132 | // Timer Functions 133 | 134 | #if ((DAP_SWD != 0) || (DAP_JTAG != 0)) 135 | 136 | // Start Timer 137 | static __inline void TIMER_START (uint32_t usec) { 138 | //TODO 139 | // SysTick->VAL = 0; 140 | // SysTick->LOAD = usec * CPU_CLOCK/1000000; 141 | // SysTick->CTRL = (1 << SysTick_CTRL_ENABLE_Pos) | 142 | // (1 << SysTick_CTRL_CLKSOURCE_Pos); 143 | } 144 | 145 | // Stop Timer 146 | static __inline void TIMER_STOP (void) { 147 | //TODO SysTick->CTRL = 0; 148 | } 149 | 150 | // Check if Timer expired 151 | static __inline uint32_t TIMER_EXPIRED (void) { 152 | return 0; //TODO return ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) ? 1 : 0); 153 | } 154 | 155 | #endif 156 | 157 | 158 | // Delay for specified time 159 | // delay: delay time in ms 160 | void Delayms(uint32_t delay) { 161 | delay *= (CPU_CLOCK/1000 + (DELAY_SLOW_CYCLES-1)) / DELAY_SLOW_CYCLES; 162 | PIN_DELAY_SLOW(delay); 163 | } 164 | 165 | 166 | // Process Delay command and prepare response 167 | // request: pointer to request data 168 | // response: pointer to response data 169 | // return: number of bytes in response 170 | static uint32_t DAP_Delay(uint8_t *request, uint8_t *response) { 171 | uint32_t delay; 172 | 173 | delay = *(request+0) | (*(request+1) << 8); 174 | delay *= (CPU_CLOCK/1000000 + (DELAY_SLOW_CYCLES-1)) / DELAY_SLOW_CYCLES; 175 | 176 | PIN_DELAY_SLOW(delay); 177 | 178 | *response = DAP_OK; 179 | return (1); 180 | } 181 | 182 | 183 | // Process Host Status command and prepare response 184 | // request: pointer to request data 185 | // response: pointer to response data 186 | // return: number of bytes in response 187 | static uint32_t DAP_HostStatus(uint8_t *request, uint8_t *response) { 188 | 189 | switch (*request) { 190 | case DAP_DEBUGGER_CONNECTED: 191 | LED_CONNECTED_OUT((*(request+1) & 1)); 192 | break; 193 | case DAP_TARGET_RUNNING: 194 | LED_RUNNING_OUT((*(request+1) & 1)); 195 | break; 196 | default: 197 | *response = DAP_ERROR; 198 | return (1); 199 | } 200 | 201 | *response = DAP_OK; 202 | return (1); 203 | } 204 | 205 | 206 | // Process Connect command and prepare response 207 | // request: pointer to request data 208 | // response: pointer to response data 209 | // return: number of bytes in response 210 | static uint32_t DAP_Connect(uint8_t *request, uint8_t *response) { 211 | uint32_t port; 212 | 213 | if (*request == DAP_PORT_AUTODETECT) { 214 | port = DAP_DEFAULT_PORT; 215 | } else { 216 | port = *request; 217 | } 218 | 219 | semihost_disable(); 220 | 221 | switch (port) { 222 | #if (DAP_SWD != 0) 223 | case DAP_PORT_SWD: 224 | DAP_Data.debug_port = DAP_PORT_SWD; 225 | PORT_SWD_SETUP(); 226 | break; 227 | #endif 228 | #if (DAP_JTAG != 0) 229 | case DAP_PORT_JTAG: 230 | DAP_Data.debug_port = DAP_PORT_JTAG; 231 | PORT_JTAG_SETUP(); 232 | break; 233 | #endif 234 | default: 235 | *response = DAP_PORT_DISABLED; 236 | return (1); 237 | } 238 | 239 | *response = port; 240 | return (1); 241 | } 242 | 243 | 244 | // Process Disconnect command and prepare response 245 | // request: pointer to request data 246 | // response: pointer to response data 247 | // return: number of bytes in response 248 | static uint32_t DAP_Disconnect(uint8_t *response) { 249 | 250 | DAP_Data.debug_port = DAP_PORT_DISABLED; 251 | PORT_OFF(); 252 | 253 | semihost_enable(); 254 | 255 | *response = DAP_OK; 256 | return (1); 257 | } 258 | 259 | 260 | // Process Reset Target command and prepare response 261 | // request: pointer to request data 262 | // response: pointer to response data 263 | // return: number of bytes in response 264 | static uint32_t DAP_ResetTarget(uint8_t *response) { 265 | 266 | *(response+1) = RESET_TARGET(); 267 | *(response+0) = DAP_OK; 268 | return (2); 269 | } 270 | 271 | 272 | // Process SWJ Pins command and prepare response 273 | // request: pointer to request data 274 | // response: pointer to response data 275 | // return: number of bytes in response 276 | #if ((DAP_SWD != 0) || (DAP_JTAG != 0)) 277 | static uint32_t DAP_SWJ_Pins(uint8_t *request, uint8_t *response) { 278 | uint32_t value; 279 | uint32_t select; 280 | uint32_t wait; 281 | 282 | value = *(request+0); 283 | select = *(request+1); 284 | wait = (*(request+2) << 0) | 285 | (*(request+3) << 8) | 286 | (*(request+4) << 16) | 287 | (*(request+5) << 24); 288 | 289 | if (select & (1 << DAP_SWJ_SWCLK_TCK)) { 290 | if (value & (1 << DAP_SWJ_SWCLK_TCK)) { 291 | PIN_SWCLK_TCK_SET(); 292 | } else { 293 | PIN_SWCLK_TCK_CLR(); 294 | } 295 | } 296 | if (select & (1 << DAP_SWJ_SWDIO_TMS)) { 297 | if (value & (1 << DAP_SWJ_SWDIO_TMS)) { 298 | PIN_SWDIO_TMS_SET(); 299 | } else { 300 | PIN_SWDIO_TMS_CLR(); 301 | } 302 | } 303 | if (select & (1 << DAP_SWJ_TDI)) { 304 | PIN_TDI_OUT(value >> DAP_SWJ_TDI); 305 | } 306 | if (select & (1 << DAP_SWJ_nTRST)) { 307 | PIN_nTRST_OUT(value >> DAP_SWJ_nTRST); 308 | } 309 | if (select & (1 << DAP_SWJ_nRESET)) { 310 | PIN_nRESET_OUT(value >> DAP_SWJ_nRESET); 311 | } 312 | 313 | if (wait) { 314 | if (wait > 3000000) wait = 3000000; 315 | TIMER_START(wait); 316 | do { 317 | if (select & (1 << DAP_SWJ_SWCLK_TCK)) { 318 | if ((value >> DAP_SWJ_SWCLK_TCK) ^ PIN_SWCLK_TCK_IN()) continue; 319 | } 320 | if (select & (1 << DAP_SWJ_SWDIO_TMS)) { 321 | if ((value >> DAP_SWJ_SWDIO_TMS) ^ PIN_SWDIO_TMS_IN()) continue; 322 | } 323 | if (select & (1 << DAP_SWJ_TDI)) { 324 | if ((value >> DAP_SWJ_TDI) ^ PIN_TDI_IN()) continue; 325 | } 326 | if (select & (1 << DAP_SWJ_nTRST)) { 327 | if ((value >> DAP_SWJ_nTRST) ^ PIN_nTRST_IN()) continue; 328 | } 329 | if (select & (1 << DAP_SWJ_nRESET)) { 330 | if ((value >> DAP_SWJ_nRESET) ^ PIN_nRESET_IN()) continue; 331 | } 332 | break; 333 | } while (!TIMER_EXPIRED()); 334 | TIMER_STOP(); 335 | } 336 | 337 | value = (PIN_SWCLK_TCK_IN() << DAP_SWJ_SWCLK_TCK) | 338 | (PIN_SWDIO_TMS_IN() << DAP_SWJ_SWDIO_TMS) | 339 | (PIN_TDI_IN() << DAP_SWJ_TDI) | 340 | (PIN_TDO_IN() << DAP_SWJ_TDO) | 341 | (PIN_nTRST_IN() << DAP_SWJ_nTRST) | 342 | (PIN_nRESET_IN() << DAP_SWJ_nRESET); 343 | 344 | *response = (uint8_t)value; 345 | return (1); 346 | } 347 | #endif 348 | 349 | 350 | // Process SWJ Clock command and prepare response 351 | // request: pointer to request data 352 | // response: pointer to response data 353 | // return: number of bytes in response 354 | #if ((DAP_SWD != 0) || (DAP_JTAG != 0)) 355 | static uint32_t DAP_SWJ_Clock(uint8_t *request, uint8_t *response) { 356 | uint32_t clock; 357 | uint32_t delay; 358 | 359 | clock = (*(request+0) << 0) | 360 | (*(request+1) << 8) | 361 | (*(request+2) << 16) | 362 | (*(request+3) << 24); 363 | 364 | if (clock == 0) { 365 | *response = DAP_ERROR; 366 | return (1); 367 | } 368 | 369 | if (clock >= MAX_SWJ_CLOCK(DELAY_FAST_CYCLES)) { 370 | DAP_Data.fast_clock = 1; 371 | DAP_Data.clock_delay = 1; 372 | } else { 373 | DAP_Data.fast_clock = 0; 374 | 375 | delay = (CPU_CLOCK/2 + (clock - 1)) / clock; 376 | if (delay > IO_PORT_WRITE_CYCLES) { 377 | delay -= IO_PORT_WRITE_CYCLES; 378 | delay = (delay + (DELAY_SLOW_CYCLES - 1)) / DELAY_SLOW_CYCLES; 379 | } else { 380 | delay = 1; 381 | } 382 | 383 | DAP_Data.clock_delay = delay; 384 | } 385 | 386 | *response = DAP_OK; 387 | return (1); 388 | } 389 | #endif 390 | 391 | 392 | // Process SWJ Sequence command and prepare response 393 | // request: pointer to request data 394 | // response: pointer to response data 395 | // return: number of bytes in response 396 | #if ((DAP_SWD != 0) || (DAP_JTAG != 0)) 397 | static uint32_t DAP_SWJ_Sequence(uint8_t *request, uint8_t *response) { 398 | uint32_t count; 399 | 400 | count = *request++; 401 | if (count == 0) count = 256; 402 | 403 | SWJ_Sequence(count, request); 404 | 405 | *response = DAP_OK; 406 | return (1); 407 | } 408 | #endif 409 | 410 | 411 | // Process SWD Configure command and prepare response 412 | // request: pointer to request data 413 | // response: pointer to response data 414 | // return: number of bytes in response 415 | #if (DAP_SWD != 0) 416 | static uint32_t DAP_SWD_Configure(uint8_t *request, uint8_t *response) { 417 | uint8_t value; 418 | 419 | value = *request; 420 | DAP_Data.swd_conf.turnaround = (value & 0x03) + 1; 421 | DAP_Data.swd_conf.data_phase = (value & 0x04) ? 1 : 0; 422 | 423 | *response = DAP_OK; 424 | 425 | return (1); 426 | } 427 | #endif 428 | 429 | 430 | // Process SWD Abort command and prepare response 431 | // request: pointer to request data 432 | // response: pointer to response data 433 | // return: number of bytes in response 434 | #if (DAP_SWD != 0) 435 | static uint32_t DAP_SWD_Abort(uint8_t *request, uint8_t *response) { 436 | uint32_t data; 437 | 438 | if (DAP_Data.debug_port != DAP_PORT_SWD) { 439 | *response = DAP_ERROR; 440 | return (1); 441 | } 442 | 443 | // Load data (Ignore DAP index) 444 | data = (*(request+1) << 0) | 445 | (*(request+2) << 8) | 446 | (*(request+3) << 16) | 447 | (*(request+4) << 24); 448 | 449 | // Write Abort register 450 | SWD_Transfer(DP_ABORT, &data); 451 | *response = DAP_OK; 452 | 453 | return (1); 454 | } 455 | #endif 456 | 457 | 458 | // Process JTAG Sequence command and prepare response 459 | // request: pointer to request data 460 | // response: pointer to response data 461 | // return: number of bytes in response 462 | #if (DAP_JTAG != 0) 463 | static uint32_t DAP_JTAG_Sequence(uint8_t *request, uint8_t *response) { 464 | uint32_t sequence_info; 465 | uint32_t sequence_count; 466 | uint32_t response_count; 467 | uint32_t count; 468 | 469 | *response++ = DAP_OK; 470 | response_count = 1; 471 | 472 | sequence_count = *request++; 473 | while (sequence_count--) { 474 | sequence_info = *request++; 475 | JTAG_Sequence(sequence_info, request, response); 476 | count = sequence_info & JTAG_SEQUENCE_TCK; 477 | if (count == 0) count = 64; 478 | count = (count + 7) / 8; 479 | request += count; 480 | if (sequence_info & JTAG_SEQUENCE_TDO) { 481 | response += count; 482 | response_count += count; 483 | } 484 | } 485 | 486 | return (response_count); 487 | } 488 | #endif 489 | 490 | 491 | // Process JTAG Configure command and prepare response 492 | // request: pointer to request data 493 | // response: pointer to response data 494 | // return: number of bytes in response 495 | #if (DAP_JTAG != 0) 496 | static uint32_t DAP_JTAG_Configure(uint8_t *request, uint8_t *response) { 497 | uint32_t count; 498 | uint32_t length; 499 | uint32_t bits; 500 | uint32_t n; 501 | 502 | count = *request++; 503 | DAP_Data.jtag_dev.count = count; 504 | 505 | bits = 0; 506 | for (n = 0; n < count; n++) { 507 | length = *request++; 508 | DAP_Data.jtag_dev.ir_length[n] = length; 509 | DAP_Data.jtag_dev.ir_before[n] = bits; 510 | bits += length; 511 | } 512 | for (n = 0; n < count; n++) { 513 | bits -= DAP_Data.jtag_dev.ir_length[n]; 514 | DAP_Data.jtag_dev.ir_after[n] = bits; 515 | } 516 | 517 | *response = DAP_OK; 518 | return (1); 519 | } 520 | #endif 521 | 522 | 523 | // Process JTAG IDCODE command and prepare response 524 | // request: pointer to request data 525 | // response: pointer to response data 526 | // return: number of bytes in response 527 | #if (DAP_JTAG != 0) 528 | static uint32_t DAP_JTAG_IDCode(uint8_t *request, uint8_t *response) { 529 | uint32_t data; 530 | 531 | if (DAP_Data.debug_port != DAP_PORT_JTAG) { 532 | err:*response = DAP_ERROR; 533 | return (1); 534 | } 535 | 536 | // Device index (JTAP TAP) 537 | DAP_Data.jtag_dev.index = *request; 538 | if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto err; 539 | 540 | // Select JTAG chain 541 | JTAG_IR(JTAG_IDCODE); 542 | 543 | // Read IDCODE register 544 | data = JTAG_ReadIDCode(); 545 | 546 | // Store Data 547 | *(response+0) = DAP_OK; 548 | *(response+1) = (uint8_t)(data >> 0); 549 | *(response+2) = (uint8_t)(data >> 8); 550 | *(response+3) = (uint8_t)(data >> 16); 551 | *(response+4) = (uint8_t)(data >> 24); 552 | 553 | return (1+4); 554 | } 555 | #endif 556 | 557 | 558 | // Process JTAG Abort command and prepare response 559 | // request: pointer to request data 560 | // response: pointer to response data 561 | // return: number of bytes in response 562 | #if (DAP_JTAG != 0) 563 | static uint32_t DAP_JTAG_Abort(uint8_t *request, uint8_t *response) { 564 | uint32_t data; 565 | 566 | if (DAP_Data.debug_port != DAP_PORT_JTAG) { 567 | err:*response = DAP_ERROR; 568 | return (1); 569 | } 570 | 571 | // Device index (JTAP TAP) 572 | DAP_Data.jtag_dev.index = *request; 573 | if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto err; 574 | 575 | // Select JTAG chain 576 | JTAG_IR(JTAG_ABORT); 577 | 578 | // Load data 579 | data = (*(request+1) << 0) | 580 | (*(request+2) << 8) | 581 | (*(request+3) << 16) | 582 | (*(request+4) << 24); 583 | 584 | // Write Abort register 585 | JTAG_WriteAbort(data); 586 | *response = DAP_OK; 587 | 588 | return (1); 589 | } 590 | #endif 591 | 592 | 593 | // Process Transfer Configure command and prepare response 594 | // request: pointer to request data 595 | // response: pointer to response data 596 | // return: number of bytes in response 597 | static uint32_t DAP_TransferConfigure(uint8_t *request, uint8_t *response) { 598 | 599 | DAP_Data.transfer.idle_cycles = *(request+0); 600 | DAP_Data.transfer.retry_count = *(request+1) | (*(request+2) << 8); 601 | DAP_Data.transfer.match_retry = *(request+3) | (*(request+4) << 8); 602 | 603 | *response = DAP_OK; 604 | 605 | return (1); 606 | } 607 | 608 | 609 | // Process SWD Transfer command and prepare response 610 | // request: pointer to request data 611 | // response: pointer to response data 612 | // return: number of bytes in response 613 | #if (DAP_SWD != 0) 614 | static uint32_t DAP_SWD_Transfer(uint8_t *request, uint8_t *response) { 615 | uint32_t request_count; 616 | uint32_t request_value; 617 | uint32_t response_count; 618 | uint32_t response_value; 619 | uint8_t *response_head; 620 | uint32_t post_read; 621 | uint32_t check_write; 622 | uint32_t match_value; 623 | uint32_t match_retry; 624 | uint32_t retry; 625 | uint32_t data; 626 | 627 | response_count = 0; 628 | response_value = 0; 629 | response_head = response; 630 | response += 2; 631 | 632 | DAP_TransferAbort = 0; 633 | 634 | post_read = 0; 635 | check_write = 0; 636 | 637 | request++; // Ignore DAP index 638 | 639 | request_count = *request++; 640 | while (request_count--) { 641 | request_value = *request++; 642 | if (request_value & DAP_TRANSFER_RnW) { 643 | // Read register 644 | if (post_read) { 645 | // Read was posted before 646 | retry = DAP_Data.transfer.retry_count; 647 | if ((request_value & (DAP_TRANSFER_APnDP | DAP_TRANSFER_MATCH_VALUE)) == DAP_TRANSFER_APnDP) { 648 | // Read previous AP data and post next AP read 649 | do { 650 | response_value = SWD_Transfer(request_value, &data); 651 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 652 | } else { 653 | // Read previous AP data 654 | do { 655 | response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); 656 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 657 | post_read = 0; 658 | } 659 | if (response_value != DAP_TRANSFER_OK) break; 660 | // Store previous AP data 661 | *response++ = (uint8_t) data; 662 | *response++ = (uint8_t)(data >> 8); 663 | *response++ = (uint8_t)(data >> 16); 664 | *response++ = (uint8_t)(data >> 24); 665 | } 666 | if (request_value & DAP_TRANSFER_MATCH_VALUE) { 667 | // Read with value match 668 | match_value = (*(request+0) << 0) | 669 | (*(request+1) << 8) | 670 | (*(request+2) << 16) | 671 | (*(request+3) << 24); 672 | request += 4; 673 | match_retry = DAP_Data.transfer.match_retry; 674 | if (request_value & DAP_TRANSFER_APnDP) { 675 | // Post AP read 676 | retry = DAP_Data.transfer.retry_count; 677 | do { 678 | response_value = SWD_Transfer(request_value, NULL); 679 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 680 | if (response_value != DAP_TRANSFER_OK) break; 681 | } 682 | do { 683 | // Read register until its value matches or retry counter expires 684 | retry = DAP_Data.transfer.retry_count; 685 | do { 686 | response_value = SWD_Transfer(request_value, &data); 687 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 688 | if (response_value != DAP_TRANSFER_OK) break; 689 | } while (((data & DAP_Data.transfer.match_mask) != match_value) && match_retry-- && !DAP_TransferAbort); 690 | if ((data & DAP_Data.transfer.match_mask) != match_value) { 691 | response_value |= DAP_TRANSFER_MISMATCH; 692 | } 693 | if (response_value != DAP_TRANSFER_OK) break; 694 | } else { 695 | // Normal read 696 | retry = DAP_Data.transfer.retry_count; 697 | if (request_value & DAP_TRANSFER_APnDP) { 698 | // Read AP register 699 | if (post_read == 0) { 700 | // Post AP read 701 | do { 702 | response_value = SWD_Transfer(request_value, NULL); 703 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 704 | if (response_value != DAP_TRANSFER_OK) break; 705 | post_read = 1; 706 | } 707 | } else { 708 | // Read DP register 709 | do { 710 | response_value = SWD_Transfer(request_value, &data); 711 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 712 | if (response_value != DAP_TRANSFER_OK) break; 713 | // Store data 714 | *response++ = (uint8_t) data; 715 | *response++ = (uint8_t)(data >> 8); 716 | *response++ = (uint8_t)(data >> 16); 717 | *response++ = (uint8_t)(data >> 24); 718 | } 719 | } 720 | check_write = 0; 721 | } else { 722 | // Write register 723 | if (post_read) { 724 | // Read previous data 725 | retry = DAP_Data.transfer.retry_count; 726 | do { 727 | response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); 728 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 729 | if (response_value != DAP_TRANSFER_OK) break; 730 | // Store previous data 731 | *response++ = (uint8_t) data; 732 | *response++ = (uint8_t)(data >> 8); 733 | *response++ = (uint8_t)(data >> 16); 734 | *response++ = (uint8_t)(data >> 24); 735 | post_read = 0; 736 | } 737 | // Load data 738 | data = (((uint32_t)*(request+0)) << 0) | 739 | (((uint32_t)*(request+1)) << 8) | 740 | (((uint32_t)*(request+2)) << 16) | 741 | (((uint32_t)*(request+3)) << 24); 742 | request += 4; 743 | if (request_value & DAP_TRANSFER_MATCH_MASK) { 744 | // Write match mask 745 | DAP_Data.transfer.match_mask = data; 746 | response_value = DAP_TRANSFER_OK; 747 | } else { 748 | // Write DP/AP register 749 | retry = DAP_Data.transfer.retry_count; 750 | do { 751 | response_value = SWD_Transfer(request_value, &data); 752 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 753 | if (response_value != DAP_TRANSFER_OK) break; 754 | check_write = 1; 755 | } 756 | } 757 | response_count++; 758 | if (DAP_TransferAbort) break; 759 | } 760 | 761 | if (response_value == DAP_TRANSFER_OK) { 762 | if (post_read) { 763 | // Read previous data 764 | retry = DAP_Data.transfer.retry_count; 765 | do { 766 | response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); 767 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 768 | if (response_value != DAP_TRANSFER_OK) goto end; 769 | // Store previous data 770 | *response++ = (uint8_t) data; 771 | *response++ = (uint8_t)(data >> 8); 772 | *response++ = (uint8_t)(data >> 16); 773 | *response++ = (uint8_t)(data >> 24); 774 | } else if (check_write) { 775 | // Check last write 776 | retry = DAP_Data.transfer.retry_count; 777 | do { 778 | response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); 779 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 780 | } 781 | } 782 | 783 | end: 784 | *(response_head+0) = (uint8_t)response_count; 785 | *(response_head+1) = (uint8_t)response_value; 786 | 787 | return (response - response_head); 788 | } 789 | #endif 790 | 791 | 792 | // Process JTAG Transfer command and prepare response 793 | // request: pointer to request data 794 | // response: pointer to response data 795 | // return: number of bytes in response 796 | #if (DAP_JTAG != 0) 797 | static uint32_t DAP_JTAG_Transfer(uint8_t *request, uint8_t *response) { 798 | uint32_t request_count; 799 | uint32_t request_value; 800 | uint32_t request_ir; 801 | uint32_t response_count; 802 | uint32_t response_value; 803 | uint8_t *response_head; 804 | uint32_t post_read; 805 | uint32_t match_value; 806 | uint32_t match_retry; 807 | uint32_t retry; 808 | uint32_t data; 809 | uint32_t ir; 810 | 811 | response_count = 0; 812 | response_value = 0; 813 | response_head = response; 814 | response += 2; 815 | 816 | DAP_TransferAbort = 0; 817 | 818 | ir = 0; 819 | post_read = 0; 820 | 821 | // Device index (JTAP TAP) 822 | DAP_Data.jtag_dev.index = *request++; 823 | if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto end; 824 | 825 | request_count = *request++; 826 | while (request_count--) { 827 | request_value = *request++; 828 | request_ir = (request_value & DAP_TRANSFER_APnDP) ? JTAG_APACC : JTAG_DPACC; 829 | if (request_value & DAP_TRANSFER_RnW) { 830 | // Read register 831 | if (post_read) { 832 | // Read was posted before 833 | retry = DAP_Data.transfer.retry_count; 834 | if ((ir == request_ir) && ((request_value & DAP_TRANSFER_MATCH_VALUE) == 0)) { 835 | // Read previous data and post next read 836 | do { 837 | response_value = JTAG_Transfer(request_value, &data); 838 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 839 | } else { 840 | // Select JTAG chain 841 | if (ir != JTAG_DPACC) { 842 | ir = JTAG_DPACC; 843 | JTAG_IR(ir); 844 | } 845 | // Read previous data 846 | do { 847 | response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); 848 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 849 | post_read = 0; 850 | } 851 | if (response_value != DAP_TRANSFER_OK) break; 852 | // Store previous data 853 | *response++ = (uint8_t) data; 854 | *response++ = (uint8_t)(data >> 8); 855 | *response++ = (uint8_t)(data >> 16); 856 | *response++ = (uint8_t)(data >> 24); 857 | } 858 | if (request_value & DAP_TRANSFER_MATCH_VALUE) { 859 | // Read with value match 860 | match_value = (*(request+0) << 0) | 861 | (*(request+1) << 8) | 862 | (*(request+2) << 16) | 863 | (*(request+3) << 24); 864 | request += 4; 865 | match_retry = DAP_Data.transfer.match_retry; 866 | // Select JTAG chain 867 | if (ir != request_ir) { 868 | ir = request_ir; 869 | JTAG_IR(ir); 870 | } 871 | // Post DP/AP read 872 | retry = DAP_Data.transfer.retry_count; 873 | do { 874 | response_value = JTAG_Transfer(request_value, NULL); 875 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 876 | if (response_value != DAP_TRANSFER_OK) break; 877 | do { 878 | // Read register until its value matches or retry counter expires 879 | retry = DAP_Data.transfer.retry_count; 880 | do { 881 | response_value = JTAG_Transfer(request_value, &data); 882 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 883 | if (response_value != DAP_TRANSFER_OK) break; 884 | } while (((data & DAP_Data.transfer.match_mask) != match_value) && match_retry-- && !DAP_TransferAbort); 885 | if ((data & DAP_Data.transfer.match_mask) != match_value) { 886 | response_value |= DAP_TRANSFER_MISMATCH; 887 | } 888 | if (response_value != DAP_TRANSFER_OK) break; 889 | } else { 890 | // Normal read 891 | if (post_read == 0) { 892 | // Select JTAG chain 893 | if (ir != request_ir) { 894 | ir = request_ir; 895 | JTAG_IR(ir); 896 | } 897 | // Post DP/AP read 898 | retry = DAP_Data.transfer.retry_count; 899 | do { 900 | response_value = JTAG_Transfer(request_value, NULL); 901 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 902 | if (response_value != DAP_TRANSFER_OK) break; 903 | post_read = 1; 904 | } 905 | } 906 | } else { 907 | // Write register 908 | if (post_read) { 909 | // Select JTAG chain 910 | if (ir != JTAG_DPACC) { 911 | ir = JTAG_DPACC; 912 | JTAG_IR(ir); 913 | } 914 | // Read previous data 915 | retry = DAP_Data.transfer.retry_count; 916 | do { 917 | response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); 918 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 919 | if (response_value != DAP_TRANSFER_OK) break; 920 | // Store previous data 921 | *response++ = (uint8_t) data; 922 | *response++ = (uint8_t)(data >> 8); 923 | *response++ = (uint8_t)(data >> 16); 924 | *response++ = (uint8_t)(data >> 24); 925 | post_read = 0; 926 | } 927 | // Load data 928 | data = (*(request+0) << 0) | 929 | (*(request+1) << 8) | 930 | (*(request+2) << 16) | 931 | (*(request+3) << 24); 932 | request += 4; 933 | if (request_value & DAP_TRANSFER_MATCH_MASK) { 934 | // Write match mask 935 | DAP_Data.transfer.match_mask = data; 936 | response_value = DAP_TRANSFER_OK; 937 | } else { 938 | // Select JTAG chain 939 | if (ir != request_ir) { 940 | ir = request_ir; 941 | JTAG_IR(ir); 942 | } 943 | // Write DP/AP register 944 | retry = DAP_Data.transfer.retry_count; 945 | do { 946 | response_value = JTAG_Transfer(request_value, &data); 947 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 948 | if (response_value != DAP_TRANSFER_OK) break; 949 | } 950 | } 951 | response_count++; 952 | if (DAP_TransferAbort) break; 953 | } 954 | 955 | if (response_value == DAP_TRANSFER_OK) { 956 | // Select JTAG chain 957 | if (ir != JTAG_DPACC) { 958 | ir = JTAG_DPACC; 959 | JTAG_IR(ir); 960 | } 961 | if (post_read) { 962 | // Read previous data 963 | retry = DAP_Data.transfer.retry_count; 964 | do { 965 | response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); 966 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 967 | if (response_value != DAP_TRANSFER_OK) goto end; 968 | // Store previous data 969 | *response++ = (uint8_t) data; 970 | *response++ = (uint8_t)(data >> 8); 971 | *response++ = (uint8_t)(data >> 16); 972 | *response++ = (uint8_t)(data >> 24); 973 | } else { 974 | // Check last write 975 | retry = DAP_Data.transfer.retry_count; 976 | do { 977 | response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); 978 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 979 | } 980 | } 981 | 982 | end: 983 | *(response_head+0) = (uint8_t)response_count; 984 | *(response_head+1) = (uint8_t)response_value; 985 | 986 | return (response - response_head); 987 | } 988 | #endif 989 | 990 | 991 | // Process SWD Transfer Block command and prepare response 992 | // request: pointer to request data 993 | // response: pointer to response data 994 | // return: number of bytes in response 995 | #if (DAP_SWD != 0) 996 | static uint32_t DAP_SWD_TransferBlock(uint8_t *request, uint8_t *response) { 997 | uint32_t request_count; 998 | uint32_t request_value; 999 | uint32_t response_count; 1000 | uint32_t response_value; 1001 | uint8_t *response_head; 1002 | uint32_t retry; 1003 | uint32_t data; 1004 | 1005 | response_count = 0; 1006 | response_value = 0; 1007 | response_head = response; 1008 | response += 3; 1009 | 1010 | DAP_TransferAbort = 0; 1011 | 1012 | request++; // Ignore DAP index 1013 | 1014 | request_count = *request | (*(request+1) << 8); 1015 | request += 2; 1016 | if (request_count == 0) goto end; 1017 | 1018 | request_value = *request++; 1019 | if (request_value & DAP_TRANSFER_RnW) { 1020 | // Read register block 1021 | if (request_value & DAP_TRANSFER_APnDP) { 1022 | // Post AP read 1023 | retry = DAP_Data.transfer.retry_count; 1024 | do { 1025 | response_value = SWD_Transfer(request_value, NULL); 1026 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1027 | if (response_value != DAP_TRANSFER_OK) goto end; 1028 | } 1029 | while (request_count--) { 1030 | // Read DP/AP register 1031 | if ((request_count == 0) && (request_value & DAP_TRANSFER_APnDP)) { 1032 | // Last AP read 1033 | request_value = DP_RDBUFF | DAP_TRANSFER_RnW; 1034 | } 1035 | retry = DAP_Data.transfer.retry_count; 1036 | do { 1037 | response_value = SWD_Transfer(request_value, &data); 1038 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1039 | if (response_value != DAP_TRANSFER_OK) goto end; 1040 | // Store data 1041 | *response++ = (uint8_t) data; 1042 | *response++ = (uint8_t)(data >> 8); 1043 | *response++ = (uint8_t)(data >> 16); 1044 | *response++ = (uint8_t)(data >> 24); 1045 | response_count++; 1046 | } 1047 | } else { 1048 | // Write register block 1049 | while (request_count--) { 1050 | // Load data 1051 | data = (*(request+0) << 0) | 1052 | (*(request+1) << 8) | 1053 | (*(request+2) << 16) | 1054 | (*(request+3) << 24); 1055 | request += 4; 1056 | // Write DP/AP register 1057 | retry = DAP_Data.transfer.retry_count; 1058 | do { 1059 | response_value = SWD_Transfer(request_value, &data); 1060 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1061 | if (response_value != DAP_TRANSFER_OK) goto end; 1062 | response_count++; 1063 | } 1064 | // Check last write 1065 | retry = DAP_Data.transfer.retry_count; 1066 | do { 1067 | response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); 1068 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1069 | } 1070 | 1071 | end: 1072 | *(response_head+0) = (uint8_t)(response_count >> 0); 1073 | *(response_head+1) = (uint8_t)(response_count >> 8); 1074 | *(response_head+2) = (uint8_t) response_value; 1075 | 1076 | return (response - response_head); 1077 | } 1078 | #endif 1079 | 1080 | 1081 | // Process JTAG Transfer Block command and prepare response 1082 | // request: pointer to request data 1083 | // response: pointer to response data 1084 | // return: number of bytes in response 1085 | #if (DAP_JTAG != 0) 1086 | static uint32_t DAP_JTAG_TransferBlock(uint8_t *request, uint8_t *response) { 1087 | uint32_t request_count; 1088 | uint32_t request_value; 1089 | uint32_t response_count; 1090 | uint32_t response_value; 1091 | uint8_t *response_head; 1092 | uint32_t retry; 1093 | uint32_t data; 1094 | uint32_t ir; 1095 | 1096 | response_count = 0; 1097 | response_value = 0; 1098 | response_head = response; 1099 | response += 3; 1100 | 1101 | DAP_TransferAbort = 0; 1102 | 1103 | // Device index (JTAP TAP) 1104 | DAP_Data.jtag_dev.index = *request++; 1105 | if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto end; 1106 | 1107 | request_count = *request | (*(request+1) << 8); 1108 | request += 2; 1109 | if (request_count == 0) goto end; 1110 | 1111 | request_value = *request++; 1112 | 1113 | // Select JTAG chain 1114 | ir = (request_value & DAP_TRANSFER_APnDP) ? JTAG_APACC : JTAG_DPACC; 1115 | JTAG_IR(ir); 1116 | 1117 | if (request_value & DAP_TRANSFER_RnW) { 1118 | // Post read 1119 | retry = DAP_Data.transfer.retry_count; 1120 | do { 1121 | response_value = JTAG_Transfer(request_value, NULL); 1122 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1123 | if (response_value != DAP_TRANSFER_OK) goto end; 1124 | // Read register block 1125 | while (request_count--) { 1126 | // Read DP/AP register 1127 | if (request_count == 0) { 1128 | // Last read 1129 | if (ir != JTAG_DPACC) { 1130 | JTAG_IR(JTAG_DPACC); 1131 | } 1132 | request_value = DP_RDBUFF | DAP_TRANSFER_RnW; 1133 | } 1134 | retry = DAP_Data.transfer.retry_count; 1135 | do { 1136 | response_value = JTAG_Transfer(request_value, &data); 1137 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1138 | if (response_value != DAP_TRANSFER_OK) goto end; 1139 | // Store data 1140 | *response++ = (uint8_t) data; 1141 | *response++ = (uint8_t)(data >> 8); 1142 | *response++ = (uint8_t)(data >> 16); 1143 | *response++ = (uint8_t)(data >> 24); 1144 | response_count++; 1145 | } 1146 | } else { 1147 | // Write register block 1148 | while (request_count--) { 1149 | // Load data 1150 | data = (*(request+0) << 0) | 1151 | (*(request+1) << 8) | 1152 | (*(request+2) << 16) | 1153 | (*(request+3) << 24); 1154 | request += 4; 1155 | // Write DP/AP register 1156 | retry = DAP_Data.transfer.retry_count; 1157 | do { 1158 | response_value = JTAG_Transfer(request_value, &data); 1159 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1160 | if (response_value != DAP_TRANSFER_OK) goto end; 1161 | response_count++; 1162 | } 1163 | // Check last write 1164 | if (ir != JTAG_DPACC) { 1165 | JTAG_IR(JTAG_DPACC); 1166 | } 1167 | retry = DAP_Data.transfer.retry_count; 1168 | do { 1169 | response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); 1170 | } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); 1171 | } 1172 | 1173 | end: 1174 | *(response_head+0) = (uint8_t)(response_count >> 0); 1175 | *(response_head+1) = (uint8_t)(response_count >> 8); 1176 | *(response_head+2) = (uint8_t) response_value; 1177 | 1178 | return (response - response_head); 1179 | } 1180 | #endif 1181 | 1182 | 1183 | // Process DAP Vendor command and prepare response 1184 | // Default function (can be overridden) 1185 | // request: pointer to request data 1186 | // response: pointer to response data 1187 | // return: number of bytes in response 1188 | __weak uint32_t DAP_ProcessVendorCommand(uint8_t *request, uint8_t *response) { 1189 | *response = ID_DAP_Invalid; 1190 | return (1); 1191 | } 1192 | 1193 | 1194 | // Process DAP command and prepare response 1195 | // request: pointer to request data 1196 | // response: pointer to response data 1197 | // return: number of bytes in response 1198 | uint32_t DAP_ProcessCommand(uint8_t *request, uint8_t *response) { 1199 | uint32_t num; 1200 | 1201 | if ((*request >= ID_DAP_Vendor0) && (*request <= ID_DAP_Vendor31)) { 1202 | return DAP_ProcessVendorCommand(request, response); 1203 | } 1204 | 1205 | *response++ = *request; 1206 | 1207 | switch (*request++) { 1208 | case ID_DAP_Info: 1209 | num = DAP_Info(*request, response+1); 1210 | *response = num; 1211 | return (2 + num); 1212 | case ID_DAP_HostStatus: 1213 | num = DAP_HostStatus(request, response); 1214 | break; 1215 | case ID_DAP_Connect: 1216 | num = DAP_Connect(request, response); 1217 | break; 1218 | case ID_DAP_Disconnect: 1219 | num = DAP_Disconnect(response); 1220 | break; 1221 | case ID_DAP_Delay: 1222 | num = DAP_Delay(request, response); 1223 | break; 1224 | case ID_DAP_ResetTarget: 1225 | num = DAP_ResetTarget(response); 1226 | break; 1227 | 1228 | #if ((DAP_SWD != 0) || (DAP_JTAG != 0)) 1229 | case ID_DAP_SWJ_Pins: 1230 | num = DAP_SWJ_Pins(request, response); 1231 | break; 1232 | case ID_DAP_SWJ_Clock: 1233 | num = DAP_SWJ_Clock(request, response); 1234 | break; 1235 | case ID_DAP_SWJ_Sequence: 1236 | num = DAP_SWJ_Sequence(request, response); 1237 | break; 1238 | #else 1239 | case ID_DAP_SWJ_Pins: 1240 | case ID_DAP_SWJ_Clock: 1241 | case ID_DAP_SWJ_Sequence: 1242 | *response = DAP_ERROR; 1243 | return (2); 1244 | #endif 1245 | 1246 | #if (DAP_SWD != 0) 1247 | case ID_DAP_SWD_Configure: 1248 | num = DAP_SWD_Configure(request, response); 1249 | break; 1250 | #else 1251 | case ID_DAP_SWD_Configure: 1252 | *response = DAP_ERROR; 1253 | return (2); 1254 | #endif 1255 | 1256 | #if (DAP_JTAG != 0) 1257 | case ID_DAP_JTAG_Sequence: 1258 | num = DAP_JTAG_Sequence(request, response); 1259 | break; 1260 | case ID_DAP_JTAG_Configure: 1261 | num = DAP_JTAG_Configure(request, response); 1262 | break; 1263 | case ID_DAP_JTAG_IDCODE: 1264 | num = DAP_JTAG_IDCode(request, response); 1265 | break; 1266 | #else 1267 | case ID_DAP_JTAG_Sequence: 1268 | case ID_DAP_JTAG_Configure: 1269 | case ID_DAP_JTAG_IDCODE: 1270 | *response = DAP_ERROR; 1271 | return (2); 1272 | #endif 1273 | 1274 | case ID_DAP_TransferConfigure: 1275 | num = DAP_TransferConfigure(request, response); 1276 | break; 1277 | 1278 | case ID_DAP_Transfer: 1279 | switch (DAP_Data.debug_port) { 1280 | #if (DAP_SWD != 0) 1281 | case DAP_PORT_SWD: 1282 | num = DAP_SWD_Transfer (request, response); 1283 | break; 1284 | #endif 1285 | #if (DAP_JTAG != 0) 1286 | case DAP_PORT_JTAG: 1287 | num = DAP_JTAG_Transfer(request, response); 1288 | break; 1289 | #endif 1290 | default: 1291 | *(response+0) = 0; // Response count 1292 | *(response+1) = 0; // Response value 1293 | num = 2; 1294 | } 1295 | break; 1296 | 1297 | case ID_DAP_TransferBlock: 1298 | switch (DAP_Data.debug_port) { 1299 | #if (DAP_SWD != 0) 1300 | case DAP_PORT_SWD: 1301 | num = DAP_SWD_TransferBlock (request, response); 1302 | break; 1303 | #endif 1304 | #if (DAP_JTAG != 0) 1305 | case DAP_PORT_JTAG: 1306 | num = DAP_JTAG_TransferBlock(request, response); 1307 | break; 1308 | #endif 1309 | default: 1310 | *(response+0) = 0; // Response count [7:0] 1311 | *(response+1) = 0; // Response count[15:8] 1312 | *(response+2) = 0; // Response value 1313 | num = 3; 1314 | } 1315 | break; 1316 | 1317 | case ID_DAP_WriteABORT: 1318 | switch (DAP_Data.debug_port) { 1319 | #if (DAP_SWD != 0) 1320 | case DAP_PORT_SWD: 1321 | num = DAP_SWD_Abort (request, response); 1322 | break; 1323 | #endif 1324 | #if (DAP_JTAG != 0) 1325 | case DAP_PORT_JTAG: 1326 | num = DAP_JTAG_Abort(request, response); 1327 | break; 1328 | #endif 1329 | default: 1330 | *response = DAP_ERROR; 1331 | return (2); 1332 | } 1333 | break; 1334 | 1335 | default: 1336 | *(response-1) = ID_DAP_Invalid; 1337 | return (1); 1338 | } 1339 | 1340 | return (1 + num); 1341 | } 1342 | 1343 | 1344 | // Setup DAP 1345 | void DAP_Setup(void) { 1346 | 1347 | // Default settings (only non-zero values) 1348 | //DAP_Data.debug_port = 0; 1349 | //DAP_Data.fast_clock = 0; 1350 | DAP_Data.clock_delay = CLOCK_DELAY(DAP_DEFAULT_SWJ_CLOCK); 1351 | //DAP_Data.transfer.idle_cycles = 0; 1352 | DAP_Data.transfer.retry_count = 100; 1353 | //DAP_Data.transfer.match_retry = 0; 1354 | //DAP_Data.transfer.match_mask = 0x000000; 1355 | #if (DAP_SWD != 0) 1356 | DAP_Data.swd_conf.turnaround = 1; 1357 | //DAP_Data.swd_conf.data_phase = 0; 1358 | #endif 1359 | #if (DAP_JTAG != 0) 1360 | //DAP_Data.jtag_dev.count = 0; 1361 | #endif 1362 | 1363 | DAP_SETUP(); // Device specific setup 1364 | } 1365 | -------------------------------------------------------------------------------- /DAP.h: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP Interface Firmware 2 | * Copyright (c) 2009-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __DAP_H__ 18 | #define __DAP_H__ 19 | 20 | 21 | // DAP Command IDs 22 | #define ID_DAP_Info 0x00 23 | #define ID_DAP_HostStatus 0x01 24 | #define ID_DAP_Connect 0x02 25 | #define ID_DAP_Disconnect 0x03 26 | #define ID_DAP_TransferConfigure 0x04 27 | #define ID_DAP_Transfer 0x05 28 | #define ID_DAP_TransferBlock 0x06 29 | #define ID_DAP_TransferAbort 0x07 30 | #define ID_DAP_WriteABORT 0x08 31 | #define ID_DAP_Delay 0x09 32 | #define ID_DAP_ResetTarget 0x0A 33 | #define ID_DAP_SWJ_Pins 0x10 34 | #define ID_DAP_SWJ_Clock 0x11 35 | #define ID_DAP_SWJ_Sequence 0x12 36 | #define ID_DAP_SWD_Configure 0x13 37 | #define ID_DAP_JTAG_Sequence 0x14 38 | #define ID_DAP_JTAG_Configure 0x15 39 | #define ID_DAP_JTAG_IDCODE 0x16 40 | 41 | // DAP Vendor Command IDs 42 | #define ID_DAP_Vendor0 0x80 43 | #define ID_DAP_Vendor1 0x81 44 | #define ID_DAP_Vendor2 0x82 45 | #define ID_DAP_Vendor3 0x83 46 | #define ID_DAP_Vendor4 0x84 47 | #define ID_DAP_Vendor5 0x85 48 | #define ID_DAP_Vendor6 0x86 49 | #define ID_DAP_Vendor7 0x87 50 | #define ID_DAP_Vendor8 0x88 51 | #define ID_DAP_Vendor9 0x89 52 | #define ID_DAP_Vendor10 0x8A 53 | #define ID_DAP_Vendor11 0x8B 54 | #define ID_DAP_Vendor12 0x8C 55 | #define ID_DAP_Vendor13 0x8D 56 | #define ID_DAP_Vendor14 0x8E 57 | #define ID_DAP_Vendor15 0x8F 58 | #define ID_DAP_Vendor16 0x90 59 | #define ID_DAP_Vendor17 0x91 60 | #define ID_DAP_Vendor18 0x92 61 | #define ID_DAP_Vendor19 0x93 62 | #define ID_DAP_Vendor20 0x94 63 | #define ID_DAP_Vendor21 0x95 64 | #define ID_DAP_Vendor22 0x96 65 | #define ID_DAP_Vendor23 0x97 66 | #define ID_DAP_Vendor24 0x98 67 | #define ID_DAP_Vendor25 0x99 68 | #define ID_DAP_Vendor26 0x9A 69 | #define ID_DAP_Vendor27 0x9B 70 | #define ID_DAP_Vendor28 0x9C 71 | #define ID_DAP_Vendor29 0x9D 72 | #define ID_DAP_Vendor30 0x9E 73 | #define ID_DAP_Vendor31 0x9F 74 | 75 | #define ID_DAP_Invalid 0xFF 76 | 77 | // DAP Status Code 78 | #define DAP_OK 0 79 | #define DAP_ERROR 0xFF 80 | 81 | // DAP ID 82 | #define DAP_ID_VENDOR 1 83 | #define DAP_ID_PRODUCT 2 84 | #define DAP_ID_SER_NUM 3 85 | #define DAP_ID_FW_VER 4 86 | #define DAP_ID_DEVICE_VENDOR 5 87 | #define DAP_ID_DEVICE_NAME 6 88 | #define DAP_ID_CAPABILITIES 0xF0 89 | #define DAP_ID_PACKET_COUNT 0xFE 90 | #define DAP_ID_PACKET_SIZE 0xFF 91 | 92 | // DAP Host Status 93 | #define DAP_DEBUGGER_CONNECTED 0 94 | #define DAP_TARGET_RUNNING 1 95 | 96 | // DAP Port 97 | #define DAP_PORT_AUTODETECT 0 // Autodetect Port 98 | #define DAP_PORT_DISABLED 0 // Port Disabled (I/O pins in High-Z) 99 | #define DAP_PORT_SWD 1 // SWD Port (SWCLK, SWDIO) + nRESET 100 | #define DAP_PORT_JTAG 2 // JTAG Port (TCK, TMS, TDI, TDO, nTRST) + nRESET 101 | 102 | // DAP SWJ Pins 103 | #define DAP_SWJ_SWCLK_TCK 0 // SWCLK/TCK 104 | #define DAP_SWJ_SWDIO_TMS 1 // SWDIO/TMS 105 | #define DAP_SWJ_TDI 2 // TDI 106 | #define DAP_SWJ_TDO 3 // TDO 107 | #define DAP_SWJ_nTRST 5 // nTRST 108 | #define DAP_SWJ_nRESET 7 // nRESET 109 | 110 | // DAP Transfer Request 111 | #define DAP_TRANSFER_APnDP (1<<0) 112 | #define DAP_TRANSFER_RnW (1<<1) 113 | #define DAP_TRANSFER_A2 (1<<2) 114 | #define DAP_TRANSFER_A3 (1<<3) 115 | #define DAP_TRANSFER_MATCH_VALUE (1<<4) 116 | #define DAP_TRANSFER_MATCH_MASK (1<<5) 117 | 118 | // DAP Transfer Response 119 | #define DAP_TRANSFER_OK (1<<0) 120 | #define DAP_TRANSFER_WAIT (1<<1) 121 | #define DAP_TRANSFER_FAULT (1<<2) 122 | #define DAP_TRANSFER_ERROR (1<<3) 123 | #define DAP_TRANSFER_MISMATCH (1<<4) 124 | 125 | 126 | // Debug Port Register Addresses 127 | #define DP_IDCODE 0x00 // IDCODE Register (SW Read only) 128 | #define DP_ABORT 0x00 // Abort Register (SW Write only) 129 | #define DP_CTRL_STAT 0x04 // Control & Status 130 | #define DP_WCR 0x04 // Wire Control Register (SW Only) 131 | #define DP_SELECT 0x08 // Select Register (JTAG R/W & SW W) 132 | #define DP_RESEND 0x08 // Resend (SW Read Only) 133 | #define DP_RDBUFF 0x0C // Read Buffer (Read Only) 134 | 135 | // JTAG IR Codes 136 | #define JTAG_ABORT 0x08 137 | #define JTAG_DPACC 0x0A 138 | #define JTAG_APACC 0x0B 139 | #define JTAG_IDCODE 0x0E 140 | #define JTAG_BYPASS 0x0F 141 | 142 | // JTAG Sequence Info 143 | #define JTAG_SEQUENCE_TCK 0x3F // TCK count 144 | #define JTAG_SEQUENCE_TMS 0x40 // TMS value 145 | #define JTAG_SEQUENCE_TDO 0x80 // TDO capture 146 | 147 | 148 | #include 149 | #include 150 | 151 | // DAP Data structure 152 | typedef struct { 153 | uint8_t debug_port; // Debug Port 154 | uint8_t fast_clock; // Fast Clock Flag 155 | uint32_t clock_delay; // Clock Delay 156 | struct { // Transfer Configuration 157 | uint8_t idle_cycles; // Idle cycles after transfer 158 | uint16_t retry_count; // Number of retries after WAIT response 159 | uint16_t match_retry; // Number of retries if read value does not match 160 | uint32_t match_mask; // Match Mask 161 | } transfer; 162 | #if (DAP_SWD != 0) 163 | struct { // SWD Configuration 164 | uint8_t turnaround; // Turnaround period 165 | uint8_t data_phase; // Always generate Data Phase 166 | } swd_conf; 167 | #endif 168 | #if (DAP_JTAG != 0) 169 | struct { // JTAG Device Chain 170 | uint8_t count; // Number of devices 171 | uint8_t index; // Device index (device at TDO has index 0) 172 | #if (DAP_JTAG_DEV_CNT != 0) 173 | uint8_t ir_length[DAP_JTAG_DEV_CNT]; // IR Length in bits 174 | uint16_t ir_before[DAP_JTAG_DEV_CNT]; // Bits before IR 175 | uint16_t ir_after [DAP_JTAG_DEV_CNT]; // Bits after IR 176 | #endif 177 | } jtag_dev; 178 | #endif 179 | } DAP_Data_t; 180 | 181 | extern DAP_Data_t DAP_Data; // DAP Data 182 | extern volatile uint8_t DAP_TransferAbort; // Transfer Abort Flag 183 | 184 | 185 | // Functions 186 | extern void SWJ_Sequence (uint32_t count, uint8_t *data); 187 | extern void JTAG_Sequence (uint32_t info, uint8_t *tdi, uint8_t *tdo); 188 | extern void JTAG_IR (uint32_t ir); 189 | extern uint32_t JTAG_ReadIDCode (void); 190 | extern void JTAG_WriteAbort (uint32_t data); 191 | extern uint8_t JTAG_Transfer (uint32_t request, uint32_t *data); 192 | extern uint8_t SWD_Transfer (uint32_t request, uint32_t *data); 193 | 194 | extern void Delayms (uint32_t delay); 195 | 196 | extern uint32_t DAP_ProcessVendorCommand (uint8_t *request, uint8_t *response); 197 | 198 | extern uint32_t DAP_ProcessCommand (uint8_t *request, uint8_t *response); 199 | extern void DAP_Setup (void); 200 | 201 | // Configurable delay for clock generation 202 | #ifndef DELAY_SLOW_CYCLES 203 | #define DELAY_SLOW_CYCLES 3 // Number of cycles for one iteration 204 | #endif 205 | static __forceinline void PIN_DELAY_SLOW (uint32_t delay) { 206 | int32_t count; 207 | 208 | count = delay; 209 | while (--count); 210 | } 211 | 212 | // Fixed delay for fast clock generation 213 | #ifndef DELAY_FAST_CYCLES 214 | #define DELAY_FAST_CYCLES 0 // Number of cycles: 0..3 215 | #endif 216 | static __forceinline void PIN_DELAY_FAST (void) { 217 | #if (DELAY_FAST_CYCLES >= 1) 218 | __nop(); 219 | #endif 220 | #if (DELAY_FAST_CYCLES >= 2) 221 | __nop(); 222 | #endif 223 | #if (DELAY_FAST_CYCLES >= 3) 224 | __nop(); 225 | #endif 226 | } 227 | 228 | 229 | #endif /* __DAP_H__ */ 230 | -------------------------------------------------------------------------------- /DAP_config.h: -------------------------------------------------------------------------------- 1 | #include 2 | #ifdef TEENSYDUINO 3 | #define TEENSY_RAWHID 4 | #include "usb_desc.h" 5 | #else 6 | #define HIDPROJECT_RAWHID 7 | #include "HID-Project.h" 8 | #endif 9 | 10 | /* CMSIS-DAP ported to run on the Arduino Micro 11 | * Copyright (C) 2016 Phillip Pearson 12 | * 13 | * CMSIS-DAP Interface Firmware 14 | * Copyright (c) 2009-2013 ARM Limited 15 | * 16 | * Licensed under the Apache License, Version 2.0 (the "License"); 17 | * you may not use this file except in compliance with the License. 18 | * You may obtain a copy of the License at 19 | * 20 | * http://www.apache.org/licenses/LICENSE-2.0 21 | * 22 | * Unless required by applicable law or agreed to in writing, software 23 | * distributed under the License is distributed on an "AS IS" BASIS, 24 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 25 | * See the License for the specific language governing permissions and 26 | * limitations under the License. 27 | */ 28 | 29 | #ifndef __DAP_CONFIG_H__ 30 | #define __DAP_CONFIG_H__ 31 | 32 | #define __forceinline __attribute__((always_inline)) 33 | #define __weak 34 | #define OS_TID int 35 | #define __task 36 | #define U64 uint64_t 37 | #define os_dly_wait delayMicroseconds 38 | 39 | #define DAP_VENDOR "Myelin" 40 | #define DAP_PRODUCT "Arduino CMSIS-DAP" 41 | #define DAP_SER_NUM "1234" 42 | 43 | //************************************************************************************************** 44 | /** 45 | \defgroup DAP_Config_Debug_gr CMSIS-DAP Debug Unit Information 46 | \ingroup DAP_ConfigIO_gr 47 | @{ 48 | Provides definitions about: 49 | - Definition of Cortex-M processor parameters used in CMSIS-DAP Debug Unit. 50 | - Debug Unit communication packet size. 51 | - Debug Access Port communication mode (JTAG or SWD). 52 | - Optional information about a connected Target Device (for Evaluation Boards). 53 | */ 54 | 55 | #include // Debug Unit Cortex-M Processor Header File 56 | 57 | /// Processor Clock of the Cortex-M MCU used in the Debug Unit. 58 | /// This value is used to calculate the SWD/JTAG clock speed. 59 | #define CPU_CLOCK F_CPU ///< Specifies the CPU Clock in Hz 60 | 61 | /// Number of processor cycles for I/O Port write operations. 62 | /// This value is used to calculate the SWD/JTAG clock speed that is generated with I/O 63 | /// Port write operations in the Debug Unit by a Cortex-M MCU. Most Cortex-M processors 64 | /// requrie 2 processor cycles for a I/O Port Write operation. If the Debug Unit uses 65 | /// a Cortex-M0+ processor with high-speed peripheral I/O only 1 processor cycle might be 66 | /// requrired. 67 | #define IO_PORT_WRITE_CYCLES 2 ///< I/O Cycles: 2=default, 1=Cortex-M0+ fast I/0 68 | 69 | #if !defined(DAP_SERIAL_LOG) 70 | #define DAP_SERIAL_LOG 1 71 | #endif 72 | 73 | /// Indicate that Serial Wire Debug (SWD) communication mode is available at the Debug Access Port. 74 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 75 | #if !defined(DAP_SWD) 76 | #define DAP_SWD 1 ///< SWD Mode: 1 = available, 0 = not available 77 | #endif 78 | 79 | /// Indicate that JTAG communication mode is available at the Debug Port. 80 | /// This information is returned by the command \ref DAP_Info as part of Capabilities. 81 | #if !defined(DAP_JTAG) 82 | #define DAP_JTAG 1 ///< JTAG Mode: 1 = available, 0 = not available. 83 | #endif 84 | 85 | /// Configure maximum number of JTAG devices on the scan chain connected to the Debug Access Port. 86 | /// This setting impacts the RAM requirements of the Debug Unit. Valid range is 1 .. 255. 87 | #define DAP_JTAG_DEV_CNT 4 ///< Maximum number of JTAG devices on scan chain 88 | 89 | /// Default communication mode on the Debug Access Port. 90 | /// Used for the command \ref DAP_Connect when Port Default mode is selected. 91 | #define DAP_DEFAULT_PORT 1 ///< Default JTAG/SWJ Port Mode: 1 = SWD, 2 = JTAG. 92 | 93 | /// Default communication speed on the Debug Access Port for SWD and JTAG mode. 94 | /// Used to initialize the default SWD/JTAG clock frequency. 95 | /// The command \ref DAP_SWJ_Clock can be used to overwrite this default setting. 96 | #define DAP_DEFAULT_SWJ_CLOCK 5000000 ///< Default SWD/JTAG clock frequency in Hz. 97 | 98 | /// Maximum Package Size for Command and Response data. 99 | /// This configuration settings is used to optimized the communication performance with the 100 | /// debugger and depends on the USB peripheral. Change setting to 1024 for High-Speed USB. 101 | #define DAP_PACKET_SIZE RAWHID_RX_SIZE ///< USB: 64 = Full-Speed, 1024 = High-Speed. 102 | 103 | /// Maximum Package Buffers for Command and Response data. 104 | /// This configuration settings is used to optimized the communication performance with the 105 | /// debugger and depends on the USB peripheral. For devices with limited RAM or USB buffer the 106 | /// setting can be reduced (valid range is 1 .. 255). Change setting to 4 for High-Speed USB. 107 | #define DAP_PACKET_COUNT 1 ///< Buffers: 64 = Full-Speed, 4 = High-Speed. 108 | 109 | 110 | /// Debug Unit is connected to fixed Target Device. 111 | /// The Debug Unit may be part of an evaluation board and always connected to a fixed 112 | /// known device. In this case a Device Vendor and Device Name string is stored which 113 | /// may be used by the debugger or IDE to configure device parameters. 114 | #define TARGET_DEVICE_FIXED 0 ///< Target Device: 1 = known, 0 = unknown; 115 | 116 | #if TARGET_DEVICE_FIXED 117 | #define TARGET_DEVICE_VENDOR "" ///< String indicating the Silicon Vendor 118 | #define TARGET_DEVICE_NAME "" ///< String indicating the Target Device 119 | #endif 120 | 121 | ///@} 122 | 123 | 124 | // Debug Port I/O Pins 125 | 126 | #ifdef TEENSYDUINO 127 | #define PIN_SWDIO 19 128 | #define PIN_SWCLK 20 129 | #define PIN_TDO 21 130 | #define PIN_TDI 22 131 | #define PIN_nRESET 23 132 | #define PIN_LED_CONNECTED LED_BUILTIN 133 | #define PIN_LED_RUNNING LED_BUILTIN 134 | #elif AT16U2_DUE 135 | #define PIN_SWDIO 2//PB2 // MOSI pin 136 | #define PIN_SWCLK 1//PB1 // SCK 137 | #define PIN_TDO 6//PB6 138 | #define PIN_TDI 7//PB7 139 | #define PIN_nRESET 8//PC7 140 | #define PIN_LED_CONNECTED LED_BUILTIN_TX 141 | #define PIN_LED_RUNNING LED_BUILTIN_RX 142 | #else 143 | #define PIN_SWDIO 2 144 | #define PIN_SWCLK 3 145 | #define PIN_TDO 4 146 | #define PIN_TDI 5 147 | #define PIN_nRESET 6 148 | #define PIN_LED_CONNECTED LED_BUILTIN_TX 149 | #define PIN_LED_RUNNING LED_BUILTIN_RX 150 | #endif 151 | 152 | 153 | //************************************************************************************************** 154 | /** 155 | \defgroup DAP_Config_PortIO_gr CMSIS-DAP Hardware I/O Pin Access 156 | \ingroup DAP_ConfigIO_gr 157 | @{ 158 | 159 | Standard I/O Pins of the CMSIS-DAP Hardware Debug Port support standard JTAG mode 160 | and Serial Wire Debug (SWD) mode. In SWD mode only 2 pins are required to implement the debug 161 | interface of a device. The following I/O Pins are provided: 162 | 163 | JTAG I/O Pin | SWD I/O Pin | CMSIS-DAP Hardware pin mode 164 | ---------------------------- | -------------------- | --------------------------------------------- 165 | TCK: Test Clock | SWCLK: Clock | Output Push/Pull 166 | TMS: Test Mode Select | SWDIO: Data I/O | Output Push/Pull; Input (for receiving data) 167 | TDI: Test Data Input | | Output Push/Pull 168 | TDO: Test Data Output | | Input 169 | nTRST: Test Reset (optional) | | Output Open Drain with pull-up resistor 170 | nRESET: Device Reset | nRESET: Device Reset | Output Open Drain with pull-up resistor 171 | 172 | 173 | DAP Hardware I/O Pin Access Functions 174 | ------------------------------------- 175 | The various I/O Pins are accessed by functions that implement the Read, Write, Set, or Clear to 176 | these I/O Pins. 177 | 178 | For the SWDIO I/O Pin there are additional functions that are called in SWD I/O mode only. 179 | This functions are provided to achieve faster I/O that is possible with some advanced GPIO 180 | peripherals that can independently write/read a single I/O pin without affecting any other pins 181 | of the same I/O port. The following SWDIO I/O Pin functions are provided: 182 | - \ref PIN_SWDIO_OUT_ENABLE to enable the output mode from the DAP hardware. 183 | - \ref PIN_SWDIO_OUT_DISABLE to enable the input mode to the DAP hardware. 184 | - \ref PIN_SWDIO_IN to read from the SWDIO I/O pin with utmost possible speed. 185 | - \ref PIN_SWDIO_OUT to write to the SWDIO I/O pin with utmost possible speed. 186 | */ 187 | 188 | 189 | // Configure DAP I/O pins ------------------------------ 190 | 191 | /** Setup JTAG I/O pins: TCK, TMS, TDI, TDO, nTRST, and nRESET. 192 | Configures the DAP Hardware I/O pins for JTAG mode: 193 | - TCK, TMS, TDI, nTRST, nRESET to output mode and set to high level. 194 | - TDO to input mode. 195 | */ 196 | static __inline void PORT_JTAG_SETUP (void) { 197 | pinMode(PIN_SWCLK, OUTPUT); 198 | pinMode(PIN_SWDIO, OUTPUT); 199 | pinMode(PIN_nRESET, OUTPUT); 200 | pinMode(PIN_TDI, OUTPUT); 201 | pinMode(PIN_TDO, INPUT); 202 | } 203 | 204 | /** Setup SWD I/O pins: SWCLK, SWDIO, and nRESET. 205 | Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode: 206 | - SWCLK, SWDIO, nRESET to output mode and set to default high level. 207 | - TDI, TMS, nTRST to HighZ mode (pins are unused in SWD mode). 208 | */ 209 | static __inline void PORT_SWD_SETUP (void) { 210 | pinMode(PIN_SWCLK, OUTPUT); 211 | pinMode(PIN_SWDIO, OUTPUT); 212 | pinMode(PIN_nRESET, OUTPUT); 213 | pinMode(PIN_TDI, INPUT); 214 | pinMode(PIN_TDO, INPUT); 215 | } 216 | 217 | /** Disable JTAG/SWD I/O Pins. 218 | Disables the DAP Hardware I/O pins which configures: 219 | - TCK/SWCLK, TMS/SWDIO, TDI, TDO, nTRST, nRESET to High-Z mode. 220 | */ 221 | static __inline void PORT_OFF (void) { 222 | pinMode(PIN_SWCLK, INPUT); 223 | pinMode(PIN_SWDIO, INPUT_PULLUP); 224 | pinMode(PIN_TDI, INPUT); 225 | pinMode(PIN_TDO, INPUT); 226 | pinMode(PIN_nRESET, INPUT_PULLUP); 227 | } 228 | 229 | 230 | // SWCLK/TCK I/O pin ------------------------------------- 231 | 232 | /** SWCLK/TCK I/O pin: Get Input. 233 | \return Current status of the SWCLK/TCK DAP hardware I/O pin. 234 | */ 235 | static __forceinline uint32_t PIN_SWCLK_TCK_IN (void) { 236 | return (0); // Not available 237 | } 238 | 239 | /** SWCLK/TCK I/O pin: Set Output to High. 240 | Set the SWCLK/TCK DAP hardware I/O pin to high level. 241 | */ 242 | static __forceinline void PIN_SWCLK_TCK_SET (void) { 243 | digitalWrite(PIN_SWCLK, HIGH); 244 | } 245 | 246 | /** SWCLK/TCK I/O pin: Set Output to Low. 247 | Set the SWCLK/TCK DAP hardware I/O pin to low level. 248 | */ 249 | static __forceinline void PIN_SWCLK_TCK_CLR (void) { 250 | digitalWrite(PIN_SWCLK, LOW); 251 | } 252 | 253 | 254 | // SWDIO/TMS Pin I/O -------------------------------------- 255 | 256 | /** SWDIO/TMS I/O pin: Get Input. 257 | \return Current status of the SWDIO/TMS DAP hardware I/O pin. 258 | */ 259 | static __forceinline uint32_t PIN_SWDIO_TMS_IN (void) { 260 | return (digitalRead(PIN_SWDIO) == HIGH) ? 1 : 0; 261 | } 262 | 263 | /** SWDIO/TMS I/O pin: Set Output to High. 264 | Set the SWDIO/TMS DAP hardware I/O pin to high level. 265 | */ 266 | static __forceinline void PIN_SWDIO_TMS_SET (void) { 267 | digitalWrite(PIN_SWDIO, HIGH); 268 | } 269 | 270 | /** SWDIO/TMS I/O pin: Set Output to Low. 271 | Set the SWDIO/TMS DAP hardware I/O pin to low level. 272 | */ 273 | static __forceinline void PIN_SWDIO_TMS_CLR (void) { 274 | digitalWrite(PIN_SWDIO, LOW); 275 | } 276 | 277 | /** SWDIO I/O pin: Get Input (used in SWD mode only). 278 | \return Current status of the SWDIO DAP hardware I/O pin. 279 | */ 280 | static __forceinline uint32_t PIN_SWDIO_IN (void) { 281 | return (digitalRead(PIN_SWDIO) == HIGH) ? 1 : 0; 282 | } 283 | 284 | /** SWDIO I/O pin: Set Output (used in SWD mode only). 285 | \param bit Output value for the SWDIO DAP hardware I/O pin. 286 | */ 287 | static __forceinline void PIN_SWDIO_OUT (uint32_t bit) { 288 | digitalWrite(PIN_SWDIO, (bit & 1) ? HIGH : LOW); 289 | } 290 | 291 | /** SWDIO I/O pin: Switch to Output mode (used in SWD mode only). 292 | Configure the SWDIO DAP hardware I/O pin to output mode. This function is 293 | called prior \ref PIN_SWDIO_OUT function calls. 294 | */ 295 | static __forceinline void PIN_SWDIO_OUT_ENABLE (void) { 296 | pinMode(PIN_SWDIO, OUTPUT); 297 | } 298 | 299 | /** SWDIO I/O pin: Switch to Input mode (used in SWD mode only). 300 | Configure the SWDIO DAP hardware I/O pin to input mode. This function is 301 | called prior \ref PIN_SWDIO_IN function calls. 302 | */ 303 | static __forceinline void PIN_SWDIO_OUT_DISABLE (void) { 304 | pinMode(PIN_SWDIO, INPUT_PULLUP); 305 | } 306 | 307 | 308 | // TDI Pin I/O --------------------------------------------- 309 | 310 | /** TDI I/O pin: Get Input. 311 | \return Current status of the TDI DAP hardware I/O pin. 312 | */ 313 | static __forceinline uint32_t PIN_TDI_IN (void) { 314 | return (digitalRead(PIN_TDI) == HIGH) ? 1 : 0; 315 | } 316 | 317 | /** TDI I/O pin: Set Output. 318 | \param bit Output value for the TDI DAP hardware I/O pin. 319 | */ 320 | static __forceinline void PIN_TDI_OUT (uint32_t bit) { 321 | digitalWrite(PIN_TDI, (bit & 1) ? HIGH : LOW); 322 | } 323 | 324 | 325 | // TDO Pin I/O --------------------------------------------- 326 | 327 | /** TDO I/O pin: Get Input. 328 | \return Current status of the TDO DAP hardware I/O pin. 329 | */ 330 | static __forceinline uint32_t PIN_TDO_IN (void) { 331 | return (digitalRead(PIN_TDO) == HIGH) ? 1 : 0; 332 | } 333 | 334 | 335 | // nTRST Pin I/O ------------------------------------------- 336 | 337 | /** nTRST I/O pin: Get Input. 338 | \return Current status of the nTRST DAP hardware I/O pin. 339 | */ 340 | static __forceinline uint32_t PIN_nTRST_IN (void) { 341 | return (0); // Not available 342 | } 343 | 344 | /** nTRST I/O pin: Set Output. 345 | \param bit JTAG TRST Test Reset pin status: 346 | - 0: issue a JTAG TRST Test Reset. 347 | - 1: release JTAG TRST Test Reset. 348 | */ 349 | static __forceinline void PIN_nTRST_OUT (uint32_t bit) { 350 | ; // Not available 351 | } 352 | 353 | // nRESET Pin I/O------------------------------------------ 354 | 355 | /** nRESET I/O pin: Get Input. 356 | \return Current status of the nRESET DAP hardware I/O pin. 357 | */ 358 | static __forceinline uint32_t PIN_nRESET_IN (void) { 359 | return (digitalRead(PIN_nRESET) == HIGH) ? 1 : 0; 360 | } 361 | 362 | /** nRESET I/O pin: Set Output. 363 | \param bit target device hardware reset pin status: 364 | - 0: issue a device hardware reset. 365 | - 1: release device hardware reset. 366 | */ 367 | static __forceinline void PIN_nRESET_OUT (uint32_t bit) { 368 | digitalWrite(PIN_nRESET, (bit & 1) ? HIGH : LOW); 369 | } 370 | 371 | ///@} 372 | 373 | 374 | //************************************************************************************************** 375 | /** 376 | \defgroup DAP_Config_LEDs_gr CMSIS-DAP Hardware Status LEDs 377 | \ingroup DAP_ConfigIO_gr 378 | @{ 379 | 380 | CMSIS-DAP Hardware may provide LEDs that indicate the status of the CMSIS-DAP Debug Unit. 381 | 382 | It is recommended to provide the following LEDs for status indication: 383 | - Connect LED: is active when the DAP hardware is connected to a debugger. 384 | - Running LED: is active when the debugger has put the target device into running state. 385 | */ 386 | 387 | /** Debug Unit: Set status of Connected LED. 388 | \param bit status of the Connect LED. 389 | - 1: Connect LED ON: debugger is connected to CMSIS-DAP Debug Unit. 390 | - 0: Connect LED OFF: debugger is not connected to CMSIS-DAP Debug Unit. 391 | */ 392 | static __inline void LED_CONNECTED_OUT (uint32_t bit) { 393 | digitalWrite(PIN_LED_CONNECTED, bit ? HIGH : LOW); 394 | } 395 | 396 | /** Debug Unit: Set status Target Running LED. 397 | \param bit status of the Target Running LED. 398 | - 1: Target Running LED ON: program execution in target started. 399 | - 0: Target Running LED OFF: program execution in target stopped. 400 | */ 401 | static __inline void LED_RUNNING_OUT (uint32_t bit) { 402 | digitalWrite(PIN_LED_RUNNING, bit ? HIGH : LOW); 403 | } 404 | 405 | ///@} 406 | 407 | 408 | //************************************************************************************************** 409 | /** 410 | \defgroup DAP_Config_Initialization_gr CMSIS-DAP Initialization 411 | \ingroup DAP_ConfigIO_gr 412 | @{ 413 | 414 | CMSIS-DAP Hardware I/O and LED Pins are initialized with the function \ref DAP_SETUP. 415 | */ 416 | 417 | /** Setup of the Debug Unit I/O pins and LEDs (called when Debug Unit is initialized). 418 | This function performs the initialization of the CMSIS-DAP Hardware I/O Pins and the 419 | Status LEDs. In detail the operation of Hardware I/O and LED pins are enabled and set: 420 | - I/O clock system enabled. 421 | - all I/O pins: input buffer enabled, output pins are set to HighZ mode. 422 | - for nTRST, nRESET a weak pull-up (if available) is enabled. 423 | - LED output pins are enabled and LEDs are turned off. 424 | */ 425 | static __inline void DAP_SETUP (void) { 426 | pinMode(PIN_SWCLK, INPUT); 427 | pinMode(PIN_SWDIO, INPUT_PULLUP); 428 | pinMode(PIN_nRESET, INPUT_PULLUP); 429 | pinMode(PIN_TDI, INPUT); 430 | pinMode(PIN_TDO, INPUT); 431 | pinMode(PIN_LED_CONNECTED, OUTPUT); 432 | LED_CONNECTED_OUT(0); 433 | pinMode(PIN_LED_RUNNING, OUTPUT); 434 | LED_RUNNING_OUT(0); 435 | } 436 | 437 | /** Reset Target Device with custom specific I/O pin or command sequence. 438 | This function allows the optional implementation of a device specific reset sequence. 439 | It is called when the command \ref DAP_ResetTarget and is for example required 440 | when a device needs a time-critical unlock sequence that enables the debug port. 441 | \return 0 = no device specific reset sequence is implemented.\n 442 | 1 = a device specific reset sequence is implemented. 443 | */ 444 | static __inline uint32_t RESET_TARGET (void) { 445 | return (0); // change to '1' when a device reset sequence is implemented 446 | } 447 | 448 | ///@} 449 | 450 | 451 | #endif /* __DAP_CONFIG_H__ */ 452 | 453 | -------------------------------------------------------------------------------- /JTAG_DP.cpp: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP Interface Firmware 2 | * Copyright (c) 2009-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "DAP_config.h" 18 | #include "DAP.h" 19 | 20 | 21 | // JTAG Macros 22 | 23 | #define PIN_TCK_SET PIN_SWCLK_TCK_SET 24 | #define PIN_TCK_CLR PIN_SWCLK_TCK_CLR 25 | #define PIN_TMS_SET PIN_SWDIO_TMS_SET 26 | #define PIN_TMS_CLR PIN_SWDIO_TMS_CLR 27 | 28 | #define JTAG_CYCLE_TCK() \ 29 | PIN_TCK_CLR(); \ 30 | PIN_DELAY(); \ 31 | PIN_TCK_SET(); \ 32 | PIN_DELAY() 33 | 34 | #define JTAG_CYCLE_TDI(tdi) \ 35 | PIN_TDI_OUT(tdi); \ 36 | PIN_TCK_CLR(); \ 37 | PIN_DELAY(); \ 38 | PIN_TCK_SET(); \ 39 | PIN_DELAY() 40 | 41 | #define JTAG_CYCLE_TDO(tdo) \ 42 | PIN_TCK_CLR(); \ 43 | PIN_DELAY(); \ 44 | tdo = PIN_TDO_IN(); \ 45 | PIN_TCK_SET(); \ 46 | PIN_DELAY() 47 | 48 | #define JTAG_CYCLE_TDIO(tdi,tdo) \ 49 | PIN_TDI_OUT(tdi); \ 50 | PIN_TCK_CLR(); \ 51 | PIN_DELAY(); \ 52 | tdo = PIN_TDO_IN(); \ 53 | PIN_TCK_SET(); \ 54 | PIN_DELAY() 55 | 56 | #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) 57 | 58 | 59 | #if (DAP_JTAG != 0) 60 | 61 | 62 | // Generate JTAG Sequence 63 | // info: sequence information 64 | // tdi: pointer to TDI generated data 65 | // tdo: pointer to TDO captured data 66 | // return: none 67 | void JTAG_Sequence (uint32_t info, uint8_t *tdi, uint8_t *tdo) { 68 | uint32_t i_val; 69 | uint32_t o_val; 70 | uint32_t bit; 71 | uint32_t n, k; 72 | 73 | n = info & JTAG_SEQUENCE_TCK; 74 | if (n == 0) n = 64; 75 | 76 | if (info & JTAG_SEQUENCE_TMS) { 77 | PIN_TMS_SET(); 78 | } else { 79 | PIN_TMS_CLR(); 80 | } 81 | 82 | while (n) { 83 | i_val = *tdi++; 84 | o_val = 0; 85 | for (k = 8; k && n; k--, n--) { 86 | JTAG_CYCLE_TDIO(i_val, bit); 87 | i_val >>= 1; 88 | o_val >>= 1; 89 | o_val |= bit << 7; 90 | } 91 | o_val >>= k; 92 | if (info & JTAG_SEQUENCE_TDO) { 93 | *tdo++ = o_val; 94 | } 95 | } 96 | } 97 | 98 | 99 | // JTAG Set IR 100 | // ir: IR value 101 | // return: none 102 | #define JTAG_IR_Function(speed) /**/ \ 103 | void JTAG_IR_##speed (uint32_t ir) { \ 104 | uint32_t n; \ 105 | \ 106 | PIN_TMS_SET(); \ 107 | JTAG_CYCLE_TCK(); /* Select-DR-Scan */ \ 108 | JTAG_CYCLE_TCK(); /* Select-IR-Scan */ \ 109 | PIN_TMS_CLR(); \ 110 | JTAG_CYCLE_TCK(); /* Capture-IR */ \ 111 | JTAG_CYCLE_TCK(); /* Shift-IR */ \ 112 | \ 113 | PIN_TDI_OUT(1); \ 114 | for (n = DAP_Data.jtag_dev.ir_before[DAP_Data.jtag_dev.index]; n; n--) { \ 115 | JTAG_CYCLE_TCK(); /* Bypass before data */ \ 116 | } \ 117 | for (n = DAP_Data.jtag_dev.ir_length[DAP_Data.jtag_dev.index] - 1; n; n--) { \ 118 | JTAG_CYCLE_TDI(ir); /* Set IR bits (except last) */ \ 119 | ir >>= 1; \ 120 | } \ 121 | n = DAP_Data.jtag_dev.ir_after[DAP_Data.jtag_dev.index]; \ 122 | if (n) { \ 123 | JTAG_CYCLE_TDI(ir); /* Set last IR bit */ \ 124 | PIN_TDI_OUT(1); \ 125 | for (--n; n; n--) { \ 126 | JTAG_CYCLE_TCK(); /* Bypass after data */ \ 127 | } \ 128 | PIN_TMS_SET(); \ 129 | JTAG_CYCLE_TCK(); /* Bypass & Exit1-IR */ \ 130 | } else { \ 131 | PIN_TMS_SET(); \ 132 | JTAG_CYCLE_TDI(ir); /* Set last IR bit & Exit1-IR */ \ 133 | } \ 134 | \ 135 | JTAG_CYCLE_TCK(); /* Update-IR */ \ 136 | PIN_TMS_CLR(); \ 137 | JTAG_CYCLE_TCK(); /* Idle */ \ 138 | PIN_TDI_OUT(1); \ 139 | } 140 | 141 | 142 | // JTAG Transfer I/O 143 | // request: A[3:2] RnW APnDP 144 | // data: DATA[31:0] 145 | // return: ACK[2:0] 146 | #define JTAG_TransferFunction(speed) /**/ \ 147 | uint8_t JTAG_Transfer##speed (uint32_t request, uint32_t *data) { \ 148 | uint32_t ack; \ 149 | uint32_t bit; \ 150 | uint32_t val; \ 151 | uint32_t n; \ 152 | \ 153 | PIN_TMS_SET(); \ 154 | JTAG_CYCLE_TCK(); /* Select-DR-Scan */ \ 155 | PIN_TMS_CLR(); \ 156 | JTAG_CYCLE_TCK(); /* Capture-DR */ \ 157 | JTAG_CYCLE_TCK(); /* Shift-DR */ \ 158 | \ 159 | for (n = DAP_Data.jtag_dev.index; n; n--) { \ 160 | JTAG_CYCLE_TCK(); /* Bypass before data */ \ 161 | } \ 162 | \ 163 | JTAG_CYCLE_TDIO(request >> 1, bit); /* Set RnW, Get ACK.0 */ \ 164 | ack = bit << 1; \ 165 | JTAG_CYCLE_TDIO(request >> 2, bit); /* Set A2, Get ACK.1 */ \ 166 | ack |= bit << 0; \ 167 | JTAG_CYCLE_TDIO(request >> 3, bit); /* Set A3, Get ACK.2 */ \ 168 | ack |= bit << 2; \ 169 | \ 170 | if (ack != DAP_TRANSFER_OK) { \ 171 | /* Exit on error */ \ 172 | PIN_TMS_SET(); \ 173 | JTAG_CYCLE_TCK(); /* Exit1-DR */ \ 174 | goto exit; \ 175 | } \ 176 | \ 177 | if (request & DAP_TRANSFER_RnW) { \ 178 | /* Read Transfer */ \ 179 | val = 0; \ 180 | for (n = 31; n; n--) { \ 181 | JTAG_CYCLE_TDO(bit); /* Get D0..D30 */ \ 182 | val |= bit << 31; \ 183 | val >>= 1; \ 184 | } \ 185 | n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1; \ 186 | if (n) { \ 187 | JTAG_CYCLE_TDO(bit); /* Get D31 */ \ 188 | for (--n; n; n--) { \ 189 | JTAG_CYCLE_TCK(); /* Bypass after data */ \ 190 | } \ 191 | PIN_TMS_SET(); \ 192 | JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ \ 193 | } else { \ 194 | PIN_TMS_SET(); \ 195 | JTAG_CYCLE_TDO(bit); /* Get D31 & Exit1-DR */ \ 196 | } \ 197 | val |= bit << 31; \ 198 | if (data) *data = val; \ 199 | } else { \ 200 | /* Write Transfer */ \ 201 | val = *data; \ 202 | for (n = 31; n; n--) { \ 203 | JTAG_CYCLE_TDI(val); /* Set D0..D30 */ \ 204 | val >>= 1; \ 205 | } \ 206 | n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1; \ 207 | if (n) { \ 208 | JTAG_CYCLE_TDI(val); /* Set D31 */ \ 209 | for (--n; n; n--) { \ 210 | JTAG_CYCLE_TCK(); /* Bypass after data */ \ 211 | } \ 212 | PIN_TMS_SET(); \ 213 | JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ \ 214 | } else { \ 215 | PIN_TMS_SET(); \ 216 | JTAG_CYCLE_TDI(val); /* Set D31 & Exit1-DR */ \ 217 | } \ 218 | } \ 219 | \ 220 | exit: \ 221 | JTAG_CYCLE_TCK(); /* Update-DR */ \ 222 | PIN_TMS_CLR(); \ 223 | JTAG_CYCLE_TCK(); /* Idle */ \ 224 | PIN_TDI_OUT(1); \ 225 | \ 226 | /* Idle cycles */ \ 227 | n = DAP_Data.transfer.idle_cycles; \ 228 | while (n--) { \ 229 | JTAG_CYCLE_TCK(); /* Idle */ \ 230 | } \ 231 | \ 232 | return (ack); \ 233 | } 234 | 235 | 236 | #undef PIN_DELAY 237 | #define PIN_DELAY() PIN_DELAY_FAST() 238 | JTAG_IR_Function(Fast); 239 | JTAG_TransferFunction(Fast); 240 | 241 | #undef PIN_DELAY 242 | #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) 243 | JTAG_IR_Function(Slow); 244 | JTAG_TransferFunction(Slow); 245 | 246 | 247 | // JTAG Read IDCODE register 248 | // return: value read 249 | uint32_t JTAG_ReadIDCode (void) { 250 | uint32_t bit; 251 | uint32_t val; 252 | uint32_t n; 253 | 254 | PIN_TMS_SET(); 255 | JTAG_CYCLE_TCK(); /* Select-DR-Scan */ 256 | PIN_TMS_CLR(); 257 | JTAG_CYCLE_TCK(); /* Capture-DR */ 258 | JTAG_CYCLE_TCK(); /* Shift-DR */ 259 | 260 | for (n = DAP_Data.jtag_dev.index; n; n--) { 261 | JTAG_CYCLE_TCK(); /* Bypass before data */ 262 | } 263 | 264 | val = 0; 265 | for (n = 31; n; n--) { 266 | JTAG_CYCLE_TDO(bit); /* Get D0..D30 */ 267 | val |= bit << 31; 268 | val >>= 1; 269 | } 270 | PIN_TMS_SET(); 271 | JTAG_CYCLE_TDO(bit); /* Get D31 & Exit1-DR */ 272 | val |= bit << 31; 273 | 274 | JTAG_CYCLE_TCK(); /* Update-DR */ 275 | PIN_TMS_CLR(); 276 | JTAG_CYCLE_TCK(); /* Idle */ 277 | 278 | return (val); 279 | } 280 | 281 | 282 | // JTAG Write ABORT register 283 | // data: value to write 284 | // return: none 285 | void JTAG_WriteAbort (uint32_t data) { 286 | uint32_t n; 287 | 288 | PIN_TMS_SET(); 289 | JTAG_CYCLE_TCK(); /* Select-DR-Scan */ 290 | PIN_TMS_CLR(); 291 | JTAG_CYCLE_TCK(); /* Capture-DR */ 292 | JTAG_CYCLE_TCK(); /* Shift-DR */ 293 | 294 | for (n = DAP_Data.jtag_dev.index; n; n--) { 295 | JTAG_CYCLE_TCK(); /* Bypass before data */ 296 | } 297 | 298 | PIN_TDI_OUT(0); 299 | JTAG_CYCLE_TCK(); /* Set RnW=0 (Write) */ 300 | JTAG_CYCLE_TCK(); /* Set A2=0 */ 301 | JTAG_CYCLE_TCK(); /* Set A3=0 */ 302 | 303 | for (n = 31; n; n--) { 304 | JTAG_CYCLE_TDI(data); /* Set D0..D30 */ 305 | data >>= 1; 306 | } 307 | n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1; 308 | if (n) { 309 | JTAG_CYCLE_TDI(data); /* Set D31 */ 310 | for (--n; n; n--) { 311 | JTAG_CYCLE_TCK(); /* Bypass after data */ 312 | } 313 | PIN_TMS_SET(); 314 | JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ 315 | } else { 316 | PIN_TMS_SET(); 317 | JTAG_CYCLE_TDI(data); /* Set D31 & Exit1-DR */ 318 | } 319 | 320 | JTAG_CYCLE_TCK(); /* Update-DR */ 321 | PIN_TMS_CLR(); 322 | JTAG_CYCLE_TCK(); /* Idle */ 323 | PIN_TDI_OUT(1); 324 | } 325 | 326 | 327 | // JTAG Set IR 328 | // ir: IR value 329 | // return: none 330 | void JTAG_IR (uint32_t ir) { 331 | if (DAP_Data.fast_clock) { 332 | JTAG_IR_Fast(ir); 333 | } else { 334 | JTAG_IR_Slow(ir); 335 | } 336 | } 337 | 338 | 339 | // JTAG Transfer I/O 340 | // request: A[3:2] RnW APnDP 341 | // data: DATA[31:0] 342 | // return: ACK[2:0] 343 | uint8_t JTAG_Transfer(uint32_t request, uint32_t *data) { 344 | if (DAP_Data.fast_clock) { 345 | return JTAG_TransferFast(request, data); 346 | } else { 347 | return JTAG_TransferSlow(request, data); 348 | } 349 | } 350 | 351 | 352 | #endif /* (DAP_JTAG != 0) */ 353 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | CMSIS-DAP Interface Firmware 2 | Copyright (c) 2009-2013 ARM Limited 3 | Copyright (c) 2016 Phillip Pearson 4 | 5 | Licensed under the Apache License, Version 2.0 (the "License"); 6 | you may not use this file except in compliance with the License. 7 | You may obtain a copy of the License at 8 | 9 | http://www.apache.org/licenses/LICENSE-2.0 10 | 11 | Unless required by applicable law or agreed to in writing, software 12 | distributed under the License is distributed on an "AS IS" BASIS, 13 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | See the License for the specific language governing permissions and 15 | limitations under the License. 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # arduino-cmsis-dap 2 | 3 | CMSIS-DAP USB-SWD/JTAG HID adapter firmware for Pro Micro and Teensy 3.2 boards 4 | 5 | Copyright (C) 2016 Phillip Pearson 6 | 7 | based on the CMSIS-DAP Interface Firmware 8 | 9 | Copyright (c) 2009-2013 ARM Limited 10 | 11 | This is a port of the core of ARM's CMSIS-DAP firmware to the Arduino environment, 12 | which lets you turn a Pro Micro (or $3.50 clone from China) 13 | or Teensy 3.2 into a 14 | CMSIS-DAP USB adapter, which you can use with OpenOCD and mbed to program and debug ARM chips using the SWD protocol, 15 | and also with OpenOCD to program and debug various chips using JTAG. 16 | 17 | See arduino-cmsis-dap.ino for installation details. -------------------------------------------------------------------------------- /SW_DP.cpp: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP Interface Firmware 2 | * Copyright (c) 2009-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "DAP_config.h" 18 | #include "DAP.h" 19 | 20 | 21 | // SW Macros 22 | 23 | #define PIN_SWCLK_SET PIN_SWCLK_TCK_SET 24 | #define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR 25 | 26 | #define SW_CLOCK_CYCLE() \ 27 | PIN_SWCLK_CLR(); \ 28 | PIN_DELAY(); \ 29 | PIN_SWCLK_SET(); \ 30 | PIN_DELAY() 31 | 32 | #define SW_WRITE_BIT(bit) \ 33 | PIN_SWDIO_OUT(bit); \ 34 | PIN_SWCLK_CLR(); \ 35 | PIN_DELAY(); \ 36 | PIN_SWCLK_SET(); \ 37 | PIN_DELAY() 38 | 39 | #define SW_READ_BIT(bit) \ 40 | PIN_SWCLK_CLR(); \ 41 | PIN_DELAY(); \ 42 | bit = PIN_SWDIO_IN(); \ 43 | PIN_SWCLK_SET(); \ 44 | PIN_DELAY() 45 | 46 | #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) 47 | 48 | 49 | // Generate SWJ Sequence 50 | // count: sequence bit count 51 | // data: pointer to sequence bit data 52 | // return: none 53 | #if ((DAP_SWD != 0) || (DAP_JTAG != 0)) 54 | void SWJ_Sequence (uint32_t count, uint8_t *data) { 55 | uint32_t val; 56 | uint32_t n; 57 | 58 | val = 0; 59 | n = 0; 60 | while (count--) { 61 | if (n == 0) { 62 | val = *data++; 63 | n = 8; 64 | } 65 | if (val & 1) { 66 | PIN_SWDIO_TMS_SET(); 67 | } else { 68 | PIN_SWDIO_TMS_CLR(); 69 | } 70 | SW_CLOCK_CYCLE(); 71 | val >>= 1; 72 | n--; 73 | } 74 | } 75 | #endif 76 | 77 | 78 | #if (DAP_SWD != 0) 79 | 80 | 81 | // SWD Transfer I/O 82 | // request: A[3:2] RnW APnDP 83 | // data: DATA[31:0] 84 | // return: ACK[2:0] 85 | #define SWD_TransferFunction(speed) /**/ \ 86 | uint8_t SWD_Transfer##speed (uint32_t request, uint32_t *data) { \ 87 | uint32_t ack; \ 88 | uint32_t bit; \ 89 | uint32_t val; \ 90 | uint32_t parity; \ 91 | \ 92 | uint32_t n; \ 93 | \ 94 | /* Packet Request */ \ 95 | parity = 0; \ 96 | SW_WRITE_BIT(1); /* Start Bit */ \ 97 | bit = request >> 0; \ 98 | SW_WRITE_BIT(bit); /* APnDP Bit */ \ 99 | parity += bit; \ 100 | bit = request >> 1; \ 101 | SW_WRITE_BIT(bit); /* RnW Bit */ \ 102 | parity += bit; \ 103 | bit = request >> 2; \ 104 | SW_WRITE_BIT(bit); /* A2 Bit */ \ 105 | parity += bit; \ 106 | bit = request >> 3; \ 107 | SW_WRITE_BIT(bit); /* A3 Bit */ \ 108 | parity += bit; \ 109 | SW_WRITE_BIT(parity); /* Parity Bit */ \ 110 | SW_WRITE_BIT(0); /* Stop Bit */ \ 111 | SW_WRITE_BIT(1); /* Park Bit */ \ 112 | \ 113 | /* Turnaround */ \ 114 | PIN_SWDIO_OUT_DISABLE(); \ 115 | for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ 116 | SW_CLOCK_CYCLE(); \ 117 | } \ 118 | \ 119 | /* Acknowledge response */ \ 120 | SW_READ_BIT(bit); \ 121 | ack = bit << 0; \ 122 | SW_READ_BIT(bit); \ 123 | ack |= bit << 1; \ 124 | SW_READ_BIT(bit); \ 125 | ack |= bit << 2; \ 126 | \ 127 | if (ack == DAP_TRANSFER_OK) { /* OK response */ \ 128 | /* Data transfer */ \ 129 | if (request & DAP_TRANSFER_RnW) { \ 130 | /* Read data */ \ 131 | val = 0; \ 132 | parity = 0; \ 133 | for (n = 32; n; n--) { \ 134 | SW_READ_BIT(bit); /* Read RDATA[0:31] */ \ 135 | parity += bit; \ 136 | val >>= 1; \ 137 | val |= bit << 31; \ 138 | } \ 139 | SW_READ_BIT(bit); /* Read Parity */ \ 140 | if ((parity ^ bit) & 1) { \ 141 | ack = DAP_TRANSFER_ERROR; \ 142 | } \ 143 | if (data) *data = val; \ 144 | /* Turnaround */ \ 145 | for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ 146 | SW_CLOCK_CYCLE(); \ 147 | } \ 148 | PIN_SWDIO_OUT_ENABLE(); \ 149 | } else { \ 150 | /* Turnaround */ \ 151 | for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ 152 | SW_CLOCK_CYCLE(); \ 153 | } \ 154 | PIN_SWDIO_OUT_ENABLE(); \ 155 | /* Write data */ \ 156 | val = *data; \ 157 | parity = 0; \ 158 | for (n = 32; n; n--) { \ 159 | SW_WRITE_BIT(val); /* Write WDATA[0:31] */ \ 160 | parity += val; \ 161 | val >>= 1; \ 162 | } \ 163 | SW_WRITE_BIT(parity); /* Write Parity Bit */ \ 164 | } \ 165 | /* Idle cycles */ \ 166 | n = DAP_Data.transfer.idle_cycles; \ 167 | if (n) { \ 168 | PIN_SWDIO_OUT(0); \ 169 | for (; n; n--) { \ 170 | SW_CLOCK_CYCLE(); \ 171 | } \ 172 | } \ 173 | PIN_SWDIO_OUT(1); \ 174 | return (ack); \ 175 | } \ 176 | \ 177 | if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { \ 178 | /* WAIT or FAULT response */ \ 179 | if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) != 0)) { \ 180 | for (n = 32+1; n; n--) { \ 181 | SW_CLOCK_CYCLE(); /* Dummy Read RDATA[0:31] + Parity */ \ 182 | } \ 183 | } \ 184 | /* Turnaround */ \ 185 | for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ 186 | SW_CLOCK_CYCLE(); \ 187 | } \ 188 | PIN_SWDIO_OUT_ENABLE(); \ 189 | if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) == 0)) { \ 190 | PIN_SWDIO_OUT(0); \ 191 | for (n = 32+1; n; n--) { \ 192 | SW_CLOCK_CYCLE(); /* Dummy Write WDATA[0:31] + Parity */ \ 193 | } \ 194 | } \ 195 | PIN_SWDIO_OUT(1); \ 196 | return (ack); \ 197 | } \ 198 | \ 199 | /* Protocol error */ \ 200 | for (n = DAP_Data.swd_conf.turnaround + 32 + 1; n; n--) { \ 201 | SW_CLOCK_CYCLE(); /* Back off data phase */ \ 202 | } \ 203 | PIN_SWDIO_OUT(1); \ 204 | return (ack); \ 205 | } 206 | 207 | 208 | #undef PIN_DELAY 209 | #define PIN_DELAY() PIN_DELAY_FAST() 210 | SWD_TransferFunction(Fast); 211 | 212 | #undef PIN_DELAY 213 | #define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) 214 | SWD_TransferFunction(Slow); 215 | 216 | 217 | // SWD Transfer I/O 218 | // request: A[3:2] RnW APnDP 219 | // data: DATA[31:0] 220 | // return: ACK[2:0] 221 | uint8_t SWD_Transfer(uint32_t request, uint32_t *data) { 222 | if (DAP_Data.fast_clock) { 223 | return SWD_TransferFast(request, data); 224 | } else { 225 | return SWD_TransferSlow(request, data); 226 | } 227 | } 228 | 229 | 230 | #endif /* (DAP_SWD != 0) */ 231 | -------------------------------------------------------------------------------- /arduino-cmsis-dap.ino: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP ported to run on the Pro Micro and Teensy 3.2 2 | * Copyright (C) 2016 Phillip Pearson 3 | * 4 | * CMSIS-DAP Interface Firmware 5 | * Copyright (c) 2009-2013 ARM Limited 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * 19 | * ******************************************************************* 20 | * 21 | * INSTALLATION INSTRUCTIONS 22 | * 23 | * DEPENDENCIES 24 | * 25 | * To build this code, you'll need the Arduino toolchain, plus the 26 | * appropriate package for your board. You'll also need to install 27 | * NicoHood's HID library: https://github.com/NicoHood/HID 28 | * 29 | * If you get an error about HID-Project.h, double check that you've 30 | * installed the HID library properly. 31 | * 32 | * BUILD SETUP 33 | * 34 | * For a device to be correctly detected as a CMSIS-DAP adapter, it must 35 | * contain the string "CMSIS-DAP" in its USB product name. Unfortunately 36 | * we can't override this from within the sketch -- you'll have to edit 37 | * files in your Arduino installation to change it. 38 | * 39 | * Arduino Micro: 40 | * Inside your Arduino installation, edit hardware/arduino/avr/boards.txt 41 | * and add CMSIS-DAP to micro.build.usb_product: 42 | * 43 | * micro.build.usb_product="Arduino Micro CMSIS-DAP" 44 | * 45 | * Sparkfun Pro Micro: 46 | * Inside your Arduino installation, edit ~/.arduino15/packages/SparkFun/hardware/avr/1.1.12/boards.txt 47 | * and add CMSIS-DAP to micro.build.usb_product: 48 | * 49 | * promicro.build.usb_product="SparkFun Pro Micro CMSIS-DAP" 50 | * 51 | * Teensy 3.2: 52 | * Inside your Arduino installation, edit hardware/teensy/avr/cores/teensy3/usb_desc.h 53 | * and change some of the text in the line starting #define PRODUCT_NAME 54 | * to include CMSIS-DAP: 55 | * 56 | * #define PRODUCT_NAME {'T','e','e','n','s','y',' ','-',' ','C','M','S','I','S','-','D','A','P'} 57 | * 58 | * You also need to select "Raw HID" under Tools | USB Type, after 59 | * selecting the Teensy 3.2 board. 60 | * 61 | * WIRING 62 | * 63 | * Connect up your SWD or JTAG target to the appropriate pins for your board: 64 | * 65 | * Pro Micro pins: 66 | * 2 SWDIO 67 | * 3 SWCLK 68 | * 4 TDO 69 | * 5 TDI 70 | * 6 /RESET 71 | * 72 | * Teensy 3.2 pins: 73 | * 19 SWDIO 74 | * 20 SWCLK 75 | * 21 TDO 76 | * 22 TDI 77 | * 23 /RESET 78 | * 79 | * Then give it a try! With OpenOCD, the command line will look something like this: 80 | * 81 | * openocd -f interface/cmsis-dap.cfg -f target/kl25.cfg 82 | * 83 | * If it doesn't work, try adding '-d' to get more debug information. 84 | * 85 | */ 86 | 87 | #include "DAP_config.h" 88 | #include "DAP.h" 89 | 90 | uint8_t rawhidRequest[DAP_PACKET_SIZE]; 91 | uint8_t rawhidResponse[DAP_PACKET_SIZE]; 92 | 93 | 94 | void setup() { 95 | Serial.begin(115200); 96 | 97 | DAP_Setup(); 98 | 99 | #ifdef HIDPROJECT_RAWHID 100 | // Set the RawHID OUT report array. 101 | // Feature reports are also (parallel) possible, see the other example for this. 102 | RawHID.begin(rawhidRequest, DAP_PACKET_SIZE); 103 | #endif 104 | } 105 | 106 | void loop() { 107 | // Check if there is new data from the RawHID device 108 | auto bytesAvailable = 109 | #ifdef HIDPROJECT_RAWHID 110 | RawHID.available(); 111 | #else 112 | RawHID.recv(rawhidRequest, 0); 113 | #endif 114 | if (bytesAvailable > 0) { 115 | #if DAP_SERIAL_LOG 116 | Serial.print("cmd "); 117 | Serial.print(rawhidRequest[0], HEX); 118 | Serial.print(" "); 119 | Serial.print(rawhidRequest[1], HEX); 120 | Serial.print(" "); 121 | #endif /* DAP_SERIAL_LOG */ 122 | auto sz = DAP_ProcessCommand(rawhidRequest, rawhidResponse); 123 | #if DAP_SERIAL_LOG 124 | Serial.print("rsp "); 125 | Serial.print(sz); 126 | Serial.println(" B"); 127 | #endif /* DAP_SERIAL_LOG */ 128 | #ifdef HIDPROJECT_RAWHID 129 | RawHID.enable(); // signal that we're ready to receive another buffer 130 | #endif 131 | if (sz > 0) { 132 | #ifdef HIDPROJECT_RAWHID 133 | RawHID.write(rawhidResponse, DAP_PACKET_SIZE); 134 | #else 135 | RawHID.send(rawhidResponse, DAP_PACKET_SIZE); 136 | #endif 137 | } 138 | } 139 | } 140 | 141 | -------------------------------------------------------------------------------- /board.cpp: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP Interface Firmware 2 | * Copyright (c) 2009-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include "board.h" 17 | 18 | /* Each board should have a unique ID and secret. For information 19 | * about obtaining a secret contact support@mbed.org 20 | */ 21 | #if defined (BOARD_FRDM_KL25Z) || defined (BOARD_TWR_KL25Z48M) 22 | #define BOARD_ID "0200" 23 | #define BOARD_SECRET "xxxxxxxx" 24 | 25 | #elif defined (BOARD_FRDM_KL05Z) 26 | #define BOARD_ID "0210" 27 | #define BOARD_SECRET "xxxxxxxx" 28 | 29 | #elif defined (BOARD_FRDM_KL46Z) 30 | #define BOARD_ID "0220" 31 | #define BOARD_SECRET "xxxxxxxx" 32 | 33 | #elif defined (BOARD_FRDM_K20D50M) 34 | #define BOARD_ID "0230" 35 | #define BOARD_SECRET "xxxxxxxx" 36 | 37 | #elif defined (BOARD_FRDM_K22F) 38 | #define BOARD_ID "0231" 39 | #define BOARD_SECRET "xxxxxxxx" 40 | 41 | #elif defined (BOARD_FRDM_K64F) 42 | #define BOARD_ID "0240" 43 | #define BOARD_SECRET "xxxxxxxx" 44 | 45 | #elif defined (BOARD_FRDM_KL02Z) 46 | #define BOARD_ID "0250" 47 | #define BOARD_SECRET "xxxxxxxx" 48 | 49 | #elif defined (BOARD_FRDM_KL26Z) 50 | #define BOARD_ID "0260" 51 | #define BOARD_SECRET "xxxxxxxx" 52 | 53 | #elif defined (BOARD_FRDM_KE02Z) 54 | #define BOARD_ID "0270" 55 | #define BOARD_SECRET "xxxxxxxx" 56 | 57 | #elif defined (BOARD_TWR_K24F) 58 | #define BOARD_ID "0280" 59 | #define BOARD_SECRET "xxxxxxxx" 60 | 61 | #elif defined (BOARD_LPC812_MAX) 62 | #define BOARD_ID "1050" 63 | #define BOARD_SECRET "xxxxxxxx" 64 | 65 | #elif defined (BOARD_SEEED_ARCH_PRO) 66 | #define BOARD_ID "9004" 67 | #define BOARD_SECRET "xxxxxxxx" 68 | 69 | #elif defined (BOARD_UBLOX_C027) 70 | #define BOARD_ID "1234" 71 | #define BOARD_SECRET "xxxxxxxx" 72 | 73 | #elif defined (BOARD_LPC1114) 74 | #define BOARD_ID "1114" 75 | #define BOARD_SECRET "xxxxxxxx" 76 | 77 | #elif defined (BOARD_BAMBINO_210) 78 | #define BOARD_ID "1600" 79 | #define BOARD_SECRET "xxxxxxxx" 80 | 81 | #elif defined (BOARD_BAMBINO_210E) 82 | #define BOARD_ID "1605" 83 | #define BOARD_SECRET "xxxxxxxx" 84 | 85 | #elif defined (BOARD_LPC1549) 86 | #define BOARD_ID "1549" 87 | #define BOARD_SECRET "xxxxxxxx" 88 | 89 | #elif defined (BOARD_LPC11U68) 90 | #define BOARD_ID "1168" 91 | #define BOARD_SECRET "xxxxxxxx" 92 | 93 | #elif defined (BOARD_LPC4337) 94 | #define BOARD_ID "1062" 95 | #define BOARD_SECRET "xxxxxxxx" 96 | 97 | #elif defined(ARDUINO_AVR_MICRO) || defined(TEENSYDUINO) || defined(ARDUINO_AVR_PROMICRO) 98 | #define BOARD_ID {1, 1, 1, 1} 99 | #define BOARD_SECRET {1, 1, 1, 1, 1, 1, 1, 1, 1} 100 | 101 | #endif 102 | 103 | #if !defined(BOARD_SECRET) || !defined(BOARD_ID) 104 | // TODO: how to check a string value using the preprocessor... 105 | #error contact support@mbed.org to obtain a secret and board ID 106 | #endif 107 | 108 | BOARD board = { 109 | BOARD_ID, // board id 110 | BOARD_SECRET // board secret 111 | }; 112 | 113 | /* Weak declaration of the board_init function for boards that don't use it */ 114 | void board_init(void) { 115 | } 116 | -------------------------------------------------------------------------------- /board.h: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP Interface Firmware 2 | * Copyright (c) 2009-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef BOARD_H 17 | #define BOARD_H 18 | 19 | #include 20 | 21 | typedef struct { 22 | const uint8_t id[4]; 23 | const uint8_t secret[9]; 24 | } BOARD; 25 | 26 | extern BOARD board; 27 | 28 | // Init function called in main() before the main task is started 29 | void board_init(void); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /dap_vendor_command.cpp: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP Interface Firmware 2 | * Copyright (c) 2009-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | //#include 17 | #include 18 | #include 19 | 20 | //#include "rl_usb.h" 21 | // #include "version.h" 22 | #include "DAP_config.h" 23 | #include "uart.h" 24 | #include "DAP.h" 25 | 26 | // Process DAP Vendor command and prepare response 27 | // Default function (can be overridden) 28 | // request: pointer to request data 29 | // response: pointer to response data 30 | // return: number of bytes in response 31 | // this function is declared as __weak in DAP.c 32 | //uint32_t DAP_ProcessVendorCommand(uint8_t *request, uint8_t *response) { 33 | // 34 | // // get unique ID command 35 | // if (*request == ID_DAP_Vendor0) { 36 | //#define FOO "I have no idea what I'm doing" 37 | // *response++ = ID_DAP_Vendor0; 38 | // *response++ = strlen(FOO); 39 | // strcpy((char *)response, FOO); 40 | // return (strlen(FOO) + 2); 41 | // } 42 | // 43 | // // else return invalid command 44 | // else { 45 | // *response = ID_DAP_Invalid; 46 | // } 47 | // return (1); 48 | //} 49 | -------------------------------------------------------------------------------- /debug_cm.h: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP Interface Firmware 2 | * Copyright (c) 2009-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef DEBUG_CM_H 17 | #define DEBUG_CM_H 18 | 19 | // Debug Port Register Addresses 20 | #define DP_IDCODE 0x00 // IDCODE Register (Read only) 21 | #define DP_ABORT 0x00 // Abort Register (Write only) 22 | #define DP_CTRL_STAT 0x04 // Control & Status 23 | #define DP_WCR 0x04 // Wire Control Register (SW Only) 24 | #define DP_DLCR 0x04 // Data Link Control Register (Renamed WCR) 25 | #define DP_SELECT 0x08 // Select Register (JTAG R/W & SW W) 26 | #define DP_RESEND 0x08 // Resend (SW Read Only) 27 | #define DP_RDBUFF 0x0C // Read Buffer (Read Only) 28 | 29 | // Abort Register definitions 30 | #define DAPABORT 0x00000001 // DAP Abort 31 | #define STKCMPCLR 0x00000002 // Clear STICKYCMP Flag (SW Only) 32 | #define STKERRCLR 0x00000004 // Clear STICKYERR Flag (SW Only) 33 | #define WDERRCLR 0x00000008 // Clear WDATAERR Flag (SW Only) 34 | #define ORUNERRCLR 0x00000010 // Clear STICKYORUN Flag (SW Only) 35 | 36 | // Debug Control and Status definitions 37 | #define ORUNDETECT 0x00000001 // Overrun Detect 38 | #define STICKYORUN 0x00000002 // Sticky Overrun 39 | #define TRNMODE 0x0000000C // Transfer Mode Mask 40 | #define TRNNORMAL 0x00000000 // Transfer Mode: Normal 41 | #define TRNVERIFY 0x00000004 // Transfer Mode: Pushed Verify 42 | #define TRNCOMPARE 0x00000008 // Transfer Mode: Pushed Compare 43 | #define STICKYCMP 0x00000010 // Sticky Compare 44 | #define STICKYERR 0x00000020 // Sticky Error 45 | #define READOK 0x00000040 // Read OK (SW Only) 46 | #define WDATAERR 0x00000080 // Write Data Error (SW Only) 47 | #define MASKLANE 0x00000F00 // Mask Lane Mask 48 | #define MASKLANE0 0x00000100 // Mask Lane 0 49 | #define MASKLANE1 0x00000200 // Mask Lane 1 50 | #define MASKLANE2 0x00000400 // Mask Lane 2 51 | #define MASKLANE3 0x00000800 // Mask Lane 3 52 | #define TRNCNT 0x001FF000 // Transaction Counter Mask 53 | #define CDBGRSTREQ 0x04000000 // Debug Reset Request 54 | #define CDBGRSTACK 0x08000000 // Debug Reset Acknowledge 55 | #define CDBGPWRUPREQ 0x10000000 // Debug Power-up Request 56 | #define CDBGPWRUPACK 0x20000000 // Debug Power-up Acknowledge 57 | #define CSYSPWRUPREQ 0x40000000 // System Power-up Request 58 | #define CSYSPWRUPACK 0x80000000 // System Power-up Acknowledge 59 | 60 | // Debug Select Register definitions 61 | #define CTRLSEL 0x00000001 // CTRLSEL (SW Only) 62 | #define APBANKSEL 0x000000F0 // APBANKSEL Mask 63 | #define APSEL 0xFF000000 // APSEL Mask 64 | 65 | // Access Port Register Addresses 66 | #define AP_CSW 0x00 // Control and Status Word 67 | #define AP_TAR 0x04 // Transfer Address 68 | #define AP_DRW 0x0C // Data Read/Write 69 | #define AP_BD0 0x10 // Banked Data 0 70 | #define AP_BD1 0x14 // Banked Data 1 71 | #define AP_BD2 0x18 // Banked Data 2 72 | #define AP_BD3 0x1C // Banked Data 3 73 | #define AP_ROM 0xF8 // Debug ROM Address 74 | #define AP_IDR 0xFC // Identification Register 75 | 76 | // AP Control and Status Word definitions 77 | #define CSW_SIZE 0x00000007 // Access Size: Selection Mask 78 | #define CSW_SIZE8 0x00000000 // Access Size: 8-bit 79 | #define CSW_SIZE16 0x00000001 // Access Size: 16-bit 80 | #define CSW_SIZE32 0x00000002 // Access Size: 32-bit 81 | #define CSW_ADDRINC 0x00000030 // Auto Address Increment Mask 82 | #define CSW_NADDRINC 0x00000000 // No Address Increment 83 | #define CSW_SADDRINC 0x00000010 // Single Address Increment 84 | #define CSW_PADDRINC 0x00000020 // Packed Address Increment 85 | #define CSW_DBGSTAT 0x00000040 // Debug Status 86 | #define CSW_TINPROG 0x00000080 // Transfer in progress 87 | #define CSW_HPROT 0x02000000 // User/Privilege Control 88 | #define CSW_MSTRTYPE 0x20000000 // Master Type Mask 89 | #define CSW_MSTRCORE 0x00000000 // Master Type: Core 90 | #define CSW_MSTRDBG 0x20000000 // Master Type: Debug 91 | #define CSW_RESERVED 0x01000000 // Reserved Value 92 | 93 | // Core Debug Register Address Offsets 94 | #define DBG_OFS 0x0DF0 // Debug Register Offset inside NVIC 95 | #define DBG_HCSR_OFS 0x00 // Debug Halting Control & Status Register 96 | #define DBG_CRSR_OFS 0x04 // Debug Core Register Selector Register 97 | #define DBG_CRDR_OFS 0x08 // Debug Core Register Data Register 98 | #define DBG_EMCR_OFS 0x0C // Debug Exception & Monitor Control Register 99 | 100 | // Core Debug Register Addresses 101 | #define DBG_HCSR (DBG_Addr + DBG_HCSR_OFS) 102 | #define DBG_CRSR (DBG_Addr + DBG_CRSR_OFS) 103 | #define DBG_CRDR (DBG_Addr + DBG_CRDR_OFS) 104 | #define DBG_EMCR (DBG_Addr + DBG_EMCR_OFS) 105 | 106 | // Debug Halting Control and Status Register definitions 107 | #define C_DEBUGEN 0x00000001 // Debug Enable 108 | #define C_HALT 0x00000002 // Halt 109 | #define C_STEP 0x00000004 // Step 110 | #define C_MASKINTS 0x00000008 // Mask Interrupts 111 | #define C_SNAPSTALL 0x00000020 // Snap Stall 112 | #define S_REGRDY 0x00010000 // Register R/W Ready Flag 113 | #define S_HALT 0x00020000 // Halt Flag 114 | #define S_SLEEP 0x00040000 // Sleep Flag 115 | #define S_LOCKUP 0x00080000 // Lockup Flag 116 | #define S_RETIRE_ST 0x01000000 // Sticky Retire Flag 117 | #define S_RESET_ST 0x02000000 // Sticky Reset Flag 118 | #define DBGKEY 0xA05F0000 // Debug Key 119 | 120 | // Debug Exception and Monitor Control Register definitions 121 | #define VC_CORERESET 0x00000001 // Reset Vector Catch 122 | #define VC_MMERR 0x00000010 // Debug Trap on MMU Fault 123 | #define VC_NOCPERR 0x00000020 // Debug Trap on No Coprocessor Fault 124 | #define VC_CHKERR 0x00000040 // Debug Trap on Checking Error Fault 125 | #define VC_STATERR 0x00000080 // Debug Trap on State Error Fault 126 | #define VC_BUSERR 0x00000100 // Debug Trap on Bus Error Fault 127 | #define VC_INTERR 0x00000200 // Debug Trap on Interrupt Error Fault 128 | #define VC_HARDERR 0x00000400 // Debug Trap on Hard Fault 129 | #define MON_EN 0x00010000 // Monitor Enable 130 | #define MON_PEND 0x00020000 // Monitor Pend 131 | #define MON_STEP 0x00040000 // Monitor Step 132 | #define MON_REQ 0x00080000 // Monitor Request 133 | #define TRCENA 0x01000000 // Trace Enable (DWT, ITM, ETM, TPIU) 134 | 135 | // NVIC: Interrupt Controller Type Register 136 | #define NVIC_ICT (NVIC_Addr + 0x0004) 137 | #define INTLINESNUM 0x0000001F // Interrupt Line Numbers 138 | 139 | // NVIC: CPUID Base Register 140 | #define NVIC_CPUID (NVIC_Addr + 0x0D00) 141 | #define CPUID_PARTNO 0x0000FFF0 // Part Number Mask 142 | #define CPUID_REVISION 0x0000000F // Revision Mask 143 | #define CPUID_VARIANT 0x00F00000 // Variant Mask 144 | 145 | // NVIC: Application Interrupt/Reset Control Register 146 | #define NVIC_AIRCR (NVIC_Addr + 0x0D0C) 147 | #define VECTRESET 0x00000001 // Reset Cortex-M (except Debug) 148 | #define VECTCLRACTIVE 0x00000002 // Clear Active Vector Bit 149 | #define SYSRESETREQ 0x00000004 // Reset System (except Debug) 150 | #define VECTKEY 0x05FA0000 // Write Key 151 | 152 | // NVIC: Debug Fault Status Register 153 | #define NVIC_DFSR (NVIC_Addr + 0x0D30) 154 | #define HALTED 0x00000001 // Halt Flag 155 | #define BKPT 0x00000002 // BKPT Flag 156 | #define DWTTRAP 0x00000004 // DWT Match 157 | #define VCATCH 0x00000008 // Vector Catch Flag 158 | #define EXTERNAL 0x00000010 // External Debug Request 159 | 160 | #endif 161 | -------------------------------------------------------------------------------- /gpio.h: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP Interface Firmware 2 | * Copyright (c) 2009-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef GPIO_H 17 | #define GPIO_H 18 | 19 | void gpio_init(void); 20 | void gpio_enable_button_flag(int task, uint16_t flag); 21 | void gpio_set_dap_led(uint8_t state); 22 | void gpio_set_cdc_led(uint8_t state); 23 | void gpio_set_msd_led(uint8_t state); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /read_uid.h: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP Interface Firmware 2 | * Copyright (c) 2009-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef READ_UID_H 17 | #define READ_UID_H 18 | 19 | #include 20 | 21 | void read_unique_id(uint32_t * id); 22 | 23 | #ifdef BOARD_UBLOX_C027 24 | void __svc(2) enter_isp(void); 25 | #endif 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /semihost.cpp: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP Interface Firmware 2 | * Copyright (c) 2009-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifdef SEMIHOST 17 | 18 | #include 19 | #include 20 | 21 | #include "tasks.h" 22 | #include "main.h" 23 | 24 | #include "target_reset.h" 25 | #include "version.h" 26 | #include "swd_host.h" 27 | #include "semihost.h" 28 | 29 | #define RESERVED_FOR_USER_APPLICATIONS (0x100) /* 0x100 - 0x1ff */ 30 | #define USR_UID (RESERVED_FOR_USER_APPLICATIONS + 1) 31 | #define USR_RESET (RESERVED_FOR_USER_APPLICATIONS + 2) 32 | #define USR_POWERDOWN (RESERVED_FOR_USER_APPLICATIONS + 4) 33 | #define USR_DISABLEDEBUG (RESERVED_FOR_USER_APPLICATIONS + 5) 34 | #define angel_SWIreason_ReportException (0x18) 35 | 36 | #define FLAGS_SH_START (1) 37 | #define FLAGS_SH_STOP (2) 38 | 39 | static OS_TID semihostTask; 40 | static OS_SEM semihostStoppedSem; 41 | static uint8_t semihostEnabled; 42 | static uint32_t r0, r1; 43 | 44 | static int shReadWord(uint32_t address, uint32_t *ptr) { 45 | return swd_read_memory(address, (uint8_t *)ptr, sizeof(uint32_t)); 46 | } 47 | 48 | static int shWriteBytes(uint32_t address, uint8_t *ptr, uint32_t count) { 49 | return swd_write_memory(address, ptr, count); 50 | } 51 | 52 | static int sh_usr_uid(uint32_t *r0, uint32_t r1) { 53 | uint32_t p1, p2; 54 | uint32_t uidSize; 55 | uint32_t i; 56 | uint8_t null = '\0'; 57 | uint8_t * id_str; 58 | 59 | // Read parameter block 60 | if (!shReadWord(r1, &p1)) 61 | return 0; 62 | 63 | if (!shReadWord(r1+4, &p2)) 64 | return 0; 65 | 66 | id_str = get_uid_string(); 67 | uidSize = strlen((const char *)id_str) - 4; 68 | 69 | // Validate parameters 70 | if (p1 == NULL) return 1; 71 | if (p2 != (uidSize+1)) return 1; // +1 for null string terminator 72 | 73 | // skip " $ $ $ length" 74 | id_str += 4; 75 | 76 | // Write data to target 77 | for (i = 0; i < uidSize; i++) { 78 | if (!shWriteBytes(p1++, id_str, 1)) 79 | return 0; 80 | id_str++; 81 | } 82 | // Write null terminator to target 83 | if (!shWriteBytes(p1, &null, 1)) 84 | return 0; 85 | 86 | *r0 = 0; // Successful 87 | return 1; 88 | } 89 | 90 | static int sh_usr_reset(uint32_t *r0, uint32_t r1) { 91 | main_reset_target(0); 92 | 93 | // Don't restart target as the target will be resetted 94 | return 0; 95 | } 96 | 97 | static int sh_report_exception(uint32_t *r0, uint32_t r1) { 98 | uint32_t p1; 99 | 100 | // Read paramter block 101 | if (!shReadWord(r1, &p1)) return 0; 102 | 103 | // TODO: r1 does not appear to be set a to a useful value, contrary to the ARM documentation? See: 104 | // DUI0205G_rvct_compiler_and_libraries_guide.pdf 7.4.2 angel_SWIreason_ReportException (0x18) 105 | return 1; 106 | } 107 | 108 | 109 | static int sh_usr_powerdown(uint32_t *r0, uint32_t r1) { 110 | main_powerdown_event(); 111 | 112 | // successful 113 | *r0 = 0; 114 | return 1; 115 | } 116 | 117 | static int sh_usr_disabledebug(uint32_t *r0, uint32_t r1) { 118 | main_disable_debug_event(); 119 | 120 | // successful 121 | *r0 = 0; 122 | return 1; 123 | } 124 | 125 | static int process_event(void) { 126 | // Returns TRUE if successful, FALSE if an error occurs 127 | uint32_t svc; 128 | 129 | svc = r0; 130 | 131 | // Set default return value 132 | r0 = 0xffffffff; 133 | 134 | switch(svc) { 135 | case USR_UID: 136 | if (!sh_usr_uid(&r0,r1)) return 0; 137 | break; 138 | case USR_RESET: 139 | if (!sh_usr_reset(&r0,r1)) return 0; 140 | break; 141 | case USR_POWERDOWN: 142 | if (!sh_usr_powerdown(&r0,r1)) return 0; 143 | break; 144 | case USR_DISABLEDEBUG: 145 | if (!sh_usr_disabledebug(&r0,r1)) return 0; 146 | break; 147 | case angel_SWIreason_ReportException: 148 | if (!sh_report_exception(&r0,r1)) return 0; 149 | break; 150 | default: 151 | break; 152 | } 153 | 154 | return 1; 155 | } 156 | 157 | static void sh_main(void) { 158 | while(1) { 159 | // Wait for start flag 160 | os_evt_wait_or(FLAGS_SH_START, NO_TIMEOUT); 161 | 162 | do { 163 | if (swd_is_semihost_event(&r0, &r1)) { 164 | if (process_event()) { 165 | swd_semihost_restart(r0); 166 | } 167 | } else { 168 | // Wait for 2 scheduler tick; the serial task may run at this point 169 | os_dly_wait(2); 170 | } 171 | // Loop until stop flag is set 172 | } while (os_evt_wait_or(FLAGS_SH_STOP, 0 )==OS_R_TMO); 173 | 174 | // Stopped 175 | os_sem_send(semihostStoppedSem); 176 | } 177 | } 178 | 179 | void semihost_init(void) { 180 | // Called from main task 181 | 182 | semihostEnabled = 0; 183 | os_sem_init(semihostStoppedSem,0); 184 | 185 | // Create semihost task 186 | semihostTask = os_tsk_create(sh_main, SEMIHOST_TASK_PRIORITY); 187 | return; 188 | } 189 | 190 | void semihost_enable(void) { 191 | // Called from: 192 | // - main task when the interface firmware starts 193 | // - cmsis-dap when a debugger closes the swd port 194 | // - drag n drop when a binary has been flashed 195 | 196 | if (semihostEnabled) return; 197 | if (semihostTask==0) return; 198 | 199 | // enable debug 200 | target_set_state(DEBUG); 201 | 202 | os_evt_set(FLAGS_SH_START, semihostTask); 203 | 204 | semihostEnabled = 1; 205 | 206 | return; 207 | } 208 | 209 | void semihost_disable(void) { 210 | // Called from: 211 | // - main task when the the interface receives the POWERDOWN semihost call 212 | // - cmsis-dap when a debugger opens the swd port 213 | // - drag n drop when a binary will be flashed 214 | 215 | if (!semihostEnabled) return; 216 | if (semihostTask==0) return; 217 | 218 | os_evt_set(FLAGS_SH_STOP, semihostTask); 219 | 220 | // Wait for semihost task to stop 221 | os_sem_wait(semihostStoppedSem, NO_TIMEOUT); 222 | semihostEnabled = 0; 223 | return; 224 | } 225 | 226 | #else /* #ifndef SEMIHOST */ 227 | void semihost_init(void) { } 228 | void semihost_enable(void) { } 229 | void semihost_disable(void){ } 230 | #endif 231 | -------------------------------------------------------------------------------- /semihost.h: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP Interface Firmware 2 | * Copyright (c) 2009-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef SEMIHOST_H 17 | #define SEMIHOST_H 18 | 19 | void semihost_init(void); 20 | void semihost_enable(void); 21 | void semihost_disable(void); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /target_reset.h: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP Interface Firmware 2 | * Copyright (c) 2009-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef TARGET_RESET_H 17 | #define TARGET_RESET_H 18 | 19 | #include "target_struct.h" 20 | 21 | void target_before_init_debug(void); 22 | uint8_t target_unlock_sequence(void); 23 | uint8_t target_set_state(TARGET_RESET_STATE state); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /target_struct.h: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP Interface Firmware 2 | * Copyright (c) 2009-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef TARGET_H 17 | #define TARGET_H 18 | 19 | #include 20 | 21 | typedef struct { 22 | uint32_t breakpoint; 23 | uint32_t static_base; 24 | uint32_t stack_pointer; 25 | } FLASH_SYSCALL; 26 | 27 | typedef struct { 28 | 29 | uint32_t init; 30 | uint32_t uninit; 31 | uint32_t erase_chip; 32 | uint32_t erase_sector; 33 | uint32_t program_page; 34 | 35 | FLASH_SYSCALL sys_call_param; 36 | 37 | uint32_t program_buffer; 38 | uint32_t algo_start; 39 | uint32_t algo_size; 40 | const uint32_t * image; 41 | 42 | uint32_t ram_to_flash_bytes_to_be_written; 43 | 44 | } TARGET_FLASH; 45 | 46 | typedef enum { 47 | RESET_HOLD, // Hold target in reset 48 | RESET_PROGRAM, // Reset target and setup for flash programming. 49 | RESET_RUN, // Reset target and run normally 50 | RESET_RUN_WITH_DEBUG, // Reset target and run with debug enabled (required for semihost) 51 | NO_DEBUG, // Disable debug on running target 52 | DEBUG // Enable debug on running target 53 | } TARGET_RESET_STATE; 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /tasks.h: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP Interface Firmware 2 | * Copyright (c) 2009-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef TASK_H 17 | #define TASK_H 18 | 19 | #define NO_TIMEOUT (0xffff) 20 | 21 | #define LOWEST_PRIORITY (1) /* Priority 0 is reserved for the RTX idle task */ 22 | #define HIGHEST_PRIORITY (254) /* Priority 255 is reserved by RTX */ 23 | 24 | #define MAIN_TASK_PRIORITY (8) 25 | #define SERIAL_TASK_PRIORITY (1) 26 | #define TIMER_TASK_PRIORITY (11) 27 | #define DAP_TASK_PRIORITY (15) 28 | #define MSC_TASK_PRIORITY (5) 29 | #define TIMER_TASK_30_PRIORITY (TIMER_TASK_PRIORITY) 30 | #define SEMIHOST_TASK_PRIORITY (2) 31 | 32 | #define TIMER_TASK_30_STACK (100) 33 | #define DAP_TASK_STACK (400) 34 | #define SERIAL_TASK_STACK (400) 35 | #define MSC_TASK_STACK (200) 36 | #define MAIN_TASK_STACK (200) 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /uart.h: -------------------------------------------------------------------------------- 1 | /* CMSIS-DAP Interface Firmware 2 | * Copyright (c) 2009-2013 ARM Limited 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef UART_H 17 | #define UART_H 18 | 19 | #include 20 | 21 | /* Parity enumerator */ 22 | typedef enum { 23 | UART_PARITY_NONE = 0, 24 | UART_PARITY_ODD = 1, 25 | UART_PARITY_EVEN = 2, 26 | UART_PARITY_MARK = 3, 27 | UART_PARITY_SPACE = 4 28 | } UART_Parity; 29 | 30 | /* Stop Bits enumerator */ 31 | typedef enum { 32 | UART_STOP_BITS_1 = 0, 33 | UART_STOP_BITS_1_5 = 1, 34 | UART_STOP_BITS_2 = 2 35 | } UART_StopBits; 36 | 37 | /* Data Bits enumerator */ 38 | typedef enum { 39 | UART_DATA_BITS_5 = 5, 40 | UART_DATA_BITS_6 = 6, 41 | UART_DATA_BITS_7 = 7, 42 | UART_DATA_BITS_8 = 8, 43 | UART_DATA_BITS_16 = 16 44 | } UART_DataBits; 45 | 46 | /* Flow control enumerator */ 47 | typedef enum { 48 | UART_FLOW_CONTROL_NONE = 0, 49 | UART_FLOW_CONTROL_RTS_CTS = 1, 50 | UART_FLOW_CONTROL_XON_XOFF = 2 51 | } UART_FlowControl; 52 | 53 | /* UART Port Properties structure */ 54 | typedef struct { 55 | uint32_t Baudrate; 56 | UART_DataBits DataBits; 57 | UART_Parity Parity; 58 | UART_StopBits StopBits; 59 | UART_FlowControl FlowControl; 60 | } UART_Configuration; 61 | 62 | /*----------------------------------------------------------------------------- 63 | * FUNCTION PROTOTYPES 64 | *----------------------------------------------------------------------------*/ 65 | 66 | /* UART driver function prototypes */ 67 | extern int32_t uart_initialize (void); 68 | extern int32_t uart_uninitialize (void); 69 | extern int32_t uart_reset (void); 70 | extern int32_t uart_set_configuration (UART_Configuration *config); 71 | extern int32_t uart_get_configuration (UART_Configuration *config); 72 | extern int32_t uart_write_free (void); 73 | extern int32_t uart_write_data (uint8_t *data, uint16_t size); 74 | extern int32_t uart_read_data (uint8_t *data, uint16_t size); 75 | 76 | #endif /* __UART_H */ 77 | --------------------------------------------------------------------------------