Anobium - 6 hours ago

PICKit+ Merge — bootloader-aware programming for GCBASIC

You can add a new GCBASIC programmer, PICKit+ Merge [Target 5v0], that merges a
bootloader hex file ( or any existing hex file ) into your compiled application hex before flashing, using
Microchip's hexmate.exe. It reuses the same PICkit hardware path as the
existing PICKit+ Cmd5v0 programmer — only the file sent to it differs.

It is seamless.

Why

A chip programmed with a bootloader needs two things resident in flash at
once: the bootloader itself (so the device can later be field-updated over
serial/USB without a PICkit) and the application code. GCBASIC only ever
compiles and outputs the application hex — it has no idea a bootloader
exists, so its compiled hex says nothing about the bootloader region the
bootloader occupies.

Flashing that application hex directly, on its own, means only the
application ends up on the chip — the bootloader region is left blank (or,
on a chip that's already been through a full-chip erase, wiped out
entirely). Getting both onto the chip in one programming pass previously
meant manually running hexmate to merge the two hex files before every
flash, or maintaining a separately-merged hex file that had to be
regenerated and kept in sync by hand whenever the application source
changed — both easy to forget, and easy to get wrong during day-to-day
development when you just want to hit "Program" after a code change.

This new tool folds that merge step into the normal GCBASIC compile-and-program
workflow: pick PICKit+ Merge [Target 5v0] as the programmer once, and every
subsequent "Program" click merges the current bootloader into the freshly
compiled application hex automatically, then flashes the result — so the
bootloader can never accidentally go missing from a build, and there's
nothing extra to remember to run by hand.

Requirements

  • GCBASIC / GCstudio installed (tested against C:\GCstudio).
  • A PIC project where a bootloader reserves a word-address range — in this
    project's case, 0x1E00-0x1EFF.
  • A hex file named after that bootloader's reserved range — in this case
    bootloader_1E00-1EFF.hex — sitting next to your .gcb source file (i.e. in
    the project root, one folder above the compiler's <basename>.build output
    folder). This file should contain only the bootloader's own
    reserved-region data — not a full blank-filled image of the whole flash
    range (see "How it works" below for why that matters). merge.cmd
    currently looks for this exact filename, so if your bootloader occupies a
    different range, name the file to match and update the BOOTHEX line in
    merge.cmd accordingly.</basename>

Note: bootloader_1E00-1EFF.hex is the file name used in this document. See
the "Customizing merge.cmd" section below for how to change it.

Installation

  1. Copy install-hexmate-merge.cmd anywhere convenient (it doesn't need to
    live inside a project folder).
  2. Run it:

install-hexmate-merge.cmd

By default it targets C:\GCstudio. If your GCstudio install lives
elsewhere, pass it as an argument:

install-hexmate-merge.cmd D:\Path\To\GCstudio

  1. The installer will:
  2. Add a hexmatelocation entry to use.ini's [toolvariables] section.
  3. Add (or patch) the [tool = pickitplusmerge] section in use.ini.
  4. Add pickitplusmerge to the programmer= list so it's selectable.
  5. Install merge.cmd into %GCSTUDIO_INSTALL_PATH%\PICKitPlus.

It's safe to run more than once — anything already in place is left
alone and reported as "already up to date / skipping". Anything it does
change is backed up first (<file>.bak_<timestamp>, next to the
original).</timestamp></file>

Selecting the new programmer

Installing it only makes the programmer available — GCBASIC still needs to
be told to use it:

  1. Open your project in the GCBASIC IDE.
  2. Go to Edit Preferences.
  3. Find the Programmer tab setting and choose PICKit+ Merge [Target 5v0] from
    the list.
  4. Save/close preferences. Compile and program as normal — the merge now
    happens automatically as part of the programming step, with no other
    workflow change.

If you ever want to go back to flashing the plain application hex (no
bootloader merge), just switch the Programmer back to PICKit+ Cmd5v0
[Target 5v0].

How it works

use.ini changes

use.ini already defines each programmer as a [tool = ...] section whose
command=/params= lines are text-substituted by the compiler (%FileName%,
%ChipModel%, %GCSTUDIO_INSTALL_PATH%, etc.) before the tool is launched.
%GCSTUDIO_INSTALL_PATH% isn't a real environment variable — GCBASIC
computes it itself from its own .exe location and substitutes it as plain
text — so it can't be read back inside a batch file; anything a called tool
needs has to be passed in as an explicit argument instead.

The installer adds:

  • hexmatelocation = %GCSTUDIO_INSTALL_PATH%\picas\pic\bin under
    [toolvariables] — hexmate.exe ships with the PIC-AS toolchain but not in
    the pic-as\bin folder GCBASIC already points at for the assembler; it's a
    folder over, in pic\bin.
  • A [tool = pickitplusmerge] section whose params now includes hexmate's
    full path as an extra positional argument, ahead of the existing
    PICKitCommandline.exe path and its flashing arguments:

params = "%FileName%" %hexmatelocation%\hexmate.exe %GCSTUDIO_INSTALL_PATH%\PICKitPlus\PICKitCommandline.exe -w -a5 -pPIC%ChipModel% -f"%FileName%" -mpec -zv

command = %GCSTUDIO_INSTALL_PATH%\PICKitPlus\merge.cmd receives these as
%1 through %9:

  • %1 — quoted path to the compiled application hex (%FileName%)
  • %2 — path to hexmate.exe
  • %3 — path to PICKitCommandline.exe
  • %4 through %9 — PICKitCommandline.exe's own flashing arguments

merge.cmd

merge.cmd runs before any hardware programming happens:

  1. Locate the bootloader hex. It derives the project root as the parent
    folder of the compiled hex's directory (the compiler's own
    <basename>.build\<basename>.hex convention), then looks for
    bootloader_1E00-1EFF.hex there. If it's missing — or hexmate.exe can't
    be found — the script aborts with a non-zero exit code and does not
    flash anything, so a missing bootloader file is never silently ignored.</basename></basename>

  2. Back up the compiled hex. The freshly-compiled application hex is
    copied to <name>_org.hex alongside it (e.g. main.build\main_org.hex)
    before anything is modified.</name>

  3. Merge with hexmate. It runs:

hexmate.exe "<name>_org.hex" +"bootloader_1E00-1EFF.hex" -o"<name>.hex"</name></name>

hexmate errors on overlapping data between input files by default; the +
prefix forces that input's data to win any conflict. Here the
application hex is the unforced base and the bootloader hex is forced on
top — so the bootloader reliably occupies its own reserved 0x1E00-0x1EFF
region, while everywhere else the application's own code passes through
untouched (the bootloader file has no data outside its reserved region,
so there's nothing for it to overwrite). This is why
bootloader_1E00-1EFF.hex — a file that only contains that narrow address
range — is used instead of a full, blank-filled bootloader image: the
latter would collide with application code at almost every address.

The output is written back to the original filename (<name>.hex), so
nothing downstream needs to know a merge happened.</name>

  1. Flash. It calls PICKitCommandline.exe with the same arguments GCBASIC
    would have passed it directly (%3 through %9), including
    -f"%FileName%" — which now resolves to the merged hex, since it was
    written back under the original name.

If the hexmate merge step itself fails, merge.cmd restores the original
(pre-merge) hex from the _org.hex backup before aborting, so the project is
never left in a broken state.

Customizing merge.cmd

The bootloader hex filename isn't the only thing that can be changed —
everything merge.cmd does is driven by a handful of lines near the top of
the file. Edit %GCSTUDIO_INSTALL_PATH%\PICKitPlus\merge.cmd directly (the
installer won't touch a file it finds already up to date, and backs up
anything it does overwrite, so hand edits are safe to make):

  • Bootloader hex filename — the line
    set "BOOTHEX=%PROJDIR%\bootloader_1E00-1EFF.hex". Change the filename to
    match your bootloader's own reserved range, e.g.
    bootloader_0C00-0CFF.hex.
  • Where the bootloader hex is looked for — the line
    for %%D in ("%APPDIR%..") do set "PROJDIR=%%~fD". Assumes the bootloader
    hex sits one folder above <basename>.build. Point BOOTHEX somewhere else
    entirely (a shared folder, a fixed path) if that's not where yours lives.</basename>
  • Backup filename pattern — the line
    set "ORGHEX=%APPDIR%%APPNAME%_org%APPEXT%". Change the _org suffix, or
    write it somewhere other than next to the compiled hex.
  • Merge priority — the line
    "%HEXMATE%" "%ORGHEX%" +"%BOOTHEX%" -o"%APPHEX%". The + forces that
    input to win address conflicts. Move it to the other filename to flip
    priority, or add extra hexmate flags (checksum, fill, addressing) here.
  • Missing-file behaviour — the two if not exist (...) blocks. Currently
    aborts and never flashes. Change to a warning followed by a jump straight
    to the flash step if you'd rather fall back to flashing the plain
    application hex when the bootloader file is absent.
  • Number of flashing arguments forwarded — the line
    "%FLASHTOOL%" %4 %5 %6 %7 %8 %9. Must match however many tokens follow
    the PICKitCommandline.exe path in pickitplusmerge's params= line in
    use.ini — extend or trim this list if that line changes.

Two related settings live in use.ini rather than merge.cmd itself:

  • hexmatelocation (under [toolvariables]) — where hexmate.exe is found.
    Point it elsewhere if you're using a different PIC-AS/XC8 install.
  • pickitplusmerge's params= line — the flashing arguments themselves
    (target voltage -a5, etc.) follow the same conventions as pickitpluscmd1
    and can be edited the same way.

Known limitation

Because the merge writes its output back over the original filename,
re-running "Program" a second time without recompiling re-merges an
already-merged hex. This is harmless to what actually gets flashed (merging
the bootloader's region on top of itself changes nothing), but the
_org.hex backup from that second run will then contain the already-merged
hex rather than the true pre-merge compiler output. Recompiling before
programming (the normal workflow) avoids this entirely.