开贴记录SWD 脱机烧录器开发过程,请各路大神指教

2019-12-09 19:23发布

参考 CMISI_DAP,BlackMagic代码。
预备下周末结案,目前方案:
1:Host用STM32F427,跑RTEMS系统, IO口模拟SWD时序。
2:flash的操作函数,由Host通过SWD下载入target ram执行。(CMISI_DAP采用这种方式)
     不知道jlink的flash操作是不是一样的原理。他要适用这么多芯片,那得有准备多少这样的小程序啊。。。
3:USB用的虚拟串口,用ST官方提供的驱动,上位机编程简单。tafget本身程序.bin文件由上位机通过虚拟串口传入。
     此虚拟串口的波特率,奇偶,起停位设置均形同虚设。

目前状态:
SWD时序基本调试通过,读写target ID/reg已经正常,暂时未经过高强度测试。。
正在弄flash操作。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
94条回答
shangdawei
1楼-- · 2019-12-13 15:14
 精彩回答 2  元偷偷看……
shangdawei
2楼-- · 2019-12-13 19:03
ARM调试接口SWD(Serial Wire Debug) 协议分析
http://www.amobbs.com/thread-5498445-1-1.html
(出处: amoBBS 阿莫电子论坛)
shangdawei
3楼-- · 2019-12-13 20:34
ARM Debug Interface v5 Architecture Specification.pdf (1.67 MB, 下载次数: 64) 2015-8-22 22:30 上传 点击文件名下载附件
shangdawei
4楼-- · 2019-12-13 21:25
https://www.xiaopingtou.cn/data/attach/1912/biie33myl84bsf09u19qlymh3hakhhf4.jpg

HyperSnap1169.png (303.44 KB, 下载次数: 4)

下载附件

2015-8-22 23:29 上传



这个使用了 SPI 接口, 可以参考一下。

混合模式,传送 Request 和 Data 时用 SPI, 传送 ACK 时用模拟的。


  1. //=================================================================================
  2. // ARM SWD Mode Port Bit masks
  3. //
  4. #if (HW_CAPABILITY&CAP_SWD_HW)
  5. #ifndef DATA_PORT
  6. #define DATA_PORT          PTAD
  7. #define DATA_PORT_DDR      PTADD
  8. #define DATA_PORT_PER      PTAPE
  9. #endif

  10. // SWD data out pin
  11. #define SWD_OUT             PTAD_PTAD2
  12. #define SWD_OUT_BIT         (2)  // Bit number!
  13. #define SWD_OUT_MASK        (1<<SWD_OUT_BIT)
  14. #define SWD_OUT_PER         PTAPE_PTAPE2
  15. #define SWD_OUT_DDR         PTADD_PTADD2

  16. // SWD data out 3-state control
  17. #define SWD_OUT_EN          PTAD_PTAD4
  18. #define SWD_OUT_EN_BIT      (4)  // Bit number!
  19. #define SWD_OUT_EN_MASK     (1<<SWD_OUT_EN_BIT)
  20. #define SWD_OUT_EN_PER      PTAPE_PTAPE4
  21. #define SWD_OUT_EN_DDR      PTADD_PTADD4

  22. // Following assume pin already configured by SWD_LOW(),SWD_HIGH(),SWD_3STATE()
  23. #define SWD_ENABLE_ASM      BCLR SWD_OUT_EN_BIT,DATA_PORT
  24. #define SWD_3STATE_ASM      BSET SWD_OUT_EN_BIT,DATA_PORT
  25. #define SWD_LOW_ASM         BCLR SWD_OUT_BIT,DATA_PORT
  26. #define SWD_HIGH_ASM        BSET SWD_OUT_BIT,DATA_PORT
  27. #define SWD_DISABLE_ASM     BCLR SWD_OUT_EN_BIT,DATA_PORT_DDR
  28. #define SWD_ENABLE_DRV_ASM  BSET SWD_OUT_EN_BIT,DATA_PORT_DDR

  29. // Following configure pin & driver
  30. #define SWD_LOW()           (SWD_OUT=0, SWD_OUT_DDR=1, SWD_OUT_EN=0, SWD_OUT_EN_DDR=1)
  31. #define SWD_HIGH()          (SWD_OUT=1, SWD_OUT_DDR=1, SWD_OUT_EN=0, SWD_OUT_EN_DDR=1)
  32. #define SWD_3STATE()        (SWD_OUT_EN=1, SWD_OUT_EN_DDR=1, SWD_OUT_DDR=1)
  33. #define SWD_DISABLE()       (SWD_OUT_EN=1, SWD_OUT_EN_DDR=0, SWD_OUT_DDR=0) // PUPs

  34. // SWD data in pin
  35. #define SWD_IN              PTAD_PTAD0
  36. #define SWD_IN_BIT          (0)  // Bit number!
  37. #define SWD_IN_MASK         (1<<SWD_IN_BIT)
  38. #define SWD_IN_PER          PTAPE_PTAPE0
  39. #define SWD_IN_DDR          PTADD_PTADD0

  40. // SWCLK out pin
  41. #define SWCLK_OUT           PTAD_PTAD3
  42. #define SWCLK_OUT_BIT       (3)  // Bit number!
  43. #define SWCLK_OUT_MASK      (1<<SWCLK_OUT_BIT)
  44. #define SWCLK_OUT_PER       PTAPE_PTAPE3
  45. #define SWCLK_OUT_DDR       PTADD_PTADD3

  46. // SWCLK enable pin - controls buffer enable
  47. #define SWCLK_OUT_EN        PTBD_PTBD1
  48. #define SWCLK_OUT_EN_BIT    (1)  // Bit number!
  49. #define SWCLK_OUT_EN_MASK   (1<<SWCLK_OUT_EN_BIT)
  50. #define SWCLK_OUT_EN_PER    PTBPE_PTBPE1
  51. #define SWCLK_OUT_EN_DDR    PTBDD_PTBDD1

  52. // Following assume pin direction already set
  53. #define SWCLK_LOW_ASM       BCLR SWCLK_OUT_BIT,DATA_PORT
  54. #define SWCLK_HIGH_ASM      BSET SWCLK_OUT_BIT,DATA_PORT

  55. // Following configure pin & driver
  56. #define SWCLK_LOW()         (SWCLK_OUT=0, SWCLK_OUT_DDR=1, SWCLK_OUT_EN=0, SWCLK_OUT_EN_DDR=1)
  57. #define SWCLK_HIGH()        (SWCLK_OUT=1, SWCLK_OUT_DDR=1, SWCLK_OUT_EN=0, SWCLK_OUT_EN_DDR=1)
  58. #define SWCLK_3STATE()      (SWCLK_OUT_EN=1, SWCLK_OUT_EN_DDR=1, SWCLK_OUT_DDR=1) // PUPs
  59. #define SWCLK_DISABLE()     (SWCLK_OUT_EN=1, SWCLK_OUT_EN_DDR=0, SWCLK_OUT_DDR=0) // PUPs

  60. #endif // CAP_SWD
复制代码
  1. /*
  2. * SWD.h
  3. *
  4. *  Created on: 04/08/2012
  5. *      Author: PODonoghue
  6. */

  7. #ifndef SWD_H_
  8. #define SWD_H_

  9. #include "Common.h"

  10. // Ack values displaced by offset introduced during read (left justified 8-bit value)
  11. #define SWD_ACK_OK       (0x1<<5)
  12. #define SWD_ACK_WAIT     (0x2<<5)
  13. #define SWD_ACK_FAULT    (0x4<<5)
  14. #define SWD_ACK_PROTOCOL (0x7<<5)

  15. void swd_interfaceIdle(void);
  16. void swd_init(void);
  17. void swd_txIdle8(void);

  18. U8 swd_test(void);

  19. U8 swd_sendCommandWithWait(U8 command);

  20. U8 swd_connect(void);
  21. U8 swd_readReg(U8 command, U8 *data);
  22. U8 swd_writeReg(U8 command, const U8 *data);
  23. U8 swd_readAPReg(const U8 *address, U8 *buff);
  24. U8 swd_writeAPReg(const U8 *address, const U8 *buff);
  25. U8 swd_clearStickyError(void);
  26. U8 swd_abortAP(void);
  27. #endif /* SWD_H_ */
复制代码
  1. /*! file
  2.     rief ARM-SWD routines

  3.    verbatim

  4.    USBDM

  5.    Copyright (C) 2007  Peter O'Donoghue

  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2 of the License, or
  9.    (at your option) any later version.

  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.

  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17.    endverbatim

  18.    Change History
  19.    +==================================================================================================
  20.    | 21 Feb 2014 | Fixed unbalanced stack in swd_sendCommandWithWait()                      V4.10.6.30
  21.    | 10 Feb 2014 | Dramatically extended retry times to allow for slow clocks               V4.10.6.20
  22.    | 30 Aug 2012 | ARM-JTAG & ARM-SWD Changes                                               V4.9.5
  23.    +==================================================================================================
  24.    endverbatim
  25. */

  26. #include "Common.h"
  27. #include "Configure.h"
  28. #include "Commands.h"
  29. #include "SWD.h"
  30. #include "Commands.h"
  31. #include "BDM.h"
  32. #include "BDM_CF.h"
  33. #include "CmdProcessing.h"
  34. #include "BDMCommon.h"
  35. #include "SPI.h"
  36. #include "TargetDefines.h"
  37. #include "SWD.h"
  38.   
  39. #if TARGET_CAPABILITY & CAP_ARM_SWD

  40. //! SPI Masks - Mask to enable SPI as master Tx
  41. #define SPIxC1_OFF      (SPIxC1_MSTR_MASK)     //!< SPI Masks - Mask to disable SPI
  42. #define SPIxC1_M_ON_TX  (SPIxC1_SPE_MASK|SPIxC1_MSTR_MASK|SPIxC1_CPOL_MASK|SPIxC1_CPHA_MASK|SPIxC1_SSOE_MASK|SPIxC1_LSBFE_MASK)
  43. #define SPIxC1_M_ON_RX  (SPIxC1_SPE_MASK|SPIxC1_MSTR_MASK|SPIxC1_CPOL_MASK)                   //!< SPI Masks - Mask to enable SPI as master Tx
  44. #define SPIxC2_M_8      (0)                                                                   //!< SPI Masks - 8-bit mode
  45. #define SPIxC2_M_16     (SPIxC2_SPIMODE_MASK)                                                 //!< SPI Masks - 8-bit mode

  46. // Can't use enumerations in assembly code
  47. #define BDM_RC_OKx                 (0)
  48. #define BDM_RC_NO_CONNECTIONx      (5)
  49. #define BDM_RC_ACK_TIMEOUTx        (30)
  50. #define BDM_RC_ARM_PARITY_ERRORx   (51)
  51. #define BDM_RC_ARM_FAULT_ERRORx    (52)

  52. #define SWD_READ_IDCODE 0xA5 // (Park,Stop,Parity,A[32],R/W,AP/DP,Start) = 10100101

  53. // Masks for SWD_WR_DP_ABORT clear sticky
  54. #define SWD_DP_ABORT_CLEAR_STICKY_ERRORS_B3 0x1E

  55. // Masks for SWD_WR_DP_ABORT abort AP
  56. #define SWD_DP_ABORT_ABORT_AP_B3 0x01

  57. // Masks for SWD_RD_DP_STATUS
  58. #define SWD_RD_DP_STATUS_ANYERROR_B3 0xB2

  59. #pragma MESSAGE DISABLE C1404 // Disable warnings about missing return value
  60. #pragma MESSAGE DISABLE C5703 // Disable warnings about unused parameter

  61. //! Sets the SWD interface to an idle state
  62. //! RESET=3-state, SWCLK=High, SWDIO=3-state (SPI off)
  63. //!
  64. void swd_interfaceIdle(void) {
  65. #ifdef RESET_3STATE
  66.    RESET_3STATE();
  67. #endif   
  68.    SWD_3STATE();
  69.    SWCLK_HIGH();
  70.    SPIC1 = SPIxC1_OFF;
  71. }

  72. //! Initialise the SWD interface and sets it to an idle state
  73. //! RESET=3-state, SWCLK=High, SWDIO=3-state
  74. //!
  75. //! @note This includes once-off initialisation such as PUPs etc
  76. //!
  77. void swd_init(void) {
  78.    // 4 pins SWD_OUT, SWD_OUT_EN, SWCLK_OUT, SWCLK_OUT_EN
  79.    // Individually controlled PUPs
  80.    SWD_OUT_PER      = 1;     // Prevent float when disabled
  81.    SWD_OUT_EN_PER   = 1;     // Prevent drive when disabled
  82.    SWCLK_OUT_PER    = 1;     // Prevent float when disabled
  83.    SWCLK_OUT_EN_PER = 1;     // Prevent drive when disabled
  84.    
  85.    SWD_IN_DDR       = 0;  // Make input
  86.    SWD_IN_PER       = 1;  // Shouldn't be req. as external PUP for speed
  87.    
  88. #ifdef RESET_IN_DDR
  89.    RESET_IN_DDR     = 0;     // Make input
  90. #endif
  91. #ifdef RESET_IN_PER
  92.    RESET_IN_PER     = 1;     // Needed for input level translation to 5V
  93. #endif
  94. #ifdef RESET_OUT_PER
  95.    RESET_OUT_PER    = 1;     // Holds RESET_OUT inactive when unused
  96. #endif
  97.    (void)spi_setSpeed(0);
  98.    swd_interfaceIdle();
  99. }

  100. //!  Turns off the SWD interface
  101. //!
  102. //!  Depending upon settings, may leave target power on.
  103. //!
  104. void swd_off( void ) {
  105. #if ((HW_CAPABILITY & CAP_FLASH) != 0)
  106.    (void)bdmSetVpp(BDM_TARGET_VPP_OFF);
  107. #endif
  108.    if (!bdm_option.leaveTargetPowered) {
  109.       VDD_OFF();
  110.    }
  111.    swd_interfaceIdle();
  112.    SWCLK_DISABLE();
  113.    SWD_DISABLE();
  114.    RESET_DISABLE();
  115. }

  116. #define SWD_DATA1_CLK1 SWCLK_OUT_MASK|SWD_OUT_EN_MASK
  117. #define SWD_DATA0_CLK1 SWCLK_OUT_MASK|0

  118. //! Transmits 1 clock with SWDIO 3-state
  119. //!
  120. void swd_turnAround() {
  121.    asm {               
  122.       // 1 clock turn-around
  123.       mov    #SWD_OUT_MASK,DATA_PORT        // SWDIO=3-state,SWCLK=0
  124.       ldx    bitDelay                       // Low time delay
  125.       dbnzx  *-0                            // [4n fppp]
  126.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=1
  127.       ldx    bitDelay                       // High time delay
  128.       dbnzx  *-0                            // [4n fppp]
  129.    }
  130. }

  131. //! Transmits 8-bits of idle (SDIO=0)
  132. //!
  133. void swd_txIdle8(void) {
  134.    asm {               
  135.      mov    #SPIxC2_M_8,SPIxC2             // Initialise SPI (8 bit)
  136.      mov    #SPIxC1_M_ON_TX,SPIC1          // Enable SPI
  137.      clr    DATA_PORT                      // Enable SWD drive
  138.      cmp    SPIxS                          // Dummy status read
  139.      clr    SPIxD                          // Tx data (=0)
  140.    L1:
  141.      brclr  SPIS_SPRF_BIT,SPIxS,L1         // Wait until Tx/Rx complete
  142.      lda    SPIxD                          // Discard rx data
  143.      mov    #SWCLK_OUT_MASK|SWD_OUT_EN_MASK,DATA_PORT // Setup for SWCLK=1, SWD=3-state
  144.      clr    SPIC1                          // Disable SPI
  145.    }
  146. }

  147. #if (SWD_IN_BIT != 0)
  148. #error "SWD_IN must be bit #0"
  149. #endif
  150. #pragma MESSAGE DISABLE C5703  // Disable warnings about unused parameter
  151. //! SWD command phase
  152. //!
  153. //! Writes 8-bit command and receives 3-bit response
  154. //! It will retry on WAIT response a limited number of times
  155. //!
  156. //! @param command - 8-bit command to write to SWD (including parity!)
  157. //!
  158. //! @return
  159. //!    == ef BDM_RC_OK              => Success        
  160. //!    == ef BDM_RC_ARM_FAULT_ERROR => FAULT response from target
  161. //!    == ef BDM_RC_ACK_TIMEOUT     => Excessive number of WAIT responses from target
  162. //!    == ef BDM_RC_NO_CONNECTION   => Unexpected/no response from target
  163. //!
  164. //! @note A turn-around clock period will be added on error responses
  165. //!
  166. uint8_t swd_sendCommandWithWait(uint8_t command) {
  167.    asm {
  168.           sta    txTiming1                      // Save data (for retry)
  169.           ldx    #(2000/250)                    // Set up outer retry count

  170.    retry_outer:
  171.           pshx                                  // Save outer retry count
  172.       mov    #250,rxTiming1                 // Reset inner retry count

  173.    retry:
  174.    
  175.       // 8-bit Start|APnDP|R/W|Parity|Stop|Park
  176.       lda    txTiming1                      // Get Tx data
  177.       mov    #SPIxC2_M_8,SPIxC2             // Initialise SPI (8 bit)
  178.       mov    #SPIxC1_M_ON_TX,SPIC1          // Enable SPI
  179.       clr    DATA_PORT                      // Enable SWD drive
  180.       cmp    SPIxS                          // Dummy status read
  181.       sta    SPIxD                          // Tx data
  182.    L1:
  183.       brclr  SPIS_SPRF_BIT,SPIxS,L1         // Wait until Tx/Rx complete
  184.       ldx    SPIxD                          // Discard rx data
  185.       SWD_3STATE_ASM                        // SWD=3-state
  186.       clr    SPIC1                          // Disable SPI

  187.       // 1 clock turn-around
  188.       bclr   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=0
  189.       ldx    bitDelay                       // Low time delay
  190.       dbnzx  *-0                            // [4n fppp]
  191.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=1
  192.       ldx    bitDelay                       // High time delay
  193.       dbnzx  *-0                            // [4n fppp]
  194.       
  195.       // 1st bit ACK
  196.       clra                                  // Clear initial data value
  197.       bclr   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=0
  198.       ldx    bitDelay                       // Low time delay
  199.       dbnzx  *-0                            // [4n fppp]
  200.       ldx    DATA_PORT                      // Capture data before rising edge
  201.       rorx
  202.       rora
  203.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=1
  204.       ldx    bitDelay                       // High time delay
  205.       dbnzx  *-0                            // [4n fppp]

  206.       // 2nd bit ACK
  207.       bclr   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=0
  208.       ldx    bitDelay                       // Low time delay
  209.       dbnzx  *-0                            // [4n fppp]
  210.       ldx    DATA_PORT                      // Capture data before rising edge
  211.       rorx
  212.       rora
  213.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=1
  214.       ldx    bitDelay                       // High time delay
  215.       dbnzx  *-0                            // [4n fppp]

  216.       // 3rd bit ACK
  217.       bclr   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=0
  218.       ldx    bitDelay                       // Low time delay
  219.       dbnzx  *-0                            // [4n fppp]
  220.       ldx    DATA_PORT
  221.       rorx
  222.       rora      
  223.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=1
  224.       ldx    bitDelay                       // High time delay
  225.       dbnzx  *-0                            // [4n fppp]
  226.       
  227.       tax
  228.       lda    #BDM_RC_OKx
  229.       cbeqx  #SWD_ACK_OK,balanceStack
  230.       
  231.       // Do turn-around clock on anything other than ACK_OK response
  232.       bclr   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=0
  233.       lda    bitDelay                       // Low time delay
  234.       dbnza  *-0                            // [4n fppp]
  235.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=1
  236.       lda    bitDelay                       // High time delay
  237.       dbnza  *-0                            // [4n fppp]
  238.       
  239.       // Check for wait response
  240.       cpx    #SWD_ACK_WAIT                  // Wait response?
  241.       bne    identifyError                  // No - exit with other error
  242.       
  243.       // Check for wait timeout
  244.       dbnz   rxTiming1,retry                // Retry limit reached
  245.       pulx
  246.       dbnzx  retry_outer   

  247.       lda    #BDM_RC_ACK_TIMEOUTx           // Too many retries
  248.       bra    done                           // Return error (stack already balanced)
  249.       
  250.    identifyError:
  251.       lda    #BDM_RC_ARM_FAULT_ERRORx       // Identify error
  252.       cbeqx  #SWD_ACK_FAULT,balanceStack
  253.       lda    #BDM_RC_NO_CONNECTIONx
  254.       
  255.    balanceStack:
  256.       pulx                                  // Balance stack
  257.       
  258.    done:
  259.    }
  260. }

  261. #pragma MESSAGE DEFAULT C5703 // Restore warnings about unused parameter

  262. #pragma MESSAGE DISABLE C5703 // Disable warnings about unused parameter
  263. //! Transmits 32-bit value
  264. //!
  265. //! Sequence as follows:
  266. //!   - 1-clock turn-around
  267. //!   - 32-bit data value
  268. //!   - 1-bit parity
  269. //!   - 8-bit idle
  270. //!
  271. //! @param data - ptr to 32-bit data to Tx
  272. //!
  273. static void swd_tx32(const uint8_t *data) {
  274.    asm {
  275.       // 1 clock turn-around
  276.       bclr   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=0
  277.       lda    bitDelay                       // Low time delay
  278.       dbnza  *-0                            // [4n fppp]
  279.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=1

  280.       mov    #SPIxC2_M_16,SPIxC2            // Initialise SPI (16 bit)
  281.       mov    #SPIxC1_M_ON_TX,SPIxC1         // Enable SPI
  282.       clr    DATA_PORT                      // Enable SWD drive

  283.       cmp    SPIxS                          // Dummy status read
  284.       
  285.       lda    3,x                            // Start Tx 1st & 2nd bytes
  286.       sta    SPIxDL                        
  287.       lda    2,x
  288.       sta    SPIxDH                        
  289.       lda    0,x                            // Do byte-wide parity
  290.       eor    1,x
  291.       eor    2,x
  292.       eor    3,x
  293.       ldhx   0,x                            // Get 3rd & 4th bytes
  294.   L1:
  295.       brclr  SPIS_SPRF_BIT,SPIxS,L1         // Wait until previous Tx/Rx complete
  296.       cphx   SPIxD16                        // Discard read data
  297.       sthx   SPIxD16                        // Tx 3rd & 4th bytes
  298.       
  299.       // Calculate nibble parity
  300.       psha             // [2]
  301.       nsa              // [1]
  302.       eor    1,sp      // [4]
  303.       ais    #1        // [2]
  304.       
  305.       // Calculate final parity
  306.       tax              // [1]
  307.       clra             // [1]
  308.       rorx             // [1]
  309.       adc    #0        // [2]
  310.       rorx             // [1]
  311.       adc    #0        // [2]
  312.       rorx             // [1]
  313.       adc    #0        // [2]
  314.       rorx             // [1]
  315.       adc    #0        // [2]
  316.       //parity in A.0

  317.   L2:
  318.      brclr  SPIS_SPRF_BIT,SPIxS,L2         // Wait until previous Tx/Rx complete
  319.      ldhx   SPIxD16                        // Discard read data
  320.       
  321. #if SWD_OUT_BIT >= 1                        // move to SWD_OUT position
  322.       lsla
  323. #endif
  324. #if SWD_OUT_BIT == 2
  325.       lsla
  326. #else
  327. #error Fix this code
  328. #endif
  329.       and    #SWD_OUT_MASK                  // SWD=p, SWCLK=0
  330.       sta    DATA_PORT                      // Set up - no effect yet
  331.       ldx    bitDelay                       // Low time delay
  332.       clr    SPIC1                          // Disable SPI,  
  333.       dbnzx  *-0                            // [4n fppp]
  334.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWD=p, SWCLK=1

  335.       // Start Tx of 8-bit idle
  336.      mov    #SPIxC2_M_8,SPIxC2             // Initialise SPI (8 bit)
  337.      mov    #SPIxC1_M_ON_TX,SPIC1          // Enable SPI
  338.      clr    DATA_PORT                      // Enable SWD drive
  339.      cmp    SPIxS                          // Dummy status read
  340.      clr    SPIxD                          // Tx data (=0)

  341.      // Wait for Idle Tx to complete
  342.    L3:
  343.      brclr  SPIS_SPRF_BIT,SPIxS,L3         // Wait until Tx/Rx complete
  344.      cmp    SPIxD                          // Discard rx data
  345.      mov    #SWCLK_OUT_MASK|SWD_OUT_EN_MASK,DATA_PORT // Setup for SWCLK=1, SWD=3-state
  346.      clr    SPIC1                          // Disable SPI
  347.       rts
  348.    }
  349. }
  350. #pragma MESSAGE DEFAULT C5703 // Restore warnings about unused parameter

  351. #pragma MESSAGE DISABLE C5703 // Disable warnings about unused parameter
  352. //! Receives a 32-bit value with parity at end (33 total)
  353. //!
  354. //! Sequence as follows:
  355. //!   - 32-bit data value
  356. //!   - 1-bit parity
  357. //!   - 8-bit idle
  358. //!
  359. //! @param data - ptr to buffer for Rx data
  360. //!
  361. //! @return BDM_RC_OK
  362. //!         BDM_RC_ARM_PARITY_ERROR
  363. //!
  364. static uint8_t swd_rx32(uint8_t *data) {
  365. #define SPIS_SPTEF_BIT (5)
  366. #define SPIS_SPRF_BIT  (7)

  367.    asm {
  368.       SWD_3STATE_ASM                        // SWD=3-state
  369.       mov    #SPIxC2_M_16,SPIxC2            // Initialise SPI (16 bit)
  370.       mov    #SPIxC1_M_ON_TX,SPIxC1         // Enable SPI
  371.       cmp    SPIxS                          // Dummy status read

  372.       sthx   SPIxD16                        // Tx dummy/Rx                        
  373.   L1:
  374.       brclr  SPIS_SPRF_BIT,SPIxS,L1         // Wait until Rx complete
  375.       lda    SPIxDH                         // Save data
  376.       sta    2,x
  377.       lda    SPIxDL
  378.       sta    3,x
  379.       sthx   SPIxD16                        // Tx dummy/Rx                        
  380.   L2:
  381.       brclr  SPIS_SPRF_BIT,SPIxS,L2         // Wait until Rx complete
  382.       lda    SPIxDH                         // Save data
  383.       sta    0,x
  384.       lda    SPIxDL
  385.       sta    1,x

  386.       bclr   SWCLK_OUT_BIT,DATA_PORT        // Setup for SWCLK=0
  387.       clr    SPIC1                          // Disable SPI (SWCLK=0)

  388.       // Parity bit
  389.       lda    bitDelay                       // Low time delay
  390.       dbnza  *-0                            // [4n fppp]
  391.       lda    DATA_PORT                      // Capture data before rising clock edge
  392.       bset   SWCLK_OUT_BIT,DATA_PORT        // SWCLK=1
  393.       and    #SWD_IN_MASK                   // Convert parity to byte width
  394.       // Single Parity bit remains - position is unimportant

  395.       // Start Tx of 8-bit idle
  396.       mov    #SPIxC2_M_8,SPIxC2             // Initialise SPI (8 bit)
  397.       mov    #SPIxC1_M_ON_TX,SPIC1          // Enable SPI
  398.       clr    DATA_PORT                      // Enable SWD drive
  399.       cmp    SPIxS                          // Dummy status read
  400.       clr    SPIxD                          // Tx data (=0)

  401.       // Do parity calculation
  402.       eor    0,x                            // Do byte-wide parity on data & parity bit
  403.       eor    1,x
  404.       eor    2,x
  405.       eor    3,x

  406.       ldx    bitDelay                       // High time delay
  407.       dbnzx  *-0                            // [4n fppp]

  408.       // Calculate nibble parity
  409.       psha             // [2]
  410.       nsa              // [1]
  411.       eor    1,sp      // [4]
  412.       ais    #1        // [2]

  413.       // Calculate final parity
  414.       tax              // [1]
  415.       clra             // [1]
  416.       rorx             // [1]
  417.       adc    #0        // [2]
  418.       rorx             // [1]
  419.       adc    #0        // [2]
  420.       rorx             // [1]
  421.       adc    #0        // [2]
  422.       rorx             // [1]
  423.       adc    #0        // [2]
  424.       and    #1
  425.       // Parity in A.0 - should be 0
  426.       beq    okExit
  427.       lda    #BDM_RC_ARM_PARITY_ERRORx
  428.    okExit:

  429.       // Wait for Idle Tx to complete
  430.    L3:
  431.       brclr  SPIS_SPRF_BIT,SPIxS,L3         // Wait until Tx/Rx complete
  432.       cmp    SPIxD                          // Discard rx data
  433.       mov    #SWCLK_OUT_MASK|SWD_OUT_EN_MASK,DATA_PORT // Setup for SWCLK=1, SWD=3-state
  434.       clr    SPIC1                          // Disable SPI
  435.       rts
  436.    }
  437. }
  438. #pragma MESSAGE DEFAULT C5703 // Restore warnings about unused parameter

  439. #pragma MESSAGE DISABLE C5703 // Disable warnings about unused parameter
  440. //! Switches interface to SWD
  441. //!
  442. //! Sequence as follows:
  443. //!  - 64-bit sequence of 1's
  444. //!  - 8-bit magic number 0xE79E
  445. //!  - 64-bit sequence of 1's
  446. //!
  447. //! @note Interface is reset even if already in SWD mode so IDCODE must be read
  448. //!       to enable interface
  449. //!
  450. static void swd_JTAGtoSWD(void) {
  451.    asm {
  452.       mov    #SPIxC2_M_16,SPIxC2            // Initialise SPI (16 bit)
  453.       mov    #SPIxC1_M_ON_TX,SPIxC1         // Enable SPI
  454.       clr    DATA_PORT                      // Enable SWD drive
  455.       cmp    SPIxS                          // Dummy status read
  456.       
  457.       bsr    txOnes                         // Send 64 clocks
  458.       ldhx   #0xE79E                        // Send magic #
  459.       sthx   SPIxD16                        
  460.   L5:
  461.       brclr  SPIS_SPTEF_BIT,SPIxS,L5        // Wait until Tx buffer empty
  462.       bsr    txOnes                         // Send 64 clocks
  463.   L6:
  464.       brclr  SPIS_SPTEF_BIT,SPIxS,L6                   // Wait until Tx buffer empty
  465.       ldhx   SPIxD16                                   // Discard last data
  466.       mov    #SWCLK_OUT_MASK|SWD_OUT_EN_MASK,DATA_PORT // Setup for SWCLK=1, SWD=3-state
  467.   L7:
  468.       brclr  SPIS_SPRF_BIT,SPIxS,L7                    // Wait until Tx complete
  469.       ldhx   SPIxD16                                   // Discard rx data
  470.       clr    SPIC1                                     // Disable SPI (SWCLK=1)
  471.       rts
  472.       
  473.   txOnes:
  474.       ldhx   #0xFFFF                        // Tx 64 bits with '1'
  475.       sthx   SPIxD16                        
  476.   L1:
  477.       brclr  SPIS_SPTEF_BIT,SPIxS,L1        // Wait until Tx buffer empty
  478.       sthx   SPIxD16                        
  479.   L2:
  480.       brclr  SPIS_SPTEF_BIT,SPIxS,L2        // Wait until Tx buffer empty
  481.       sthx   SPIxD16                        
  482.   L3:
  483.       brclr  SPIS_SPTEF_BIT,SPIxS,L3        // Wait until Tx buffer empty
  484.       sthx   SPIxD16                        
  485.   L4:
  486.       brclr  SPIS_SPTEF_BIT,SPIxS,L4        // Wait until Tx buffer empty
  487.       rts
  488.    }
  489. }
  490. #pragma MESSAGE DEFAULT C5703 // Restore warnings about unused parameter

  491. //! SWD - Try to connect to the target
  492. //!
  493. //! This will do the following:
  494. //! - Switch the interface to SWD mode
  495. //! - Read IDCODE
  496. //!
  497. //! @return
  498. //!    == ef BDM_RC_OK              => Success        
  499. //!    == ef BDM_RC_NO_CONNECTION   => Unexpected/no response from target
  500. //!
  501. uint8_t swd_connect(void) {
  502.    uint8_t buff[4];        
  503.    
  504.    swd_JTAGtoSWD();
  505.    swd_txIdle8();
  506.      
  507.    // Target must respond to read IDCODE immediately
  508.    return swd_readReg(SWD_READ_IDCODE, buff);
  509. }

  510. //! Read ARM-SWD DP & AP register
  511. //!
  512. //! @param command - SWD command byte to select register etc.
  513. //! @param data    - buffer for 32-bit value read
  514. //!
  515. //! @return
  516. //!    == ef BDM_RC_OK               => Success        
  517. //!    == ef BDM_RC_ARM_FAULT_ERROR  => FAULT response from target
  518. //!    == ef BDM_RC_ACK_TIMEOUT      => Excessive number of WAIT responses from target
  519. //!    == ef BDM_RC_NO_CONNECTION    => Unexpected/no response from target
  520. //!    == ef BDM_RC_ARM_PARITY_ERROR => Parity error on data read
  521. //!
  522. //! @note Action and Data returned depends on register (some responses are pipelined)
  523. //!   SWD_RD_DP_IDCODE - Value from IDCODE reg
  524. //!   SWD_RD_DP_STATUS - Value from STATUS reg
  525. //!   SWD_RD_DP_RESEND - LAST value read (AP read or DP-RDBUFF), FAULT on sticky error   
  526. //!   SWD_RD_DP_RDBUFF - Value from last AP read and clear READOK flag in STRL/STAT, FAULT on sticky error
  527. //!   SWD_RD_AP_REGx   - Value from last AP read, clear READOK flag in STRL/STAT and INITIATE next AP read, FAULT on sticky error
  528. //!
  529. uint8_t swd_readReg(uint8_t command, uint8_t *data) {
  530.    uint8_t rc = swd_sendCommandWithWait(command);
  531.    if (rc != BDM_RC_OK) {
  532.       return rc;
  533.    }
  534.    return swd_rx32(data);
  535. }

  536. //! Write ARM-SWD DP & AP register
  537. //!
  538. //! @param command - SWD command byte to select register etc.
  539. //! @param data    - buffer containing 32-bit value to write
  540. //!
  541. //! @return
  542. //!    == ef BDM_RC_OK               => Success        
  543. //!    == ef BDM_RC_ARM_FAULT_ERROR  => FAULT response from target
  544. //!    == ef BDM_RC_ACK_TIMEOUT      => Excessive number of WAIT responses from target
  545. //!    == ef BDM_RC_NO_CONNECTION    => Unexpected/no response from target
  546. //!
  547. //! @note Action depends on register (some responses are pipelined)
  548. //!   SWD_WR_DP_ABORT   - Write value to ABORT register (accepted)
  549. //!   SWD_WR_DP_CONTROL - Write value to CONTROL register (may be pending), FAULT on sticky error.
  550. //!   SWD_WR_DP_SELECT  - Write value to SELECT register (may be pending), FAULT on sticky error.
  551. //!   SWD_WR_AP_REGx    - Write to AP register.  May initiate action e.g. memory access.  Result is pending, FAULT on sticky error.
  552. //!
  553. uint8_t swd_writeReg(uint8_t command, const uint8_t *data) {
  554.    uint8_t rc = swd_sendCommandWithWait(command);
  555.    if (rc != BDM_RC_OK) {
  556.       return rc;
  557.    }
  558.    swd_tx32(data);
  559.    return rc;
  560. }

  561. //! Write register of Access Port
  562. //!
  563. //! @param 16-bit address
  564. //!    A[15:8]  => DP-AP-SELECT[31:24] (AP # Select)
  565. //!    A[7:4]   => DP-AP-SELECT[7:4]   (Bank select within AP)
  566. //!    A[3:2]   => APACC[3:2]          (Register select within bank)
  567. //! @param buff
  568. //!   - [1..4]  =>  32-bit register value
  569. //!
  570. //! @return
  571. //!  == ef BDM_RC_OK => success
  572. //!
  573. //! @note - Access is completed before return
  574. //!
  575. uint8_t swd_writeAPReg(const uint8_t *address, const uint8_t *buff) {
  576.    static const uint8_t writeAP[] = {SWD_WR_AP_REG0,   SWD_WR_AP_REG1,    SWD_WR_AP_REG2,   SWD_WR_AP_REG3};
  577.    uint8_t rc;
  578.    uint8_t regNo = writeAP[(address[1]&0xC)>>2];
  579.    uint8_t selectData[4];
  580.    selectData[0] = address[0];
  581.    selectData[1] = 0;
  582.    selectData[2] = 0;
  583.    selectData[3] = address[1]&0xF0;
  584.    
  585.    // Set up SELECT register for AP access
  586.    rc = swd_writeReg(SWD_WR_DP_SELECT, selectData);
  587.    if (rc != BDM_RC_OK) {
  588.       return rc;
  589.    }
  590.    // Initiate write to AP register
  591.    rc = swd_writeReg(regNo, buff);
  592.    if (rc != BDM_RC_OK) {
  593.       return rc;
  594.    }
  595.    // Read from READBUFF register to allow stall/status response
  596.    return swd_readReg(SWD_RD_DP_RDBUFF, selectData);
  597. }

  598. //! Read register of Access Port
  599. //!
  600. //! @param 16-bit address
  601. //!    A[15:8]  => DP-AP-SELECT[31:24] (AP # Select)
  602. //!    A[7:4]   => DP-AP-SELECT[7:4]   (Bank select within AP)
  603. //!    A[3:2]   => APACC[3:2]          (Register select within bank)
  604. //! @param buff
  605. //!   - [1..4]  =>  32-bit register value
  606. //!
  607. //! @return
  608. //!  == ef BDM_RC_OK => success
  609. //!
  610. //! @note - Access is completed before return
  611. //!
  612. uint8_t swd_readAPReg(const uint8_t *address, uint8_t *buff) {
  613.    static const uint8_t readAP[]  = {SWD_RD_AP_REG0,   SWD_RD_AP_REG1,    SWD_RD_AP_REG2,   SWD_RD_AP_REG3};
  614.    uint8_t rc;
  615.    uint8_t regNo = readAP[(address[1]&0xC)>>2];
  616.    uint8_t selectData[4];
  617.    selectData[0] = address[0];
  618.    selectData[1] = 0;
  619.    selectData[2] = 0;
  620.    selectData[3] = address[1]&0xF0;

  621.    // Set up SELECT register for AP access
  622.    rc = swd_writeReg(SWD_WR_DP_SELECT, selectData);
  623.    if (rc != BDM_RC_OK) {
  624.      return rc;
  625.    }
  626.    // Initiate read from AP register (dummy data)
  627.    rc = swd_readReg(regNo, buff);
  628.    if (rc != BDM_RC_OK) {
  629.      return rc;           
  630.    }
  631.    // Read from READBUFF register
  632.    return swd_readReg(SWD_RD_DP_RDBUFF, buff);
  633. }

  634. //! ARM-SWD - clear sticky bits
  635. //!
  636. //! @return error code
  637. //!
  638. uint8_t swd_clearStickyError(void) {
  639.    static const uint8_t swdClearErrors[4] = {0,0,0,SWD_DP_ABORT_CLEAR_STICKY_ERRORS_B3};
  640.    return swd_writeReg(SWD_WR_DP_ABORT, swdClearErrors);
  641. }

  642. //! ARM-SWD - clear sticky bits and abort AP transactions
  643. //!
  644. //! @return error code
  645. //!
  646. uint8_t swd_abortAP(void) {
  647.    static const uint8_t swdClearErrors[4] =
  648.       {0,0,0,SWD_DP_ABORT_CLEAR_STICKY_ERRORS_B3|SWD_DP_ABORT_ABORT_AP_B3};
  649.    return swd_writeReg(SWD_WR_DP_ABORT, swdClearErrors);
  650. }

  651. uint8_t swd_test(void) {
  652.    return swd_connect();
  653. //   swd_JTAGtoSWD();
  654. //   return BDM_RC_OK;
  655. //   return swd_connect();
  656. }
  657. #endif // HW_CAPABILITY && CAP_SWD_HW
复制代码

shangdawei
5楼-- · 2019-12-14 01:47
abbott.yang 发表于 2015-8-21 16:12
观察了SWD波形,想用SPI的8字节数据去套这个协议。。可惜都不是8字节对齐,中间还有有接收ACK。。。shang ...

JLink 大概用到了 TIMER + SPI + DMA, 没有频繁的中断。
huangqi412
6楼-- · 2019-12-14 03:25
 精彩回答 2  元偷偷看……

一周热门 更多>