support programming rp2350, add a new example to program metro rp2350 from firmware.h

rename program_rp2040_uf2.ino to program_rp2_from_sdcard.ino
change include SdFat.h to SdFat_Adafruit_Fork.h
This commit is contained in:
hathach 2025-03-05 16:47:56 +07:00
parent 1130b8c29d
commit 759bdeb282
No known key found for this signature in database
GPG key ID: 26FAB84F615C3C52
23 changed files with 7294 additions and 28 deletions

View file

@ -1,7 +1,7 @@
// Testing basic peripherals on Brain
// required for Host MSC block device
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
// required for USB host
#include "pio_usb.h"

View file

@ -9,7 +9,7 @@
// - There is no need to connect IO0/Reset since we will use DTR/RTS to reset ESP32
// required for Host MSC block device
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
// required for USB host
#include "pio_usb.h"

View file

@ -6,7 +6,7 @@
// - Brain TX/RX <-> ESP32 RX/TX
// required for Host MSC block device
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
// required for USB host
#include "pio_usb.h"

View file

@ -6,7 +6,7 @@
// - Brain's USB host to Target USB
// required for Host MSC block device
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
// required for USB host
#include "pio_usb.h"

View file

@ -6,7 +6,7 @@
// - Brain's USB host to Target USB
// required for Host MSC block device
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
// required for USB host
#include "pio_usb.h"

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,135 @@
// This sketch program rp2040 by copying UF2 file from SDCard to
// rp2040 bootrom
// Hardware wiring:
// - Brain's Target GPIO28 to RP2 bootsel
// - Brain's Target Reset to RP2 Reset
// - Brain's USB host to RP2040 USB interface
// required for Host MSC block device
#include "SdFat_Adafruit_Fork.h"
// required for USB host
#include "pio_usb.h"
#include "Adafruit_TinyUSB.h"
#include "Adafruit_TestBed_Brains.h"
// firmware.h is converted using tools/file2carray.py e.g
// python tools/file2carray.py cdc_msc.uf2
// above command will generate cdc_msc.uf2.h with bindata, bindata_len
#include "metro_rp2350_cdc_msc.uf2.h"
// RP2040 Boot VID/PID
#define BOOT_VID 0x2e8a
#define BOOT_PID_RP2040 0x0003
#define BOOT_PID_RP2350 0x000f
// If USB filesystem is mounted
volatile bool is_usbfs_mounted = false;
//--------------------------------------------------------------------+
// Setup and Loop on Core0
//--------------------------------------------------------------------+
void print_speed(size_t count, uint32_t ms) {
Brain.LCD_printf(0, "%.01fKB %.01fs", count/1000.0F, ms / 1000.0F);
Serial.printf("Completed %u bytes in %.02f seconds.\r\n", count, ms / 1000.0F);
Serial.printf("Speed : %.02f KB/s\r\n", (count / 1000.0F) / (ms / 1000.0F));
}
void setup() {
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("Program RP2 by copy UF2 from Internal Flash to Bootloader!");
// sync: wait for Brain.begin() called in core1 before accessing SD or other peripherals
while (!Brain.inited()) delay(10);
// wait for USB filesystem is mounted. USB host bit-banging and task is
// processed on core1
while (!is_usbfs_mounted) delay(10);
// Copy UF2 file
Brain.LCD_printf(0, "Copying firmware");
Serial.println("Copying UF2 from Flash to USBHFS");
uint32_t ms = millis();
size_t copied_bytes = Brain.rp2_programUF2(bindata, bindata_len);
print_speed(copied_bytes, millis() - ms);
// wait for rp2040 boot rom to reset
// while (is_usbfs_mounted) delay(10);
}
void loop() {
Serial.flush();
}
//--------------------------------------------------------------------+
// Setup and Loop on Core1
//--------------------------------------------------------------------+
// call usbh_begin() here to make pio usb background task run on core1
// NOTE: Brain.begin() should be called here as well to prevent race condition
void setup1() {
Brain.begin();
Brain.usbh_begin();
Brain.LCD_printf(1, "No USB Device");
// reset rp2040 target into Boot Rom, default bootsel = 28, reset duration = 10 ms
Brain.rp2_targetResetBootRom();
}
// core1's loop: process usb host task on core1
void loop1() {
Brain.USBHost.task();
}
//--------------------------------------------------------------------+
// TinyUSB Host callbacks
// Note: running in the same core where Brain.USBHost.task() is called
//--------------------------------------------------------------------+
bool is_rp2_bootloader(uint16_t vid, uint16_t pid) {
return (vid == BOOT_VID && (pid == BOOT_PID_RP2040 || pid == BOOT_PID_RP2350));
}
extern "C" {
// Invoked when device is mounted (configured)
void tuh_mount_cb(uint8_t dev_addr) {
uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid);
if (!is_rp2_bootloader(vid, pid)) {
Brain.LCD_printf(1, "UnkDev %04x:%04x", vid, pid);
}
}
/// Invoked when device is unmounted (bus reset/unplugged)
void tuh_umount_cb(uint8_t dev_addr) {
(void)dev_addr;
Brain.LCD_printf(1, "No USB Device");
}
// Invoked when a device with MassStorage interface is mounted
void tuh_msc_mount_cb(uint8_t dev_addr) {
uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid);
if (is_rp2_bootloader(vid, pid)) {
is_usbfs_mounted = Brain.usbh_mountFS(dev_addr);
if (is_usbfs_mounted) {
uint16_t rp2variant = (pid == BOOT_PID_RP2040 ? 2040 : 2350);
Brain.LCD_printf(1, "RP%u Bootldr", rp2variant);
}
}
}
// Invoked when a device with MassStorage interface is unmounted
void tuh_msc_umount_cb(uint8_t dev_addr) {
is_usbfs_mounted = false;
Brain.usbh_umountFS(dev_addr);
}
}

View file

@ -6,7 +6,7 @@
// - Brain's USB host to RP2040 USB interface
// required for Host MSC block device
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
// required for USB host
#include "pio_usb.h"
@ -79,7 +79,7 @@ void setup() {
Serial.println("Copying from SD to USBHFS: " UF2_FILE_PATH);
uint32_t ms = millis();
size_t copied_bytes = Brain.rp2040_programUF2(UF2_FILE_PATH);
size_t copied_bytes = Brain.rp2_programUF2(UF2_FILE_PATH);
print_speed(copied_bytes, millis() - ms);
@ -104,7 +104,7 @@ void setup1() {
Brain.LCD_printf(1, "No USB Device");
// reset rp2040 target into Boot Rom, default bootsel = 28, reset duration = 10 ms
Brain.rp2040_targetResetBootRom();
Brain.rp2_targetResetBootRom();
}
// core1's loop: process usb host task on core1

View file

@ -6,7 +6,7 @@
// - Brain's USB host to Target USB
// required for Host MSC block device
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
// required for USB host
#include "pio_usb.h"

View file

@ -6,7 +6,7 @@
// - Brain's USB host to Target USB
// required for Host MSC block device
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
// required for USB host
#include "pio_usb.h"

View file

@ -6,7 +6,7 @@
// - Brain's USB host to Target USB
// required for Host MSC block device
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
// required for USB host
#include "pio_usb.h"

View file

@ -6,7 +6,7 @@
// - Brain's USB host to Target USB
// required for Host MSC block device
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
// required for USB host
#include "pio_usb.h"

View file

@ -2,7 +2,7 @@
// to LCD. Also determine if device support MSC or HID
// required for Host MSC block device
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
// required for USB host
#include "pio_usb.h"

View file

@ -2,7 +2,7 @@
// to LCD. Also determine if device support MSC or HID
// required for Host MSC block device
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
// required for USB host
#include "pio_usb.h"

View file

@ -20,7 +20,7 @@
* from https://github.com/adafruit/nina-fw/releases/tag/1.7.5 in this example directory.
*/
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
// #include "Adafruit_TinyUSB.h"
#include "Adafruit_TestBed.h"

View file

@ -6,7 +6,7 @@
#include "Wire.h"
#include "ESP32BootROM.h"
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
#define RED 0xFF0000
#define YELLOW 0xFFFF00

View file

@ -24,7 +24,7 @@
#ifdef ARDUINO_RASPBERRY_PI_PICO
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
#include "pio_usb.h"
#include "Adafruit_DAP.h"
@ -133,8 +133,8 @@ bool Adafruit_TestBed_Brains::inited(void) { return _inited; }
// RP2040 Target
//--------------------------------------------------------------------+
void Adafruit_TestBed_Brains::rp2040_targetResetBootRom(int bootsel_pin,
uint32_t reset_ms) {
void Adafruit_TestBed_Brains::rp2_targetResetBootRom(int bootsel_pin,
uint32_t reset_ms) {
pinMode(bootsel_pin, OUTPUT);
digitalWrite(bootsel_pin, LOW);
@ -146,7 +146,41 @@ void Adafruit_TestBed_Brains::rp2040_targetResetBootRom(int bootsel_pin,
pinMode(bootsel_pin, INPUT);
}
size_t Adafruit_TestBed_Brains::rp2040_programUF2(const char *fpath) {
size_t Adafruit_TestBed_Brains::rp2_programUF2(const uint8_t *buffer,
size_t bufsize) {
size_t copied_bytes = 0;
const char *dst_name = "FIRMWARE.UF2";
File32 fdst = USBH_FS.open(dst_name, O_WRONLY | O_CREAT);
if (!fdst) {
Serial.printf("USBH_FS: cannot create file: %s\r\n", dst_name);
} else {
while (copied_bytes < bufsize) {
size_t count = bufsize - copied_bytes;
if (count > 4096) {
count = 4096; // write 1 sector each
}
setLED(HIGH);
size_t wr_count = fdst.write(buffer, count);
setLED(LOW);
buffer += wr_count;
copied_bytes += wr_count;
if (wr_count != count) {
Serial.println("USBH_FS: Failed to write file");
break;
}
}
}
fdst.close();
return copied_bytes;
}
size_t Adafruit_TestBed_Brains::rp2_programUF2(const char *fpath) {
File32 fsrc = SD.open(fpath);
if (!fsrc) {
Serial.printf("SD: cannot open file: %s\r\n", fpath);
@ -154,7 +188,6 @@ size_t Adafruit_TestBed_Brains::rp2040_programUF2(const char *fpath) {
}
size_t copied_bytes = 0;
const char *dst_name = "FIRMWARE.UF2";
File32 fdst = USBH_FS.open(dst_name, O_WRONLY | O_CREAT);

View file

@ -3,7 +3,7 @@
#ifdef ARDUINO_RASPBERRY_PI_PICO
#include "SdFat.h"
#include "SdFat_Adafruit_Fork.h"
#include "Adafruit_TestBed.h"
#include <LiquidCrystal.h>
@ -49,15 +49,25 @@ public:
bool usbh_mountFS(uint8_t dev_addr);
bool usbh_umountFS(uint8_t dev_addr);
//--------------------------------------------------------------------+1
// RP2 (rp2040 and rp2350) Target
//--------------------------------------------------------------------+
// RP2040 Target
//--------------------------------------------------------------------+
// reset rp2040 target to Boot ROM
void rp2040_targetResetBootRom(int bootsel_pin = 28, uint32_t reset_ms = 20);
// reset rp2 target to Boot ROM
void rp2_targetResetBootRom(int bootsel_pin = 28, uint32_t reset_ms = 20);
// program rp2040 target by copying UF2 file from SDCard
// program rp2 target by copying UF2 file stored in flash
size_t rp2_programUF2(const uint8_t *buffer, size_t bufsize);
// program rp2 target by copying UF2 file from SDCard
// return number of copied bytes (typically uf2 file size)
size_t rp2040_programUF2(const char *fpath);
size_t rp2_programUF2(const char *fpath);
// backward compatibility
void rp2040_targetResetBootRom(int bootsel_pin = 28, uint32_t reset_ms = 20) {
rp2_targetResetBootRom(bootsel_pin, reset_ms);
}
size_t rp2040_programUF2(const char *fpath) { return rp2_programUF2(fpath); }
//--------------------------------------------------------------------+
// DAP (samd21/51, nrf5x, stm32f4 etc..) Target

45
tools/file2carray.py Normal file
View file

@ -0,0 +1,45 @@
#!/usr/bin/env python3
import argparse
import random
import os
import sys
import time
import subprocess
from pathlib import Path
from multiprocessing import Pool
from weakref import finalize
def print_carray(f, payload):
while len(payload) > 0:
f.write('\n ')
f.write(', '.join('0x{:02x}'.format(x) for x in payload[0:16]))
f.write(',')
payload = payload[16:]
f.write('\n')
def main():
parser = argparse.ArgumentParser(description='Convert binary files to C array format')
parser.add_argument('files', nargs='+', help='Binary files to convert')
args = parser.parse_args()
files = args.files
for fin_name in files:
if not os.path.isfile(fin_name):
print(f"File {fin_name} does not exist")
continue
with open(fin_name, 'rb') as fin:
contents = fin.read()
fout_name = fin_name + '.h'
with open(fout_name, 'w') as fout:
print(f"Converting {fin_name} to {fout_name}")
fout.write(f'const size_t bindata_len = {len(contents)};\n')
fout.write(f'const uint8_t bindata[] __attribute__((aligned(16))) = {{')
print_carray(fout, contents)
fout.write('};\n')
if __name__ == '__main__':
sys.exit(main())