DAP600 - SWD -> JTAG Mode Switch Issue

We are seeing an asymmetric SWJ‑DP mode‑switching issue on the SoC:

  • Working: JTAG → SWD (IDCODE and register accesses pass).
  • Failing: SWD → JTAG. The device does not enter Dormant, so JTAG IDCODE and subsequent register accesses fail.

For reference, at IP level this switching works. The IP uses dap_dp_switchmode() whereas the SoC flow uses dap_dp_switchmode1(), which dynamically adapts to the SoC component tree/ROM‑table rather than a fixed pointer. Function definitions are in the attached document.

 

Test sequence (SoC):

 

Failing sequence (SWD → JTAG):

  1. Start in JTAG default mode.
  2. Switch to SWD and perform register accesses → PASS.
  3. Switch back to JTAG → IDCODE read fails and register accesses fail.
  4. Switch back to SWD → IDCODE/register checks PASS.

Passing sequence(JTAG -> SWD):

  1. Start in JTAG and perform accesses → PASS.
  2. Switch to SWD → IDCODE/register PASS.
  3. Switch back to JTAG → IDCODE/register PASS.

Core/IP Passing Sequence:

 

  1. After Reset(nTRST), We are in JTAG mode
    2. Switching from JTAG to SWD mode without any transactions
    3. Accessing Scratchpad register with data 5A5A5A5A(both write and read)
    4. Sending a Handshake to TB by writing fffffff1 from C test and reading same value in TB
    5. After reading fffffff1 going to CX min scenario.
    6. doing Dummy write
    7. Waiting for 10000 SWCLK cycles
    8. Switching from SWD mode TO JTAG mode and reading the idcode. 

uint32_t dap_dp_switchmode(void)

{

   uint32_t     sw_dpidr    = 0;

   uint32_t     jtag_idcode = 0;

 

   if(init_data.default_route_index == 0)

   {

      MSG("[CXDT MSG] dap_dp_switchmode: Switching route to access the DP using Serial Wire:\n");

 

      init_data.default_route_index = 1;

 

      if(SelectMemRoute(&mydp->addr, 0, route_p, MAX_ROUTESTEPS) == 0)

        return FAIL;

 

      if(ReadReg(DP_DPIDR, &sw_dpidr, route_p) == FAIL)

        return FAIL;

 

      MSG("[CXDT MSG] dap_dp_switchmode: Read  SW_DPIDR: 0x%08x", sw_dpidr);

 

      // Check for expected value

      if(sw_dpidr == EXPECTED_SW_DPIDR)

      {

        MSG("\n");

        return PASS;

      }

      else

      {

        MSG_ERROR("Expected SW DPIDR: 0x%08x\n", EXPECTED_SW_DPIDR);

        return FAIL;

      }

   }

   if(init_data.default_route_index == 1)

   {

      MSG("[CXDT MSG] dap_dp_switchmode: Switching route to access the DP using JTAG:\n");

 

      init_data.default_route_index = 0;

 

      if(SelectMemRoute(&mydp->addr, 0, route_p, MAX_ROUTESTEPS) == 0)

        return FAIL;

      if(ReadReg(JTAG_IDCODE, &jtag_idcode, route_p) == FAIL)

        return FAIL;

 

      MSG("[CXDT MSG] dap_dp_switchmode: Read JTAG IDCODE: 0x%08x", jtag_idcode);

 

      // Check for expected value

      if(jtag_idcode == EXPECTED_JTAG_IDCODE)

        {

          MSG("\n");

          return PASS;

        }

      else

        {

          MSG("Expected JTAG IDCODE: 0x%08x\n", EXPECTED_JTAG_IDCODE);

          return FAIL;

        }

   }

}

 

uint32_t dap_dp_switchmode1(void)

{

   uint32_t     sw_dpidr    = 0;

   uint32_t     jtag_idcode = 0;

 

   if(SOC_DATA.default_route_index == 0)

   {

      MSG("[CXDT MSG] dap_dp_switchmode1: Switching route to access the DP using Serial Wire:\n");

 

      SOC_DATA.default_route_index = 1;

 

       for(uint32_t instindex = 0; instindex < *socdata_p->num_components_p; instindex++)

    {

        csinst_t * inst_p = &socdata_p->components_p[instindex];

            if(inst_p->type == DEBUGPORT)

            {

                MSG("\nCXDT MSG:Checking Debug Port: inst[%u] (%s)\n", instindex, inst_p->name);

                if(SelectMemRoute(&inst_p->addr, 0, route_p, MAX_ROUTESTEPS) == 0)

                {

                    MSG_ERROR("TUBE:Could not access DP.\n");

                    return FAIL;

                }

            }

    }

 

      if(ReadReg(DP_DPIDR, &sw_dpidr, route_p) == FAIL)

        return FAIL;

 

      MSG("[CXDT MSG] dap_dp_switchmode1: Read  SW_DPIDR: 0x%08x", sw_dpidr);

 

      // Check for expected value

      if(sw_dpidr == EXPECTED_SW_DPIDR)

      {

        MSG("\n");

        return PASS;

      }

      else

      {

        MSG_ERROR("Expected SW DPIDR: 0x%08x\n", EXPECTED_SW_DPIDR);

        return FAIL;

      }

   }

   if(SOC_DATA.default_route_index == 1)

   {

      MSG("[CXDT MSG] dap_dp_switchmode1: Switching route to access the DP using JTAG:\n");

 

      SOC_DATA.default_route_index = 0;

 

       for(uint32_t instindex = 0; instindex < *socdata_p->num_components_p; instindex++)

      {

        csinst_t * inst_p = &socdata_p->components_p[instindex];

            if(inst_p->type == DEBUGPORT)

            {

                MSG("\nCXDT MSG:Checking Debug Port: inst[%u] (%s)\n", instindex, inst_p->name);

                if(SelectMemRoute(&inst_p->addr, 0, route_p, MAX_ROUTESTEPS) == 0)

                {

                    MSG_ERROR("TUBE:Could not access DP.\n");

                    return FAIL;

                }

            }

    }

      if(ReadReg(JTAG_IDCODE, &jtag_idcode, route_p) == FAIL)

        return FAIL;

 

      MSG("[CXDT MSG] dap_dp_switchmode1: Read JTAG IDCODE: 0x%08x", jtag_idcode);

 

      // Check for expected value

      if(jtag_idcode == EXPECTED_JTAG_IDCODE)

        {

          MSG("\n");

          return PASS;

        }

      else

        {

          MSG("Expected JTAG IDCODE: 0x%08x\n", EXPECTED_JTAG_IDCODE);

          return FAIL;

        }

   }

}