This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM3359: Cortex-A8 does not restart on MPU wakeup when DBGEN is active

Part Number: AM3359
Other Parts Discussed in Thread: CCSTUDIO

Dear all,

I'm currently trying to work out a full cycle for debugging Deep Sleep operation through JTAG. I have come pretty far already but there is a particular oddity I cannot really get around. I'm using OpenOCD, not CCS, because it neatly integrates into my development environment.

Here's the procedure I developed for debugging entry into a Deep Sleep or Standby state:

  1. Prepare system for the target DS state (clocks, wakeup source, etc) and execute WFI
  2. A8 waits in WFI instruction but PRCM doesn't wake up CM3 because ICEPick forces the MPU clock to active
  3. Write 0x2000 into the ICEPick core control register of the A8 core (Register 0x60, IR=ROUTER), this clears the clock request from ICEPick
  4. CM3 wakes up and completes the sleep cycle, A8 MPU power domain is now OFF

Provided the MOSC is still on (e.g. in Standby), PRCM and CONTROL registers can now be inspected and compared to desired values.

Now, wake up the M3 through one of the configure wakekup sources, it prepares the system for resume and eventually wakes up the MPU subsystem and here is where it gets odd. I could not find any hint that my resume function was getting executed and at first I thought I had made some programming mistake, but then I found:

After wakeup, the Cortex-A8 simply doesn't execute any instructions while the internal DBGEN signal is asserted.

Deasserting DBGEN by clearing bit 13 in the ICEPick core control register would immediately cause the A8 to start execution, but re-asserting it would just as consequently into the same strange halting state as before, consequently preventing debugging because the core would not accept commands written to DBGITR in this state.

Poking around in various debug registers I found that DBGDSCR states that the core is halted and the MOE field reads 0b0100, External Debug Request. However the core does not respond to restart requests. I also found that DBGPRCR contains 0x5, so the "HCWR" bit is set which would halt the core on a warm reset. That would make sense and describe the observed behaviour, but contrary to documentation the core doesn't restart if PRCR.HCWR is cleared. It simply stays halted.

The "Integration Input Status" register then gave the next hint, because there the "CTI EDBGRQ" bit it set and points towards the CTI.

Dumping the CTI registers showed a rather odd configuration:

CTI_ENABLE = 0x1
CTI_GATE = 0x0
CTI_INENx = 0xf (0 <= x <= 7)
CTI_OUTENx = 0xf (0 <=x <= 7)
CTI_TRIGOUT_STATUS = 0x1ff
CTI_TRIGIN_STATUS = 0x6f

TRIGOUT and TRIGIN would sometimes have other content but bit EDBGRQ of TRIGOUT would always be set, showing that the CTI indeed asserted an external debug request to the A8. However, trying to clear EDBGRQ by writing to CTI_INTACK did not have any effect. Eventually I found that the following sequence allows the A8 to restart and also allows asserting DBGEN and getting back full debug capabilities:

  1. write 0x0 to CTI_ENABLE
  2. write 0x8 to ICEPick core control register for the Cortex A8 (0x60)
  3. write 0x0 to CTI_ENABLE again (actually, any access to any CTI register is will do, read or write doesn't matter)
  4. write 0x2008 to ICEPick register 0x60

At this point the Cortex-A8 is running and DBGEN is asserted and it would respond normally to debug requests from the debugger. However, between de-asserting and re-asserting of DBGEN, the A8 will have executed quite a large amount of instructions which definitely prevents debugging of the initial wakeup code.

This strikes me as rather odd. It looks like it was attempted to allow debugging of the MPU wakeup, which would explain the value of DBGPRCR, but the CTI configuration found after waking of the MPU power domain looks more like a proper reset was missing.

So the question would be, is this behaviour as intended by the design? How would a proper restart of the MPU look like without loosing the ability to debug after a resume? Note, that without running through the steps 1-6 described above it is _not_ possible to debug the A8 with JTAG until the next Power-On-Reset, even if you never attached the debugger before the system went to DS. Attaching the debugger would simply halt the A8 core but not allow control, a state which is (almost) completely useless for debugging.

Best regards,

Matthias

  • The PM experts have been notified. They will respond here.
  • Hi Matthias,


    Below you can find a link top the Suspend-Resume debug wiki:

    But from what I understand, your question is more related to AM335x Debug management than power management. Have you check the below e2e threads?

    Regards,
    Pavel

  • Also found the below info:

    The control of DBGEN is via the ICEPick non-JTAG control register, which is comprehended in ICEPick router scan sequence. If you are using standard JTAG emulators from Blackhawk or Spectrum Digital, you don't have to worry about.
  • Hi Pavel,

    thanks for the links, I have all this information but my problem goes beyond what was discussed there, I'm afraid.

    Best regards,

    Matthias

  • Matthias,

    I found that all these registers, settings and signals (DBGEN, CTI EDBGRQ, PRCR, DSCR, etc) are documented in the Cortex-A8 ARM documentations:

    infocenter.arm.com/.../DDI0344K_cortex_a8_r3p2_trm.pdf

    Have you check your questions with the ARM support team?

    Regards,
    Pavel
  • Hello Pavel,

    I know all these signals and registers are in the TRM, this is where I got the information from. Would the ARM support team be able to help with silicon integration issues? I suspect it's something like this rather than a problem with the documentation.

    Regards
    Matthias
  • Matthias Welwarsky said:
    Dumping the CTI registers showed a rather odd configuration

    That's rather an understatement, "nuts" is more the word that comes to mind.

    Matthias Welwarsky said:
    the CTI configuration found after waking of the MPU power domain looks more like a proper reset was missing.

    I agree.

    This is not a question for ARM support, only TI's factory team might be able to verify whether an incorrect reset is used for the CTI (e.g. one only asserted at POR and not when the MPU domain is powered off during suspend), and whether there's any alternative way to ensure it gets properly reset.

  • Hello Pavel,

    just one more bit of information: If I force the CTI to release the external debug request through the integration test registers by writing '0' into ITTRIGOUT, the A8 immediately restarts. So it's pretty obvious that the only factor keeping the A8 core halted is the CTI.

  • Hi Matthias,

    Most debug subsystem logic is not affected by warm reset. This allows you to maintain any debug sessions throughout a warm reset event.

    For more information regarding DebugSS (CTI is part of that Subsystem) reset management refer to the AM335x TRM:

    - Table 8-25. Reset Sources - see "Reset source blockable by emulation" and "Resets test and emulation logic"
    - 8.1.7.4.4 Test Reset (TRSTz)
    - 8.1.7.7 Reset Priority
    - 8.1.7.8 Trace Functionality Across Reset
    - 8.1.13.3.3 PM_WKUP_PWRSTST Register
    - 8.1.13.4.3 RM_MPU_RSTST Register
    - 8.1.13.5.3 PRM_RSTST Register

    You can also check with the CCStudio team in the CCStudio e2e forum, they can advice also regarding JTAG related questions.

    Regards,
    Pavel
  • Hello Pavel,

    thanks for the pointers. The TRSTz could prove interesting, but Table 8-25 contradicts what is written in 8.1.7.4.4. The prose in this chapter says TRSTz resets the debug logic, but the table has a N in that cell. Could you clarify? Also, CTI might be unaffected by a reset of the debug logic. Could you clarify this?

    Also, I think the debug logic is in the MPU power domain, i.e. it will need a reset when the MPU is woken up after a DS transition, or the debug logic might come back up with a completely corrupt configuration.

    Best regards,
    Matthias

  • Pavel,

    I've checked if asserting TRSTz can be useful, but TRST also resets ICEPick, which releases DBGEN, which is exactly _not_ what I want. Also, CTI is completely unimpressed by TRSTz.

    BR,
    Matthias
  • Just FYI, I've found a more condensed sequence to restore the A8 and have updated my original post.
  • Hi Matthias,

    The CTI behavior is odd, and I will need to look in that a little more. That said, the behavior that you have described may also be the result of ICECrusher interraction--I will need additional datapoints to rule that out. Two requests:

    1] After the problem has occurred, and before any register updates to ICEPick or CTI are made, can you please read and report the value of the following ICECrusher registers:

    0x4B14_3000
    0x4B14_3004
    0x4B14_3008
    0x4B14_3010
    0x4B14_3014
    0x4B14_3020
    0x4B14_30F8
    0x4B14_30FC


    2] Just before you start the sequence of entry into deep sleep, read and report the values of both the ICECrusher registers listed above and the CTI registers

    thanks,
    --Jason Peck
  • Hi Jason,

    thanks for your response. I will make that specific test when I have the target connected again. For now I can share the following dump I did in the course of the investigation already:

    Normal Operation, A8 not in WFI
    version : (0x80003000): 0x00113d62
    config : (0x80003004): 0x20c04000
    debug_csr : (0x80003008): 0x00018000
    trigger : (0x80003010): 0x200e00e0
    reset_csr : (0x80003014): 0x40000018
    intr_csr : (0x80003020): 0x38000000
    test : (0x8000302c): 0x00000002
    oslock : (0x800030f8): 0x00000000
    dcon : (0x800030fc): 0x20700000

    A8 held after wakeup:
    version : (0x80003000): 0x00113d62
    config : (0x80003004): 0x20c04000
    debug_csr : (0x80003008): 0x00038000
    trigger : (0x80003010): 0x200e00e0
    reset_csr : (0x80003014): 0x40000018
    intr_csr : (0x80003020): 0x38000000
    test : (0x8000302c): 0x00000002
    oslock : (0x800030f8): 0x00000000
    dcon : (0x800030fc): 0x20700000

    Unfortunately, ICECrusher is basically undocumented as far as search engines can find out.

    Best regards,
    Matthias
  • By the way, if you look at my previous posts, I was able to "unblock" the A8 by clearing the TRIGOUT signals of the CTI through the integration test registers. Nothing else, just enabling integration mode and writing 0 to ITTRIGOUT.
  • Matthias,

    From the addresses you provided, I take it that you are using the DAP's APB-AP to initiate the accesses. The addresses that I provided for the ICECrusher registers are the addresses of the same registers as viewed from the SOC memory map (e.g. via DAP AHB-AP) so no need to run that particular experiment.

    It would still be useful to see the CTI register values before you start the deep-sleep sequencing and after you wakeup.

    thanks,
    --Jason Peck
  • Hi Jason,

    here's the dump of the CTI registers around suspend:

    Before Suspend (A8 already in WFI but clock forced on by ICEPick)

         CTR (0x0000) 0x00000000
        GATE (0x0140) 0x0000000f
       INEN0 (0x0020) 0x00000000
       INEN1 (0x0024) 0x00000000
       INEN2 (0x0028) 0x00000000
       INEN3 (0x002c) 0x00000000
       INEN4 (0x0030) 0x00000000
       INEN5 (0x0034) 0x00000000
       INEN6 (0x0038) 0x00000000
       INEN7 (0x003c) 0x00000000
      OUTEN0 (0x00a0) 0x00000000
      OUTEN1 (0x00a4) 0x00000000
      OUTEN2 (0x00a8) 0x00000000
      OUTEN3 (0x00ac) 0x00000000
      OUTEN4 (0x00b0) 0x00000000
      OUTEN5 (0x00b4) 0x00000000
      OUTEN6 (0x00b8) 0x00000000
      OUTEN7 (0x00bc) 0x00000000
        TRIN (0x0130) 0x00000020
       TROUT (0x0134) 0x00000000
        CHIN (0x0138) 0x00000000
       CHOUT (0x013c) 0x00000000
      APPSET (0x0014) 0x00000000
      APPCLR (0x0018) 0x00000000

    On Resume, MPU module woken up
         CTR (0x0000) 0x00000001
        GATE (0x0140) 0x00000000
       INEN0 (0x0020) 0x0000000f
       INEN1 (0x0024) 0x0000000f
       INEN2 (0x0028) 0x0000000f
       INEN3 (0x002c) 0x0000000f
       INEN4 (0x0030) 0x0000000f
       INEN5 (0x0034) 0x0000000f
       INEN6 (0x0038) 0x0000000f
       INEN7 (0x003c) 0x0000000f
      OUTEN0 (0x00a0) 0x0000000f
      OUTEN1 (0x00a4) 0x0000000f
      OUTEN2 (0x00a8) 0x0000000f
      OUTEN3 (0x00ac) 0x0000000f
      OUTEN4 (0x00b0) 0x0000000f
      OUTEN5 (0x00b4) 0x0000000f
      OUTEN6 (0x00b8) 0x0000000f
      OUTEN7 (0x00bc) 0x0000000f
        TRIN (0x0130) 0x00000061
       TROUT (0x0134) 0x000001ff
        CHIN (0x0138) 0x00000000
       CHOUT (0x013c) 0x00000000
      APPSET (0x0014) 0x0000000f
      APPCLR (0x0018) 0x00000000


    However, meanwhile I have found out what is happening and maybe you could confirm:

    Basically, when the MPU PD is powered up on resume, the CTI module logic comes up with all writeable bits in the configuration set to 1. That is visible in the dump and I've checked looking at a few more registers. Especially, ITCTRL is affected, too, and so the CTI is in Integration Test Mode when it comes up. At the same time, ITTRIGOUT is also preset with all-ones, causing all outgoing triggers to be asserted. In test mode, all outgoing signals only reflect the content of the integration test registers, which explains nicely why I was not able to influence the CTI by ACKing the halt trigger or why disabling it had no effect.

    That condenses my resume sequence to

    1. write 0 to 0x80002f00
    2. write 0 to 0x80002000

    That immediately unlocks the A8. What I believe is that in the Deepsleep resume, the CTI logic is not reset together with the MPU and so it comes up with an "all ones" configuration. Why all-ones is beyond my knowledge, it could be random bits as well with other chips or in other environments. That would be bad as it would make restoration of functionality much more complicated.


    Best regards,

    Matthias

  • Matthias,

    There is a retention-related issue with the CTI registers. That is why the register values are corrupted after exiting DeepSleep.

    As you have observed, when both EDBGRQ (from CTI) and DBGEN (from ICEPick) are =1 the A8 will enter the debug suspended state.

    To workaround this issue in your debugger, I suggest that, after exiting DeepSleep, the CTI regsiters be restored to their pre-DeepSleep state (values will vary according to how your debugger is setup to use the CTI). If DBGEN=1, this restore step would take place after exiting DeepSleep and after the CPU has already halted  (i.e. due to DBGEN=1 and EDBGRQ=1) 

    One other note, when you do not have an active debug session, I highly recommend that DBGEN be cleared so that your application's execution is not affected by this issue.


    --Jason Peck

  • Hello Jason,

    Thanks for your input. That procedure would not be difficult to implement. Saving and restoring the CTI module makes sense, though in my specific configuration the CTI is not at all used and it will be enough to just disable it.

    I'm guessing though that it would make even more sense to save and restore the debug logic of the A8 core, too. Break and Watchpoint registers and everything connected to debug and run control (DRCR, DSCR, PRCR).

    BR,
    Matthias