]> git.sur5r.net Git - openocd/blobdiff - src/jtag/jtag.c
Change tap_state naming to be consistent with SVF documentation.
[openocd] / src / jtag / jtag.c
index 0c74c4168bd3254e8e14cf282b61f53a1718ef3d..d48641836f274157e171eb3ba616c087e9aea368 100644 (file)
@@ -87,22 +87,22 @@ int tap_move_map[16] = {
 
 tap_transition_t tap_transitions[16] =
 {
-       {TAP_TLR, TAP_RTI},             /* TLR */
-       {TAP_SIS, TAP_CD},              /* SDS */
-       {TAP_E1D, TAP_SD},              /* CD  */
-       {TAP_E1D, TAP_SD},              /* SD  */
-       {TAP_UD,  TAP_PD},              /* E1D */
-       {TAP_E2D, TAP_PD},              /* PD  */
-       {TAP_UD,  TAP_SD},              /* E2D */
-       {TAP_SDS, TAP_RTI},             /* UD  */
-       {TAP_SDS, TAP_RTI},             /* RTI */
-       {TAP_TLR, TAP_CI},              /* SIS */
-       {TAP_E1I, TAP_SI},              /* CI  */
-       {TAP_E1I, TAP_SI},              /* SI  */
-       {TAP_UI,  TAP_PI},              /* E1I */
-       {TAP_E2I, TAP_PI},              /* PI  */
-       {TAP_UI,  TAP_SI},              /* E2I */
-       {TAP_SDS, TAP_RTI}              /* UI  */
+       {TAP_RESET, TAP_IDLE},          /* TLR */
+       {TAP_IRSELECT, TAP_DRCAPTURE},          /* SDS */
+       {TAP_DREXIT1, TAP_DRSHIFT},             /* CD  */
+       {TAP_DREXIT1, TAP_DRSHIFT},             /* SD  */
+       {TAP_DRUPDATE,  TAP_DRPAUSE},           /* E1D */
+       {TAP_DREXIT2, TAP_DRPAUSE},             /* PD  */
+       {TAP_DRUPDATE,  TAP_DRSHIFT},           /* E2D */
+       {TAP_DRSELECT, TAP_IDLE},               /* UD  */
+       {TAP_DRSELECT, TAP_IDLE},               /* RTI */
+       {TAP_RESET, TAP_IRCAPTURE},             /* SIS */
+       {TAP_IREXIT1, TAP_IRSHIFT},             /* CI  */
+       {TAP_IREXIT1, TAP_IRSHIFT},             /* SI  */
+       {TAP_IRUPDATE,  TAP_IRPAUSE},           /* E1I */
+       {TAP_IREXIT2, TAP_IRPAUSE},             /* PI  */
+       {TAP_IRUPDATE,  TAP_IRSHIFT},           /* E2I */
+       {TAP_DRSELECT, TAP_IDLE}                /* UI  */
 };
 
 char* jtag_event_strings[] =
@@ -115,8 +115,8 @@ char* jtag_event_strings[] =
  * inside the drivers, but we don't want to break
  * linking the drivers!!!!
  */
-enum tap_state end_state = TAP_TLR;
-enum tap_state cur_state = TAP_TLR;
+enum tap_state end_state = TAP_RESET;
+enum tap_state cur_state = TAP_RESET;
 int jtag_trst = 0;
 int jtag_srst = 0;
 
@@ -125,8 +125,8 @@ jtag_command_t **last_comand_pointer = &jtag_command_queue;
 static jtag_tap_t *jtag_all_taps = NULL;
 
 enum reset_types jtag_reset_config = RESET_NONE;
-enum tap_state cmd_queue_end_state = TAP_TLR;
-enum tap_state cmd_queue_cur_state = TAP_TLR;
+enum tap_state cmd_queue_end_state = TAP_RESET;
+enum tap_state cmd_queue_cur_state = TAP_RESET;
 
 int jtag_verify_capture_ir = 1;
 
@@ -273,12 +273,12 @@ int Jim_Command_drscan(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
 int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 
 
-jtag_tap_t *jtag_AllTaps(void) 
-{ 
-  return jtag_all_taps; 
+jtag_tap_t *jtag_AllTaps(void)
+{
+  return jtag_all_taps;
 };
 
-int 
+int
 jtag_NumTotalTaps(void)
 {
        jtag_tap_t *t;
@@ -310,25 +310,6 @@ jtag_NumEnabledTaps(void)
        return n;
 }
 
-jtag_tap_t *
-jtag_NextEnabledTap( jtag_tap_t *p )
-{
-       if( p == NULL ){
-               // start at the head of list
-               p = jtag_AllTaps();
-       } else {
-               // start *after* this one
-               p = p->next_tap;
-       }
-       while( p ){
-               if( p->enabled ){
-                       break;
-               } else {
-                       p = p->next_tap;
-               }
-       }
-       return p;
-}
 
 jtag_tap_t *jtag_TapByString( const char *s )
 {
@@ -369,7 +350,7 @@ jtag_TapByJimObj( Jim_Interp *interp, Jim_Obj *o )
                t = NULL;
        }  else {
                t = jtag_TapByString( cp );
-       } 
+       }
        if( t == NULL ){
                Jim_SetResult_sprintf(interp,"Tap: %s is unknown", cp );
        }
@@ -385,7 +366,7 @@ jtag_TapByAbsPosition( int n )
 
        orig_n = n;
        t = jtag_AllTaps();
-       
+
        while( t && (n > 0)) {
                n--;
                t = t->next_tap;
@@ -482,6 +463,39 @@ void* cmd_queue_alloc(size_t size)
        int offset;
        u8 *t;
 
+       /*
+        * WARNING:
+        *    We align/round the *SIZE* per below
+        *    so that all pointers returned by
+        *    this function are reasonably well
+        *    aligned.
+        *
+        * If we did not, then an "odd-length" request would cause the
+        * *next* allocation to be at an *odd* address, and because
+        * this function has the same type of api as malloc() - we
+        * must also return pointers that have the same type of
+        * alignment.
+        *
+        * What I do not/have is a reasonable portable means
+        * to align by...
+        *
+        * The solution here, is based on these suggestions.
+        * http://gcc.gnu.org/ml/gcc-help/2008-12/msg00041.html
+        *
+        */
+       union worse_case_align {
+         int i;
+         long l;
+         float f;
+         void *v;
+       };
+#define ALIGN_SIZE  (sizeof(union worse_case_align))
+
+       // The alignment process.
+       size = (size + ALIGN_SIZE -1) & (~(ALIGN_SIZE-1));
+       // Done...
+
+
        if (*p_page)
        {
                while ((*p_page)->next)
@@ -529,7 +543,7 @@ static void jtag_prelude1(void)
                return;
        }
 
-       if (cmd_queue_end_state == TAP_TLR)
+       if (cmd_queue_end_state == TAP_RESET)
                jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
 }
 
@@ -945,7 +959,7 @@ int MINIDRIVER(interface_jtag_add_plain_dr_scan)(int num_fields, scan_field_t *f
 
 void jtag_add_tlr(void)
 {
-       jtag_prelude(TAP_TLR);
+       jtag_prelude(TAP_RESET);
 
        int retval;
        retval=interface_jtag_add_tlr();
@@ -955,7 +969,7 @@ void jtag_add_tlr(void)
 
 int MINIDRIVER(interface_jtag_add_tlr)()
 {
-       enum tap_state state = TAP_TLR;
+       enum tap_state state = TAP_RESET;
        jtag_command_t **last_cmd = jtag_get_last_command_p();
 
        /* allocate memory for a new list member */
@@ -986,9 +1000,9 @@ void jtag_add_pathmove(int num_states, enum tap_state *path)
 
        for (i=0; i<num_states; i++)
        {
-               if (path[i] == TAP_TLR)
+               if (path[i] == TAP_RESET)
                {
-                       LOG_ERROR("BUG: TAP_TLR is not a valid state for pathmove sequences");
+                       LOG_ERROR("BUG: TAP_RESET is not a valid state for pathmove sequences");
                        exit(-1);
                }
                if ((tap_transitions[cur_state].low != path[i])&&
@@ -1140,7 +1154,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
        if (trst_with_tlr)
        {
                LOG_DEBUG("JTAG reset with TLR instead of TRST");
-               jtag_add_end_state(TAP_TLR);
+               jtag_add_end_state(TAP_RESET);
                jtag_add_tlr();
                jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
                return;
@@ -1152,7 +1166,7 @@ void jtag_add_reset(int req_tlr_or_trst, int req_srst)
                 * and inform possible listeners about this
                 */
                LOG_DEBUG("TRST line asserted");
-               cmd_queue_cur_state = TAP_TLR;
+               cmd_queue_cur_state = TAP_RESET;
                jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
        }
        else
@@ -1182,9 +1196,9 @@ int MINIDRIVER(interface_jtag_add_reset)(int req_trst, int req_srst)
 void jtag_add_end_state(enum tap_state state)
 {
        cmd_queue_end_state = state;
-       if ((cmd_queue_end_state == TAP_SD)||(cmd_queue_end_state == TAP_SI))
+       if ((cmd_queue_end_state == TAP_DRSHIFT)||(cmd_queue_end_state == TAP_IRSHIFT))
        {
-               LOG_ERROR("BUG: TAP_SD/SI can't be end state. Calling code should use a larger scan field");
+               LOG_ERROR("BUG: TAP_DRSHIFT/SI can't be end state. Calling code should use a larger scan field");
        }
 }
 
@@ -1348,7 +1362,7 @@ int jtag_check_value(u8 *captured, void *priv, scan_field_t *field)
                                char *in_check_mask_char;
                                in_check_mask_char = buf_to_str(field->in_check_mask, (num_bits > 64) ? 64 : num_bits, 16);
                                LOG_WARNING("value captured during scan didn't pass the requested check:");
-                               LOG_WARNING("captured: 0x%s check_value: 0x%s check_mask: 0x%s", 
+                               LOG_WARNING("captured: 0x%s check_value: 0x%s check_mask: 0x%s",
                                                        captured_char, in_check_value_char, in_check_mask_char);
                                free(in_check_mask_char);
                        }
@@ -1477,7 +1491,7 @@ int jtag_examine_chain(void)
                buf_set_u32(idcode_buffer, i * 32, 32, 0x000000FF);
        }
 
-       jtag_add_plain_dr_scan(1, &field, TAP_TLR);
+       jtag_add_plain_dr_scan(1, &field, TAP_RESET);
        jtag_execute_queue();
 
        for (i = 0; i < JTAG_MAX_CHAIN_SIZE * 4; i++)
@@ -1499,7 +1513,7 @@ int jtag_examine_chain(void)
                LOG_ERROR("JTAG: No taps enabled?");
                return ERROR_JTAG_INIT_FAILED;
        }
-       
+
        for (bit_count = 0; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;)
        {
                u32 idcode = buf_get_u32(idcode_buffer, bit_count, 32);
@@ -1560,26 +1574,42 @@ int jtag_examine_chain(void)
                if (tap)
                {
                        tap->idcode = idcode;
-                       if( tap->expected_id ){
-                               if( tap->idcode != tap->expected_id ){
-                                       LOG_ERROR("ERROR: Tap: %s - Expected id: 0x%08x, Got: 0x%08x",
+
+                       if (tap->expected_ids_cnt > 0) {
+                               /* Loop over the expected identification codes and test for a match */
+                               u8 ii;
+                               for (ii = 0; ii < tap->expected_ids_cnt; ii++) {
+                                       if( tap->idcode == tap->expected_ids[ii] ){
+                                               break;
+                                       }
+                               }
+
+                               /* If none of the expected ids matched, log an error */
+                               if (ii == tap->expected_ids_cnt) {
+                                       LOG_ERROR("JTAG tap: %s             got: 0x%08x (mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)",
                                                          tap->dotted_name,
-                                                         tap->expected_id,
-                                                         idcode );
-                                       LOG_ERROR("ERROR: expected: mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x",
-                                                         EXTRACT_MFG( tap->expected_id ),
-                                                         EXTRACT_PART( tap->expected_id ),
-                                                         EXTRACT_VER( tap->expected_id ) );
-                                       LOG_ERROR("ERROR:      got: mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x",
+                                                         idcode,
                                                          EXTRACT_MFG( tap->idcode ),
                                                          EXTRACT_PART( tap->idcode ),
                                                          EXTRACT_VER( tap->idcode ) );
+                                       for (ii = 0; ii < tap->expected_ids_cnt; ii++) {
+                                               LOG_ERROR("JTAG tap: %s expected %hhu of %hhu: 0x%08x (mfg: 0x%3.3x, part: 0x%4.4x, ver: 0x%1.1x)",
+                                                                 tap->dotted_name,
+                                                                 ii + 1,
+                                                                 tap->expected_ids_cnt,
+                                                                 tap->expected_ids[ii],
+                                                                 EXTRACT_MFG( tap->expected_ids[ii] ),
+                                                                 EXTRACT_PART( tap->expected_ids[ii] ),
+                                                                 EXTRACT_VER( tap->expected_ids[ii] ) );
+                                       }
+
+                                       return ERROR_JTAG_INIT_FAILED;
                                } else {
                                        LOG_INFO("JTAG Tap/device matched");
                                }
                        } else {
 #if 0
-                               LOG_INFO("JTAG TAP ID: 0x%08x - Unknown - please report (A) chipname and (B) idcode to the openocd project", 
+                               LOG_INFO("JTAG TAP ID: 0x%08x - Unknown - please report (A) chipname and (B) idcode to the openocd project",
                                                 tap->idcode);
 #endif
                        }
@@ -1632,7 +1662,7 @@ int jtag_validate_chain(void)
        field.in_handler = NULL;
        field.in_handler_priv = NULL;
 
-       jtag_add_plain_ir_scan(1, &field, TAP_TLR);
+       jtag_add_plain_ir_scan(1, &field, TAP_RESET);
        jtag_execute_queue();
 
        tap = NULL;
@@ -1642,7 +1672,7 @@ int jtag_validate_chain(void)
                if( tap == NULL ){
                        break;
                }
-               
+
 
                if (buf_get_u32(ir_test, chain_pos, 2) != 0x1)
                {
@@ -1697,7 +1727,7 @@ jim_newtap_cmd( Jim_GetOptInfo *goi )
                { .name = NULL                          ,   .value = -1 },
        };
 
-               
+
        pTap = malloc( sizeof(jtag_tap_t) );
        memset( pTap, 0, sizeof(*pTap) );
        if( !pTap ){
@@ -1706,7 +1736,7 @@ jim_newtap_cmd( Jim_GetOptInfo *goi )
        }
        //
        // we expect CHIP + TAP + OPTIONS
-       // 
+       //
        if( goi->argc < 3 ){
                Jim_SetResult_sprintf(goi->interp, "Missing CHIP TAP OPTIONS ....");
                return JIM_ERR;
@@ -1716,17 +1746,17 @@ jim_newtap_cmd( Jim_GetOptInfo *goi )
 
        Jim_GetOpt_String( goi, &cp, NULL );
        pTap->tapname = strdup(cp);
-       
+
        // name + dot + name + null
        x = strlen(pTap->chip) + 1 + strlen(pTap->tapname) + 1;
        cp = malloc( x );
        sprintf( cp, "%s.%s", pTap->chip, pTap->tapname );
        pTap->dotted_name = cp;
 
-       LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params", 
+       LOG_DEBUG("Creating New Tap, Chip: %s, Tap: %s, Dotted: %s, %d params",
                          pTap->chip, pTap->tapname, pTap->dotted_name, goi->argc);
 
-       
+
        // default is enabled
        pTap->enabled = 1;
 
@@ -1737,7 +1767,7 @@ jim_newtap_cmd( Jim_GetOptInfo *goi )
 
        // clear them as we find them
        reqbits = (NTREQ_IRLEN | NTREQ_IRCAPTURE | NTREQ_IRMASK);
-       
+
        while( goi->argc ){
                e = Jim_GetOpt_Nvp( goi, opts, &n );
                if( e != JIM_OK ){
@@ -1753,9 +1783,30 @@ jim_newtap_cmd( Jim_GetOptInfo *goi )
                        pTap->enabled = 0;
                        break;
                case NTAP_OPT_EXPECTED_ID:
+               {
+                       u32 *new_expected_ids;
+
                        e = Jim_GetOpt_Wide( goi, &w );
-                       pTap->expected_id = w;
+                       if( e != JIM_OK) {
+                               Jim_SetResult_sprintf(goi->interp, "option: %s bad parameter", n->name);
+                               return e;
+                       }
+
+                       new_expected_ids = malloc(sizeof(u32) * (pTap->expected_ids_cnt + 1));
+                       if (new_expected_ids == NULL) {
+                               Jim_SetResult_sprintf( goi->interp, "no memory");
+                               return JIM_ERR;
+                       }
+
+                       memcpy(new_expected_ids, pTap->expected_ids, sizeof(u32) * pTap->expected_ids_cnt);
+
+                       new_expected_ids[pTap->expected_ids_cnt] = w;
+
+                       free(pTap->expected_ids);
+                       pTap->expected_ids = new_expected_ids;
+                       pTap->expected_ids_cnt++;
                        break;
+               }
                case NTAP_OPT_IRLEN:
                case NTAP_OPT_IRMASK:
                case NTAP_OPT_IRCAPTURE:
@@ -1766,7 +1817,7 @@ jim_newtap_cmd( Jim_GetOptInfo *goi )
                        }
                        if( (w < 0) || (w > 0xffff) ){
                                // wacky value
-                               Jim_SetResult_sprintf( goi->interp, "option: %s - wacky value: %d (0x%x)", 
+                               Jim_SetResult_sprintf( goi->interp, "option: %s - wacky value: %d (0x%x)",
                                                                           n->name, (int)(w), (int)(w));
                                return JIM_ERR;
                        }
@@ -1789,12 +1840,13 @@ jim_newtap_cmd( Jim_GetOptInfo *goi )
 
        // Did we get all the options?
        if( reqbits ){
-               // no 
+               // no
                Jim_SetResult_sprintf( goi->interp,
-                                                          "newtap: %s missing required parameters", 
+                                                          "newtap: %s missing required parameters",
                                                           pTap->dotted_name);
                // fixme: Tell user what is missing :-(
                // no memory leaks pelase
+               free(((void *)(pTap->expected_ids)));
                free(((void *)(pTap->chip)));
                free(((void *)(pTap->tapname)));
                free(((void *)(pTap->dotted_name)));
@@ -1811,23 +1863,23 @@ jim_newtap_cmd( Jim_GetOptInfo *goi )
                                 pTap->ir_length,
                                 pTap->ir_capture_value );
        buf_set_u32( pTap->expected_mask,
-                                0, 
+                                0,
                                 pTap->ir_length,
                                 pTap->ir_capture_mask );
-       buf_set_ones( pTap->cur_instr, 
+       buf_set_ones( pTap->cur_instr,
                                  pTap->ir_length );
 
        pTap->bypass = 1;
 
 
        jtag_register_event_callback(jtag_reset_callback, pTap );
-       
+
        ppTap = &(jtag_all_taps);
        while( (*ppTap) != NULL ){
                ppTap = &((*ppTap)->next_tap);
        }
        *ppTap = pTap;
-       { 
+       {
                static int n_taps = 0;
                pTap->abs_chain_position = n_taps++;
        }
@@ -1913,8 +1965,8 @@ jim_jtag_command( Jim_Interp *interp, int argc, Jim_Obj *const *argv )
                        Jim_SetResultString( goi.interp, "Too many parameters",-1 );
                        return JIM_ERR;
                }
-               
-               { 
+
+               {
                        jtag_tap_t *t;
                        t = jtag_TapByJimObj( goi.interp, goi.argv[0] );
                        if( t == NULL ){
@@ -2194,7 +2246,7 @@ int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, cha
        //   argv[ 1] = ir capture
        //   argv[ 2] = ir mask
        //   argv[ 3] = not actually used by anything but in the docs
-       
+
        if( argc < 4 ){
                command_print( cmd_ctx, "OLD DEPRECATED SYNTAX: Please use the NEW syntax");
                return ERROR_OK;
@@ -2208,7 +2260,7 @@ int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, cha
        command_print( cmd_ctx, "jtag newtap stm32 cortexm3  ....., thus creating the tap: \"stm32.cortexm3\"");
        command_print( cmd_ctx, "jtag newtap stm32 boundry  ....., and the tap: \"stm32.boundery\"");
        command_print( cmd_ctx, "And then refer to the taps by the dotted name.");
-       
+
 
 
        newargs[0] = Jim_NewStringObj( interp, "jtag", -1   );
@@ -2237,7 +2289,7 @@ int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, cha
                         Jim_GetString( newargs[8], NULL ),
                         Jim_GetString( newargs[9], NULL ) );
 
-               
+
 
        e = jim_jtag_command( interp, 10, newargs );
        if( e != JIM_OK ){
@@ -2256,21 +2308,28 @@ int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char
        command_print(cmd_ctx, "---|--------------------|---------|------------|------------|------|------|------|---------");
 
        while( tap ){
-               u32 expected, expected_mask, cur_instr;
+               u32 expected, expected_mask, cur_instr, ii;
                expected = buf_get_u32(tap->expected, 0, tap->ir_length);
                expected_mask = buf_get_u32(tap->expected_mask, 0, tap->ir_length);
                cur_instr = buf_get_u32(tap->cur_instr, 0, tap->ir_length);
+
                command_print(cmd_ctx,
                                          "%2d | %-18s |    %c    | 0x%08x | 0x%08x | 0x%02x | 0x%02x | 0x%02x | 0x%02x",
                                          tap->abs_chain_position,
                                          tap->dotted_name,
                                          tap->enabled ? 'Y' : 'n',
-                                         tap->idcode, 
-                                         tap->expected_id,
-                                         tap->ir_length, 
-                                         expected, 
-                                         expected_mask, 
+                                         tap->idcode,
+                                         (tap->expected_ids_cnt > 0 ? tap->expected_ids[0] : 0),
+                                         tap->ir_length,
+                                         expected,
+                                         expected_mask,
                                          cur_instr);
+
+               for (ii = 1; ii < tap->expected_ids_cnt; ii++) {
+                       command_print(cmd_ctx, "   |                    |         |            | 0x%08x |      |      |      |         ",
+                                                 tap->expected_ids[ii]);
+               }
+
                tap = tap->next_tap;
        }