📄 jtagfunc.c
字号:
/*==========================================================================*\
| |
| JTAGfunc.c |
| |
| JTAG Control Sequences for Erasing / Programming / Fuse Burning |
|----------------------------------------------------------------------------|
| Project: JTAG Functions |
| Developed using: IAR Embedded Workbench 3.40B [Kickstart] |
|----------------------------------------------------------------------------|
| 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 01/06 STO Added entry sequence for SpyBiWire devices |
| Minor cosmetic changes |
| 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 "JTAGfunc.h"
#include "LowLevelFunc.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
through TDI.
Arguments: word data (16-bit data, MSB first)
Result: word (value is shifted out via TDO simultaneously)
*/
word DR_Shift16(word data)
{
// JTAG FSM state = Run-Test/Idle
SetTMS();
ClrTCK();
SetTCK();
// JTAG FSM state = Select DR-Scan
ClrTMS();
ClrTCK();
SetTCK();
// JTAG FSM state = Capture-DR
ClrTCK();
SetTCK();
// JTAG FSM state = Shift-DR, Shift in TDI (16-bit)
return(Shift(F_WORD, data));
// JTAG FSM state = Run-Test/Idle
}
//----------------------------------------------------------------------------
/* Function for shifting a new instruction into the JTAG instruction
register through TDI (MSB first, but with interchanged MSB - LSB, to
simply use the same shifting function, Shift(), as used in DR_Shift16).
Arguments: byte Instruction (8bit JTAG instruction, MSB first)
Result: word TDOword (value shifted out from TDO = JTAG ID)
*/
word IR_Shift(byte instruction)
{
// JTAG FSM state = Run-Test/Idle
SetTMS();
ClrTCK();
SetTCK();
// JTAG FSM state = Select DR-Scan
ClrTCK();
SetTCK();
// JTAG FSM state = Select IR-Scan
ClrTMS();
ClrTCK();
SetTCK();
// JTAG FSM state = Capture-IR
ClrTCK();
SetTCK();
// JTAG FSM state = Shift-IR, Shift in TDI (8-bit)
return(Shift(F_BYTE, instruction));
// JTAG FSM state = Run-Test/Idle
}
//----------------------------------------------------------------------------
/* Reset target JTAG interface and perform fuse-HW check.
Arguments: None
Result: None
*/
void ResetTAP(void)
{
word i;
// process TDI first to settle fuse current
SetTDI();
SetTMS();
SetTCK();
// Now fuse is checked, Reset JTAG FSM
for (i = 6; i > 0; i--)
{
ClrTCK();
SetTCK();
}
// JTAG FSM is now in Test-Logic-Reset
ClrTCK();
ClrTMS();
SetTCK();
// JTAG FSM is now in Run-Test/IDLE
// Perform fuse check
ClrTMS();
SetTMS();
ClrTMS();
SetTMS();
}
//----------------------------------------------------------------------------
/* 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)
*/
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)
*/
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
*/
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
*/
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
*/
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)
*/
word VerifyPSA(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
&DataArray[0] == 0 ? (PSA_CRC ^= 0xFFFF) : (PSA_CRC ^= DataArray[i]);
// Clock through the PSA
SetTCLK();
ClrTCLK(); // set here -> Fixes problem with F123 PSA in RAM
ClrTCK();
SetTMS();
SetTCK(); // Select DR scan
ClrTCK();
ClrTMS();
SetTCK(); // Capture DR
ClrTCK();
SetTCK(); // Shift DR
ClrTCK();
SetTMS();
SetTCK(); // Exit DR
ClrTCK();
SetTCK();
ClrTMS();
ClrTCK();
SetTCK();
}
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 Device index 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(void)
{
word i;
if (bJtag4Sbw)
{
//entry JTAG4 sequence
ClrRST();
usDelay(1); //delay 1 uS
ClrTST();
MsDelay(5);
SetRST();
SetTST();
usDelay(8); // 8us delay
ClrRST();
usDelay(8); // 8us delay
ClrTST();
usDelay(3); // 2us delay
SetTST();
SetRST();
MsDelay(10);
ReleaseRST();
//JTAG4 mode is entered!
}
ResetTAP(); // 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
{
return(STATUS_ERROR); // target Watchdog disable.
}
return(STATUS_OK);
}
//----------------------------------------------------------------------------
/* Function to release the target device from JTAG control
Argument: word Addr (0xFFFE: Perform Reset, means Load Reset Vector into PC,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -