📄 jtagfunc430x.c
字号:
/*==========================================================================*\
| |
| JTAGfunc.c |
| |
| JTAG Control Sequences for Erasing / Programming / Fuse Burning |
|----------------------------------------------------------------------------|
| Project: JTAG Functions |
| Developed using: IAR Embedded Workbench 3.40A [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 SBW 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 "JTAGfunc430X.h"
#include "LowLevelFunc430X.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)
*/
static 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 given 20-bit address word into the
JTAG address register through TDI.
Arguments: unsigned long address (20-bit address word, MSB first)
Result: unsigned long TDOvalue (is shifted out via TDO simultaneously)
*/
static unsigned long DR_Shift20(unsigned long address)
{
// 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_430X(address));
// 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)
*/
static 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
*/
static 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)
*/
static word ExecutePUC_430X(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_430X(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_430X(unsigned long 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((word)(0x0080 | (((Addr)>>8) & 0x0F00))); // "mova #addr20,PC" instruction
ClrTCLK();
SetTCLK();
DR_Shift16(Addr); // second word of "mova #addr20,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)
*/
word VerifyPSA_430X(unsigned long StartAddr, unsigned long Length, word *DataArray)
{
word TDOword;
unsigned int i;
const word POLY = 0x0805; // Polynom value for PSA calculation
word PSA_CRC = (word)(StartAddr-2); // Start value for PSA calculation
ExecutePUC_430X();
if(DeviceHas_EnhVerify())
{
SetPC_430X(StartAddr-4);
HaltCPU();
ClrTCLK();
IR_Shift(IR_DATA_16BIT);
DR_Shift20(StartAddr-2);
}
else
{
SetPC_430X(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_430X();
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_430X(void)
{
word i;
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_430X()) // 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,
otherwise: Load Addr into PC)
Result: None
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -