SPI SWD Protocol Implement
//=================================================================================
// ARM SWD Mode Port Bit masks
//
#if (HW_CAPABILITY&CAP_SWD_HW)
#ifndef DATA_PORT
#define DATA_PORT PTAD
#define DATA_PORT_DDR PTADD
#define DATA_PORT_PER PTAPE
#endif // SWD data out pin
#define SWD_OUT PTAD_PTAD2
#define SWD_OUT_BIT (2) // Bit number!
#define SWD_OUT_MASK (1<<SWD_OUT_BIT)
#define SWD_OUT_PER PTAPE_PTAPE2
#define SWD_OUT_DDR PTADD_PTADD2 // SWD data out 3-state control
#define SWD_OUT_EN PTAD_PTAD4
#define SWD_OUT_EN_BIT (4) // Bit number!
#define SWD_OUT_EN_MASK (1<<SWD_OUT_EN_BIT)
#define SWD_OUT_EN_PER PTAPE_PTAPE4
#define SWD_OUT_EN_DDR PTADD_PTADD4 // Following assume pin already configured by SWD_LOW(),SWD_HIGH(),SWD_3STATE()
#define SWD_ENABLE_ASM BCLR SWD_OUT_EN_BIT,DATA_PORT
#define SWD_3STATE_ASM BSET SWD_OUT_EN_BIT,DATA_PORT
#define SWD_LOW_ASM BCLR SWD_OUT_BIT,DATA_PORT
#define SWD_HIGH_ASM BSET SWD_OUT_BIT,DATA_PORT
#define SWD_DISABLE_ASM BCLR SWD_OUT_EN_BIT,DATA_PORT_DDR
#define SWD_ENABLE_DRV_ASM BSET SWD_OUT_EN_BIT,DATA_PORT_DDR // Following configure pin & driver
#define SWD_LOW() (SWD_OUT=0, SWD_OUT_DDR=1, SWD_OUT_EN=0, SWD_OUT_EN_DDR=1)
#define SWD_HIGH() (SWD_OUT=1, SWD_OUT_DDR=1, SWD_OUT_EN=0, SWD_OUT_EN_DDR=1)
#define SWD_3STATE() (SWD_OUT_EN=1, SWD_OUT_EN_DDR=1, SWD_OUT_DDR=1)
#define SWD_DISABLE() (SWD_OUT_EN=1, SWD_OUT_EN_DDR=0, SWD_OUT_DDR=0) // PUPs // SWD data in pin
#define SWD_IN PTAD_PTAD0
#define SWD_IN_BIT (0) // Bit number!
#define SWD_IN_MASK (1<<SWD_IN_BIT)
#define SWD_IN_PER PTAPE_PTAPE0
#define SWD_IN_DDR PTADD_PTADD0 // SWCLK out pin
#define SWCLK_OUT PTAD_PTAD3
#define SWCLK_OUT_BIT (3) // Bit number!
#define SWCLK_OUT_MASK (1<<SWCLK_OUT_BIT)
#define SWCLK_OUT_PER PTAPE_PTAPE3
#define SWCLK_OUT_DDR PTADD_PTADD3 // SWCLK enable pin - controls buffer enable
#define SWCLK_OUT_EN PTBD_PTBD1
#define SWCLK_OUT_EN_BIT (1) // Bit number!
#define SWCLK_OUT_EN_MASK (1<<SWCLK_OUT_EN_BIT)
#define SWCLK_OUT_EN_PER PTBPE_PTBPE1
#define SWCLK_OUT_EN_DDR PTBDD_PTBDD1 // Following assume pin direction already set
#define SWCLK_LOW_ASM BCLR SWCLK_OUT_BIT,DATA_PORT
#define SWCLK_HIGH_ASM BSET SWCLK_OUT_BIT,DATA_PORT // Following configure pin & driver
#define SWCLK_LOW() (SWCLK_OUT=0, SWCLK_OUT_DDR=1, SWCLK_OUT_EN=0, SWCLK_OUT_EN_DDR=1)
#define SWCLK_HIGH() (SWCLK_OUT=1, SWCLK_OUT_DDR=1, SWCLK_OUT_EN=0, SWCLK_OUT_EN_DDR=1)
#define SWCLK_3STATE() (SWCLK_OUT_EN=1, SWCLK_OUT_EN_DDR=1, SWCLK_OUT_DDR=1) // PUPs
#define SWCLK_DISABLE() (SWCLK_OUT_EN=1, SWCLK_OUT_EN_DDR=0, SWCLK_OUT_DDR=0) // PUPs #endif // CAP_SWD
/*
* SWD.h
*
* Created on: 04/08/2012
* Author: PODonoghue
*/ #ifndef SWD_H_
#define SWD_H_ #include "Common.h" // Ack values displaced by offset introduced during read (left justified 8-bit value)
#define SWD_ACK_OK (0x1<<5)
#define SWD_ACK_WAIT (0x2<<5)
#define SWD_ACK_FAULT (0x4<<5)
#define SWD_ACK_PROTOCOL (0x7<<5) void swd_interfaceIdle(void);
void swd_init(void);
void swd_txIdle8(void); U8 swd_test(void); U8 swd_sendCommandWithWait(U8 command); U8 swd_connect(void);
U8 swd_readReg(U8 command, U8 *data);
U8 swd_writeReg(U8 command, const U8 *data);
U8 swd_readAPReg(const U8 *address, U8 *buff);
U8 swd_writeAPReg(const U8 *address, const U8 *buff);
U8 swd_clearStickyError(void);
U8 swd_abortAP(void);
#endif /* SWD_H_ */
/*! \file
\brief ARM-SWD routines \verbatim USBDM Copyright (C) 2007 Peter O'Donoghue This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version. This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\endverbatim Change History
+==================================================================================================
| 21 Feb 2014 | Fixed unbalanced stack in swd_sendCommandWithWait() V4.10.6.30
| 10 Feb 2014 | Dramatically extended retry times to allow for slow clocks V4.10.6.20
| 30 Aug 2012 | ARM-JTAG & ARM-SWD Changes V4.9.5
+==================================================================================================
\endverbatim
*/ #include "Common.h"
#include "Configure.h"
#include "Commands.h"
#include "SWD.h"
#include "Commands.h"
#include "BDM.h"
#include "BDM_CF.h"
#include "CmdProcessing.h"
#include "BDMCommon.h"
#include "SPI.h"
#include "TargetDefines.h"
#include "SWD.h" #if TARGET_CAPABILITY & CAP_ARM_SWD //! SPI Masks - Mask to enable SPI as master Tx
#define SPIxC1_OFF (SPIxC1_MSTR_MASK) //!< SPI Masks - Mask to disable SPI
#define SPIxC1_M_ON_TX (SPIxC1_SPE_MASK|SPIxC1_MSTR_MASK|SPIxC1_CPOL_MASK|SPIxC1_CPHA_MASK|SPIxC1_SSOE_MASK|SPIxC1_LSBFE_MASK)
#define SPIxC1_M_ON_RX (SPIxC1_SPE_MASK|SPIxC1_MSTR_MASK|SPIxC1_CPOL_MASK) //!< SPI Masks - Mask to enable SPI as master Tx
#define SPIxC2_M_8 (0) //!< SPI Masks - 8-bit mode
#define SPIxC2_M_16 (SPIxC2_SPIMODE_MASK) //!< SPI Masks - 8-bit mode // Can't use enumerations in assembly code
#define BDM_RC_OKx (0)
#define BDM_RC_NO_CONNECTIONx (5)
#define BDM_RC_ACK_TIMEOUTx (30)
#define BDM_RC_ARM_PARITY_ERRORx (51)
#define BDM_RC_ARM_FAULT_ERRORx (52) #define SWD_READ_IDCODE 0xA5 // (Park,Stop,Parity,A[32],R/W,AP/DP,Start) = 10100101 // Masks for SWD_WR_DP_ABORT clear sticky
#define SWD_DP_ABORT_CLEAR_STICKY_ERRORS_B3 0x1E // Masks for SWD_WR_DP_ABORT abort AP
#define SWD_DP_ABORT_ABORT_AP_B3 0x01 // Masks for SWD_RD_DP_STATUS
#define SWD_RD_DP_STATUS_ANYERROR_B3 0xB2 #pragma MESSAGE DISABLE C1404 // Disable warnings about missing return value
#pragma MESSAGE DISABLE C5703 // Disable warnings about unused parameter //! Sets the SWD interface to an idle state
//! RESET=3-state, SWCLK=High, SWDIO=3-state (SPI off)
//!
void swd_interfaceIdle(void) {
#ifdef RESET_3STATE
RESET_3STATE();
#endif
SWD_3STATE();
SWCLK_HIGH();
SPIC1 = SPIxC1_OFF;
} //! Initialise the SWD interface and sets it to an idle state
//! RESET=3-state, SWCLK=High, SWDIO=3-state
//!
//! @note This includes once-off initialisation such as PUPs etc
//!
void swd_init(void) {
// 4 pins SWD_OUT, SWD_OUT_EN, SWCLK_OUT, SWCLK_OUT_EN
// Individually controlled PUPs
SWD_OUT_PER = ; // Prevent float when disabled
SWD_OUT_EN_PER = ; // Prevent drive when disabled
SWCLK_OUT_PER = ; // Prevent float when disabled
SWCLK_OUT_EN_PER = ; // Prevent drive when disabled SWD_IN_DDR = ; // Make input
SWD_IN_PER = ; // Shouldn't be req. as external PUP for speed #ifdef RESET_IN_DDR
RESET_IN_DDR = ; // Make input
#endif
#ifdef RESET_IN_PER
RESET_IN_PER = ; // Needed for input level translation to 5V
#endif
#ifdef RESET_OUT_PER
RESET_OUT_PER = ; // Holds RESET_OUT inactive when unused
#endif
(void)spi_setSpeed();
swd_interfaceIdle();
} //! Turns off the SWD interface
//!
//! Depending upon settings, may leave target power on.
//!
void swd_off( void ) {
#if ((HW_CAPABILITY & CAP_FLASH) != 0)
(void)bdmSetVpp(BDM_TARGET_VPP_OFF);
#endif
if (!bdm_option.leaveTargetPowered) {
VDD_OFF();
}
swd_interfaceIdle();
SWCLK_DISABLE();
SWD_DISABLE();
RESET_DISABLE();
} #define SWD_DATA1_CLK1 SWCLK_OUT_MASK|SWD_OUT_EN_MASK
#define SWD_DATA0_CLK1 SWCLK_OUT_MASK|0 //! Transmits 1 clock with SWDIO 3-state
//!
void swd_turnAround() {
asm {
// 1 clock turn-around
mov #SWD_OUT_MASK,DATA_PORT // SWDIO=3-state,SWCLK=0
ldx bitDelay // Low time delay
dbnzx *- // [4n fppp]
bset SWCLK_OUT_BIT,DATA_PORT // SWCLK=1
ldx bitDelay // High time delay
dbnzx *- // [4n fppp]
}
} //! Transmits 8-bits of idle (SDIO=0)
//!
void swd_txIdle8(void) {
asm {
mov #SPIxC2_M_8,SPIxC2 // Initialise SPI (8 bit)
mov #SPIxC1_M_ON_TX,SPIC1 // Enable SPI
clr DATA_PORT // Enable SWD drive
cmp SPIxS // Dummy status read
clr SPIxD // Tx data (=0)
L1:
brclr SPIS_SPRF_BIT,SPIxS,L1 // Wait until Tx/Rx complete
lda SPIxD // Discard rx data
mov #SWCLK_OUT_MASK|SWD_OUT_EN_MASK,DATA_PORT // Setup for SWCLK=1, SWD=3-state
clr SPIC1 // Disable SPI
}
} #if (SWD_IN_BIT != 0)
#error "SWD_IN must be bit #0"
#endif
#pragma MESSAGE DISABLE C5703 // Disable warnings about unused parameter
//! SWD command phase
//!
//! Writes 8-bit command and receives 3-bit response
//! It will retry on WAIT response a limited number of times
//!
//! @param command - 8-bit command to write to SWD (including parity!)
//!
//! @return \n
//! == \ref BDM_RC_OK => Success \n
//! == \ref BDM_RC_ARM_FAULT_ERROR => FAULT response from target \n
//! == \ref BDM_RC_ACK_TIMEOUT => Excessive number of WAIT responses from target \n
//! == \ref BDM_RC_NO_CONNECTION => Unexpected/no response from target
//!
//! @note A turn-around clock period will be added on error responses
//!
uint8_t swd_sendCommandWithWait(uint8_t command) {
asm {
sta txTiming1 // Save data (for retry)
ldx #(/) // Set up outer retry count retry_outer:
pshx // Save outer retry count
mov #,rxTiming1 // Reset inner retry count retry: // 8-bit Start|APnDP|R/W|Parity|Stop|Park
lda txTiming1 // Get Tx data
mov #SPIxC2_M_8,SPIxC2 // Initialise SPI (8 bit)
mov #SPIxC1_M_ON_TX,SPIC1 // Enable SPI
clr DATA_PORT // Enable SWD drive
cmp SPIxS // Dummy status read
sta SPIxD // Tx data
L1:
brclr SPIS_SPRF_BIT,SPIxS,L1 // Wait until Tx/Rx complete
ldx SPIxD // Discard rx data
SWD_3STATE_ASM // SWD=3-state
clr SPIC1 // Disable SPI // 1 clock turn-around
bclr SWCLK_OUT_BIT,DATA_PORT // SWCLK=0
ldx bitDelay // Low time delay
dbnzx *- // [4n fppp]
bset SWCLK_OUT_BIT,DATA_PORT // SWCLK=1
ldx bitDelay // High time delay
dbnzx *- // [4n fppp] // 1st bit ACK
clra // Clear initial data value
bclr SWCLK_OUT_BIT,DATA_PORT // SWCLK=0
ldx bitDelay // Low time delay
dbnzx *- // [4n fppp]
ldx DATA_PORT // Capture data before rising edge
rorx
rora
bset SWCLK_OUT_BIT,DATA_PORT // SWCLK=1
ldx bitDelay // High time delay
dbnzx *- // [4n fppp] // 2nd bit ACK
bclr SWCLK_OUT_BIT,DATA_PORT // SWCLK=0
ldx bitDelay // Low time delay
dbnzx *- // [4n fppp]
ldx DATA_PORT // Capture data before rising edge
rorx
rora
bset SWCLK_OUT_BIT,DATA_PORT // SWCLK=1
ldx bitDelay // High time delay
dbnzx *- // [4n fppp] // 3rd bit ACK
bclr SWCLK_OUT_BIT,DATA_PORT // SWCLK=0
ldx bitDelay // Low time delay
dbnzx *- // [4n fppp]
ldx DATA_PORT
rorx
rora
bset SWCLK_OUT_BIT,DATA_PORT // SWCLK=1
ldx bitDelay // High time delay
dbnzx *- // [4n fppp] tax
lda #BDM_RC_OKx
cbeqx #SWD_ACK_OK,balanceStack // Do turn-around clock on anything other than ACK_OK response
bclr SWCLK_OUT_BIT,DATA_PORT // SWCLK=0
lda bitDelay // Low time delay
dbnza *- // [4n fppp]
bset SWCLK_OUT_BIT,DATA_PORT // SWCLK=1
lda bitDelay // High time delay
dbnza *- // [4n fppp] // Check for wait response
cpx #SWD_ACK_WAIT // Wait response?
bne identifyError // No - exit with other error // Check for wait timeout
dbnz rxTiming1,retry // Retry limit reached
pulx
dbnzx retry_outer lda #BDM_RC_ACK_TIMEOUTx // Too many retries
bra done // Return error (stack already balanced) identifyError:
lda #BDM_RC_ARM_FAULT_ERRORx // Identify error
cbeqx #SWD_ACK_FAULT,balanceStack
lda #BDM_RC_NO_CONNECTIONx balanceStack:
pulx // Balance stack done:
}
} #pragma MESSAGE DEFAULT C5703 // Restore warnings about unused parameter #pragma MESSAGE DISABLE C5703 // Disable warnings about unused parameter
//! Transmits 32-bit value
//!
//! Sequence as follows:
//! - 1-clock turn-around
//! - 32-bit data value
//! - 1-bit parity
//! - 8-bit idle
//!
//! @param data - ptr to 32-bit data to Tx
//!
static void swd_tx32(const uint8_t *data) {
asm {
// 1 clock turn-around
bclr SWCLK_OUT_BIT,DATA_PORT // SWCLK=0
lda bitDelay // Low time delay
dbnza *- // [4n fppp]
bset SWCLK_OUT_BIT,DATA_PORT // SWCLK=1 mov #SPIxC2_M_16,SPIxC2 // Initialise SPI (16 bit)
mov #SPIxC1_M_ON_TX,SPIxC1 // Enable SPI
clr DATA_PORT // Enable SWD drive cmp SPIxS // Dummy status read lda ,x // Start Tx 1st & 2nd bytes
sta SPIxDL
lda ,x
sta SPIxDH
lda ,x // Do byte-wide parity
eor ,x
eor ,x
eor ,x
ldhx ,x // Get 3rd & 4th bytes
L1:
brclr SPIS_SPRF_BIT,SPIxS,L1 // Wait until previous Tx/Rx complete
cphx SPIxD16 // Discard read data
sthx SPIxD16 // Tx 3rd & 4th bytes // Calculate nibble parity
psha // [2]
nsa // [1]
eor ,sp // [4]
ais # // [2] // Calculate final parity
tax // [1]
clra // [1]
rorx // [1]
adc # // [2]
rorx // [1]
adc # // [2]
rorx // [1]
adc # // [2]
rorx // [1]
adc # // [2]
//parity in A.0 L2:
brclr SPIS_SPRF_BIT,SPIxS,L2 // Wait until previous Tx/Rx complete
ldhx SPIxD16 // Discard read data #if SWD_OUT_BIT >= 1 // move to SWD_OUT position
lsla
#endif
#if SWD_OUT_BIT == 2
lsla
#else
#error Fix this code
#endif
and #SWD_OUT_MASK // SWD=p, SWCLK=0
sta DATA_PORT // Set up - no effect yet
ldx bitDelay // Low time delay
clr SPIC1 // Disable SPI,
dbnzx *- // [4n fppp]
bset SWCLK_OUT_BIT,DATA_PORT // SWD=p, SWCLK=1 // Start Tx of 8-bit idle
mov #SPIxC2_M_8,SPIxC2 // Initialise SPI (8 bit)
mov #SPIxC1_M_ON_TX,SPIC1 // Enable SPI
clr DATA_PORT // Enable SWD drive
cmp SPIxS // Dummy status read
clr SPIxD // Tx data (=0) // Wait for Idle Tx to complete
L3:
brclr SPIS_SPRF_BIT,SPIxS,L3 // Wait until Tx/Rx complete
cmp SPIxD // Discard rx data
mov #SWCLK_OUT_MASK|SWD_OUT_EN_MASK,DATA_PORT // Setup for SWCLK=1, SWD=3-state
clr SPIC1 // Disable SPI
rts
}
}
#pragma MESSAGE DEFAULT C5703 // Restore warnings about unused parameter #pragma MESSAGE DISABLE C5703 // Disable warnings about unused parameter
//! Receives a 32-bit value with parity at end (33 total)
//!
//! Sequence as follows:
//! - 32-bit data value
//! - 1-bit parity
//! - 8-bit idle
//!
//! @param data - ptr to buffer for Rx data
//!
//! @return BDM_RC_OK \n
//! BDM_RC_ARM_PARITY_ERROR
//!
static uint8_t swd_rx32(uint8_t *data) {
#define SPIS_SPTEF_BIT (5)
#define SPIS_SPRF_BIT (7) asm {
SWD_3STATE_ASM // SWD=3-state
mov #SPIxC2_M_16,SPIxC2 // Initialise SPI (16 bit)
mov #SPIxC1_M_ON_TX,SPIxC1 // Enable SPI
cmp SPIxS // Dummy status read sthx SPIxD16 // Tx dummy/Rx
L1:
brclr SPIS_SPRF_BIT,SPIxS,L1 // Wait until Rx complete
lda SPIxDH // Save data
sta ,x
lda SPIxDL
sta ,x
sthx SPIxD16 // Tx dummy/Rx
L2:
brclr SPIS_SPRF_BIT,SPIxS,L2 // Wait until Rx complete
lda SPIxDH // Save data
sta ,x
lda SPIxDL
sta ,x bclr SWCLK_OUT_BIT,DATA_PORT // Setup for SWCLK=0
clr SPIC1 // Disable SPI (SWCLK=0) // Parity bit
lda bitDelay // Low time delay
dbnza *- // [4n fppp]
lda DATA_PORT // Capture data before rising clock edge
bset SWCLK_OUT_BIT,DATA_PORT // SWCLK=1
and #SWD_IN_MASK // Convert parity to byte width
// Single Parity bit remains - position is unimportant // Start Tx of 8-bit idle
mov #SPIxC2_M_8,SPIxC2 // Initialise SPI (8 bit)
mov #SPIxC1_M_ON_TX,SPIC1 // Enable SPI
clr DATA_PORT // Enable SWD drive
cmp SPIxS // Dummy status read
clr SPIxD // Tx data (=0) // Do parity calculation
eor ,x // Do byte-wide parity on data & parity bit
eor ,x
eor ,x
eor ,x ldx bitDelay // High time delay
dbnzx *- // [4n fppp] // Calculate nibble parity
psha // [2]
nsa // [1]
eor ,sp // [4]
ais # // [2] // Calculate final parity
tax // [1]
clra // [1]
rorx // [1]
adc # // [2]
rorx // [1]
adc # // [2]
rorx // [1]
adc # // [2]
rorx // [1]
adc # // [2]
and #
// Parity in A.0 - should be 0
beq okExit
lda #BDM_RC_ARM_PARITY_ERRORx
okExit: // Wait for Idle Tx to complete
L3:
brclr SPIS_SPRF_BIT,SPIxS,L3 // Wait until Tx/Rx complete
cmp SPIxD // Discard rx data
mov #SWCLK_OUT_MASK|SWD_OUT_EN_MASK,DATA_PORT // Setup for SWCLK=1, SWD=3-state
clr SPIC1 // Disable SPI
rts
}
}
#pragma MESSAGE DEFAULT C5703 // Restore warnings about unused parameter #pragma MESSAGE DISABLE C5703 // Disable warnings about unused parameter
//! Switches interface to SWD
//!
//! Sequence as follows:
//! - 64-bit sequence of 1's
//! - 8-bit magic number 0xE79E
//! - 64-bit sequence of 1's
//!
//! @note Interface is reset even if already in SWD mode so IDCODE must be read
//! to enable interface
//!
static void swd_JTAGtoSWD(void) {
asm {
mov #SPIxC2_M_16,SPIxC2 // Initialise SPI (16 bit)
mov #SPIxC1_M_ON_TX,SPIxC1 // Enable SPI
clr DATA_PORT // Enable SWD drive
cmp SPIxS // Dummy status read bsr txOnes // Send 64 clocks
ldhx #0xE79E // Send magic #
sthx SPIxD16
L5:
brclr SPIS_SPTEF_BIT,SPIxS,L5 // Wait until Tx buffer empty
bsr txOnes // Send 64 clocks
L6:
brclr SPIS_SPTEF_BIT,SPIxS,L6 // Wait until Tx buffer empty
ldhx SPIxD16 // Discard last data
mov #SWCLK_OUT_MASK|SWD_OUT_EN_MASK,DATA_PORT // Setup for SWCLK=1, SWD=3-state
L7:
brclr SPIS_SPRF_BIT,SPIxS,L7 // Wait until Tx complete
ldhx SPIxD16 // Discard rx data
clr SPIC1 // Disable SPI (SWCLK=1)
rts txOnes:
ldhx #0xFFFF // Tx 64 bits with '1'
sthx SPIxD16
L1:
brclr SPIS_SPTEF_BIT,SPIxS,L1 // Wait until Tx buffer empty
sthx SPIxD16
L2:
brclr SPIS_SPTEF_BIT,SPIxS,L2 // Wait until Tx buffer empty
sthx SPIxD16
L3:
brclr SPIS_SPTEF_BIT,SPIxS,L3 // Wait until Tx buffer empty
sthx SPIxD16
L4:
brclr SPIS_SPTEF_BIT,SPIxS,L4 // Wait until Tx buffer empty
rts
}
}
#pragma MESSAGE DEFAULT C5703 // Restore warnings about unused parameter //! SWD - Try to connect to the target
//!
//! This will do the following:
//! - Switch the interface to SWD mode
//! - Read IDCODE
//!
//! @return \n
//! == \ref BDM_RC_OK => Success \n
//! == \ref BDM_RC_NO_CONNECTION => Unexpected/no response from target
//!
uint8_t swd_connect(void) {
uint8_t buff[]; swd_JTAGtoSWD();
swd_txIdle8(); // Target must respond to read IDCODE immediately
return swd_readReg(SWD_READ_IDCODE, buff);
} //! Read ARM-SWD DP & AP register
//!
//! @param command - SWD command byte to select register etc.
//! @param data - buffer for 32-bit value read
//!
//! @return \n
//! == \ref BDM_RC_OK => Success \n
//! == \ref BDM_RC_ARM_FAULT_ERROR => FAULT response from target \n
//! == \ref BDM_RC_ACK_TIMEOUT => Excessive number of WAIT responses from target \n
//! == \ref BDM_RC_NO_CONNECTION => Unexpected/no response from target \n
//! == \ref BDM_RC_ARM_PARITY_ERROR => Parity error on data read
//!
//! @note Action and Data returned depends on register (some responses are pipelined)\n
//! SWD_RD_DP_IDCODE - Value from IDCODE reg \n
//! SWD_RD_DP_STATUS - Value from STATUS reg \n
//! SWD_RD_DP_RESEND - LAST value read (AP read or DP-RDBUFF), FAULT on sticky error \n
//! SWD_RD_DP_RDBUFF - Value from last AP read and clear READOK flag in STRL/STAT, FAULT on sticky error \n
//! SWD_RD_AP_REGx - Value from last AP read, clear READOK flag in STRL/STAT and INITIATE next AP read, FAULT on sticky error
//!
uint8_t swd_readReg(uint8_t command, uint8_t *data) {
uint8_t rc = swd_sendCommandWithWait(command);
if (rc != BDM_RC_OK) {
return rc;
}
return swd_rx32(data);
} //! Write ARM-SWD DP & AP register
//!
//! @param command - SWD command byte to select register etc.
//! @param data - buffer containing 32-bit value to write
//!
//! @return \n
//! == \ref BDM_RC_OK => Success \n
//! == \ref BDM_RC_ARM_FAULT_ERROR => FAULT response from target \n
//! == \ref BDM_RC_ACK_TIMEOUT => Excessive number of WAIT responses from target \n
//! == \ref BDM_RC_NO_CONNECTION => Unexpected/no response from target
//!
//! @note Action depends on register (some responses are pipelined)\n
//! SWD_WR_DP_ABORT - Write value to ABORT register (accepted) \n
//! SWD_WR_DP_CONTROL - Write value to CONTROL register (may be pending), FAULT on sticky error. \n
//! SWD_WR_DP_SELECT - Write value to SELECT register (may be pending), FAULT on sticky error. \n
//! SWD_WR_AP_REGx - Write to AP register. May initiate action e.g. memory access. Result is pending, FAULT on sticky error.
//!
uint8_t swd_writeReg(uint8_t command, const uint8_t *data) {
uint8_t rc = swd_sendCommandWithWait(command);
if (rc != BDM_RC_OK) {
return rc;
}
swd_tx32(data);
return rc;
} //! Write register of Access Port
//!
//! @param 16-bit address \n
//! A[15:8] => DP-AP-SELECT[31:24] (AP # Select) \n
//! A[7:4] => DP-AP-SELECT[7:4] (Bank select within AP) \n
//! A[3:2] => APACC[3:2] (Register select within bank)
//! @param buff \n
//! - [1..4] => 32-bit register value
//!
//! @return
//! == \ref BDM_RC_OK => success
//!
//! @note - Access is completed before return
//!
uint8_t swd_writeAPReg(const uint8_t *address, const uint8_t *buff) {
static const uint8_t writeAP[] = {SWD_WR_AP_REG0, SWD_WR_AP_REG1, SWD_WR_AP_REG2, SWD_WR_AP_REG3};
uint8_t rc;
uint8_t regNo = writeAP[(address[]&0xC)>>];
uint8_t selectData[];
selectData[] = address[];
selectData[] = ;
selectData[] = ;
selectData[] = address[]&0xF0; // Set up SELECT register for AP access
rc = swd_writeReg(SWD_WR_DP_SELECT, selectData);
if (rc != BDM_RC_OK) {
return rc;
}
// Initiate write to AP register
rc = swd_writeReg(regNo, buff);
if (rc != BDM_RC_OK) {
return rc;
}
// Read from READBUFF register to allow stall/status response
return swd_readReg(SWD_RD_DP_RDBUFF, selectData);
} //! Read register of Access Port
//!
//! @param 16-bit address \n
//! A[15:8] => DP-AP-SELECT[31:24] (AP # Select) \n
//! A[7:4] => DP-AP-SELECT[7:4] (Bank select within AP) \n
//! A[3:2] => APACC[3:2] (Register select within bank)
//! @param buff \n
//! - [1..4] => 32-bit register value
//!
//! @return
//! == \ref BDM_RC_OK => success
//!
//! @note - Access is completed before return
//!
uint8_t swd_readAPReg(const uint8_t *address, uint8_t *buff) {
static const uint8_t readAP[] = {SWD_RD_AP_REG0, SWD_RD_AP_REG1, SWD_RD_AP_REG2, SWD_RD_AP_REG3};
uint8_t rc;
uint8_t regNo = readAP[(address[]&0xC)>>];
uint8_t selectData[];
selectData[] = address[];
selectData[] = ;
selectData[] = ;
selectData[] = address[]&0xF0; // Set up SELECT register for AP access
rc = swd_writeReg(SWD_WR_DP_SELECT, selectData);
if (rc != BDM_RC_OK) {
return rc;
}
// Initiate read from AP register (dummy data)
rc = swd_readReg(regNo, buff);
if (rc != BDM_RC_OK) {
return rc;
}
// Read from READBUFF register
return swd_readReg(SWD_RD_DP_RDBUFF, buff);
} //! ARM-SWD - clear sticky bits
//!
//! @return error code
//!
uint8_t swd_clearStickyError(void) {
static const uint8_t swdClearErrors[] = {,,,SWD_DP_ABORT_CLEAR_STICKY_ERRORS_B3};
return swd_writeReg(SWD_WR_DP_ABORT, swdClearErrors);
} //! ARM-SWD - clear sticky bits and abort AP transactions
//!
//! @return error code
//!
uint8_t swd_abortAP(void) {
static const uint8_t swdClearErrors[] =
{,,,SWD_DP_ABORT_CLEAR_STICKY_ERRORS_B3|SWD_DP_ABORT_ABORT_AP_B3};
return swd_writeReg(SWD_WR_DP_ABORT, swdClearErrors);
} uint8_t swd_test(void) {
return swd_connect();
// swd_JTAGtoSWD();
// return BDM_RC_OK;
// return swd_connect();
}
#endif // HW_CAPABILITY && CAP_SWD_HW
SPI SWD Protocol Implement的更多相关文章
- Serial Wire Debug (SWD) Interface -- PSoc5
PSoC 5 supports programming through the serial wire debug (SWD) interface. There are two signals in ...
- Programming Internal Flash Over the Serial Wire Debug <SWD> Interface -- EFM32
1 Debug Interface Overview 1.1 Serial Wire Debug Serial Wire Debug (SWD) is a two-wire protocol for ...
- 【Dubbo 源码解析】02_Dubbo SPI
Dubbo SPI:(version:2.6.*) Dubbo 微内核 + 插件 模式,得益于 Dubbo SPI .其中 ExtentionLoader是 Dubbo SPI 最核心的类,它负责扩展 ...
- SWD Connect/Transfer Source Code
Serial Wire Debug interface The Serial Wire Debug protocol operates with a synchronous serial interf ...
- swddude -- A SWD programmer for ARM Cortex microcontrollers.
Introducing swddude I love the ARM Cortex-M series of microcontrollers. The sheer computational po ...
- 分布式的几件小事(五)dubbo的spi思想是什么
1.什么是SPI机制 SPI 全称为 Service Provider Interface,是一种服务发现机制. SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实 ...
- Introduction to Cortex Serial Wire Debugging
Serial Wire Debug (SWD) provides a debug port for severely pin limited packages, often the case for ...
- ARM architecture
http://en.wikipedia.org/wiki/ARM_architecture ARM architecture ARM architectures The ARM logo De ...
- Motan
https://github.com/weibocom/motan/wiki/zh_userguide http://www.cnblogs.com/mantu/p/5885996.html(源码分析 ...
随机推荐
- 按esc键 关闭模态框
<!-- help start --> <div class="modal fade" id="myModal" tabindex=" ...
- C 语言结构体之点运算符( . )和箭头运算符( -> )的区别
很多时候,在对结构体进行相应的编码时,时而发现是用点运算符( . ),时而是用箭头运算符( -> ):那么这两者之间的使用有什么区别么? 相同点:两者都是二元操作符,而且右边的操作数都是成员的名 ...
- bash脚本:集群资源争夺战crazy-killer
背景 公司的集群很多人一起用,有时候就难免资源紧张,某次需要用的时候没资源等了半天还是没资源,再等半天还是没资源,于是就写了个脚本泄愤,建议看到的人拷走放在自己公司集群上长期运行 :) 实现 此脚本运 ...
- 关于v4包的Fragment过渡动画的事件监听无响应问题解决
项目中部分功能模块采用了单Activity+多Fragment模式,当Fragment切换时,需要在过渡动画执行完后做一些操作,通常就是在自己封装的FragmentBase中重写onCreateAni ...
- requests(二): json请求中固定键名顺序&消除键和值之间的空格
继上一篇requests发送json请求的文章后,实际工作中遇到了以下2种情况. 1:服务端要求json字符串,键名的顺序固定 2.服务端对于接收到的json数据中,若key和value之间有空格, ...
- deeplearning.ai学习seq2seq模型
一.seq2seq架构图 seq2seq模型左边绿色的部分我们称之为encoder,左边的循环输入最终生成一个固定向量作为右侧的输入,右边紫色的部分我们称之为decoder.单看右侧这个结构跟我们之前 ...
- Windows下设置oracle数据库定时备份
1编写备份脚本 echo backup oracle database...... echo %~dp0 set file_dir=%~dp0 echo backup time...... set & ...
- Linux字符集的查看及修改【转】
一·查看字符集字符集在系统中体现形式是一个环境变量,以CentOS6.5为例,其查看当前终端使用字符集的方式可以有以下几种方式: 1.[root@david ~]# echo $LANGzh_CN.G ...
- centos6.8安装mysql5.6【转】
首先先要去看看本机有没有默认的mysql, 本地默认有的,我们应先卸载,在安装新的这个逻辑. rpm -qa | grep mysql 我本机默认安装的mysql5.1.73 下一步删除 rpm -e ...
- 文字小于12px时,设置line-height不居中问题
设置了文字了小于12px时,会存在设置了line-height的不生效的问题,主要是由于基线的问题,这篇文章解释的很清楚,有兴趣的可以看下https://blog.csdn.net/q12151634 ...