⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jtagfuncsbw.c

📁 msp430的jtag程序下载的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*==========================================================================*\
|                                                                            |
| 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 + -