📄 jtagfuncsbw.c
字号:
/*==========================================================================*\
| |
| JTAGfunc.c |
| |
| JTAG Control Sequences for Erasing / Programming / Fuse Burning |
|----------------------------------------------------------------------------|
| Project: JTAG Functions |
| Developed using: IAR Embedded Workbench 3.40B |
|----------------------------------------------------------------------------|
| Author: STO |
| Version: 1.6 |
| Initial Version: 04-17-02 |
| Last Change: 07-31-06 |
|----------------------------------------------------------------------------|
| Version history: |
| 1.0 04/02 FRGR Initial version. |
| 1.1 04/02 ALB2 Formatting changes, added comments. |
| 1.2 08/02 ALB2 Initial code release with Lit# SLAA149. |
| 1.3 09/05 JDI 'ResetTAP': added SetTDI for fuse check |
| search for F2xxx to find respective modifications in |
| 'SetPC', 'HaltCPU', 'VerifyPSA', 'EraseFLASH' |
| 'WriteFLASH' |
| SUN1 Software delays redesigned to use TimerA harware; |
| see MsDelay() routine. |
| 1.4 12/05 STO Adapted for SpyBiWire JTAG mode |
| NOTE: |
| For security fuse blow please use new hardware schematic rev. 1.3. |
| Othewise the target CPU can be demaged |
| 1.5 03/06 STO BlowFuse() make correct fuse check after blowing. |
| 1.6 07/06 STO Loop in WriteFLASH() changed. |
|----------------------------------------------------------------------------|
| Designed 2002 by Texas Instruments Germany |
\*==========================================================================*/
#include "JTAGfuncSBW.h"
#include "LowLevelFuncSBW.h"
#include "Devices.h"
/****************************************************************************/
/* Low level routines for accessing the target device via JTAG: */
/****************************************************************************/
//----------------------------------------------------------------------------
/* Function for shifting a given 16-bit word into the JTAG data register.
Arguments: word data (16-bit data, MSB first)
Result: word (TDO value is shifted out)
*/
static word DR_Shift16_sbw(word data)
{
// JTAG FSM state = Run-Test/Idle
if (TCLK_saved & SBWDATO)
{
TMSH_TDIH();
}
else
{
TMSH_TDIL();
}
// JTAG FSM state = Select DR-Scan
TMSL_TDIH();
// JTAG FSM state = Capture-DR
TMSL_TDIH();
// JTAG FSM state = Shift-DR, Shiftin TDI (16 bit)
return(Shift_sbw(F_WORD, data));
// JTAG FSM state = Run-Test/Idle
}
//----------------------------------------------------------------------------
/* Function for shifting a new instruction into the JTAG instruction
register (MSB first, but with interchanged MSB - LSB, to
simply use the same shifting function, Shift_sbw(), as used in DR_Shift16_sbw).
Arguments: byte Instruction (8bit JTAG instruction, MSB first)
Result: word TDO valuse shifted out (TDO = JTAG ID)
*/
static word IR_Shift_sbw(byte instruction)
{
// JTAG FSM state = Run-Test/Idle
if (TCLK_saved & SBWDATO)
{
TMSH_TDIH();
}
else
{
TMSH_TDIL();
}
// JTAG FSM state = Select DR-Scan
TMSH_TDIH();
// JTAG FSM state = Select IR-Scan
TMSL_TDIH();
// JTAG FSM state = Capture-IR
TMSL_TDIH();
// JTAG FSM state = Shift-IR, Shiftin TDI (8 bit)
return(Shift_sbw(F_BYTE, instruction)); // JTAG FSM state = Run-Test/Idle
}
//----------------------------------------------------------------------------
/* Reset target JTAG interface and perform fuse-HW check.
Arguments: None
Result: None
*/
static void ResetTAP_sbw(void)
{
word i;
// Now fuse is checked, Reset JTAG FSM
for (i = 6; i > 0; i--) // 6 is nominal
{
TMSH_TDIH();
}
// JTAG FSM is now in Test-Logic-Reset
TMSL_TDIH(); // now in Run/Test Idle
// Fuse check
TMSH_TDIH();
TMSL_TDIH();
TMSH_TDIH();
TMSL_TDIH();
TMSH_TDIH();
// In every TDI slot a TCK for the JTAG machine is generated.
// Thus we need to get TAP in Run/Test Idle state back again.
TMSH_TDIH();
TMSL_TDIH();
}
//----------------------------------------------------------------------------
/* Function to execute a Power-Up Clear (PUC) using JTAG CNTRL SIG register
Arguments: None
Result: word (STATUS_OK if JTAG ID is valid, STATUS_ERROR otherwise)
*/
static word ExecutePUC(void)
{
word JtagVersion;
// Perform Reset
IR_Shift(IR_CNTRL_SIG_16BIT);
DR_Shift16(0x2C01); // Apply Reset
DR_Shift16(0x2401); // Remove Reset
ClrTCLK();
SetTCLK();
ClrTCLK();
SetTCLK();
ClrTCLK();
JtagVersion = IR_Shift(IR_ADDR_CAPTURE); // read JTAG ID, checked at function end
SetTCLK();
WriteMem(F_WORD, 0x0120, 0x5A80); // Disable Watchdog on target device
if (JtagVersion != JTAG_ID)
{
return(STATUS_ERROR);
}
return(STATUS_OK);
}
//----------------------------------------------------------------------------
/* Function to set target CPU JTAG FSM into the instruction fetch state
Argument: None
Result: word (STATUS_OK if instr. fetch was set, STATUS_ERROR otherwise)
*/
static word SetInstrFetch(void)
{
word i;
IR_Shift(IR_CNTRL_SIG_CAPTURE);
// Wait until CPU is in instr. fetch state, timeout after limited attempts
for (i = 50; i > 0; i--)
{
if (DR_Shift16(0x0000) & 0x0080)
{
return(STATUS_OK);
}
ClrTCLK();
SetTCLK();
}
return(STATUS_ERROR);
}
//----------------------------------------------------------------------------
/* Load a given address into the target CPU's program counter (PC).
Argument: word Addr (destination address)
Result: None
*/
static void SetPC(word Addr)
{
SetInstrFetch(); // Set CPU into instruction fetch mode, TCLK=1
// Load PC with address
IR_Shift(IR_CNTRL_SIG_16BIT);
DR_Shift16(0x3401); // CPU has control of RW & BYTE.
IR_Shift(IR_DATA_16BIT);
DR_Shift16(0x4030); // "mov #addr,PC" instruction
ClrTCLK();
SetTCLK(); // F2xxx
DR_Shift16(Addr); // "mov #addr,PC" instruction
ClrTCLK();
IR_Shift(IR_ADDR_CAPTURE);
SetTCLK();
ClrTCLK(); // Now the PC should be on Addr
IR_Shift(IR_CNTRL_SIG_16BIT);
DR_Shift16(0x2401); // JTAG has control of RW & BYTE.
}
//----------------------------------------------------------------------------
/* Function to set the CPU into a controlled stop state
*/
static void HaltCPU(void)
{
SetInstrFetch(); // Set CPU into instruction fetch mode
IR_Shift(IR_DATA_16BIT);
DR_Shift16(0x3FFF); // Send JMP $ instruction
ClrTCLK();
IR_Shift(IR_CNTRL_SIG_16BIT);
DR_Shift16(0x2409); // Set JTAG_HALT bit
SetTCLK();
}
//----------------------------------------------------------------------------
/* Function to release the target CPU from the controlled stop state
*/
static void ReleaseCPU(void)
{
ClrTCLK();
IR_Shift(IR_CNTRL_SIG_16BIT);
DR_Shift16(0x2401); // Clear the HALT_JTAG bit
IR_Shift(IR_ADDR_CAPTURE);
SetTCLK();
}
//----------------------------------------------------------------------------
/* This function compares the computed PSA (Pseudo Signature Analysis) value
to the PSA value shifted out from the target device.
It is used for very fast data block write or erasure verification.
Arguments: word StartAddr (Start address of data block to be checked)
word Length (Number of words within data block)
word *DataArray (Pointer to array with the data, 0 for Erase Check)
Result: word (STATUS_OK if comparison was successful, STATUS_ERROR otherwise)
*/
static word VerifyPSA_sbw(word StartAddr, word Length, word *DataArray)
{
word TDOword, i;
word POLY = 0x0805; // Polynom value for PSA calculation
word PSA_CRC = StartAddr-2; // Start value for PSA calculation
ExecutePUC();
if(DeviceHas_EnhVerify())
{
SetPC(StartAddr-4);
HaltCPU();
ClrTCLK();
IR_Shift(IR_DATA_16BIT);
DR_Shift16(StartAddr-2);
}
else
{
SetPC(StartAddr-2);
SetTCLK();
ClrTCLK();
}
IR_Shift(IR_DATA_PSA);
for (i = 0; i < Length; i++)
{
// Calculate the PSA (Pseudo Signature Analysis) value
if ((PSA_CRC & 0x8000) == 0x8000)
{
PSA_CRC ^= POLY;
PSA_CRC <<= 1;
PSA_CRC |= 0x0001;
}
else
{
PSA_CRC <<= 1;
}
// if pointer is 0 then use erase check mask, otherwise data
if (DataArray == 0)
{
PSA_CRC ^= 0xFFFF;
}
else
{
PSA_CRC ^= DataArray[i];
}
// Clock through the PSA
SetTCLK();
ClrTCLK();
TMSH_TDIL();
TMSL_TDIL();
TMSL_TDIL();
TMSH_TDIL();
TMSH_TDIL();
TMSL_TDIL();
}
IR_Shift(IR_SHIFT_OUT_PSA);
TDOword = DR_Shift16(0x0000); // Read out the PSA value
SetTCLK();
if(DeviceHas_EnhVerify())
{
ReleaseCPU();
}
ExecutePUC();
return((TDOword == PSA_CRC) ? STATUS_OK : STATUS_ERROR);
}
/****************************************************************************/
/* High level routines for accessing the target device via JTAG: */
/* */
/* From the following, the user is relieved from coding anything. */
/* To provide better understanding and clearness, some functionality is */
/* coded generously. (Code and speed optimization enhancements may */
/* be desired) */
/****************************************************************************/
//----------------------------------------------------------------------------
/* Function to take target device under JTAG control. Disables the target
watchdog. Sets the global DEVICE variable as read from the target device.
Arguments: None
Result: word (STATUS_ERROR if fuse is blown, incorrect JTAG ID or
synchronizing time-out; STATUS_OK otherwise)
*/
word GetDevice_sbw(void)
{
word i;
// Reset Test logic
ClrSBWTDIO(); // put device in normal operation: Reset = 0
ClrSBWTCK(); // TEST pin = 0
MsDelay(1); // wait 1ms (minimum: 100us)
// SpyBiWire entry sequence
SetSBWTDIO(); // Reset = 1
SetSBWTCK(); // TEST pin = 1
// initial 1 SBWCLKs to enter sbw-mode
ClrSBWTCK();
SetSBWTCK();
// SpyBiWire mode is active now
ResetTAP_sbw(); // Reset JTAG state machine, check fuse HW
if (IsFuseBlown()) // Stop here if fuse is already blown
{
return(STATUS_FUSEBLOWN);
}
IR_Shift(IR_CNTRL_SIG_16BIT);
DR_Shift16(0x2401); // Set device into JTAG mode + read
if (IR_Shift(IR_CNTRL_SIG_CAPTURE) != JTAG_ID)
{
return(STATUS_ERROR);
}
// Wait until CPU is synchronized, timeout after a limited # of attempts
for (i = 50; i > 0; i--)
{
if (DR_Shift16(0x0000) & 0x0200)
{
word DeviceId;
DeviceId = ReadMem(F_WORD, 0x0FF0);// Get target device type
//(bytes are interchanged)
DeviceId = (DeviceId << 8) + (DeviceId >> 8); // swop bytes
//Set Device index, which is used by functions in Device.c
SetDevice(DeviceId);
break;
}
else
{
if (i == 1)
{
return(STATUS_ERROR); // Timeout reached, return false
}
}
}
if (!ExecutePUC()) // Perform PUC, Includes
{ // target Watchdog disable.
return(STATUS_ERROR);
}
return(STATUS_OK);
}
//----------------------------------------------------------------------------
/* Function to release the target device from JTAG control
Argument: word Addr (0xFFFE: Perform Reset, means Load Reset Vector into PC,
otherwise: Load Addr into PC)
Result: None
*/
void ReleaseDevice(word Addr)
{
if (Addr == V_RESET)
{
IR_Shift(IR_CNTRL_SIG_16BIT);
DR_Shift16(0x2C01); // Perform a reset
DR_Shift16(0x2401);
}
else
{
SetPC(Addr); // Set target CPU's PC
}
IR_Shift(IR_CNTRL_SIG_RELEASE);
}
//----------------------------------------------------------------------------
/* This function writes one byte/word at a given address ( <0xA00)
Arguments: word Format (F_BYTE or F_WORD)
word Addr (Address of data to be written)
word Data (shifted data)
Result: None
*/
void WriteMem(word Format, word Addr, word Data)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -