- Initial commit of base firmware - which is still very raw

This commit is contained in:
2025-08-18 09:46:18 +02:00
parent 9d7afd129f
commit 7da2b4415f
75 changed files with 12872 additions and 0 deletions

4
Firmware/build/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
./*
!./*.txt
!./*.bat
!./*.py

View File

@@ -0,0 +1,189 @@
import os
import time
import shutil
import glob
from pathlib import Path
from string import ascii_uppercase
from os import path
import usb.core
import usb.backend.libusb1
# Device configurations
DEVICES = {
'RP2040': {
'vendor_id': 0x2E8A,
'product_id': 0x000A,
'name': 'RP2040'
},
'RP2350': {
'vendor_id': 0x2E8A,
'product_id': 0x0009,
'name': 'RP2350'
}
}
# USB control constants
RESET_INTERFACE = 2
REQUEST_BOOTSEL = 0x01
REQUEST_RESET = 0x02
# Timing constants
TIMEOUT_THRESHOLD_s = 10
TIMEOUT_INCREMENT_ms = 100
def detect_device():
"""
Detect which Pico device is connected.
Returns device type string or None if no device found.
"""
print("Auto-detecting connected device...")
for device_type, config in DEVICES.items():
device = usb.core.find(idVendor=config['vendor_id'], idProduct=config['product_id'])
if device is not None:
print(f"{config['name']} detected")
return device_type
return None
def reset_device_to_bootloader(device_type):
"""
Reset the specified device type to bootloader mode.
"""
config = DEVICES[device_type]
print(f"Resetting {config['name']} to bootloader mode...")
device = usb.core.find(idVendor=config['vendor_id'], idProduct=config['product_id'])
if device is None:
print(f'No {config["name"]} device found')
print(f'Make sure your {config["name"]} is connected and not in bootloader mode')
return False
print(f"{config['name']} device found, attempting to enter bootloader mode...")
try:
usb.util.claim_interface(device, RESET_INTERFACE)
Request_Type = (0 << 6) | 1 # Standard Request Host-to-Device and to interface
wIndex = RESET_INTERFACE
wValue = 0 # No other data
device.ctrl_transfer(Request_Type, REQUEST_BOOTSEL, wValue, wIndex, [])
print("Bootloader reset command sent successfully!")
print(f"{config['name']} should now appear as a USB drive for programming")
return True
except usb.core.USBError as e:
# print(f"USB Error: {e}")
# print("This is normal - the device resets and disconnects")
return True # This is actually expected behavior
except Exception as e:
print(f"Unexpected error: {e}")
return False
finally:
try:
usb.util.release_interface(device, RESET_INTERFACE)
except:
pass # Device may have already disconnected
def find_uf2_drive():
"""
Find the UF2 bootloader drive by looking for characteristic files.
Both RP2040 and RP2350 use the same UF2 bootloader mechanism.
"""
for drive in ascii_uppercase:
if path.exists(drive + ":\\INDEX.HTM") and path.exists(drive + ":\\INFO_UF2.TXT"):
return drive + ":\\"
return ""
def copy_uf2_file(device_type):
"""
Copy the UF2 file to the detected bootloader drive.
"""
print("Looking for UF2 bootloader drive...")
TARGET_DRIVE = find_uf2_drive()
Timeout_Counter = 0
# Wait for drive to appear
while not TARGET_DRIVE:
time.sleep(TIMEOUT_INCREMENT_ms/1000)
TARGET_DRIVE = find_uf2_drive()
Timeout_Counter = Timeout_Counter + TIMEOUT_INCREMENT_ms
if Timeout_Counter >= TIMEOUT_THRESHOLD_s * 1000:
print(f"Error: Drive for {device_type} could not be found")
return False
print(f"Found {device_type} drive at: {TARGET_DRIVE}")
# Change to script directory and find UF2 files
os.chdir(os.path.dirname(os.path.realpath(__file__)))
uf2_files = glob.glob("./*.uf2")
if len(uf2_files) == 0:
print("Error: No uf2-file has been found")
return False
print(f"Copying {uf2_files[0]} to {device_type}...")
try:
shutil.copy(uf2_files[0], TARGET_DRIVE)
print("Copy completed successfully!")
return True
except Exception as e:
print(f"Error copying file: {e}")
return False
def main():
"""
Main function to orchestrate the programming process.
"""
print("=== Pico Programmer ===")
# Detect device
device_type = detect_device()
if device_type:
# Device found - attempt reset to bootloader
print(f"\n-----------------------")
print(f"Resetting {device_type}...")
print(f"-----------------------")
# Reset to bootloader
if not reset_device_to_bootloader(device_type):
print("Failed to reset device to bootloader mode")
os._exit(1)
print(f"\n-----------------------")
print(f"Copying uf2-file...")
print(f"-----------------------")
# Copy UF2 file
if not copy_uf2_file(device_type):
print("Failed to copy UF2 file")
os._exit(1)
print(f"\nProgramming {device_type} completed successfully!")
else:
# No device found - skip reset and try to find bootloader drive directly
print("No supported Pico device found in normal mode")
print("Skipping reset step and looking for existing bootloader drive...")
print(f"\n-----------------------")
print(f"Looking for bootloader drive...")
print(f"-----------------------")
# Try to find and copy to existing bootloader drive
if not copy_uf2_file("RP2xxx"): # Generic name since we don't know the specific type
print("No bootloader drive found and no device to reset")
print("Make sure your device is:")
print("1. Connected and in normal mode (for auto-reset), OR")
print("2. Already in bootloader mode (showing as USB drive)")
os._exit(1)
print(f"\nProgramming completed successfully!")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1 @@
6

View File

@@ -0,0 +1 @@
0

View File

@@ -0,0 +1,26 @@
@echo Off
echo.
echo -----------------------
echo Updating Build Number...
echo -----------------------
set /p version=<build_version.txt
@echo Major version number: %version%
set /p old=< build_number.txt
set /a new=%old%+1
@echo New build number: %new%
@echo Firmware Version: %version%.%new%
echo.
@echo %new% > build_number.txt
if %new% lss 10 set version_build_string=%version%.000%new%
if %new% geq 10 if %new% lss 100 set version_build_string=%version%.00%new%
if %new% geq 100 if %new% lss 1000 set version_build_string=%version%.0%new%
if %new% geq 1000 set version_build_string=%version%.%new%
(
echo #define VERSION %version%
echo #define BUILD %new%
echo #define VERSION_BUILD_STRING "%version_build_string%"
) > ..\\Version.h

View File

@@ -0,0 +1,49 @@
@echo Off
setlocal enabledelayedexpansion
echo.
echo =========================
echo Pico Auto-Programmer
echo =========================
REM Read version and build number for file versioning
set /p version=<build_version.txt
set /p new=< build_number.txt
if %new% lss 10 set version_build_string=%version%.000%new%
if %new% geq 10 if %new% lss 100 set version_build_string=%version%.00%new%
if %new% geq 100 if %new% lss 1000 set version_build_string=%version%.0%new%
if %new% geq 1000 set version_build_string=%version%.%new%
REM Create versions directory if it doesn't exist
if not exist versions\ mkdir versions
REM Copy UF2 files with version numbers to versions folder
for %%f in (*.uf2) do (
set filename_base=%%~nf
set filename_with_version=!filename_base!_!version_build_string!.uf2
copy %%f versions\!filename_with_version! >nul 2>&1
)
echo.
echo Running unified Pico programmer...
echo.
REM Call the unified Python script
call python ./Pico_Reset_And_Program.py
if %errorlevel% == 0 (
echo.
echo =========================
echo Programming Success!
echo =========================
) else (
echo.
echo =========================
echo Programming Error
echo =========================
exit /b 1
)
echo.
exit /b