Programing the CW308 with target LPC55S69

Hello,

I am trying to use the target LPC55S6X with a Arm Cortex-M33 on the ChipWhisperer Pro UFO Board (CW308_LPC55S6X).

When using the jupyter notebook interface, we usually do something like:

prog = cw.programmers.STM32FProgrammer # or XMEGAProgrammer, etc.
cw.program_target(scope, prog, firmware_path)

But for the LPC55S6X, I do not see which programmer I should use among those available. Is there any tutorial with this target board that I missed?

Besides, I use the same UFO board configuration as the one I used for the STM32F3 target (which is detailed below), as I did not find information regarding this target. Please let me know if anything is incorrect.

J3           : HS2/OUT
J1-VREF      : J1-3.3V (left)
EXT-DC SWITCH (bottom-left switch) : AUTO S1 (left)
J14          : FILT / FLIT_LP-FILT-HP : left
3.3V SRC     : J1/CW (up)
VADJ SRC     : 5V (down)
1.2V LDO SRC : J1/CW (right)
1.8V LDO SRC : J1/CW (right)
2.5V LDO SRC : EXT-DC (left)
3.3V LDO SRC : EXT-DC (left)
5V LDO SRC   : EXT-DC (left)

Thanks,
Quentin

Hi Quentin,

You’ll need to use an external JTAG programmer for that target. I haven’t programmed that target personally, but anything that works with OpenOCD should be able to do it.

As for board setup, it should be pretty similar to the F3. The only major difference is that this target requires a 1.2V VCC, meaning you’ll need the 1.2V LED to be illuminated on the CW308.

Alex

Hi Alex,

Thank you for your reply.
I am not familiar with JTAG programming. I have looked around a bit, and still have some questions. From what I understand, the steps are following (using mainly this page):

  1. On the CW308, use jumper wires to connect the following pins:
    J5 Pin 12 (SCK) → J8 Pin 6 (J_TCK)
    J5 Pin 18 (PDID) → J8 Pin 5 (J_TMS)
    J5 Pin 13 (MISO) → J8 Pin 4 (J_TDO)
    J5 Pin 14 (MOSI) → J8 Pin 3 (J_TDI)
    (source: here)

Question: the tutorial states that these connections are for the STM32F3 board; are they the same for any board using JTAG, in particular the LPC55S6x?

  1. Run the following commands:
import chipwhisperer as cw
scope = cw.scope()
scope.enable_MPSSE(1)
  1. Create a file myconfigfile.cfg with the following content:
source [/path/to/cw_openocd.cfg]
transport select swd
ftdi vid_pid 0x2b3e 0xace3
source [target/lpc55s6x.cfg]

Question: is 0xace3 the correct ProductID to put in that file? (I found it here)

Question: where can I get the file lpc55s6x.cfg? I did not find it neither in the chipwhisperer.git nor in the openocd provided files.

  1. Run openocd -f myconfigfile.cfg

  2. Create a file load_firmware.cfg with the following content:

init
targets
halt
flash write_image erase /path/to/fw.elf
flash verify_image /path/to/fw.elf
reset run
shutdown
  1. Run openocd -f load_firmware.cfg

  2. After loading the firmware, get the scope and target again and force one reset cycle with the following commands:

   scope = cw.scope()
   scope.default_setup()
   target = cw.target(scope)

   scope.io.nrst = "low"
   time.sleep(0.7)
   scope.io.nrst = "high_z"
  1. Run captures as usual

Is that globally ok?

Thanks again,
Quentin

I’ll have to look into this. It looks like OpenOCD support for this target is currently in development, and I’ve seen PyOCD recommended as well, so there might be a few different options.

Our JTAG implementation might not work with this target - it’s just a bitbanged emulation of an FTDI chip, so lots of things aren’t really right with regards to frequency or meeting the requirements for buffers/commands. You may need a third party JTAG programmer.

BTW, 0xACE3 is correct for the Pro.

Hello Alex,

Do you have any update on this?
Do you know if there is a documented way of programming this target board in the current project state, or if someone managed to do it recently?

Thank you,
Quentin

Sorry, haven’t had a chance to look at this yet, I’ll try to take a look this week.

Sorry about the delay on this. It seems like OpenOCD doesn’t support this by default, but there is a proposed patch that does: https://review.openocd.org/c/openocd/+/8189. I’m still playing around trying to get this to work with a tigard GitHub - tigard-tools/tigard: An FTDI FT2232H-based multi-protocol tool for hardware hacking. I’m currently able to communicate over SWD, but there’s some flash configuration that needs to be done, so I’m currently looking in to that.

PyOCD also seems promising, but I haven’t had any luck with that yet: https://pyocd.io/

Thanks Alex. I will try the solution with the OpenOCD patch as soon as I can. I will update this thread once I have.

BTW I wouldn’t expect the debugging implementation in ChipWhisperer to work for this. You’ll almost certainly need an external debugger.

Hello Alex,

I have just tried to program the target board using the OpenOCD patch. However, when running the ‘openocd -f lpc_configfile.cfg’, I get the following output and warning:

$ openocd -f lpc_config_file.cfg 
Open On-Chip Debugger 0.12.0+dev-00634-g23c33e1d3-dirty (2024-10-10-15:03)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : FTDI SWD mode enabled
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 1000 kHz
Warn : Haven't made progress in mpsse_flush() for 2002ms.
Warn : Haven't made progress in mpsse_flush() for 4004ms.
Warn : Haven't made progress in mpsse_flush() for 8004ms.
Warn : Haven't made progress in mpsse_flush() for 16002ms.
Warn : Haven't made progress in mpsse_flush() for 32005ms.
Warn : Haven't made progress in mpsse_flush() for 64009ms.

And so on…

Is it related to the remark you made in your last post about the (external) debugger? I did not understand what it meant actually…

Incidentally, do you know how we can stop this openocd command properly? Ctrl+C doesn’t work, neither does kill (without -9), and I am afraid to make things go wrong if I brutally disconnect the chip/force kill the command…

What was meant was that you’ll need a commercial programming tool such as Segger J-Link (which we have confirmed to work).

We’ve updated the RTFM page to reflect this.

What was meant was that you’ll need a commercial programming tool such as Segger J-Link (which we have confirmed to work).

Ok, thank you. It’s just that from Alex’s response, I more or less understood that using the OpenOCD patch he mentioned could be sufficient to have it work without a third party tool.

The LPC55S69’s Boot ROM has a security feature that blocks debug access during early boot stages . Specifically:

  1. On reset, the Boot ROM executes first - The CPU starts running code from ROM at 0x13000000

  2. The Debug Access Port (DAP) is disabled - The MEM-AP (Memory Access Port) that allows debuggers to read/write memory is not accessible immediately after reset

  3. Standard debug methods fail - Commands like reset halt don’t work because the debug interface isn’t ready

  4. The chip appears “locked” - Even though SWD is physically connected, the debugger can’t control the CPU

This is intentional design by NXP - the Boot ROM must complete certain initializations before debug access is allowed . However, when the flash is blank or contains invalid firmware, the Boot ROM never reaches the point where it enables debug access.

Below is lpc55xx_unlock procedure to force-enable debug access by directly manipulating the Debug Mailbox (AP2).

# lpc55xx-unlock.cfg
proc lpc55xx_unlock { } {
    global _CHIPNAME
    
    echo "Starting LPC55S69 unlock sequence..."
    
    # AP2 is the Debug Mailbox (DM)
    set dm_ap 2
    
    # DM register offsets
    set DM_CSW 0x00
    set DM_REQUEST 0x04
    set DM_RETURN 0x08
    
    # DM command values
    set DM_CSW_RESYNCH_REQ_MASK 0x01
    set DM_CSW_CHIP_RESET_REQ_MASK 0x20
    set DM_START_DBG_SESSION 7
    
    # Step 1: Set RESYNCH_REQ and CHIP_RESET_REQ in DM.CSW
    echo "Step 1: Requesting chip reset via debug mailbox..."
    set cmd [expr {$DM_CSW_RESYNCH_REQ_MASK | $DM_CSW_CHIP_RESET_REQ_MASK}]
    $_CHIPNAME.dap apreg $dm_ap $DM_CSW $cmd
    sleep 200
    
    # Step 2: Verify CSW cleared (reset completed)
    set csw [$_CHIPNAME.dap apreg $dm_ap $DM_CSW]
    if {$csw != 0} {
        echo "Warning: DM.CSW not cleared after reset: $csw"
    }
    
    # Step 3: Write debug unlock request
    echo "Step 3: Sending debug unlock request..."
    $_CHIPNAME.dap apreg $dm_ap $DM_REQUEST $DM_START_DBG_SESSION
    sleep 100
    
    # Step 4: Read return status
    set status [$_CHIPNAME.dap apreg $dm_ap $DM_RETURN]
    set status_low [expr {$status & 0xFFFF}]
    if {$status_low == 0} {
        echo "Unlock successful!"
    } else {
        echo "Unlock returned error: 0x$status_low"
        return -error "Unlock failed"
    }
    
    # Step 5: Now examine the CPU
    echo "Examining CPU..."
    $_CHIPNAME.cpu arp_examine
}

# Execute the sequence
init
lpc55xx_unlock
halt

The steps this procedure does:

1. Write to DM_CSW with reset bits - Forces a chip reset without losing debug connection.

2. Check DM_CSW cleared - Verifies reset completed.

3. Write 7 to DM_REQUEST - Sends "start debug session" command to Boot ROM.

4. Read DM_RETURN - Checks if Boot ROM accepted the request (0 = success).

5. arp_examine - Re-examines CPU, now with full debug access.

Without lpc55xx_unlock I get:

bash-3.2$ ../src/openocd -f interface/jlink.cfg -c "transport select swd" -f target/lpc55xx.cfg
Open On-Chip Debugger 0.12.0+dev-02431-gd73afae35 (2026-03-19-15:48)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : J-Link V11 compiled Jan 30 2023 11:22:20
Info : Hardware version: 11.00
Info : VTarget = 3.303 V
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x6ba02477
Error: [lpc55xx.cpu] Could not find MEM-AP to control the core
Error: [lpc55xx.cpu] Examination failed
Warn : target lpc55xx.cpu examination failed
Info : [lpc55xx.cpu] starting gdb server on 3333
Info : Listening on port 3333 for gdb connections

With extra functionality:

bash-3.2$ ../src/openocd -f interface/jlink.cfg -c "transport select swd" -f target/lpc55xx.cfg -f lpc55xx-unlock.cfg
Open On-Chip Debugger 0.12.0+dev-02431-gd73afae35 (2026-03-19-15:48)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : J-Link V11 compiled Jan 30 2023 11:22:20
Info : Hardware version: 11.00
Info : VTarget = 3.305 V
Info : clock speed 1000 kHz
Info : SWD DPIDR 0x6ba02477
Error: [lpc55xx.cpu] Could not find MEM-AP to control the core
Error: [lpc55xx.cpu] Examination failed
Warn : target lpc55xx.cpu examination failed
Info : [lpc55xx.cpu] starting gdb server on 3333
Info : Listening on port 3333 for gdb connections
Starting LPC55S69 unlock sequence...
Step 1: Requesting chip reset via debug mailbox...
Step 3: Sending debug unlock request...
Unlock successful!
Examining CPU...
Info : [lpc55xx.cpu] Cortex-M33 r0p3 processor detected
Info : [lpc55xx.cpu] target has 8 breakpoints, 4 watchpoints
Warn : [lpc55xx.cpu] target was in unknown state when halt was requested
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections

Finally, connect to the OpenOCD via telnet and write the flash by

flash write_image erase /path/to/firmware.elf