www.pudn.com > jtagsrc.rar > tapctrl.c
/* * tapctrl.c : 1). Implement TAP controller state transitions. 2). Implement required JTAG public instructions. * * Copyright (C) 2004, OPEN-JTAG, All rights reserved. */ #include#include "jtag.h" #include "xjerr.h" #include "tapctrl.h" /* Used to record the current TAP state */ static int tap_state = TAPSTAT_UNDEFINED; /* * TAP state transition array - * This array descripes the TAP state machine. It is used * to instruct the TAP state transition. */ static const tap_state_t state_trans[NUM_OF_STATES] = { {TAPSTAT_SHIFT_DR, TAPSTAT_UPDATE_DR}, //TAPSTAT_EXIT2_DR {TAPSTAT_PAUSE_DR, TAPSTAT_UPDATE_DR}, //TAPSTAT_EXIT1_DR {TAPSTAT_SHIFT_DR, TAPSTAT_EXIT1_DR}, //TAPSTAT_SHIFT_DR {TAPSTAT_PAUSE_DR, TAPSTAT_EXIT2_DR}, //TAPSTAT_PAUSE_DR {TAPSTAT_CAPTURE_IR, TAPSTAT_TSTLOG_RST}, //TAPSTAT_SELECT_IR_SCAN {TAPSTAT_RUNTEST_IDLE, TAPSTAT_SELECT_DR_SCAN}, //TAPSTAT_UPDATE_DR {TAPSTAT_SHIFT_DR, TAPSTAT_EXIT1_DR}, //TAPSTAT_CAPTURE_DR {TAPSTAT_CAPTURE_DR, TAPSTAT_SELECT_IR_SCAN}, //TAPSTAT_SELECT_DR_SCAN {TAPSTAT_SHIFT_IR, TAPSTAT_UPDATE_IR}, //TAPSTAT_EXIT2_IR {TAPSTAT_PAUSE_IR, TAPSTAT_UPDATE_IR}, //TAPSTAT_EXIT1_IR {TAPSTAT_SHIFT_IR, TAPSTAT_EXIT1_IR}, //TAPSTAT_SHIFT_IR {TAPSTAT_PAUSE_IR, TAPSTAT_EXIT2_IR}, //TAPSTAT_PAUSE_IR {TAPSTAT_RUNTEST_IDLE, TAPSTAT_SELECT_DR_SCAN}, //TAPSTAT_RUNTST_IDLE {TAPSTAT_RUNTEST_IDLE, TAPSTAT_SELECT_DR_SCAN}, //TAPSTAT_UPDATE_IR {TAPSTAT_SHIFT_IR, TAPSTAT_EXIT1_IR}, //TAPSTAT_CAPTURE_IR {TAPSTAT_RUNTEST_IDLE, TAPSTAT_TSTLOG_RST}, //TAPSTAT_TSTLOG_RST }; /* * tapctrl_next_state() - * Make TAP controller go to the next adjacent state * according to the value of tms. Before exit from this * route, the current state of TAP controller will be * updated. * * @tms: the new logic value for TMS signal, it must be 0 or 1. */ static int tapctrl_next_state(u8 tms) { if(tap_state < 0x0 || tap_state > 0xF) return XJERR_TAPSTATE_INVALID; jtag_wri_tms(tms); jtag_wri_tck(); if(tms) tap_state = state_trans[tap_state].next_state[1]; else tap_state = state_trans[tap_state].next_state[0]; return XJ_OK; } /* * tapctrl_acs_reg() - * This route is used to access selected test data registers or * instruction regisger depending on the current TAP controller's * state. If the TAP controller's state is Shift-DR, selected * test data register will be accessed. If the TAP controller's * state is Shift-IR, the instruction register will be accessed. * When calling this route, please make sure that the current TAP's * state is Shift-DR or Shift-IR. When return from this route, the * TAP controller will enter the Exit1-DR/Exit1-IR state. * * @bit_len: the length in terms of bit to be shifted into the selected register. * @shift_in: data to be shifted into the selected register. * @shift_out: buffer to receive the data shifted out from selected register. * * shift_in and shift_out can't both be NULL at the same time. */ static int tapctrl_acs_reg(int bit_len, const u32 *shift_in, u32 *shift_out) { int bit_idx, word_idx; u32 wri_data, rd_data; //Check the current TAP controller's state and the paramaters if( (tap_state != TAPSTAT_SHIFT_DR) && (tap_state != TAPSTAT_SHIFT_IR) ) return XJ_ERROR; if(bit_len <= 0) return XJ_ERROR; if( (shift_in == NULL) && (shift_out == NULL) ) return XJ_ERROR; //Access the cells of selected scan chain for(bit_idx = 0; bit_idx < bit_len; bit_idx++){ //update wri_data and rd_data if(bit_idx%32 == 0){ word_idx = bit_idx/32; if(shift_in != NULL) wri_data = shift_in[word_idx]; else wri_data = 0; rd_data = 0; } //Write 1 bit jtag_wri_tdi((u8) (wri_data & 0x1) ); wri_data >>= 1; /* * If this is the last bit, enter the next TAP state (Exit1-DR/Exit1-IR). * Otherwise, stay at current TPA state (Shift-DR/Shift-IR) for further access */ if(bit_idx == bit_len - 1) tapctrl_next_state(1); else tapctrl_next_state(0); //Read 1 bit if( jtag_rd_rdo() ) rd_data |= (1 << (bit_idx%32)); /* update rd_buf when necessary * 1). when read 32 bits * 2). last bit */ if( (bit_idx%32 == 31 || bit_idx == bit_len - 1) && shift_out != NULL ) shift_out[word_idx] = rd_data; } return XJ_OK; } /* * tapctrl_acs_ireg() - * This route is used to access JTAG instruction register. * Please make sure that TAP controller is in the Run-Test/Idle or * Select-DR-Scan state when calling this route. If the JTAG instruction * is RESTART, the TAP Controller will enter Run-Test/Idle state b4 returning; * else, the TAP Controller will enter Select-DR-Scan state b4 returning. * * @instruction: public JTAG instruction to be shifted into the instruction * register. */ int tapctrl_acs_ireg(u32 instruction) { int status; int val = 0; u32 shift_in; u32 shift_out; shift_out = 0; shift_in = instruction; if(tap_state == TAPSTAT_RUNTEST_IDLE) tapctrl_next_state(1); //Run-Test/Idle -> Select-DR-Scan else if(tap_state == TAPSTAT_SELECT_DR_SCAN) ; //Select-DR-Scan -> Select-DR-Scan else return XJ_ERROR; tapctrl_next_state(1); //Select-DR-Scan -> Select-IR-Scan tapctrl_next_state(0); //Select-IR-Scan -> Capture-IR tapctrl_next_state(0); //Capture-IR -> Shift-IR status = tapctrl_acs_reg(4, &shift_in, &shift_out); tapctrl_next_state(1); //Exit1-IR -> Update-IR if(instruction == JTAG_RESTART) tapctrl_next_state(0); //Update-IR -> Run-Test/Idle else tapctrl_next_state(1); //Update-IR -> Select-DR-Scan if(status != XJ_OK) return XJERR_ACSIREG_FAIL; if(shift_out != 0x1) return XJERR_ACSIREG_FAIL; return XJ_OK; } /* * tapctrl_acs_dreg() - * This route is used to access selected data register. * Please make sure that TAP controller is in the Run-Test/Idle or * Select-DR-Scan state when calling this route. On returning * from this route, the TAP Controller will return to Run-Test/Idle * state. * * @bit_len: the length in terms of bit to be shifted into the data register. * @shift_in: data to be shifted into the data register. * @shift_out: buffer to receive the data shifted out from data register. * @run_test: flag used to control enter which state b4 returning. */ int tapctrl_acs_dreg(int bit_len, const u32 *shift_in, u32 *shift_out) { int status; int val = 0; if(tap_state == TAPSTAT_RUNTEST_IDLE) tapctrl_next_state(1); //Run-Test/Idle -> Select-DR-Scan else if(tap_state == TAPSTAT_SELECT_DR_SCAN) ; //Select-DR-Scan -> Select-DR-Scan else return XJ_ERROR; tapctrl_next_state(0); //Select-DR-Scan -> Capture-DR tapctrl_next_state(0); //Capture-DR -> Shift-DR status = tapctrl_acs_reg(bit_len, shift_in, shift_out); tapctrl_next_state(1); //Exit1-DR -> Update-DR tapctrl_next_state(0); //Update-DR -> Run-Test/Idle if(status != XJ_OK) return XJERR_ACSIREG_FAIL; else return XJ_OK; } /* * tapctrl_reset() - * This route is used to reset the TAP controller. * This route will put the TAP controller into the * Run-Test/Idle state. Please note that this route * should be called to initialize the TAP controller before * any operations can be applied to the TAP controller. * * There are two methods to reset the TAP controller. * 1). The optional TRST* input provides for asynchronous initialization of * the TAP controller. To force the TAP controller into the correct state * after power-up, nTRST must be driven LOW and then HIGH again. It is * recommended that TMS should be held at 1 while the signal applied at * nTRST changes from 0 to 1. * 2). No matter what the original state of the controller, it will enter Test- * Logic-Reset when TMS is held high for at least five rising edges of TCK. * The controller remains in this state while TMS is high. */ int tapctrl_reset(void) { int i; //Reset the TAP controller through nTRST jtag_wri_tms(1); jtag_wri_ntrst(0); //Drive Low first Sleep(50); jtag_wri_ntrst(1); //Drive High Sleep(50); //Reset the TAP controller through TMS for (i = 1; i <= 10; i++){ jtag_wri_tms(1); jtag_wri_tck(); } //Update the state of TAP controller tap_state = TAPSTAT_TSTLOG_RST; /* Now enter Run-Test/Idle state and stay here */ tapctrl_next_state(0); //Test-Logic Reset -> Run-Test/Idle tapctrl_next_state(0); //Run-Test/Idle -> Run-Test/Idle return XJ_OK; } /* * tapctrl_init() - * This route is used to initialize the TAP Controller by * calling tapctrl_reset(). */ int tapctrl_init(void) { return tapctrl_reset(); } /* * tapctrl_runtest() - * Produce an TAP state trnasition from the Run-Test/Idle state * to Run-Test/Idle state. */ int tapctrl_runtest(void) { if(tap_state != TAPSTAT_RUNTEST_IDLE) return XJ_ERROR; else return tapctrl_next_state(0); }