Metadata-Version: 2.4
Name: bmlab-toolkit
Version: 0.1.5
Summary: CI/CD toolkit for flashing and testing embedded devices
Author-email: BareMetal Test Lab <makloun@hotmail.com>
License: MIT
Project-URL: Homepage, https://github.com/BareMetalTestLab/bmlab-flash-toolkit
Project-URL: Repository, https://github.com/BareMetalTestLab/bmlab-flash-toolkit
Project-URL: Bug Tracker, https://github.com/BareMetalTestLab/bmlab-flash-toolkit/issues
Project-URL: Documentation, https://github.com/BareMetalTestLab/bmlab-flash-toolkit#readme
Keywords: embedded,firmware,flashing,jlink,stm32,ci-cd,testing
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pylink-square>=1.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Dynamic: license-file

# bmlab-toolkit

CI/CD toolkit for flashing and testing embedded devices.

## Features

- Flash embedded devices (currently supports JLink)
- List and detect connected programmers
- Automatic STM32 device detection (F1/F4/F7/G0 series)
- Support for multiple firmware formats (.hex, .bin)
- **Real-Time Transfer (RTT) support** - Connect to device RTT for real-time communication
- Single unified command-line interface
- Extensible architecture for supporting additional programmers

## Installation

```bash
pip install bmlab-toolkit
```

## Usage

### Command Line

List connected programmers:
```bash
bmlab-flash
# or specify programmer type
bmlab-flash --programmer jlink
```

Flash a device with auto-detected programmer (uses first available JLink):
```bash
bmlab-flash <firmware_file>
```

Flash with specific serial number:
```bash
bmlab-flash <firmware_file> --serial <serial_number>
```

Flash with specific MCU:
```bash
bmlab-flash <firmware_file> --mcu STM32F765ZG
```

Specify programmer explicitly:
```bash
bmlab-flash <firmware_file> --programmer jlink --serial 123456
```

Get help:
```bash
bmlab-flash --help
```

### RTT (Real-Time Transfer)

Connect to JLink RTT for real-time communication with the target device:

```bash
# Connect with auto-detection and read for 10 seconds
bmlab-jlink-rtt

# Specify JLink serial number
bmlab-jlink-rtt --serial 123456789

# Connect via IP address (no MCU needed)
bmlab-jlink-rtt --ip 192.168.1.100

# Specify MCU explicitly
bmlab-jlink-rtt --mcu STM32F765ZG

# Read indefinitely until Ctrl+C
bmlab-jlink-rtt -t 0

# Send message after connection
bmlab-jlink-rtt --msg "hello\n"

# Send message after custom delay
bmlab-jlink-rtt --msg "test" --msg-timeout 2.0

# Connect without resetting target
bmlab-jlink-rtt --no-reset

# Verbose output
bmlab-jlink-rtt -v
```

Get RTT help:
```bash
bmlab-jlink-rtt --help
```

### Scanning for Devices

Scan for USB-connected JLink devices:
```bash
bmlab-scan
```

Scan network for JLink Remote Servers:
```bash
# Scan entire network
bmlab-scan --network 192.168.1.0/24

# Scan specific IP range (last octet)
bmlab-scan --network 192.168.1.0/24 --start-ip 100 --end-ip 150

# With debug output
bmlab-scan --network 192.168.1.0/24 --log-level DEBUG
```

### Parallel Flashing

Flash multiple devices simultaneously using the provided script:

```bash
# Flash multiple IPs from command line
examples/parallel_flash.sh firmware.bin 192.168.1.100 192.168.1.101 192.168.1.102

# Flash with specific MCU type
examples/parallel_flash.sh --mcu STM32F765ZG firmware.bin 192.168.1.100 192.168.1.101

# Flash from IP list file
cat > ips.txt << EOF
192.168.1.100
192.168.1.101
192.168.1.102
EOF

examples/parallel_flash.sh firmware.bin $(cat ips.txt)
```

The script outputs simple status for each device:
```
192.168.1.100 OK
192.168.1.101 OK
192.168.1.102 FAULT
```

### Parallel RTT Reading

Read RTT from multiple devices simultaneously and save to log files:

```bash
# Read RTT from multiple devices (default 10 seconds)
examples/parallel_rtt.sh 192.168.1.100 192.168.1.101 192.168.1.102

# Read for 30 seconds with specific MCU
examples/parallel_rtt.sh --mcu STM32F765ZG --timeout 30 192.168.1.100 192.168.1.101

# Read indefinitely until Ctrl+C
examples/parallel_rtt.sh --timeout 0 192.168.1.100 192.168.1.101

# Read from IP list file
examples/parallel_rtt.sh $(cat ips.txt)
```

Output:
```
Output directory: rtt_logs_20251214_143052

192.168.1.100 OK (saved to rtt_logs_20251214_143052/rtt_192.168.1.100.log)
192.168.1.101 OK (saved to rtt_logs_20251214_143052/rtt_192.168.1.101.log)
192.168.1.102 FAULT (see rtt_logs_20251214_143052/rtt_192.168.1.102.log)

All RTT sessions completed
```

Log files are saved in a timestamped directory with ANSI color codes removed for clean text output.

### Python API

#### Flashing

```python
from bmlab_toolkit import JLinkProgrammer

# Create programmer instance (auto-detect serial)
prog = JLinkProgrammer()

# Or specify serial number
prog = JLinkProgrammer(serial=123456789)

# Flash firmware (auto-detect MCU)
prog.flash("firmware.hex")

# Flash with specific MCU
prog.flash("firmware.hex", mcu="STM32F765ZG")

# Flash without reset
prog.flash("firmware.hex", reset=False)
```

#### RTT Communication

```python
from bmlab_toolkit import JLinkProgrammer
import time

# Create programmer
prog = JLinkProgrammer(serial=123456789)

try:
    # Connect to target
    prog._connect_target(mcu="STM32F765ZG")
    
    # Reset device (optional)
    prog.reset(halt=False)
    time.sleep(0.5)
    
    # Start RTT
    prog.start_rtt(delay=1.0)
    
    # Send data
    prog.rtt_write(b"Hello, device!\n")
    
    # Read data
    data = prog.rtt_read(max_bytes=4096)
    if data:
        print(data.decode('utf-8', errors='replace'))
    
    # Stop RTT
    prog.stop_rtt()
    
finally:
    # Disconnect
    prog._disconnect_target()
```

## Development

```bash
# Install in editable mode with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest
```

## Currently Supported

### Programmers
- JLink (via pylink-square)

### Devices
- STM32F1 series (Low/Medium/High/XL density, Connectivity line)
- STM32F4 series (F405/407/415/417, F427/429/437/439)
- STM32F7 series (F74x/75x, F76x/77x)
- STM32G0 series (G0x0, G0x1, G0Bx/G0Cx)

## Roadmap

### Planned Features
  
- **Device Testing** - Automated testing capabilities
  - Run tests on connected devices
  - Collect and analyze test results via RTT
  - Generate test reports
  
- **Additional Programmers**
  - ST-Link support
  - OpenOCD support
  - Custom programmer interfaces

## Extending with New Programmers

The library is organized into functional modules:

- `constants.py` - Programmer type constants
- `list_devices.py` - Device detection and listing functionality
- `flashing.py` - Flashing operations
- `jlink_device_detector.py` - STM32-specific device detection

To add support for a new programmer:

1. Add the programmer constant to `src/bmlab_toolkit/constants.py`:
```python
PROGRAMMER_STLINK = "stlink"
SUPPORTED_PROGRAMMERS = [PROGRAMMER_JLINK, PROGRAMMER_STLINK]
```

2. Implement device listing in `src/bmlab_toolkit/list_devices.py`:
```python
def _get_stlink_devices() -> List[Dict[str, Any]]:
    # Implementation here
    pass

# Update get_connected_devices() function to handle new programmer
```

3. Implement flashing function in `src/bmlab_toolkit/flashing.py`:
```python
def _flash_with_stlink(serial: int, fw_file: str, mcu: str = None) -> None:
    # Implementation here
    pass

# Add case in flash_device_by_usb()
elif programmer_lower == PROGRAMMER_STLINK:
    _flash_with_stlink(serial, fw_file, mcu)
```

4. Update documentation and tests

## License

MIT
