pycmsisdapswitcher 2.0.2.19
Recovers or switches bootloader and application firmware on Microchip programmers, debuggers, and development boards between Microchip and CMSIS-DAP v2 implementations.
License: MIT
Requires Python: >=3.10
Keywords: Microchip

# pycmsisdapswitcher 

## Introduction 
The pycmsisdapswitcher is a command line Python standalone package and library with two functionalities:  
- to **recover** the bootloader firmware and the application firmware on a Microchip&reg; programmer/debugger or a Microchip development board in recovery mode
- to **switch** the application firmware on a Microchip programmer/debugger or a Microchip development board between the Microchip proprietary implementation and the Arm&reg; CMSIS-DAP v2 compliant implementation

## 🚀 Quick Start

Install and recover / switch firmware on supported targets:
```bash
pip install pycmsisdapswitcher
pycmsisdapswitcher --help
```

## Supported targets    
**Recover:** 
- Microchip ICD5, ICD4, ICE4, PICkit5, PICkit4, PICkit Basic and Snap programmer/debugger tools
- Microchip boards with PKoB4 debugger (please refer to the board user guide).  

**Switch:** 
- Microchip PICkit5, PICkit4, PICkit Basic and Snap programmer/debugger tools
- Microchip boards with PKoB4 debugger (please refer to the board user guide).  

## Installation via pypi.org
```bash
pip install pycmsisdapswitcher
```
> **Note:**  
> It is recommended to use a [virtual environment](https://docs.python.org/3/tutorial/venv.html) to avoid dependency conflicts with other Python packages.

## Installation via test.pypi.org
An alternative URL is required for dependencies not available on test.pypi.org :
```bash
pip install -i https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple pycmsisdapswitcher
```
> **Note:**  
> It is recommended to use a [virtual environment](https://docs.python.org/3/tutorial/venv.html) to avoid dependency conflicts with other Python packages.

## Command-Line Usage
```bash
pycmsisdapswitcher --action=<action_to_perform> --target=<supported_target> --bootsource=<bootloader_source> --appsource=<application_source> --fwtype=<firmware_type> --verbose=<logging_verbosity_level> --showhowto --version --help
```

### Options

| Option       | Values / Description                                                      |
|--------------|---------------------------------------------------------------------------|
| `--action`   | `'recover'` or `'switch'` (default)                                       |
| `--target`   | programmer/debugger name or `'evalboard'` <br> See notes 1 and 2 below.   |
| `--bootsource` | source of the bootloader firmware: `'server'` (default) for public packs repository, `'cache'` for offline operation or a path to a .hex or .atpack file <br> See notes 3, 4 and 5 below.      |
| `--appsource` | source of the application firmware: `'server'` (default) for public packs repository, `'cache'` for offline operation or a path to a .hex or .atpack file <br> See notes 3, 4 and 5 below.      |
| `--fwtype`   | type of application firmware to switch to:`'mplab'` for Microchip proprietary implementation or `'cmsis'` (default) for ARM compliant implementation |
| `--verbose` | logging verbosity level: `'debug'`, `'info'`(default), `'warning'`, `'error'` or `'critical'`  |
| `--showhowto` | shows how to put the target in recovery mode |
| `--help` | shows the pycmsisdapswitcher help |
| `--version` | shows the pycmsisdapswitcher installed version |


> **Note 1:**  
> The target name is not required if `action == 'switch'`. In this mode, target auto-detection is used (see [Safeguard against multiple connected targets](#safeguard-against-multiple-connected-targets))

> **Note 2:**  
> See the [Supported targets](#supported-targets) section for a list of supported devices.

> **Note 3:**  
> When a firmware is successfully downloaded from the server, it is saved to the cache and used in subsequent recovery or switch operations.

> **Note 4:**  
> If a `.hex` file is provided, the pycmsisdapswitcher cannot verify that it is a valid file.

> **Note 5:**  
> If a `.atpack` file is provided, the pycmsisdapswitcher will attempt to unzip it and extract the required file from the archive, gracefully terminating in case of errors.

> **Note 6:**  
> If --appsource is set to 'cache' or a .hex file is provided, the --fwtype value must match the firmware type of the application to be retrieved from the cache or associated with the .hex file. See examples below.

## Safeguard against multiple connected targets
If more than one supported target is detected when the operation starts, the operation is gracefully terminated and an error is logged.

## Examples
**Show how to put supported_target in recovery mode**
```bash
pycmsisdapswitcher --action recover --target supported_target --showhowto
```

**Recover bootloader + CMSIS-DAP v2 type app on supported_target, retrieve both files from pack server, set logging verbosity level to debug**
```bash
pycmsisdapswitcher --action recover --target supported_target --verbose debug
```

**Recover bootloader + MPLAB type app on supported_target, retrieve both files from cache**
```bash
pycmsisdapswitcher --action recover --target supported_target --bootsource cache --appsource cache --fwtype mplab
```

**Recover bootloader + MPLAB type app on supported_target, retrieve boot file from pack server, use provided .hex file for app**
```bash
pycmsisdapswitcher --action recover --target supported_target --appsource path_to_appfile --fwtype mplab
```

**Recover bootloader + CMSIS-DAP v2 type app on supported_target, retrieve boot file from pack server, retrieve app file from cache**
```bash
pycmsisdapswitcher --action recover --target supported_target --appsource cache
```

**Recover bootloader + CMSIS-DAP v2 type app on supported_target, use provided .hex files for both**
```bash
pycmsisdapswitcher --action recover --target supported_target --bootsource path_to_bootfile  --appsource path_to_appfile
```

**Switch application on supported_target to CMSIS-DAP v2 type app, retrieve app file from pack server, set logging verbosity level to debug**
```bash
pycmsisdapswitcher --verbose debug
```

**Switch application on supported_target to MPLAB type app, retrieve app file from cache**
```bash
pycmsisdapswitcher --appsource cache --fwtype mplab
```

**Switch application on supported_target to CMSIS-DAP v2 type, use provided .hex file for app**
```bash
pycmsisdapswitcher  --appsource path_to_appfile
```

**Switch application on supported_target to MPLAB type, use provided .hex file for app**
```bash
pycmsisdapswitcher  --appsource path_to_appfile --fwtype mplab
```

## Usage as library. 
- install the pycmsisdapswitcher in the virtual environment of the Python project that will use it as a library
- import the pycmsisdapswitcher function(s) used in the project and the pycmsisdapswitcher base exception:  
```bash
from pycmsisdapswitcher.recover_main import recover # If used
from pycmsisdapswitcher.switcher_main import switch # If used
from pycmsisdapswitcher.errors import PyCmsisDapSwitcherError
```
> **Note**  
> Function(s) arguments can be viewed by hovering over the function call 

- call a pycmsisdapswitcher function with named arguments inside a try/except block to handle the exceptions, e.g.:
```bash
    try:
        # Switch a supported target application firmware to CMSIS-DAP mode using the public packs repository
        switch( ) 
    except PyCmsisDapSwitcherError as e:
        print(f"Switch failed! {e}")
    except Exception as e: 
        print(f"Unexpected error: {e}")
```
```bash
    try:
        # Switch a supported target application firmware to MPLAB mode using the public packs repository
        switch(fw_type='mplab') 
    except PyCmsisDapSwitcherError as e:
        print(f"Switch failed! {e}")
    except Exception as e: 
        print(f"Unexpected error: {e}")
```

### Note for Windows® users  

If the output shows an error message such as  
> The device has no langid (permission issue, no string descriptors supported or device error)

please double check in the Device Manager that the target has been bound to WinUSB&trade;
If it hasn't, you can manually bind the target to WinUSB by using either
* [Zadig](https://zadig.akeo.ie/), or
* [Microchip USB installer](https://shelf.download.microchip.com/shelf/38d86b7d2dda2fdc5b46d00a4ee962c9c7c405925a4eef0ee181e6547348dc6e/MPLABCOMM-v6.25-installers.zip)


### Note for Linux® users
USB devices require custom udev rules, which must be added to a .rules file in /etc/udev/rules.d/, targeting the device’s vendor ID (VID == 04d8 for Microchip) and applicable product IDs (PIDs).

PIDs for the pycmsisdapswitcher supported targets are:
```h
PICkit Basic:
    'MPLAB_BOOT_PID': 0x9057,
    'MPLAB_APP_PID': (0x9054, 0x9055, 0x9056),
    'CMSIS_V2_APP_PID': (0x90ab, 0x90ac, 0x90ad, 0x90ae)
    
PKoB4 board: 
    'MPLAB_BOOT_PID': 0x810a,
    'MPLAB_APP_PID': (0x8109, 0x810b, 0x810c, 0x810d),
    'CMSIS_APP_PID': 0x2175,
    'CMSIS_V2_APP_PID': (0x904a, 0x904b, 0x904c, 0x904d)
    
PICkit 5:
    'MPLAB_BOOT_PID': 0x9035,
    'MPLAB_APP_PID': 0x9036,
    'CMSIS_V2_APP_PID': 0x90b0

PICkit 4:
    'MPLAB_BOOT_PID': 0x9017,
    'MPLAB_APP_PID': (0x9012, 0x901b, 0x901d, 0x9028),
    'CMSIS_V2_APP_PID': 0x90af

Snap:
    'MPLAB_BOOT_PID': 0x9019,
    'MPLAB_APP_PID': (0x9018, 0x901c, 0x901e, 0x9029),
    'CMSIS_V2_APP_PID': 0x90b1

ICD5:
    'MPLAB_BOOT_PID': 0x9037,
    'MPLAB_APP_PID': (0x9038, 0x903f)

ICD4:
    'MPLAB_BOOT_PID': 0x9015,
    'MPLAB_APP_PID': 0x9015  
    
ICE4:
    'MPLAB_BOOT_PID' = 0x901f
    'MPLAB_APP_PID' = (0x9020, 0x9021, 0x9022, 0x9023)
```

Example, pycmsisdapswitcher.rules content for PICkit Basic:
```h
# PICkit Basic
SUBSYSTEM=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="9057", MODE="0666"
SUBSYSTEM=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="9054", MODE="0666"
SUBSYSTEM=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="9055", MODE="0666"
SUBSYSTEM=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="9056", MODE="0666"
SUBSYSTEM=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="90ab", MODE="0666"
SUBSYSTEM=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="90ac", MODE="0666"
SUBSYSTEM=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="90ad", MODE="0666"
SUBSYSTEM=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="90ae", MODE="0666"
``` 


# Changelog

## [2.0.2] - November 2025

New API (see 'Command-Line Usage' under 'Project description' for details):
- Added recovery functionality.
- Expanded switching functionality options.
- Added usage as a library.

## [1.0] - March 2025

- Initial release