/** * @brief Test the first state transition * * When transitioning from UNKNOWN to a state, the TAP should be reset. * If TRST is assigned, that signal should be used. Otherwise the TAP * should be clocked 5 times with TMS high to enter into the RESET state. */ bool jtagTAP_TestTxFromUnknown() { //Setup HasTRST = false; TMSStateTx = 0; TRSTChanged = 0; InvalidSignal = false; jtagTAP_Init(); //Test jtagTAP_SetState(JTAGTAP_STATE_IDLE); //Check //Without TRST, TMS should be high for 5 clock cycles and then low for one. //The earliest TMS value appears in the higher bits of TMSState so the ending //value of TMS state should be 0x0000003E ASSERT(TMSStateTx == 0x3E, "Incorrect transitions. TMS values are %08X, should be %08X", TMSStateTx, 0x3E); ASSERT(TRSTChanged == 0, "TRST transitioned %i times. It shouldn't have", TRSTChanged); //re-setup HasTRST = true; TMSStateTx = 0xFFFFFFFF; TRSTChanged = 0; jtagTAP_Init(); //Test jtagTAP_SetState(JTAGTAP_STATE_IDLE); //Check //With TRST, TMS should be low for one clock cycle. TRST should toggle low then high. //The ending value of TMS state should be 0xFFFFFFFE. ASSERT(TMSStateTx == 0xFFFFFFFE, "Incorrect transitions. TMS values are %08X, should be %08X", TMSStateTx, 0xFFFFFFFE); ASSERT(TRSTChanged == 2, "TRST transitioned %i times. It should have done it %i times", TRSTChanged, 2); //Check that an invalid signal wasn't set at some point ASSERT(!InvalidSignal, "An invalid signal was specified at some point"); return true; }
/** * @brief Test the RESET transitions * * When transitioning from a state to RESET, the TAP should walk the states * and finish at reset. If TRST is assigned, that signal should be used and * the state set as RESET with TMS high. */ bool jtagTAP_TestReset() { //Setup HasTRST = false; TMSStateTx = 0; TRSTChanged = 0; InvalidSignal = false; TAPState = JTAGTAP_STATE_DR_SHIFT; jtagTAP_SetState(JTAGTAP_STATE_RESET); //Check //Without TRST, TMS should be high for 5 clock cycles. //The earliest TMS value appears in the higher bits of TMSState so the ending //value of TMS state should be 0x0000001F ASSERT(TMSStateTx == 0x1F, "Incorrect transitions. TMS values are %08X, should be %08X", TMSStateTx, 0x1F); ASSERT(TRSTChanged == 0, "TRST transitioned %i times. It shouldn't have", TRSTChanged); //re-setup HasTRST = true; TMSStateTx = 0x0FFFFFF0; TRSTChanged = 0; //Test TAPState = JTAGTAP_STATE_DR_SHIFT; jtagTAP_SetState(JTAGTAP_STATE_RESET); //Check //With TRST, TMS shouldn't change. TRST should toggle low then high. //TMS should be set high and the state should be RESET ASSERT(TMSStateTx == 0x0FFFFFF0, "Incorrect transitions. TMS values are %08X, should be %08X", TMSStateTx, 0x0FFFFFF0); ASSERT(TRSTChanged == 2, "TRST transitioned %i times. It should have done it %i times", TRSTChanged, 2); ASSERT(TAPState == JTAGTAP_STATE_RESET, "State isn't RESET: %i", TAPState); ASSERT(TMSStateCurrent, "Current state of TMS isn't high"); //Check that an invalid signal wasn't set at some point ASSERT(!InvalidSignal, "An invalid signal was specified at some point"); return true; }
/** * @brief Attempts to determine if a device is attached via JTAG * * For the provided pin combination, this function will reset the tap and scan * out the data register, either getting an ID CODE, a BYPASS or garbage. It * will attempt to analyse the results to see if it's a valid result. * * @param[in] tck The pin the TCK signal is on, for scanning * @param[in] tms The pin the TMS signal is on, for scanning */ static void knock_ScanReset(unsigned int tck, unsigned int tms) { unsigned int count; int unchanged_count = -1; //the first time through always results in a unchanged count uint16_t data, data_changed = 0x0000; uint16_t prev_data; uint16_t data_interesting = 0x0000; uint16_t scan_results[KNOCK_RESULTS]; jtagTAP_SetState(JTAGTAP_STATE_UNKNOWN); jtagTAP_SetState(JTAGTAP_STATE_DR_SHIFT); prev_data = GPIOD_IDR; for(count = 0; count < KNOCK_RESULTS; ++count) { data = GPIOD_IDR; data_changed = data ^ prev_data; data_interesting |= data_changed; prev_data = data; scan_results[count] = data; jtag_Clock(); if(data_changed == 0) { if(++unchanged_count == KNOCK_UNCHANGED) { break; } } else { unchanged_count = 0; //something changed, reset the count. } } if(data_interesting != 0) { //a line changed state at least once, lets inspect unsigned int bit = 0; for(bit = 0; bit < knock_PinCount; ++bit) { if(((data_interesting >> bit) & 0x01) == 1) { //this line changed unsigned int index; data_interesting &= ~(1 << bit); //mask off this bit, until it proves itself for(index = 0; index < count; ++index) { if((((scan_results[index] >> bit) & 0x01) == 1) && (count - index >= 32)) { //this could be a potential ID CODE, get it uint32_t idcode = 0x80000000; unsigned int code_end = index + 32; while(++index < code_end) { idcode >>= 1; idcode |= ((scan_results[index] >> bit) & 0x01) << 31; } if((idcode != 0xFFFFFFFF)) { data_interesting |= (1 << bit); //this is interesting, keep it } --index; //fixup } } } } knock_ScanResetFindTDI(tck, tms, data_interesting, scan_results[count-1], count); }