RP2350 XIP Cache not re-enabled after flash loader

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • RP2350 XIP Cache not re-enabled after flash loader

      J-Link Version info:

      Source Code

      1. SEGGER J-Link Commander V8.24 (Compiled Mar 26 2025 15:34:49)
      2. DLL version V8.24, compiled Mar 26 2025 15:33:55
      3. Connecting to J-Link via USB...O.K.
      4. Firmware: J-Link V11 compiled Feb 20 2025 16:24:17
      5. Hardware version: V11.00

      Hardware used: Raspberry Pi Pico 2 (ARM mode)

      I noticed a drastic loss of performance when debugging with J-Link that went away if I simply reset the MCU after flashing and attached to the running program.
      I eventually narrowed it down to the XIP Cache being disabled and I think the following shows the problem using just J-Link Commander.

      Given the following JLinkScript:

      C Source Code: testxip.jlinkscript

      1. __constant U32 XIP_CTRL = 0x400C8000;
      2. void XIPCheck(void)
      3. {
      4. U32 value;
      5. value = JLINK_MEM_ReadU32(XIP_CTRL);
      6. JLINK_SYS_Report1("XIP_CTRL = ", value);
      7. }
      8. int HandleBeforeFlashProg(void) { XIPCheck(); return 0; }
      9. int HandleAfterFlashProg(void) { XIPCheck(); return 0; }
      10. int AfterResetTarget(void) { XIPCheck(); return 0; }
      Display All
      Connecting to the board after powering it up, you can see this register isn't reset to the power on default after the flash program has finished:

      Source Code

      1. Type "connect" to establish a target connection, '?' for help
      2. J-Link>con
      3. Please specify device / core. <Default>: RP2350_M33_0
      4. Type '?' for selection dialog
      5. Device>
      6. Please specify target interface:
      7. J) JTAG (Default)
      8. S) SWD
      9. T) cJTAG
      10. TIF>s
      11. Specify target interface speed [kHz]. <Default>: 4000 kHz
      12. Speed>
      13. Device "RP2350_M33_0" selected.
      14. Connecting to target via SWD
      15. ConfigTargetSettings() start
      16. ConfigTargetSettings() end - Took 44us
      17. InitTarget() start
      18. InitTarget() end - Took 12.6ms
      19. Found SW-DP with ID 0x4C013477
      20. DPIDR: 0x4C013477
      21. CoreSight SoC-600 or later (DPv3 detected)
      22. AP map detection skipped. User specified AP map and usage.
      23. AP[0]: Core found
      24. AP[0]: AHB-AP ROM base: 0xE00FF000
      25. CPUID register: 0x411FD210. Implementer code: 0x41 (ARM)
      26. Feature set: Mainline
      27. Cache: No cache
      28. Found Cortex-M33 r1p0, Little endian.
      29. FPUnit: 8 code (BP) slots and 0 literal slots
      30. Security extension: implemented
      31. Secure debug: enabled
      32. CoreSight components:
      33. ROMTbl[0] @ E00FF000
      34. [0][0]: E000E000 CID B105900D PID 000BBD21 DEVARCH 47702A04 DEVTYPE 00 Cortex-M33
      35. [0][1]: E0001000 CID B105900D PID 000BBD21 DEVARCH 47701A02 DEVTYPE 00 DWT
      36. [0][2]: E0002000 CID B105900D PID 000BBD21 DEVARCH 47701A03 DEVTYPE 00 FPB
      37. [0][3]: E0000000 CID B105900D PID 000BBD21 DEVARCH 47701A01 DEVTYPE 43 ITM
      38. [0][5]: E0041000 CID B105900D PID 002BBD21 DEVARCH 47724A13 DEVTYPE 13 ETM
      39. [0][6]: E0042000 CID B105900D PID 000BBD21 DEVARCH 47701A14 DEVTYPE 14 CSS600-CTI
      40. Memory zones:
      41. Zone: "Default" Description: Default access mode
      42. Cortex-M33 identified.
      43. J-Link>reset
      44. Reset delay: 0 ms
      45. Reset type: NORMAL (https://wiki.segger.com/J-Link_Reset_Strategies)
      46. Reset: ARMv8M core with Security Extension enabled detected. Switch to secure domain.
      47. Reset: Halt core after reset via DEMCR.VC_CORERESET.
      48. Reset: Reset device via AIRCR.SYSRESETREQ.
      49. AfterResetTarget() start
      50. XIP_CTRL = 0x00000083
      51. AfterResetTarget() end - Took 2.04ms
      52. J-Link>erase
      53. No address range specified, 'Erase Chip' will be executed
      54. 'erase': Performing implicit reset & halt of MCU.
      55. Reset type: NORMAL (https://wiki.segger.com/J-Link_Reset_Strategies)
      56. Reset: ARMv8M core with Security Extension enabled detected. Switch to secure domain.
      57. Reset: Halt core after reset via DEMCR.VC_CORERESET.
      58. Reset: Reset device via AIRCR.SYSRESETREQ.
      59. AfterResetTarget() start
      60. XIP_CTRL = 0x00000083
      61. AfterResetTarget() end - Took 2.55ms
      62. Erasing device...
      63. HandleBeforeFlashProg() start
      64. XIP_CTRL = 0x00000083
      65. HandleBeforeFlashProg() end - Took 2.80ms
      66. J-Link: Flash download: Total time needed: 1.752s (Prepare: 0.173s, Compare: 0.000s, Erase: 1.486s, Program: 0.000s, Verify: 0.000s, Restore: 0.092s)
      67. HandleAfterFlashProg() start
      68. XIP_CTRL = 0x00000000
      69. HandleAfterFlashProg() end - Took 2.72ms
      70. Erasing done.
      Display All
      Here's where the SDK defines the reset value for this register:

      C Source Code: pico-sdk\src\rp2350\hardware_regs\include\hardware\regs\xip.h

      1. // Register : XIP_CTRL
      2. // Description : Cache control register. Read-only from a Non-secure context.
      3. #define XIP_CTRL_OFFSET _u(0x00000000)
      4. #define XIP_CTRL_BITS _u(0x00000ffb)
      5. #define XIP_CTRL_RESET _u(0x00000083)
      See also section 4.4.5 of the RP2350 datasheet.

      I did notice a few other peripheral registers didn't match their power on defaults.
      Apart from the XIP Cache control register, the differences seem benign but I'm listing them for completeness.
      Peripheral
      Register
      Address
      Value after power on
      Value after download
      Notes
      PPB
      FP_CTRL
      0xE0002000
      0x10000080
      0x10000081
      Enable flag
      OTP
      INTR
      0x40120164
      0x00000000
      0x00000010
      Inconsistent repro
      POWMAN
      STATE
      0x40100038
      0x00000000
      0x00000100
      Req ignored
      POWMAN
      INTR
      0x401000E0
      0x00000000
      0x00000004
      Req ignored
      WATCHDOG
      CTRL
      0x400D8000
      0x07000000
      0x07FFFFFF
      Timer value, harmless?
      XIP_CTRL
      CTRL
      0x400C8000
      0x00000083
      0x00000000
      See above



      These were found by running a simple "while(1);" firmware, dumping all the registers with Ozone, comparing and filtering out the non-deterministic registers.

      Please let me know if you need more information!