How to properly set the upload port on macOS LPC1768 Board & ULINK-ME

Compiling works fine, uploading doesn’t.
It’s the same error as before.
Thank you very much for your time and effort :slight_smile:

I was wondering, would this whole stuff work better with another tool instead of the ulink-me, for example the black magic probe?

The tool says the verify failed, but not the program. The board might still run the correct firmware regardless. Can you check with the LED pins above to be sure?

According to the board’s JSON file posted above it does support Black magic probe and also a Jlink. You would have to set upload_protocol = jlink or = blackmagic. Though the debugger you have which is CMSIS-DAP compatible should really work too (as we saw it does program correctly, just the source binary is wrong). And maybe these programmers will also fail the verify step if the checksum is wrong.

These are the pins I have on the board:

The checksum still fails.

Ok so what if you take this code, use P1_28 instead of LED1, recompile and manually re-upload. Does the LED blink? (Maybe press the reset button after upload, too)

Ah, better try these files first.

platformio.ini

[env:lpc1768]
platform = nxplpc
board = lpc1768
framework = mbed
build_flags = -D MCB1700
extra_scripts = extra_script.py
upload_protocol = custom
upload_flags =
    -f
    scripts/interface/cmsis-dap.cfg
    -f
    scripts/board/mcb1700.cfg

(extra define comes from here so that the board has the correct clock PLL settings…)

extra_script.py (must be at the same level at the platformio.ini)

Import("env", "projenv")

import sys
import struct
import intelhex
import time


# from https://github.com/basilfx/lpc_checksum/blob/master/lpc_checksum.py by Bas Stottelaar
BLOCK_START = 0
BLOCK_COUNT = 7
BLOCK_SIZE = 4
BLOCK_TOTAL = (BLOCK_COUNT * BLOCK_SIZE)

def checksum(filename, format="bin", read_only=False):
    """
    Calculate the checksum of a given binary image. The checksum is written
    back to the file and is returned. When read_only is set to True, the file
    will not be changed.
    filename  -- firmware file to checksum
    format    -- input file format (bin or hex, default bin)
    read_only -- whether to write checksum back to the file (default False)
    """

    # Open the firmware file.
    handle = intelhex.IntelHex()
    handle.loadfile(filename, format=format)

    # Read the data blocks used for checksum calculation.
    block = bytearray(handle.gets(BLOCK_START, BLOCK_TOTAL))

    if len(block) != BLOCK_TOTAL:
        raise Exception("Could not read the required number of bytes.")

    # Compute the checksum value.
    result = 0

    for i in range(BLOCK_COUNT):
        value, = struct.unpack_from("I", block, i * BLOCK_SIZE)
        result = (result + value) % 0xFFFFFFFF

    result = ((~result) + 1) & 0xFFFFFFFF

    # Write checksum back to the file.
    if not read_only:
        handle.puts(BLOCK_START + BLOCK_TOTAL, struct.pack("I", result))
        handle.tofile(filename, format=format)

    # Done
    return result

def post_bin_file(source, target, env):
    print("==== Post building BIN file ====")
    target_firmware_bin = str(target[0])
    #print(source, target, env)
    print("Firmware path: %s" % target_firmware_bin)
    ret_check = checksum(target_firmware_bin)
    print("Wrote checksum 0x%x into binary." % ret_check)
    

# fix checksum
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", post_bin_file)
# fix openocd target 
platform = env.PioPlatform()
env.Prepend(
    UPLOADERFLAGS=["-s", platform.get_package_dir("tool-openocd") or ""]
)
env.Append(
    UPLOADERFLAGS=["-c", "program {{$SOURCE}} verify reset; shutdown"]
)
env.Replace(
    UPLOADER="openocd",
    UPLOADCMD="$UPLOADER $UPLOADERFLAGS"
)

(If you’re having problems with “firmware file not found” then remove one set of {} again in the UPLOADERFLAGS line, but this is what the docs said…)

and src\main.cpp

#include "mbed.h"

DigitalOut myled(P1_28);

int main() {
    while(1) {
        myled = 1;
        wait(1);
        myled = 0;
        wait(1);
    }
}

If all goes well uploading (pio run -t upload -v) should output something like that in the end

post_bin_file([".pio\build\lpc1768\firmware.bin"], [".pio\build\lpc1768\firmware.elf"])
==== Post building BIN file ====
Firmware path: .pio\build\lpc1768\firmware.bin
Wrote checksum 0xefff3172 into binary.
<lambda>(["upload"], [".pio\build\lpc1768\firmware.bin"])
AVAILABLE: blackmagic, cmsis-dap, custom, jlink, mbed
CURRENT: upload_protocol = custom
openocd -s C:\Users\Maxi\.platformio\packages\tool-openocd -f scripts/interface/cmsis-dap.cfg -f scripts/board/mcb1700.cfg -c "program {{.pio\build\lpc1768\firmware.bin}} verify reset; shutdown"
xPack OpenOCD, 32-bit Open On-Chip Debugger 0.10.0+dev (2019-07-17-07:34)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
[...] more stuff here

using this platformio.ini:

[env:lpc1768]
platform = nxplpc
board = lpc1768
framework = mbed
build_flags = -D MCB1700
extra_scripts = extra_script.py
upload_protocol = custom
upload_flags =
    -f
    scripts/interface/cmsis-dap.cfg
    -f
    scripts/board/mcb1700.cfg
debug_tool = custom
debug_server =
    openocd
    -f
    ../scripts/interface/cmsis-dap.cfg
    -f
    ../scripts/board/mcb1700.cfg

This python extra script, in the same directory as the platformio.ini:

Import("env", "projenv")

import sys
import struct
import intelhex
import time


# from https://github.com/basilfx/lpc_checksum/blob/master/lpc_checksum.py by Bas Stottelaar
BLOCK_START = 0
BLOCK_COUNT = 7
BLOCK_SIZE = 4
BLOCK_TOTAL = (BLOCK_COUNT * BLOCK_SIZE)

def checksum(filename, format="bin", read_only=False):
    """
    Calculate the checksum of a given binary image. The checksum is written
    back to the file and is returned. When read_only is set to True, the file
    will not be changed.
    filename  -- firmware file to checksum
    format    -- input file format (bin or hex, default bin)
    read_only -- whether to write checksum back to the file (default False)
    """

    # Open the firmware file.
    handle = intelhex.IntelHex()
    handle.loadfile(filename, format=format)

    # Read the data blocks used for checksum calculation.
    block = bytearray(handle.gets(BLOCK_START, BLOCK_TOTAL))

    if len(block) != BLOCK_TOTAL:
        raise Exception("Could not read the required number of bytes.")

    # Compute the checksum value.
    result = 0

    for i in range(BLOCK_COUNT):
        value, = struct.unpack_from("I", block, i * BLOCK_SIZE)
        result = (result + value) % 0xFFFFFFFF

    result = ((~result) + 1) & 0xFFFFFFFF

    # Write checksum back to the file.
    if not read_only:
        handle.puts(BLOCK_START + BLOCK_TOTAL, struct.pack("I", result))
        handle.tofile(filename, format=format)

    # Done
    return result

def post_bin_file(source, target, env):
    print("==== Post building BIN file ====")
    target_firmware_bin = str(target[0])
    #print(source, target, env)
    print("Firmware path: %s" % target_firmware_bin)
    ret_check = checksum(target_firmware_bin)
    print("Wrote checksum 0x%x into binary." % ret_check)
    

# fix checksum
env.AddPostAction("$BUILD_DIR/${PROGNAME}.bin", post_bin_file)
# fix openocd target 
platform = env.PioPlatform()
env.Prepend(
    UPLOADERFLAGS=["-s", platform.get_package_dir("tool-openocd") or ""]
)
env.Append(
    UPLOADERFLAGS=["-c", "program {$SOURCE} verify reset; shutdown"]
)
env.Replace(
    UPLOADER="openocd",
    UPLOADCMD="$UPLOADER $UPLOADERFLAGS"
)

This Blinky example program:

#include "mbed.h"

DigitalOut myled(P1_28);

int main() {
    while(1) {
        myled = 1;
        wait(1);
        myled = 0;
        wait(1);
    }
}

Command in the project folder(platformio.ini location)

pio run -t upload

or

pio run -t upload -v

I get a proper write and the program seems to work fine.

Log:

john@83adbc14  ~/Documents/PlatformIO/Projects/Testing MCB1768  pio run -t upload                                                                                                            ✔  10184  12:11:55
Processing lpc1768 (platform: nxplpc; board: lpc1768; framework: mbed)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/nxplpc/lpc1768.html
PLATFORM: NXP LPC 4.4.0 > NXP mbed LPC1768
HARDWARE: LPC1768 96MHz, 64KB RAM, 512KB Flash
DEBUG: Current (cmsis-dap) On-board (cmsis-dap) External (blackmagic, jlink)
PACKAGES: toolchain-gccarmnoneeabi 1.70201.0 (7.2.1), framework-mbed 5.51304.190826 (5.13.4)
Collecting mbed sources...
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 4 compatible libraries
Scanning dependencies...
No dependencies
Checking size .pio/build/lpc1768/firmware.elf
Memory Usage -> http://bit.ly/pio-memory-usage
DATA:    [=         ]   5.3% (used 3441 bytes from 65536 bytes)
PROGRAM: [=         ]   6.5% (used 34068 bytes from 524288 bytes)
Configuring upload protocol...
AVAILABLE: blackmagic, cmsis-dap, custom, jlink, mbed
CURRENT: upload_protocol = custom
Uploading .pio/build/lpc1768/firmware.bin
xPack OpenOCD, 64-bit Open On-Chip Debugger 0.10.0+dev (2019-07-17-15:21)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
Info : CMSIS-DAP: SWD  Supported
Info : CMSIS-DAP: JTAG Supported
Info : CMSIS-DAP: FW Version = 1.0
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : SWCLK/TCK = 0 SWDIO/TMS = 1 TDI = 1 TDO = 1 nTRST = 0 nRESET = 1
Info : CMSIS-DAP: Interface ready
Info : clock speed 10 kHz
Info : SWD DPIDR 0x2ba01477
Info : lpc17xx.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : lpc17xx.cpu: external reset detected
Info : Listening on port 3333 for gdb connections
target halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x1fff0080 msp: 0x10001ffc
Info : High speed (adapter_khz 12500) may be limited by adapter firmware.
** Programming Started **
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
Info : SWD DPIDR 0x2ba01477
shutdown command invoked

I wonder, if the LEDs below P1_28 are supposed to be turned on the whole time in the mbed Blinky example?

2 Likes

Great news! :slight_smile:

Then the default pin state on boot might be just output high or just floating, which makes the buffer (if it’s implemented as a double-inverter) output high (see schematics page 3 lower left corner).

If you add these global variables they should be off.

DigitalOut led2(P1_29, 0);
DigitalOut led3(P1_31, 0);
DigitalOut led4(P2_2, 0);
DigitalOut led5(P2_3, 0);
DigitalOut led6(P2_4, 0);
DigitalOut led7(P2_5, 0);
DigitalOut led8(P2_6, 0);

Also debugging should be possible with the openocd server if you add

debug_tool = custom
debug_server =
    openocd
    -f
    scripts/interface/cmsis-dap.cfg
    -f
    scripts/board/mcb1700.cfg

(docs)

1 Like

Thank you very much :smiley:

/Users/john/.gdbinit:1: Error in sourced command file:
No symbol table is loaded.  Use the "file" command.
Reading symbols from /Users/john/Documents/PlatformIO/Projects/Testing MCB1768/.pio/build/lpc1768/firmware.elf...
done.
PlatformIO Unified Debugger -> http://bit.ly/pio-debug
PlatformIO: debug_tool = custom
PlatformIO: Initializing remote target...
Open On-Chip Debugger 0.10.0+dev-00930-g09eb941c (2019-09-12-19:27)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
embedded:startup.tcl:26: Error: Can't find scripts/interface/cmsis-dap.cfg
in procedure 'script'
at file "embedded:startup.tcl", line 26
.pioinit:13: Error in sourced command file:
Remote connection closed

Solves my previous problem:

[env:lpc1768]
platform = nxplpc
board = lpc1768
framework = mbed
build_flags = -D MCB1700
extra_scripts = extra_script.py
upload_protocol = custom
upload_flags =
    -f
    scripts/interface/cmsis-dap.cfg
    -f
    scripts/board/mcb1700.cfg
debug_tool = custom
debug_server =
    openocd
    -f
    ../scripts/interface/cmsis-dap.cfg
    -f
    ../scripts/board/mcb1700.cfg