Compare commits

..

No commits in common. "master" and "brain-esp32-s2-s3" have entirely different histories.

82 changed files with 2232 additions and 194379 deletions

View file

@ -17,12 +17,7 @@ jobs:
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- uses: actions/checkout@v3
- name: Run pre-commit
uses: pre-commit/action@v3.0.0
- uses: actions/checkout@v3
with:
repository: adafruit/ci-arduino

2
.gitignore vendored
View file

@ -1,2 +0,0 @@
.idea
.pio

View file

@ -1,25 +0,0 @@
# SPDX-FileCopyrightText: 2020 Diego Elio Pettenò
#
# SPDX-License-Identifier: Unlicense
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-yaml
- id: trailing-whitespace
- id: end-of-file-fixer
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v15.0.7
hooks:
- id: clang-format
exclude: ^(examples/.*.ino)
types_or: [c++, c, header]
- repo: https://github.com/codespell-project/codespell
rev: v2.2.4
hooks:
- id: codespell
exclude: ^(tools/esp_stub.py)
args: [-w]

View file

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

View file

@ -0,0 +1,184 @@
// This sketch program ESP32 by flashing bin file from SD Card
// Hardware wiring:
// - Brain GPIO28 <-> ESP32 IO0
// - Brain Reset <-> ESP32 Enable
// - Brain TX/RX <-> ESP32 RX/TX
// required for Host MSC block device
#include "SdFat.h"
// required for USB host
#include "pio_usb.h"
#include "Adafruit_TinyUSB.h"
#include "Adafruit_TestBed_Brains.h"
#define ESP32_RESET 27
#define ESP32_IO0 28
//#define ESP32_BAUDRATE 921600
#define ESP32_BAUDRATE 115200
// CDC Host object
Adafruit_USBH_CDC SerialHost;
// Defined an boot rom object that use UART Serial1
ESP32BootROMClass ESP32BootROM(SerialHost, ESP32_IO0, ESP32_RESET);
// Bin files header to program
#define BOARD_FEATHER_S2 0
#define BOARD_FEATHER_S3 1
#define BOARD_DEVKIT_S2 2
#define BOARD_DEVKIT_S3 3
// select which bins to flash
#define BIN_FILES BOARD_FEATHER_S2
#if BIN_FILES == BOARD_FEATHER_S2
#include "feather_esp32s2_binaries.h"
#elif BIN_FILES == BOARD_FEATHER_S3
#include "feather_esp32s3_binaries.h"
#elif BIN_FILES == BOARD_DEVKIT_S2
#include "esp32s2_devkit_binaries.h"
#elif BIN_FILES == BOARD_DEVKIT_S3
#include "esp32s3_devkit_binaries.h"
#endif
struct {
uint32_t addr;
esp32_zipfile_t const * zfile;
} bin_list [] =
{
#if BIN_FILES == BOARD_FEATHER_S2
{ 0x1000 , &esp32s2_feather_test_ino_bootloader },
{ 0x8000 , &esp32s2_feather_test_ino_partitions },
{ 0xe000 , &boot_app0 },
{ 0x10000 , &esp32s2_feather_test_ino },
{ 0x2d0000, &tinyuf2 },
#elif BIN_FILES == BOARD_FEATHER_S3
{ 0x0000 , &esp32s3_feather_test_ino_bootloader },
{ 0x8000 , &esp32s3_feather_test_ino_partitions },
{ 0xe000 , &boot_app0 },
{ 0x10000 , &esp32s3_feather_test_ino },
{ 0x2d0000, &tinyuf2 },
#elif BIN_FILES == BOARD_DEVKIT_S2
{ 0x1000 , &Blink_ino_bootloader },
{ 0x8000 , &Blink_ino_partitions },
{ 0xe000 , &boot_app0 },
{ 0x10000 , &Blink_ino },
#elif BIN_FILES == BOARD_DEVKIT_S3
{ 0x0000 , &Blink_ino_bootloader },
{ 0x8000 , &Blink_ino_partitions },
{ 0xe000 , &boot_app0 },
{ 0x10000 , &Blink_ino },
#endif
};
enum {
BIN_LIST_COUNT = sizeof(bin_list)/sizeof(bin_list[0])
};
//--------------------------------------------------------------------+
// Setup and Loop on Core0
//--------------------------------------------------------------------+
void print_speed(size_t count, uint32_t ms) {
float count_k = count / 1000.0F;
float sec = ms / 1000.0F;
float speed = count_k / sec;
Brain.LCD_printf(0, "%.01fKB %.01fs", count_k, sec);
Brain.LCD_printf(1, "Spd: %.01f KB/s", speed);
}
void setup() {
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("Tester Brains: Programming ESP32 with UART!");
// sync: wait for Brain.begin() called in core1 before accessing SD or other peripherals
while (!Brain.inited()) delay(10);
while ( !Brain.esp32_begin(&ESP32BootROM, ESP32_BAUDRATE) ) {
delay(100);
}
// Writing bin files
size_t total_bytes = 0;
uint32_t ms = millis();
for(size_t i=0; i<BIN_LIST_COUNT; i++) {
Brain.LCD_printf("Flashing file %u", i);
size_t wr_count = Brain.esp32_programFlashDefl(bin_list[i].zfile, bin_list[i].addr);
total_bytes += wr_count;
if (!wr_count) {
Brain.LCD_printf_error("Failed to flash");
}
}
print_speed(total_bytes, millis() - ms);
Brain.esp32_end();
// reset ESP32 to run new firmware
Brain.targetReset();
}
void loop() {
}
//--------------------------------------------------------------------+
// 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();
// Since we only support 1 CDC interface with Tester (also CFG_TUH_CDC = 1)
// the index will always be 0 for SerialHost
// SerialHost.setInterfaceIndex(0);
SerialHost.begin(115200);
Brain.LCD_printf(0, "No USB attached");
Brain.LCD_printf(1, "Plug your device");
}
// core1's loop: process usb host task on core1
void loop1() {
Brain.USBHost.task();
// periodically flush SerialHost if connected
if ( SerialHost && SerialHost.connected() ) {
SerialHost.flush();
}
yield();
}
//--------------------------------------------------------------------+
// TinyUSB Host callbacks
// Note: running in the same core where Brain.USBHost.task() is called
//--------------------------------------------------------------------+
extern "C" {
// Invoked when device is mounted (configured)
void tuh_mount_cb (uint8_t daddr)
{
uint16_t vid, pid;
tuh_vid_pid_get(daddr, &vid, &pid);
Serial.printf("Device attached, address = %d\r\n", daddr);
Brain.LCD_printf("USBID %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");
}
}

View file

@ -0,0 +1,120 @@
// This sketch program ESP32 by flashing bin file from on-flash (with .h header)
// Hardware wiring:
// - Brain GPIO28 <-> ESP32 IO0
// - Brain Reset <-> ESP32 Enable
// - Brain TX/RX <-> ESP32 RX/TX
// required for Host MSC block device
#include "SdFat.h"
// required for USB host
#include "pio_usb.h"
#include "Adafruit_TinyUSB.h"
#include "Adafruit_TestBed_Brains.h"
#define ESP32_RESET 27
#define ESP32_IO0 28
#define ESP32_BAUDRATE 2000000
//#define ESP32_BAUDRATE 921600
//#define ESP32_BAUDRATE 115200
// Bin files header to program
#define BIN_WIFI_AP_SKETCH 0
#define BIN_NINA_1_7_4 1
// select which bins to flash
#define BIN_FILES BIN_WIFI_AP_SKETCH
#if BIN_FILES == BIN_WIFI_AP_SKETCH
#include "wifi_ap_binaries.h"
#elif BIN_FILES == BIN_NINA_1_7_4
#include "nina_1_7_4_binaries.h"
#endif
// Compressed binaries files generated by tools/esp_compress.py
struct {
uint32_t addr;
esp32_zipfile_t const * zfile;
} bin_list[] = {
#if BIN_FILES == BIN_WIFI_AP_SKETCH
{ 0x10000, &WiFiAccessPoint_ino },
{ 0x1000 , &WiFiAccessPoint_ino_bootloader },
{ 0x8000 , &WiFiAccessPoint_ino_partitions },
{ 0xe000 , &boot_app0 },
#elif BIN_FILES == BIN_NINA_1_7_4
{ 0x00000, &NINA_W102_1_7_4 },
#endif
};
enum {
BIN_LIST_COUNT = sizeof(bin_list)/sizeof(bin_list[0])
};
// Defined an boot rom object that use UART Serial1
ESP32BootROMClass ESP32BootROM(Serial1, ESP32_IO0, ESP32_RESET);
//--------------------------------------------------------------------+
// Setup and Loop on Core0
//--------------------------------------------------------------------+
void print_speed(size_t count, uint32_t ms) {
float count_k = count / 1000.0F;
float sec = ms / 1000.0F;
float speed = count_k / sec;
Brain.LCD_printf(0, "%.01fKB %.01fs", count_k, sec);
Brain.LCD_printf(1, "Spd: %.01f KB/s", speed);
}
void setup() {
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("Tester Brains: Programming ESP32 with UART!");
Brain.begin();
while ( !Brain.esp32_begin(&ESP32BootROM, ESP32_BAUDRATE) ) {
// retry syncing
delay(100);
}
// Writing bin files
size_t total_bytes = 0;
uint32_t ms = millis();
for(size_t i=0; i<BIN_LIST_COUNT; i++) {
Brain.LCD_printf(0, "Flashing file %u", i);
size_t wr_count = Brain.esp32_programFlashDefl(bin_list[i].zfile, bin_list[i].addr);
total_bytes += wr_count;
if (!wr_count) {
Brain.LCD_printf_error("Failed to flash");
}
}
print_speed(total_bytes, millis() - ms);
Brain.esp32_end();
// reset ESP32 to run new firmware
Brain.targetReset();
}
void loop() {
}
//--------------------------------------------------------------------+
// 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() {
}
// core1's loop: process usb host task on core1
void loop1() {
yield();
}

View file

@ -0,0 +1,129 @@
// This sketch program ESP32 by flashing bin file from SD Card
// Hardware wiring:
// - Brain GPIO28 <-> ESP32 IO0
// - Brain Reset <-> ESP32 Enable
// - Brain TX/RX <-> ESP32 RX/TX
// required for Host MSC block device
#include "SdFat.h"
// required for USB host
#include "pio_usb.h"
#include "Adafruit_TinyUSB.h"
#include "Adafruit_TestBed_Brains.h"
#define ESP32_RESET 27
#define ESP32_IO0 28
#define ESP32_BAUDRATE 2000000
//#define ESP32_BAUDRATE 921600
//#define ESP32_BAUDRATE 115200
// Bin files on SDCard to program
// These files can be generated by any of Arduino sketches
// The example use WiFiAccessPoint sketch, which we can verify its running image
// by simply scan for existence of ssid "YourAP"
struct {
uint32_t addr;
const char* fpath;
} bin_list [] = {
{ 0x1000 , "esp32/WiFiAccessPoint/WiFiAccessPoint.ino.bootloader.bin" },
{ 0x8000 , "esp32/WiFiAccessPoint/WiFiAccessPoint.ino.partitions.bin" },
{ 0xe000 , "esp32/WiFiAccessPoint/boot_app0.bin" },
{ 0x10000 , "esp32/WiFiAccessPoint/WiFiAccessPoint.ino.bin" },
};
enum {
BIN_LIST_COUNT = sizeof(bin_list)/sizeof(bin_list[0])
};
// Defined an boot rom object that use UART Serial1
ESP32BootROMClass ESP32BootROM(Serial1, ESP32_IO0, ESP32_RESET);
//--------------------------------------------------------------------+
// Setup and Loop on Core0
//--------------------------------------------------------------------+
void prepare_sd(void) {
if (!Brain.SD_detected()) {
Brain.LCD_printf(0, "No SD Card");
while ( !Brain.SD_detected() ) delay(10);
}
if ( !Brain.SD_begin(SD_SCK_MHZ(16)) ) {
Brain.LCD_printf(0, "SD init failed");
while(1) delay(10);
}
Brain.LCD_printf(0, "SD mounted");
// Print out file on SD if Serial is connected
if (Serial) {
Serial.println();
Serial.println("SD Contents:");
Serial.printf("Card size = %0.1f GB\n", 0.000000512 * Brain.SD.card()->sectorCount());
Brain.SD.ls(LS_R | LS_DATE | LS_SIZE);
}
}
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("Tester Brains: Programming ESP32 with UART!");
Brain.begin();
// prepare SD Card
prepare_sd();
while ( !Brain.esp32_begin(&ESP32BootROM, ESP32_BAUDRATE) ) {
// retry syncing
delay(100);
}
// Writing bin files
size_t total_bytes = 0;
uint32_t ms = millis();
for(size_t i=0; i<BIN_LIST_COUNT; i++) {
Brain.LCD_printf("Flashing file %u", i);
size_t wr_count = Brain.esp32_programFlash(bin_list[i].fpath, bin_list[i].addr);
total_bytes += wr_count;
if (!wr_count) {
Brain.LCD_printf_error("Failed to flash");
}
}
print_speed(total_bytes, millis() - ms);
Brain.esp32_end(false);
// reset ESP32 to run new firmware
Brain.targetReset();
}
void loop() {
}
//--------------------------------------------------------------------+
// 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() {
}
// core1's loop: process usb host task on core1
void loop1() {
yield();
}

View file

@ -1,151 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2023 Ha Thach (tinyusb.org) for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef ESP_BINARIES_H_
#define ESP_BINARIES_H_
// Configuration: select which bins to flash
#define BIN_FILES BIN_C6_BLINK_IO8
//--------------------------------------------------------------------+
// LIST OF BINARIES
//--------------------------------------------------------------------+
#define BIN_ESP32_NINA_1_7_4 0 // nina 1.7.4
#define BIN_ESP32_WIFI_AP_SKETCH 1 // esp32 AP with ssdi "YourAP"
#define BIN_FEATHER_ESP32_V2_BLINKY 2 // Feather esp32 v2 blinky sketch
#define BIN_FEATHER_S2 10 // Feather esp32s2 factory firmware
#define BIN_FEATHER_S3 11 // Feather esp32s3 factory firmware
#define BIN_METRO_S2 12 // Metro esp32s2 factory firmware
#define BIN_DEVKIT_S2 20 // Espressif s2 devkit
#define BIN_DEVKIT_S3 21 // Espressif s3 devkit
#define BIN_FEATHER_8266_BLINKY 30 // Feather esp8266 blinky sketch
#define BIN_C6_BLINK_IO8 40 // Blink sketch for C6 with LED on IO8
//--------------------------------------------------------------------+
// Binaries include
//--------------------------------------------------------------------+
#if BIN_FILES == BIN_ESP32_WIFI_AP_SKETCH
#include "esp_binaries/wifi_ap_binaries.h"
#elif BIN_FILES == BIN_FEATHER_ESP32_V2_BLINKY
#include "esp_binaries/feather_esp32_v2_blinky_binaries.h"
#elif BIN_FILES == BIN_NINA_1_7_4
#include "esp_binaries/nina_1_7_4_binaries.h"
#elif BIN_FILES == BIN_FEATHER_S2
#include "esp_binaries/feather_esp32s2_binaries.h"
#elif BIN_FILES == BIN_METRO_S2
#include "esp_binaries/metro_esp32s2_binaries.h"
#elif BIN_FILES == BIN_FEATHER_S3
#include "esp_binaries/feather_esp32s3_binaries.h"
#elif BIN_FILES == BIN_DEVKIT_S2
#include "esp_binaries/esp32s2_devkit_binaries.h"
#elif BIN_FILES == BIN_DEVKIT_S3
#include "esp_binaries/esp32s3_devkit_binaries.h"
#elif BIN_FILES == BIN_FEATHER_8266_BLINKY
#include "esp_binaries/feather_esp8266_blinky.h"
#elif BIN_FILES == BIN_C6_BLINK_IO8
#include "esp_binaries/c6_blink_io8.h"
#else
#error "Please select BIN_FILES in esp_binaries.h"
#endif
struct {
uint32_t addr;
esp32_zipfile_t const *zfile;
} bin_files[] = {
#if BIN_FILES == BIN_NINA_1_7_4
{0x00000, &NINA_W102_1_7_4},
#elif BIN_FILES == BIN_FEATHER_ESP32_V2_BLINKY
{0x1000, &feather_esp32v2_blinky_bootloader},
{0x8000, &feather_esp32v2_blinky_partitions},
{0xe000, &boot_app0},
{0x10000, &feather_esp32v2_blinky},
#elif BIN_FILES == BIN_FEATHER_S2
{0x1000, &esp32s2_feather_test_ino_bootloader},
{0x8000, &esp32s2_feather_test_ino_partitions},
{0xe000, &boot_app0},
{0x10000, &esp32s2_feather_test_ino},
{0x2d0000, &tinyuf2},
#elif BIN_FILES == BIN_METRO_S2
{0x1000, &selftest_ino_bootloader},
{0x8000, &selftest_ino_partitions},
{0xe000, &boot_app0},
{0x10000, &selftest_ino},
{0x2d0000, &tinyuf2},
#elif BIN_FILES == BIN_FEATHER_S3
{0x0000, &esp32s3_feather_test_ino_bootloader},
{0x8000, &esp32s3_feather_test_ino_partitions},
{0xe000, &boot_app0},
{0x10000, &esp32s3_feather_test_ino},
{0x2d0000, &tinyuf2},
#elif BIN_FILES == BIN_DEVKIT_S2
{0x1000, &Blink_ino_bootloader},
{0x8000, &Blink_ino_partitions},
{0xe000, &boot_app0},
{0x10000, &Blink_ino},
#elif BIN_FILES == BIN_DEVKIT_S3
{0x0000, &Blink_ino_bootloader},
{0x8000, &Blink_ino_partitions},
{0xe000, &boot_app0},
{0x10000, &Blink_ino},
#elif BIN_FILES == BIN_FEATHER_8266_BLINKY
{0x0000, &Blink_ino},
#elif BIN_FILES == BIN_C6_BLINK_IO8
{0x00000, &c6_blink_io8_bootloader},
{0x8000, &c6_blink_io8_partitions},
{0xe000, &boot_app0},
{0x10000, &c6_blink_io8},
#else
#error "Please select BIN_FILES in esp_binaries.h"
#endif
};
enum { BIN_FILES_COUNT = sizeof(bin_files) / sizeof(bin_files[0]) };
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,181 +0,0 @@
// This sketch program ESP32 by flashing bin file via Serial Host.
// Hardware wiring is a bit different between S2/S3 and ESP32 + USB-to-UART chip
// For S2/S3 with native USB
// - Brain GPIO28 <-> ESP32 IO0
// - Brain Reset <-> ESP32 Enable
// - Brain USB Host <-> ESP32 native usb
// For ESP32 with USB-to-UART chip
// - Brain USB Host <-> ESP32 native usb
// - 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_Adafruit_Fork.h"
// required for USB host
#include "pio_usb.h"
#include "Adafruit_TinyUSB.h"
#include "Adafruit_TestBed_Brains.h"
// Change BIN_FILES in esp_binaries.h header to select which binaries to flash
// bin_files[] is defined accordingly
#include "esp_binaries.h"
// 1 if programming ESP32-S2/S3 via native USB
// 0 if programming ESP32/8266 via USB-to-UART chip such as FTDI/CP210x/CH9102f
#define ESP32_NATIVE_USB 1
#define ESP32_RESET 27
#define ESP32_IO0 28
// Note: baudrate does not matter if programming S2/S3 native USB
// But does matter if programming ESP32/8266 via USB-to-UART chip
#define ESP32_BAUDRATE (115200*8)
// CDC Host object
Adafruit_USBH_CDC SerialHost;
#if ESP32_NATIVE_USB
// Declare BootROM with IO0 and Reset will use GPIO for bootloader reset
// This is typically for programming ESP32-S2/S3 via native USB
ESP32BootROMClass ESP32BootROM(SerialHost, ESP32_IO0, ESP32_RESET);
#else
// Defined an boot rom object that use SerialHost
// Declare BootROM without IO0 and Reset will use SerialHost.setDtrRts() for bootloader reset
// This is for programming ESP32/8266 via USB-to-UART chip such as FTDI/CP210x/CH9102f
ESP32BootROMClass ESP32BootROM(SerialHost);
#endif
//--------------------------------------------------------------------+
// Setup and Loop on Core0
//--------------------------------------------------------------------+
void print_speed(size_t count, uint32_t ms) {
float count_k = count / 1000.0F;
float sec = ms / 1000.0F;
float speed = count_k / sec;
Brain.LCD_printf(0, "%.01fKB %.01fs", count_k, sec);
Brain.LCD_printf(1, "Spd: %.01f KB/s", speed);
}
// Reset using DTR/RTS
void reset_with_dtr_rts(uint32_t ms) {
SerialHost.setDtrRts(false, true);
delay(ms);
SerialHost.setDtrRts(false, false);
}
void setup() {
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("Tester Brains: Programming ESP32 with SerialHost!");
// sync: wait for Brain.begin() called in core1 before accessing SD or other peripherals
while (!Brain.inited()) delay(10);
while (!Brain.esp32_begin(&ESP32BootROM, ESP32_BAUDRATE)) {
delay(100);
}
// Writing bin files
size_t total_bytes = 0;
uint32_t ms = millis();
for (size_t i = 0; i < BIN_FILES_COUNT; i++) {
Brain.LCD_printf("Flashing file %u", i);
Serial.printf("File %s\r\n", bin_files[i].zfile->name);
size_t wr_count = Brain.esp32_programFlashDefl(bin_files[i].zfile, bin_files[i].addr);
total_bytes += wr_count;
if (!wr_count) {
Brain.LCD_printf_error("Failed to flash");
}
}
print_speed(total_bytes, millis() - ms);
Brain.esp32_end();
// reset ESP32 to run new firmware
Brain.targetReset(); // reset using Reset pin GPIO27
// Reset using DTR if GPIO27 is not connected
reset_with_dtr_rts(20);
}
void loop() {
}
//--------------------------------------------------------------------+
// 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();
// Since we only support 1 CDC interface with Tester (also CFG_TUH_CDC = 1)
// the index will always be 0 for SerialHost
SerialHost.begin(115200);
Brain.LCD_printf(0, "No USB attached");
Brain.LCD_printf(1, "Plug your device");
}
// core1's loop: process usb host task on core1
void loop1() {
if (Brain.esp32_s3_inReset()) {
// Note: S3 has an USB-OTG errata
// https://www.espressif.com/sites/default/files/documentation/esp32-s3_errata_en.pdf
// which is walkarounded by idf/arduino-esp32 to always mux JTAG to USB for
// uploading and/or power on. Afterwards USB-OTG will be set up if selected
// so. However rp2040 USBH is running too fast and can actually retrieve
// device/configuration descriptor of JTAG before the OTG is fully setup.
// We delay a bit here
delay(500);
Brain.esp32_s3_clearReset();
}
Brain.USBHost.task();
// periodically flush SerialHost if connected
if (SerialHost && SerialHost.connected()) {
SerialHost.flush();
}
yield();
}
//--------------------------------------------------------------------+
// TinyUSB Host callbacks
// Note: running in the same core where Brain.USBHost.task() is called
//--------------------------------------------------------------------+
extern "C" {
// Invoked when device is mounted (configured)
void tuh_mount_cb(uint8_t daddr) {
uint16_t vid, pid;
tuh_vid_pid_get(daddr, &vid, &pid);
Serial.printf("Device attached, address = %d\r\n", daddr);
Brain.LCD_printf("USBID %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 CDC interface is mounted
// idx is index of cdc interface in the internal pool.
void tuh_cdc_mount_cb(uint8_t idx) {
// bind SerialHost object to this interface index
SerialHost.mount(idx);
}
// Invoked when a device with CDC interface is unmounted
void tuh_cdc_umount_cb(uint8_t idx) {
// unbind SerialHost if this interface is unmounted
SerialHost.umount(idx);
}
}

View file

@ -1,142 +0,0 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2023 Ha Thach (tinyusb.org) for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef ESP_BINARIES_H_
#define ESP_BINARIES_H_
// Configuration: select which bins to flash
#define BIN_FILES BIN_C6_BLINK_IO8
//--------------------------------------------------------------------+
// LIST OF BINARIES
//--------------------------------------------------------------------+
#define BIN_ESP32_NINA_1_7_4 0 // nina 1.7.4
#define BIN_ESP32_WIFI_AP_SKETCH 1 // esp32 AP with ssdi "YourAP"
#define BIN_FEATHER_S2 10 // Feather esp32s2 factory firmware
#define BIN_FEATHER_S3 11 // Feather esp32s3 factory firmware
#define BIN_METRO_S2 12 // Metro esp32s2 factory firmware
#define BIN_DEVKIT_S2 20 // Espressif s2 devkit
#define BIN_DEVKIT_S3 21 // Espressif s3 devkit
#define BIN_ESP8266 30 // Espressif esp8266
#define BIN_C6_BLINK_IO8 40 // Blink sketch for C6 with LED on IO8
//--------------------------------------------------------------------+
// Binaries include
//--------------------------------------------------------------------+
#if BIN_FILES == BIN_ESP32_WIFI_AP_SKETCH
#include "esp_binaries/wifi_ap_binaries.h"
#elif BIN_FILES == BIN_NINA_1_7_4
#include "esp_binaries/nina_1_7_4_binaries.h"
#elif BIN_FILES == BIN_FEATHER_S2
#include "esp_binaries/feather_esp32s2_binaries.h"
#elif BIN_FILES == BIN_METRO_S2
#include "esp_binaries/metro_esp32s2_binaries.h"
#elif BIN_FILES == BIN_FEATHER_S3
#include "esp_binaries/feather_esp32s3_binaries.h"
#elif BIN_FILES == BIN_DEVKIT_S2
#include "esp_binaries/esp32s2_devkit_binaries.h"
#elif BIN_FILES == BIN_DEVKIT_S3
#include "esp_binaries/esp32s3_devkit_binaries.h"
#elif BIN_FILES == BIN_ESP8266
#include "esp_binaries/esp8266_binaries.h"
#elif BIN_FILES == BIN_C6_BLINK_IO8
#include "esp_binaries/c6_blink_io8.h"
#else
#error "Please select BIN_FILES in esp_binaries.h"
#endif
struct {
uint32_t addr;
esp32_zipfile_t const *zfile;
} bin_files[] = {
#if BIN_FILES == BIN_NINA_1_7_4
{0x00000, &NINA_W102_1_7_4},
#elif BIN_FILES == BIN_FEATHER_S2
{0x1000, &esp32s2_feather_test_ino_bootloader},
{0x8000, &esp32s2_feather_test_ino_partitions},
{0xe000, &boot_app0},
{0x10000, &esp32s2_feather_test_ino},
{0x2d0000, &tinyuf2},
#elif BIN_FILES == BIN_METRO_S2
{0x1000, &selftest_ino_bootloader},
{0x8000, &selftest_ino_partitions},
{0xe000, &boot_app0},
{0x10000, &selftest_ino},
{0x2d0000, &tinyuf2},
#elif BIN_FILES == BIN_FEATHER_S3
{0x0000, &esp32s3_feather_test_ino_bootloader},
{0x8000, &esp32s3_feather_test_ino_partitions},
{0xe000, &boot_app0},
{0x10000, &esp32s3_feather_test_ino},
{0x2d0000, &tinyuf2},
#elif BIN_FILES == BIN_DEVKIT_S2
{0x1000, &Blink_ino_bootloader},
{0x8000, &Blink_ino_partitions},
{0xe000, &boot_app0},
{0x10000, &Blink_ino},
#elif BIN_FILES == BIN_DEVKIT_S3
{0x0000, &Blink_ino_bootloader},
{0x8000, &Blink_ino_partitions},
{0xe000, &boot_app0},
{0x10000, &Blink_ino},
#elif BIN_FILES == BIN_ESP8266
{0x00000, &esp8266_blink_io0},
#elif BIN_FILES == BIN_C6_BLINK_IO8
{0x00000, &c6_blink_io8_bootloader},
{0x8000, &c6_blink_io8_partitions},
{0xe000, &boot_app0},
{0x10000, &c6_blink_io8},
#else
#error "Please select BIN_FILES in esp_binaries.h"
#endif
};
enum { BIN_FILES_COUNT = sizeof(bin_files) / sizeof(bin_files[0]) };
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,134 +0,0 @@
// This sketch program ESP32 by flashing bin file from on-flash (with .h header)
// Supported/tested ESP MCU are: ESP32, ESP32-S2, ESP32-S3, ESP8266
// Hardware wiring:
// - Brain GPIO28 <-> ESP32 IO0
// - Brain Reset <-> ESP32 Enable
// - Brain TX/RX <-> ESP32 RX/TX
// 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"
// Change BIN_FILES in esp_binaries.h header to select which binaries to flash
// bin_files[] is defined accordingly
#include "esp_binaries.h"
#define ESP32_RESET 27
#define ESP32_IO0 28
#define ESP32_BAUDRATE 2000000
//#define ESP32_BAUDRATE 1500000
//#define ESP32_BAUDRATE 921600
//#define ESP32_BAUDRATE 115200
// Defined an boot rom object that use UART Serial1
ESP32BootROMClass ESP32BootROM(Serial1, ESP32_IO0, ESP32_RESET);
//--------------------------------------------------------------------+
// Setup and Loop on Core0
//--------------------------------------------------------------------+
void print_speed(size_t count, uint32_t ms) {
float count_k = count / 1000.0F;
float sec = ms / 1000.0F;
float speed = count_k / sec;
Brain.LCD_printf(0, "%.01fKB %.01fs", count_k, sec);
Brain.LCD_printf(1, "Spd: %.01f KB/s", speed);
}
void setup() {
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("Tester Brains: Programming ESP with UART!");
// sync: wait for Brain.begin() called in core1 before accessing SD or other peripherals
while (!Brain.inited()) delay(10);
while (!Brain.esp32_begin(&ESP32BootROM, ESP32_BAUDRATE)) {
// retry syncing
delay(100);
}
// Writing bin files
size_t total_bytes = 0;
uint32_t ms = millis();
for (size_t i = 0; i < BIN_FILES_COUNT; i++) {
Brain.LCD_printf(0, "Flashing file %u", i);
Serial.printf("File: %s\r\n", bin_files[i].zfile->name);
size_t wr_count = Brain.esp32_programFlashDefl(bin_files[i].zfile, bin_files[i].addr);
total_bytes += wr_count;
if (!wr_count) {
Brain.LCD_printf_error("Failed to flash");
}
}
print_speed(total_bytes, millis() - ms);
Brain.esp32_end();
// reset ESP32 to run new firmware
Brain.targetReset();
}
void loop() {
}
//--------------------------------------------------------------------+
// 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(0, "No USB attached");
Brain.LCD_printf(1, "Plug your device");
}
// core1's loop: process usb host task on core1
void loop1() {
if (Brain.esp32_s3_inReset()) {
// Note: S3 has an USB-OTG errata
// https://www.espressif.com/sites/default/files/documentation/esp32-s3_errata_en.pdf
// which is walkarounded by idf/arduino-esp32 to always mux JTAG to USB for
// uploading and/or power on. Afterwards USB-OTG will be set up if selected
// so. However rp2040 USBH is running too fast and can actually retrieve
// device/configuration descriptor of JTAG before the OTG is fully setup.
// We delay a bit here
delay(500);
Brain.esp32_s3_clearReset();
}
Brain.USBHost.task();
yield();
}
//--------------------------------------------------------------------+
// TinyUSB Host callbacks
// Note: running in the same core where Brain.USBHost.task() is called
//--------------------------------------------------------------------+
extern "C" {
// Invoked when device is mounted (configured)
void tuh_mount_cb(uint8_t daddr) {
uint16_t vid, pid;
tuh_vid_pid_get(daddr, &vid, &pid);
Serial.printf("Device attached, address = %d\r\n", daddr);
Brain.LCD_printf("USBID %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");
}
}

View file

@ -6,7 +6,7 @@
// - Brain's USB host to Target USB
// required for Host MSC block device
#include "SdFat_Adafruit_Fork.h"
#include "SdFat.h"
// required for USB host
#include "pio_usb.h"
@ -17,7 +17,11 @@
#include "Adafruit_TestBed_Brains.h"
// file path on SDCard to program
// RP2040 Boot VID/PID
#define BOOT_VID 0x2e8a
#define BOOT_PID 0x0003
// file path on SDCard to prograom
#define TEST_FILE_PATH "nrf/feather_nrf52840/bleblink.bin"
// DAP interface for nRF5x
@ -62,10 +66,8 @@ void setup() {
// erase chip before programming
Brain.dap_eraseChip();
// for nrf52840 don't use crc32 as it is not supported.
// Note: verify is with reading back increase programming time by 2x
uint32_t ms = millis();
size_t copied_bytes = Brain.dap_programFlash(TEST_FILE_PATH, 0, true, false);
size_t copied_bytes = Brain.dap_programFlash(TEST_FILE_PATH, 0);
ms = millis() - ms;
print_speed(copied_bytes, ms);
@ -108,7 +110,9 @@ void tuh_mount_cb (uint8_t dev_addr)
uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid);
Brain.LCD_printf("USBID %04x:%04x", vid, pid);
if ( !(vid == BOOT_VID && pid == BOOT_PID) ) {
Brain.LCD_printf(1, "UnkDev %04x:%04x", vid, pid);
}
}
/// Invoked when device is unmounted (bus reset/unplugged)

View file

@ -1,121 +0,0 @@
// This sketch program SAMD with bin file from SDCard using Adafruit_DAP
// Hardware wiring:
// - Brain's header Reset <-> Target Reset
// - Brain's header SWDIO <-> Target SWDIO
// - Brain's header SWCLK <-> Target SWCLK
// - Brain's USB host to Target USB
// required for Host MSC block device
#include "SdFat_Adafruit_Fork.h"
// required for USB host
#include "pio_usb.h"
#include "Adafruit_TinyUSB.h"
// required for DAP programming
#include "Adafruit_DAP.h"
#include "Adafruit_TestBed_Brains.h"
// file path on SDCard to program
#define TEST_FILE_PATH "nrf/feather_nrf52840/bleblink.bin"
// DAP interface for nRF5x
Adafruit_DAP_nRF5x dap;
//--------------------------------------------------------------------+
// Setup and Loop on Core0
//--------------------------------------------------------------------+
void print_speed(size_t count, uint32_t ms) {
Brain.LCD_printf(0, "%.01fKB in %.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("Tester Brains: nRF52840 programming !");
// sync: wait for Brain.usbh_begin() called in core1 before accessing SD or other peripherals
while (!Brain.usbh_inited()) delay(10);
Brain.SD_begin(SD_SCK_MHZ(16));
// Print out file on SD if Serial is connected
if (Serial) {
Serial.println();
Serial.println("SD Contents:");
Serial.printf("Card size = %0.1f GB\n", 0.000000512 * Brain.SD.card()->sectorCount());
Brain.SD.ls(LS_R | LS_SIZE);
}
Brain.targetReset();
Brain.dap_begin(&dap);
Brain.dap_connect();
Brain.dap_unprotectBoot();
// erase chip before programming
Brain.dap_eraseChip();
// for nrf52840 don't use crc32 as it is not supported.
// Note: verify is with reading back increase programming time by 2x
uint32_t ms = millis();
size_t copied_bytes = Brain.dap_programFlash(TEST_FILE_PATH, 0, true, false);
ms = millis() - ms;
print_speed(copied_bytes, ms);
Brain.dap_protectBoot();
Brain.dap_disconnect();
Brain.targetReset();
}
void loop() {
}
//--------------------------------------------------------------------+
// 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");
}
// 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
//--------------------------------------------------------------------+
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);
Brain.LCD_printf("USBID %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");
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,135 +0,0 @@
// 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_Adafruit_Fork.h"
#include "SdFat.h"
// required for USB host
#include "pio_usb.h"
@ -60,6 +60,11 @@ void print_speed(size_t count, uint32_t ms) {
}
void setup() {
// For debugging tinyusb
if (CFG_TUSB_DEBUG) {
Serial1.begin(115200);
}
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("Tester Brains: UF2 copy from SD to USBH FS test!");
@ -70,7 +75,7 @@ void setup() {
// prepare SD Card
prepare_sd();
// wait for USB filesystem is mounted. USB host bit-banging and task is
// wait for USB filesytem is mounted. USB host bit-banging and task is
// processed on core1
while (!is_usbfs_mounted) delay(10);
@ -79,7 +84,7 @@ void setup() {
Serial.println("Copying from SD to USBHFS: " UF2_FILE_PATH);
uint32_t ms = millis();
size_t copied_bytes = Brain.rp2_programUF2(UF2_FILE_PATH);
size_t copied_bytes = Brain.rp2040_programUF2(UF2_FILE_PATH);
print_speed(copied_bytes, millis() - ms);
@ -88,7 +93,6 @@ void setup() {
}
void loop() {
Serial.flush();
}
//--------------------------------------------------------------------+
@ -104,7 +108,7 @@ void setup1() {
Brain.LCD_printf(1, "No USB Device");
// reset rp2040 target into Boot Rom, default bootsel = 28, reset duration = 10 ms
Brain.rp2_targetResetBootRom();
Brain.rp2040_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_Adafruit_Fork.h"
#include "SdFat.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_Adafruit_Fork.h"
#include "SdFat.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_Adafruit_Fork.h"
#include "SdFat.h"
// required for USB host
#include "pio_usb.h"

View file

@ -1,112 +0,0 @@
// This sketch program SAMD with bin file from SDCard using Adafruit_DAP
// Hardware wiring:
// - Brain's header Reset <-> Target Reset
// - Brain's header SWDIO <-> Target SWDIO
// - Brain's header SWCLK <-> Target SWCLK
// - Brain's USB host to Target USB
// required for Host MSC block device
#include "SdFat_Adafruit_Fork.h"
// required for USB host
#include "pio_usb.h"
#include "Adafruit_TinyUSB.h"
// required for DAP programming
#include "Adafruit_DAP.h"
#include "Adafruit_TestBed_Brains.h"
// file path on SDCard to hold nrf52840 binary
#define READ_FILE_PATH "nrf/readback.bin"
#define READ_SIZE (1024u*1024u) // 1 MB
// DAP interface for nRF5x
Adafruit_DAP_nRF5x dap;
//--------------------------------------------------------------------+
// Setup and Loop on Core0
//--------------------------------------------------------------------+
void print_speed(size_t count, uint32_t ms) {
Brain.LCD_printf(0, "%.01fKB in %.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("Tester Brains: Reading nRF52840 to SD Card!");
// sync: wait for Brain.usbh_begin() called in core1 before accessing SD or other peripherals
while (!Brain.usbh_inited()) delay(10);
Brain.SD_begin(SD_SCK_MHZ(16));
// Print out file on SD if Serial is connected
if (Serial) {
Serial.println();
Serial.println("SD Contents:");
Serial.printf("Card size = %0.1f GB\n", 0.000000512 * Brain.SD.card()->sectorCount());
Brain.SD.ls(LS_R | LS_SIZE);
}
Brain.targetReset();
Brain.dap_begin(&dap);
Brain.dap_connect();
uint32_t ms = millis();
size_t nbytes = Brain.dap_readFlash(READ_FILE_PATH, 0, READ_SIZE);
ms = millis() - ms;
print_speed(nbytes, ms);
Brain.dap_disconnect();
Brain.targetReset();
}
void loop() {
}
//--------------------------------------------------------------------+
// 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");
}
// 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
//--------------------------------------------------------------------+
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);
Brain.LCD_printf("USBID %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");
}
}

View file

@ -1,115 +0,0 @@
// Testing USB host hardware on Brain by printing out VID/PID of attached device
// to LCD. Also determine if device support MSC or HID
// 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"
typedef struct {
uint16_t vid;
uint16_t pid;
bool mounted;
} dev_info_t;
// CFG_TUH_DEVICE_MAX is defined by tusb_config header
dev_info_t dev_info[CFG_TUH_DEVICE_MAX] = { 0 };
//--------------------------------------------------------------------+
// Setup and Loop on Core0
//--------------------------------------------------------------------+
void setup() {
}
void loop() {
// Scan and print VID/PID
uint8_t dev_count = 0;
for(uint8_t daddr=1; daddr < CFG_TUH_DEVICE_MAX+1; daddr++) {
dev_info_t const* dev = &dev_info[daddr-1];
if ( dev->mounted ) {
dev_count++;
Brain.LCD_printf("[%u] %04X:%04X", daddr, dev->vid, dev->pid);
}
delay(1000);
}
if ( dev_count == 0 ) {
Brain.LCD_printf(0, "No USB attached");
Brain.LCD_printf(1, "Plug your device");
}else {
Brain.LCD_printf("Devices num: %u", dev_count);
delay(1000);
}
}
//--------------------------------------------------------------------+
// Setup and Loop on Core1
//--------------------------------------------------------------------+
// call usbh_begin() hrere to make pio usb background task run on core1
// NOTE: Brain.begin() should be called here as well to prevent race condition
void setup1() {
Serial.begin(115200);
// while (!Serial) delay(10);
Serial.println("Tester Brains USB Host test!");
// Init Brain peripherals
Brain.begin();
// Init Brain USB Host
Brain.usbh_begin();
Brain.LCD_printf(0, "No USB attached");
Brain.LCD_printf(1, "Plug your device");
}
// core1's loop: process usb host task on core1
void loop1()
{
Brain.USBHost.task();
}
//--------------------------------------------------------------------+
// TinyUSB Host callbacks
//--------------------------------------------------------------------+
extern "C" {
// Invoked when device is mounted (configured)
void tuh_mount_cb (uint8_t daddr)
{
dev_info_t* dev = &dev_info[daddr-1];
dev->mounted = true;
tuh_vid_pid_get(daddr, &dev->vid, &dev->pid);
Serial.printf("Device attached, address = %d\r\n", daddr);
}
/// Invoked when device is unmounted (bus reset/unplugged)
void tuh_umount_cb(uint8_t daddr)
{
dev_info_t* dev = &dev_info[daddr-1];
dev->mounted = false;
Serial.printf("Device removed, address = %d\r\n", daddr);
}
// Invoked when a device with CDC interface is mounted
// idx is index of cdc interface in the internal pool.
void tuh_cdc_mount_cb(uint8_t idx) {
}
// Invoked when a device with CDC interface is unmounted
void tuh_cdc_umount_cb(uint8_t idx) {
}
}

View file

@ -2,7 +2,7 @@
// to LCD. Also determine if device support MSC or HID
// required for Host MSC block device
#include "SdFat_Adafruit_Fork.h"
#include "SdFat.h"
// required for USB host
#include "pio_usb.h"
@ -13,11 +13,6 @@
// CDC Host object
Adafruit_USBH_CDC SerialHost;
enum {
COLOR_NO_DEV = 0x00000ff,
COLOR_MOUNTED = 0x00ff00,
};
//--------------------------------------------------------------------+
// Setup and Loop on Core0
//--------------------------------------------------------------------+
@ -62,10 +57,9 @@ void setup1() {
// Init Brain USB Host
Brain.usbh_begin();
Brain.setColor(COLOR_NO_DEV);
// Since we only support 1 CDC interface with Tester (also CFG_TUH_CDC = 1)
// the index will always be 0 for SerialHost
// SerialHost.setInterfaceIndex(0);
SerialHost.begin(115200);
Brain.LCD_printf(0, "No USB attached");
@ -95,8 +89,8 @@ void tuh_mount_cb (uint8_t daddr)
tuh_vid_pid_get(daddr, &vid, &pid);
Serial.printf("Device attached, address = %d\r\n", daddr);
Brain.setColor(COLOR_MOUNTED);
Brain.LCD_printf(0, "USBID %04x:%04x", vid, pid);
Brain.LCD_printf(1, "MS %u HID %u CDC %u", tuh_msc_mounted(daddr), tuh_hid_instance_count(daddr), SerialHost.mounted());
}
@ -104,22 +98,9 @@ void tuh_mount_cb (uint8_t daddr)
void tuh_umount_cb(uint8_t daddr)
{
Serial.printf("Device removed, address = %d\r\n", daddr);
Brain.setColor(COLOR_NO_DEV);
Brain.LCD_printf(0, "No USB attached");
Brain.LCD_printf(1, "Plug your device");
}
// Invoked when a device with CDC interface is mounted
// idx is index of cdc interface in the internal pool.
void tuh_cdc_mount_cb(uint8_t idx) {
// bind SerialHost object to this interface index
SerialHost.mount(idx);
}
// Invoked when a device with CDC interface is unmounted
void tuh_cdc_umount_cb(uint8_t idx) {
// unbind SerialHost if this interface is unmounted
SerialHost.umount(idx);
}
}

View file

@ -7,10 +7,9 @@ extern Adafruit_TestBed TB;
#if defined(ARDUINO_ARCH_RP2040) \
|| defined(ARDUINO_ADAFRUIT_QTPY_ESP32S2) \
|| defined(ARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM) \
|| defined(ARDUINO_ADAFRUIT_QTPY_ESP32S3_N4R2) \
|| defined(ARDUINO_ADAFRUIT_QTPY_ESP32S3) \
|| defined(ARDUINO_ADAFRUIT_QTPY_ESP32_PICO) \
|| defined(ARDUINO_SAM_DUE) \
|| defined(ARDUINO_ARCH_RENESAS_UNO)
|| defined(ARDUINO_SAM_DUE)
#define SECONDARY_I2C_PORT &Wire1
#endif
@ -26,7 +25,7 @@ void setup() {
#if defined(ARDUINO_ADAFRUIT_QTPY_ESP32S2) || \
defined(ARDUINO_ADAFRUIT_QTPY_ESP32S3_NOPSRAM) || \
defined(ARDUINO_ADAFRUIT_QTPY_ESP32S3_N4R2) || \
defined(ARDUINO_ADAFRUIT_QTPY_ESP32S3) || \
defined(ARDUINO_ADAFRUIT_QTPY_ESP32_PICO)
// ESP32 is kinda odd in that secondary ports must be manually
// assigned their pins with setPins()!

View file

@ -1,30 +0,0 @@
// Generated by tools/esp_compress.py
#define ESP_BINARIES_COUNT (1)
// const esp32_zipfile_t NINA_W102_1_7_5
const esp32_zipfile_t NINA_W102_1_7_5 = {
.name = "NINA_W102-1.7.5.bin.gz",
.data = NULL,
.compressed_len = 634996,
.uncompressed_len = 1160192,
.md5 =
{
0x07,
0x7c,
0xec,
0x6d,
0xaa,
0x68,
0x13,
0xc5,
0xa4,
0x68,
0x0f,
0x45,
0xc9,
0xd8,
0x77,
0x6b,
},
};

View file

@ -1,146 +0,0 @@
/* This sketch run on SAMD21/SAMD51 to program ESP32 by flashing bin file from SD Card
* Supported/tested ESP MCU are: ESP32, ESP32-S2, ESP32-S3, ESP8266
* Hardware wiring:
* - TB D2 <-> ESP32 IO0
* - TB D3 <-> ESP32 Enable
* - TB TX/RX <-> ESP32 RX/TX
*
* How to run this example:
* 0. Define ESP32_RESET, ESP32_IO0, SD_CS, SD_DETECT in this sketch according to your hardware setup
* 1. Generate compressed binary and its metadata (len, md5 etc..) by running:
* python3 tools/esp_compress.py --sd <directory_of_bin_files>
* For example: python tools/esp_compress.py --sd .
* 2. .bin.gz (e.g NINA_W102-1.7.5.bin.gz) and esp_binaries.h will be generated in the same directory
* 3. Copy esp_binaries.h to this example directory
* 4. Copy .bin.gz files to SD Card within BIN_DIR (defined in this sketch)
* 5. Insert SD Card to board
* 6. Upload this sketch to board
*
* Note: for convenience, this example included generated 'NINA_W102-1.7.5.bin.gz' and 'esp_binaries.h'
* from https://github.com/adafruit/nina-fw/releases/tag/1.7.5 in this example directory.
*/
#include "SdFat_Adafruit_Fork.h"
// #include "Adafruit_TinyUSB.h"
#include "Adafruit_TestBed.h"
//--------------------------------------------------------------------+
// Hardware Configuration
//--------------------------------------------------------------------+
// These are defined in airlift-capable board such PyPortal, PyBadge, etc.
#if defined(ESP32_GPIO0) && defined(ESP32_RESETN)
#define ESP32_RESET ESP32_RESETN
#define ESP32_IO0 ESP32_GPIO0
#else
#define ESP32_RESET 2
#define ESP32_IO0 3
#endif
#if defined(ARDUINO_PYPORTAL_M4)
#define SD_CS 32
#define SD_DETECT 33
#else
#define SD_CS 4
#define SD_DETECT 5 // optional
#endif
#define ESP32_BAUDRATE 2000000
//#define ESP32_BAUDRATE 1500000
//#define ESP32_BAUDRATE 921600
//#define ESP32_BAUDRATE 115200
//--------------------------------------------------------------------+
// Binaries and Path
//--------------------------------------------------------------------+
#define BIN_DIR "/" // SD card's directory that contains bin files
#include "esp_binaries.h"
struct {
uint32_t addr;
esp32_zipfile_t const *zfile;
} bin_files[] = {
{0x00000, &NINA_W102_1_7_5}
};
enum { BIN_FILES_COUNT = sizeof(bin_files) / sizeof(bin_files[0]) };
//--------------------------------------------------------------------+
// Defined an boot rom object that use UART Serial1
ESP32BootROMClass ESP32BootROM(Serial1, ESP32_IO0, ESP32_RESET);
SdFat SD;
File32 fbin;
//--------------------------------------------------------------------+
// Implementation
//--------------------------------------------------------------------+
void print_speed(size_t count, uint32_t ms) {
float count_k = count / 1000.0F;
float sec = ms / 1000.0F;
float speed = count_k / sec;
Serial.print(count_k); Serial.print("KB "); Serial.print(sec); Serial.println("s");
Serial.print("Spd: "); Serial.print(speed); Serial.println(" KB/s");
}
void setup() {
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("TestBed: Programming ESP32 with UART!");
#ifdef SD_DETECT
pinMode(SD_DETECT, INPUT_PULLUP);
if (digitalRead(SD_DETECT) == LOW) {
Serial.println("SD Card not inserted");
while (1) delay(10);
}
#endif
if (!SD.begin(SD_CS, SD_SCK_MHZ(12))) {
Serial.println("SD Card init failed");
while (1) delay(10);
}
Serial.println("SD Card init OK");
TB.begin();
while ( !TB.esp32_begin(&ESP32BootROM, ESP32_BAUDRATE) ) {
// retry syncing
delay(100);
}
// Writing bin files
size_t total_bytes = 0;
uint32_t ms = millis();
for(size_t i=0; i<BIN_FILES_COUNT; i++) {
Serial.printf("Flashing file %u\r\n", i);
Serial.printf("File: %s\r\n", bin_files[i].zfile->name);
char bin_path[128] = BIN_DIR;
strcat(bin_path, bin_files[i].zfile->name);
fbin.open(&SD, bin_path);
if (!fbin) {
Serial.printf("Failed to open file %s\r\n", bin_files[i].zfile->name);
continue;
}
size_t wr_count = TB.esp32_programFlashDefl(bin_files[i].zfile, bin_files[i].addr, &fbin);
total_bytes += wr_count;
if (!wr_count) {
Serial.printf("Failed to flash");
}
fbin.close();
}
print_speed(total_bytes, millis() - ms);
TB.esp32_end();
// reset ESP32 to run new firmware
TB.targetReset();
}
void loop() {
}

View file

@ -1,5 +1,5 @@
name=Adafruit TestBed
version=1.14.2
version=1.7.0
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=Adafruit's internal test bed code library

View file

@ -1,25 +1,10 @@
#include "Adafruit_TestBed.h"
// change to 1 to skip pre-flash md5 check for testing
#define SKIP_PRE_FLASH_MD5_CHECK 0
static inline uint32_t div_ceil(uint32_t v, uint32_t d) {
return (v + d - 1) / d;
}
Adafruit_TestBed::Adafruit_TestBed(void) {
#if defined(ADAFRUIT_METRO_M0_EXPRESS)
neopixelPin = 40;
neopixelNum = 1;
#elif defined(ADAFRUIT_FEATHER_M0_EXPRESS)
neopixelPin = 8;
neopixelNum = 1;
#endif
esp32boot = NULL;
_esp32_flash_defl = false;
_esp32_chip_detect = 0;
_esp32s3_in_reset = false;
}
/**************************************************************************/
@ -48,11 +33,6 @@ void Adafruit_TestBed::begin(void) {
digitalWrite(ledPin, LOW);
}
if (targetResetPin >= 0) {
pinMode(targetResetPin, OUTPUT);
digitalWrite(targetResetPin, HIGH);
}
#if defined(__AVR__)
analogRef = 5.0;
#elif defined(ARDUINO_ARCH_RP2040)
@ -170,23 +150,6 @@ void Adafruit_TestBed::targetPowerCycle(uint16_t off_time) {
targetPower(1);
}
void Adafruit_TestBed::targetReset(uint32_t reset_ms) {
digitalWrite(targetResetPin, LOW);
delay(reset_ms);
digitalWrite(targetResetPin, HIGH);
// Note: S3 has an USB-OTG errata
// https://www.espressif.com/sites/default/files/documentation/esp32-s3_errata_en.pdf
// which is walkarounded by idf/arduino-esp32 to always mux JTAG to USB for
// uploading and/or power on. Afterwards USB-OTG will be set up if selected
// so. However rp2040 USBH is running too fast and can actually retrieve
// device/configuration descriptor of JTAG before the OTG is fully setup.
// Mark this for application usage
if (_esp32_chip_detect == CHIP_DETECT_MAGIC_ESP32S3) {
_esp32s3_in_reset = true;
}
}
/**************************************************************************/
/*!
@brief Read the ADC on a pin and convert it to a voltage
@ -197,7 +160,7 @@ void Adafruit_TestBed::targetReset(uint32_t reset_ms) {
/**************************************************************************/
float Adafruit_TestBed::readAnalogVoltage(uint16_t pin, float multiplier) {
float a = analogRead(pin);
// theSerial->println(a);
theSerial->println(a);
#if defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_ADAFRUIT_QTPY_ESP32C3)
if (a > 3000) {
@ -221,13 +184,11 @@ float Adafruit_TestBed::readAnalogVoltage(uint16_t pin, float multiplier) {
@param name Human readable name for the pin
@param multiplier If there's a resistor divider, put the inverse here
@param value What voltage the pin should be
@param error Percent of error permitted (10 is 10%)
@return True if the pin voltage is within 10% of target
*/
/**************************************************************************/
bool Adafruit_TestBed::testAnalogVoltage(uint16_t pin, const char *name,
float multiplier, float value,
uint8_t error) {
float multiplier, float value) {
float voltage = readAnalogVoltage(pin, multiplier);
theSerial->print(name);
theSerial->print(F(" output voltage: "));
@ -235,13 +196,11 @@ bool Adafruit_TestBed::testAnalogVoltage(uint16_t pin, const char *name,
theSerial->print(F(" V (should be "));
theSerial->print(value);
theSerial->print(" V)...");
if (abs(voltage - value) > (value * error / 100.0)) {
if (abs(voltage - value) > (value / 10.0)) {
theSerial->println("Failed");
return false;
}
theSerial->print(F("OK within "));
theSerial->print(error);
theSerial->println("%");
theSerial->println(F("OK within 10%"));
return true;
}
@ -421,8 +380,7 @@ void Adafruit_TestBed::beep(uint32_t freq, uint32_t duration) {
if (piezoPin < 0)
return;
pinMode(piezoPin, OUTPUT);
#if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_SAM_DUE) && \
!defined(ARDUINO_METRO_ESP32S2)
#if !defined(ARDUINO_ARCH_ESP32) && !defined(ARDUINO_SAM_DUE)
tone(piezoPin, freq, duration);
#else
// suppress compiler warns
@ -455,203 +413,4 @@ void Adafruit_TestBed::beepNblink(void) {
#endif
}
/**************************************************************************/
/*!
@brief light the LED for 500ms, if defined
*/
/**************************************************************************/
void Adafruit_TestBed::blink(void) {
if (ledPin >= 0) {
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH);
}
delay(500);
if (ledPin >= 0) {
digitalWrite(ledPin, LOW);
}
}
//--------------------------------------------------------------------+
// ESP32 Target
//--------------------------------------------------------------------+
bool Adafruit_TestBed::esp32_begin(ESP32BootROMClass *bootrom,
uint32_t baudrate) {
esp32boot = bootrom;
Serial.println("Syncing ESP32");
_esp32_chip_detect = esp32boot->begin(baudrate);
if (_esp32_chip_detect) {
setColor(0xFFFFFF);
Serial.println("Synced OK");
return true;
} else {
Serial.println("Sync failed!");
return false;
}
}
void Adafruit_TestBed::esp32_end(bool reset_esp) {
if (esp32boot->isRunningStub()) {
// skip sending flash_finish to ROM loader here,
// as it causes the loader to exit and run user code
esp32boot->beginFlash(0, 0, esp32boot->getFlashWriteSize());
if (_esp32_flash_defl) {
esp32boot->endFlashDefl(reset_esp);
} else {
esp32boot->endFlash(reset_esp);
}
}
esp32boot->end();
}
bool Adafruit_TestBed::esp32_s3_inReset(void) { return _esp32s3_in_reset; }
void Adafruit_TestBed::esp32_s3_clearReset(void) { _esp32s3_in_reset = false; }
static void print_buf(uint8_t const *buf, size_t len) {
for (size_t i = 0; i < len; i++) {
Serial.print(buf[i], HEX);
}
Serial.println();
}
size_t
Adafruit_TestBed::_esp32_programFlashDefl_impl(const esp32_zipfile_t *zfile,
uint32_t addr, File32 *fsrc) {
if (!esp32boot) {
return 0;
}
// Check if MD5 matches to skip this file
uint8_t esp_md5[16];
#if !SKIP_PRE_FLASH_MD5_CHECK
esp32boot->md5Flash(addr, zfile->uncompressed_len, esp_md5);
Serial.print("Flash MD5: ");
print_buf(esp_md5, 16);
if (0 == memcmp(zfile->md5, esp_md5, 16)) {
Serial.println("MD5 matched");
return zfile->uncompressed_len;
}
#endif
// Write Size is different depending on ROM (1K) or Stub (16KB)
uint32_t const block_size = esp32boot->getFlashWriteSize();
uint8_t *buf = NULL;
bool const use_sdcard = (fsrc != NULL);
if (use_sdcard) {
buf = (uint8_t *)malloc(block_size);
if (!buf) {
Serial.print("No memory ");
Serial.println(block_size);
return 0;
}
}
Serial.print("Compressed ");
Serial.print(zfile->uncompressed_len);
Serial.print(" bytes to ");
Serial.println(zfile->compressed_len);
if (!esp32boot->beginFlashDefl(addr, zfile->uncompressed_len,
zfile->compressed_len)) {
Serial.println("beginFlash failed!");
if (buf) {
free(buf);
}
return 0;
}
_esp32_flash_defl = true;
//------------- Flashing -------------//
uint32_t written = 0;
uint32_t const block_num = div_ceil(zfile->compressed_len, block_size);
for (uint32_t i = 0; i < block_num; i++) {
setLED(HIGH);
// Serial.print("Pckt %lu/%lu", i + 1, block_num);
Serial.print("Packet ");
Serial.print(i + 1);
Serial.print("/");
Serial.println(block_num);
uint32_t const remain = zfile->compressed_len - written;
uint32_t const wr_count = (remain < block_size) ? remain : block_size;
uint8_t const *data;
if (!use_sdcard) {
// file contents is stored in internal flash (e.g rp2040)
data = zfile->data + written;
} else {
// file contents is stored in sdcard
memset(buf, 0xff, block_size); // empty it out
if (wr_count != fsrc->read(buf, wr_count)) {
Serial.println("File contents does not matched with compressed_len");
free(buf);
return 0;
}
data = buf;
}
// Note: flash deflat does not need padding
if (!esp32boot->dataFlashDefl(data, wr_count)) {
Serial.println("Failed to flash");
break;
}
written += wr_count;
setLED(LOW);
}
Serial.println();
// Stub only writes each block to flash after 'ack'ing the receive,
// so do a final dummy operation which will not be 'ack'ed
// until the last block has actually been written out to flash
if (esp32boot->isRunningStub()) {
Serial.println("Dummy read chip detect after final block");
(void)esp32boot->read_chip_detect();
}
//------------- MD5 verification -------------//
Serial.println("Verifying MD5");
esp32boot->md5Flash(addr, zfile->uncompressed_len, esp_md5);
if (0 == memcmp(zfile->md5, esp_md5, 16)) {
Serial.println("MD5 matched");
} else {
Serial.println("MD5 mismatched!!");
Serial.print("File: ");
print_buf(zfile->md5, 16);
Serial.print("ESP : ");
print_buf(esp_md5, 16);
}
if (buf) {
free(buf);
}
return zfile->uncompressed_len;
}
size_t Adafruit_TestBed::esp32_programFlashDefl(const esp32_zipfile_t *zfile,
uint32_t addr) {
return _esp32_programFlashDefl_impl(zfile, addr, NULL);
}
size_t Adafruit_TestBed::esp32_programFlashDefl(const esp32_zipfile_t *zfile,
uint32_t addr, File32 *fsrc) {
return _esp32_programFlashDefl_impl(zfile, addr, fsrc);
}
Adafruit_TestBed TB;

View file

@ -5,9 +5,6 @@
#include "Arduino.h"
#include "Wire.h"
#include "ESP32BootROM.h"
#include "SdFat_Adafruit_Fork.h"
#define RED 0xFF0000
#define YELLOW 0xFFFF00
#define GREEN 0x00FF00
@ -16,14 +13,6 @@
#define PURPLE 0xFF00FF
#define WHITE 0xFFFFFF
typedef struct {
const char *name;
const uint8_t *data;
const uint32_t compressed_len;
const uint32_t uncompressed_len;
const uint8_t md5[16];
} esp32_zipfile_t;
/**************************************************************************/
/*!
@brief A helper class for making test beds and functions. Lots of handy lil
@ -44,11 +33,9 @@ public:
void targetPower(bool on);
void targetPowerCycle(uint16_t off_time = 10);
void targetReset(uint32_t reset_ms = 20);
float readAnalogVoltage(uint16_t pin, float multiplier = 1);
bool testAnalogVoltage(uint16_t pin, const char *name, float multiplier,
float value, uint8_t error = 10);
float value);
bool testpins(uint8_t a, uint8_t b, uint8_t *allpins, uint8_t num_allpins);
@ -59,29 +46,10 @@ public:
void beep(uint32_t freq, uint32_t duration);
void beepNblink(void);
void blink(void);
uint32_t timestamp(void);
void printTimeTaken(bool restamp = false);
//--------------------------------------------------------------------+
// ESP32 Target
//--------------------------------------------------------------------+
bool esp32_begin(ESP32BootROMClass *bootrom, uint32_t baudrate);
void esp32_end(bool reset_esp = false);
// program esp32 target with compressed data stored in internal flash
size_t esp32_programFlashDefl(const esp32_zipfile_t *zfile, uint32_t addr);
// program esp32 target with compressed file from SDCard
size_t esp32_programFlashDefl(const esp32_zipfile_t *zfile, uint32_t addr,
File32 *fsrc);
bool esp32_s3_inReset(void);
void esp32_s3_clearReset(void);
ESP32BootROMClass *esp32boot; // ESP32 ROM
//////////////////
TwoWire *theWire = &Wire; ///< The I2C port used in scanning
Stream *theSerial = &Serial; ///< The Serial port used for debugging
@ -92,8 +60,6 @@ public:
int16_t targetPowerPin = -1; ///< Set to a target power pin if used
bool targetPowerPolarity = HIGH; ///< What to set the power pin to, for ON
int targetResetPin = -1; ///< Set to target reset pin if used
int16_t neopixelPin = -1; ///< The neopixel connected pin if any
uint8_t neopixelNum = 0; ///< How many neopixels are on board, if any
Adafruit_NeoPixel *pixels =
@ -104,15 +70,6 @@ public:
private:
uint32_t millis_timestamp = 0; ///< A general purpose timestamp
bool _esp32_flash_defl;
uint32_t _esp32_chip_detect;
bool _esp32s3_in_reset;
size_t _esp32_programFlashDefl_impl(const esp32_zipfile_t *zfile,
uint32_t addr, File32 *fsrc);
};
extern Adafruit_TestBed TB;
#endif

View file

@ -22,9 +22,9 @@
* THE SOFTWARE.
*/
#ifdef ARDUINO_ARCH_RP2040
#ifdef ARDUINO_RASPBERRY_PI_PICO
#include "SdFat_Adafruit_Fork.h"
#include "SdFat.h"
#include "pio_usb.h"
#include "Adafruit_DAP.h"
@ -34,16 +34,8 @@
#define USBHOST_RHPORT 1
// Workaround force F_CPU to 240MHz for programming RP2350 due to handshake
// timeout
#if F_CPU != 120000000L && F_CPU != 240000000L
#error "F_CPU must be set to either 120Mhz or 240Mhz for pio-usb host"
#endif
Adafruit_TestBed_Brains Brain;
volatile bool LCD_semaphore = false;
// Simple and low code CRC calculation (copied from PicoOTA)
class BrainCRC32 {
public:
@ -71,6 +63,10 @@ private:
uint32_t crc;
};
static inline uint32_t div_ceil(uint32_t v, uint32_t d) {
return (v + d - 1) / d;
}
/**************************************************************************/
/*!
@brief Initializer, sets up the timestamp, neopixels, piezo, led,
@ -96,11 +92,13 @@ Adafruit_TestBed_Brains::Adafruit_TestBed_Brains() {
_usbh_dp_pin = 20; // USB Host D+
_vbus_en_pin = 22; // USB Host VBus enable
targetResetPin = 27;
_target_rst = 27;
_target_swdio = 2;
_target_swdclk = 3;
dap = NULL;
esp32boot = NULL;
_esp32_flash_defl = false;
}
void Adafruit_TestBed_Brains::begin(void) {
@ -112,8 +110,8 @@ void Adafruit_TestBed_Brains::begin(void) {
neopixelNum = 1;
pinMode(neopixelPin, OUTPUT);
pinMode(targetResetPin, OUTPUT);
digitalWrite(targetResetPin, HIGH);
pinMode(_target_rst, OUTPUT);
digitalWrite(_target_rst, HIGH);
pinMode(_sd_detect_pin, INPUT_PULLUP);
pinMode(_vbus_en_pin, OUTPUT);
@ -135,13 +133,20 @@ void Adafruit_TestBed_Brains::begin(void) {
bool Adafruit_TestBed_Brains::inited(void) { return _inited; }
void Adafruit_TestBed_Brains::targetReset(uint32_t reset_ms) {
digitalWrite(_target_rst, LOW);
delay(reset_ms);
digitalWrite(_target_rst, HIGH);
}
//--------------------------------------------------------------------+
// RP2040 Target
//--------------------------------------------------------------------+
void Adafruit_TestBed_Brains::rp2_targetResetBootRom(int bootsel_pin,
void Adafruit_TestBed_Brains::rp2040_targetResetBootRom(int bootsel_pin,
uint32_t reset_ms) {
pinMode(bootsel_pin, OUTPUT);
digitalWrite(bootsel_pin, LOW);
targetReset(reset_ms);
@ -152,41 +157,7 @@ void Adafruit_TestBed_Brains::rp2_targetResetBootRom(int bootsel_pin,
pinMode(bootsel_pin, INPUT);
}
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) {
size_t Adafruit_TestBed_Brains::rp2040_programUF2(const char *fpath) {
File32 fsrc = SD.open(fpath);
if (!fsrc) {
Serial.printf("SD: cannot open file: %s\r\n", fpath);
@ -194,6 +165,7 @@ size_t Adafruit_TestBed_Brains::rp2_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);
@ -252,17 +224,17 @@ bool Adafruit_TestBed_Brains::dap_begin(Adafruit_DAP *dp) {
dap = dp;
return dap->begin(_target_swdclk, _target_swdio, targetResetPin,
return dap->begin(_target_swdclk, _target_swdio, _target_rst,
dap_err_hanlder);
}
bool Adafruit_TestBed_Brains::dap_connect(uint32_t swj_clock) {
bool Adafruit_TestBed_Brains::dap_connect(void) {
if (!dap) {
return false;
}
LCD_printf("Connecting...");
if (!dap->targetConnect(swj_clock)) {
if (!dap->targetConnect()) {
return false;
}
@ -272,6 +244,10 @@ bool Adafruit_TestBed_Brains::dap_connect(uint32_t swj_clock) {
LCD_printf(0, "Unknown MCU");
LCD_printf(1, "ID = %08X", dsu_did);
while (1) {
delay(1);
}
return false;
}
@ -301,9 +277,9 @@ bool Adafruit_TestBed_Brains::dap_unprotectBoot(void) {
return false;
}
Serial.println("Unlock chip...");
LCD_printf("Unlock chip...");
bool ret = dap->unprotectBoot();
Serial.println(ret ? "OK" : "Failed");
LCD_printf(ret ? "OK" : "Failed");
return ret;
}
@ -312,9 +288,9 @@ bool Adafruit_TestBed_Brains::dap_protectBoot(void) {
return false;
}
Serial.println("Lock chip...");
LCD_printf("Lock chip...");
bool ret = dap->protectBoot();
Serial.println(ret ? "OK" : "Failed");
LCD_printf(ret ? "OK" : "Failed");
return ret;
}
@ -335,15 +311,14 @@ bool Adafruit_TestBed_Brains::dap_eraseChip(void) {
dap->erase();
ms = millis() - ms;
LCD_printf("Erased in %.02fs", ms / 1000.0F);
LCD_printf("done in %.02fs", ms / 1000.0F);
}
return true;
}
size_t Adafruit_TestBed_Brains::dap_programFlash(const char *fpath,
uint32_t addr, bool do_verify,
bool do_crc32) {
uint32_t addr) {
if (!dap) {
return 0;
}
@ -386,8 +361,7 @@ size_t Adafruit_TestBed_Brains::dap_programFlash(const char *fpath,
return 0;
}
LCD_printf("Programming...");
uint32_t ms = millis();
LCD_printf("Programming..");
BrainCRC32 crc32;
dap->program_start(addr, fsize);
@ -395,42 +369,22 @@ size_t Adafruit_TestBed_Brains::dap_programFlash(const char *fpath,
uint32_t addr_tmp = addr;
while (fsrc.available()) {
memset(buf, 0xff, bufsize); // empty it out
uint32_t rd_count = fsrc.read(buf, bufsize);
setLED(HIGH);
// don't verify each write if we use crc32
if (!dap->programFlash(addr_tmp, buf, bufsize, !do_crc32 && do_verify)) {
Serial.printf("Failed to program block at %08lX\n", addr_tmp);
free(buf);
fsrc.close();
return addr_tmp - addr;
}
if (do_crc32) {
dap->programBlock(addr_tmp, buf, bufsize);
crc32.add(buf, rd_count);
}
setLED(LOW);
addr_tmp += bufsize;
setLED(LOW);
}
Serial.printf("Programming end, t = %lu ms\r\n", millis(), millis() - ms);
if (do_crc32) {
ms = millis();
Serial.printf("CRC32 start\r\n", ms);
uint32_t target_crc = dap->computeFlashCRC32(addr, fsize);
Serial.printf("CRC32 end, t = %lu ms\r\n", millis(), millis() - ms);
if (target_crc != crc32.get()) {
LCD_printf("CRC Failed");
Serial.printf("CRC mismtached: %08lX != %08lX\n", crc32.get(),
target_crc);
} else {
LCD_printf("Done!");
}
Serial.printf("CRC mismtached: %08lX != %08lX\n", crc32.get(), target_crc);
} else {
LCD_printf("Done!");
}
@ -441,47 +395,222 @@ size_t Adafruit_TestBed_Brains::dap_programFlash(const char *fpath,
return fsize;
}
size_t Adafruit_TestBed_Brains::dap_readFlash(const char *fpath, uint32_t addr,
size_t size) {
if (!dap) {
//--------------------------------------------------------------------+
// ESP32 Target
//--------------------------------------------------------------------+
bool Adafruit_TestBed_Brains::esp32_begin(ESP32BootROMClass *bootrom,
uint32_t baudrate) {
esp32boot = bootrom;
LCD_printf("Syncing ESP32");
bool ret = esp32boot->begin(baudrate);
if (ret) {
LCD_printf("Synced OK");
} else {
LCD_printf_error("Sync failed!");
}
return ret;
}
void Adafruit_TestBed_Brains::esp32_end(bool reset_esp) {
if (esp32boot->isRunningStub()) {
// skip sending flash_finish to ROM loader here,
// as it causes the loader to exit and run user code
esp32boot->beginFlash(0, 0, esp32boot->getFlashWriteSize());
if (_esp32_flash_defl) {
esp32boot->endFlashDefl(reset_esp);
} else {
esp32boot->endFlash(reset_esp);
}
}
esp32boot->end();
}
size_t
Adafruit_TestBed_Brains::esp32_programFlashDefl(const esp32_zipfile_t *zfile,
uint32_t addr) {
if (!esp32boot) {
return 0;
}
size_t bufsize = 4096;
uint8_t *buf = (uint8_t *)malloc(bufsize);
// Check if MD5 matches to skip this file
uint8_t esp_md5[16];
#if 1 // change to 0 to skip pre-flash md5 check for testing
esp32boot->md5Flash(addr, zfile->uncompressed_len, esp_md5);
if (0 == memcmp(zfile->md5, esp_md5, 16)) {
LCD_printf(2, "MD5 matched");
return zfile->uncompressed_len;
}
#endif
// Write Size is different depending on ROM (1K) or Stub (16KB)
uint32_t const block_size = esp32boot->getFlashWriteSize();
Serial.printf("Compressed %lu bytes to %lu\r\n", zfile->uncompressed_len,
zfile->compressed_len);
if (!esp32boot->beginFlashDefl(addr, zfile->uncompressed_len,
zfile->compressed_len)) {
LCD_printf_error("beginFlash failed!");
} else {
_esp32_flash_defl = true;
uint32_t const block_num = div_ceil(zfile->compressed_len, block_size);
//------------- Flashing -------------//
uint8_t const *data = zfile->data;
uint32_t remain = zfile->compressed_len;
for (uint32_t i = 0; i < block_num; i++) {
setLED(HIGH);
LCD_printf(1, "Pckt %u/%u", i + 1, block_num);
uint32_t const wr_count = MIN(block_size, remain);
// Note: flash deflat does not need padding
if (!esp32boot->dataFlashDefl(data, wr_count)) {
LCD_printf_error("Failed to flash");
break;
}
setLED(LOW);
data += wr_count;
remain -= wr_count;
}
Serial.println();
// Stub only writes each block to flash after 'ack'ing the receive,
// so do a final dummy operation which will not be 'ack'ed
// until the last block has actually been written out to flash
if (esp32boot->isRunningStub()) {
(void)esp32boot->read_chip_detect();
}
//------------- MD5 verification -------------//
esp32boot->md5Flash(addr, zfile->uncompressed_len, esp_md5);
if (0 == memcmp(zfile->md5, esp_md5, 16)) {
LCD_printf(2, "MD5 matched");
} else {
LCD_error(NULL, "MD5 mismatched!!");
Serial.printf("File: ");
for (size_t i = 0; i < 16; i++) {
Serial.printf("%02X ", zfile->md5[i]);
}
Serial.println();
Serial.printf("ESP : ");
for (size_t i = 0; i < 16; i++) {
Serial.printf("%02X ", esp_md5[i]);
}
Serial.println();
}
}
return zfile->uncompressed_len;
}
size_t Adafruit_TestBed_Brains::esp32_programFlash(const char *fpath,
uint32_t addr) {
if (!esp32boot) {
return 0;
}
// Write Size is different depending on ROM (1K) or Stub (16KB)
uint32_t const block_size = esp32boot->getFlashWriteSize();
uint8_t *buf = (uint8_t *)malloc(block_size);
if (!buf) {
LCD_printf_error("No memory %u\n", block_size);
return 0;
}
File32 fsrc = SD.open(fpath, O_CREAT | O_WRONLY);
File32 fsrc = SD.open(fpath);
if (!fsrc) {
Serial.printf("SD: cannot open file: %s\r\n", fpath);
return 0;
}
uint32_t fsize = fsrc.fileSize();
uint32_t total_count = 0;
LCD_printf("Reading...");
Serial.printf("fsize = %lu, block size = %lu\r\n", fsize, block_size);
size_t remain = size;
while (remain) {
uint32_t count = min(remain, bufsize);
if (!esp32boot->beginFlash(addr, fsize, block_size)) {
LCD_printf_error("beginFlash failed!");
} else {
LCD_printf("#Packets %u", div_ceil(fsize, block_size));
MD5Builder md5;
md5.begin();
//------------- Flashing -------------//
while (fsrc.available()) {
memset(buf, 0xff, block_size); // empty it out
uint32_t const rd_count = fsrc.read(buf, block_size);
setLED(HIGH);
if (!dap->dap_read_block(addr, buf, (int)count)) {
Serial.printf("Failed to read block at %08lX\n", addr);
Serial.printf("#");
if (!esp32boot->dataFlash(buf, block_size)) {
LCD_printf_error("Failed to flash");
break;
}
setLED(LOW);
fsrc.write(buf, count);
LCD_printf("%d remaining", remain);
addr += count;
remain -= count;
md5.add(buf, rd_count);
total_count += rd_count;
}
Serial.println();
// Stub only writes each block to flash after 'ack'ing the receive,
// so do a final dummy operation which will not be 'ack'ed
// until the last block has actually been written out to flash
if (esp32boot->isRunningStub()) {
(void)esp32boot->read_chip_detect();
}
fsrc.close();
LCD_printf("Done!");
//------------- MD5 verification -------------//
md5.calculate();
Serial.printf("md5 = %s\r\n", md5.toString().c_str());
return size - remain;
uint8_t file_md5[16];
md5.getBytes(file_md5);
uint8_t esp_md5[16];
esp32boot->md5Flash(addr, fsize, esp_md5);
if (0 == memcmp(file_md5, esp_md5, 16)) {
LCD_printf("MD5 matched");
} else {
LCD_printf_error("MD5 mismatched!!");
Serial.printf("File: ");
for (size_t i = 0; i < 16; i++) {
Serial.printf("%02X ", file_md5[i]);
}
Serial.println();
Serial.printf("ESP : ");
for (size_t i = 0; i < 16; i++) {
Serial.printf("%02X ", esp_md5[i]);
}
Serial.println();
}
}
free(buf);
fsrc.close();
return total_count;
}
//--------------------------------------------------------------------+
@ -514,225 +643,16 @@ bool Adafruit_TestBed_Brains::SD_begin(uint32_t max_clock) {
//--------------------------------------------------------------------+
// LCD
//--------------------------------------------------------------------+
#define NOP1 __asm volatile("nop");
#define NOP2 NOP1 NOP1
#define NOP3 NOP2 NOP1
#define NOP4 NOP2 NOP2
#define NOP5 NOP4 NOP1
#define NOP6 NOP4 NOP2
#define NOP7 NOP4 NOP3
#define NOP8 NOP4 NOP4
#define NOP9 NOP8 NOP1
#define NOP10 NOP8 NOP2
#define NOP11 NOP8 NOP3
#define NOP12 NOP8 NOP4
#define NOP13 NOP8 NOP5
#define NOP14 NOP8 NOP6
#define NOP15 NOP8 NOP7
#define NOP16 NOP8 NOP8
#define NOP17 NOP16 NOP1
#define NOP18 NOP16 NOP2
#define NOP19 NOP16 NOP3
#define NOP20 NOP16 NOP4
#define NOP21 NOP16 NOP5
#define NOP22 NOP16 NOP6
#define NOP23 NOP16 NOP7
#define NOP24 NOP16 NOP8
#define NOP25 NOP16 NOP9
#define NOP26 NOP16 NOP10
#define NOP27 NOP16 NOP11
#define NOP28 NOP16 NOP12
#define NOP29 NOP16 NOP13
#define NOP30 NOP16 NOP14
#define NOP31 NOP16 NOP15
#define NOP32 NOP16 NOP16
#define NOP33 NOP32 NOP1
#define NOP34 NOP32 NOP2
#define NOP35 NOP32 NOP3
#define NOP36 NOP32 NOP4
#define NOP37 NOP32 NOP5
#define NOP38 NOP32 NOP6
#define NOP39 NOP32 NOP7
#define NOP40 NOP32 NOP8
#define NOP41 NOP32 NOP9
#define NOP42 NOP32 NOP10
#define NOP43 NOP32 NOP11
#define NOP44 NOP32 NOP12
#define NOP45 NOP32 NOP13
#define NOP46 NOP32 NOP14
#define NOP47 NOP32 NOP15
#define NOP48 NOP32 NOP16
#define NOP49 NOP48 NOP1
#define NOP50 NOP48 NOP2
#define NOP51 NOP48 NOP3
#define NOP52 NOP48 NOP4
#define NOP53 NOP48 NOP5
#define NOP54 NOP48 NOP6
#define NOP55 NOP48 NOP7
#define NOP56 NOP48 NOP8
#define NOP57 NOP48 NOP9
#define NOP58 NOP48 NOP10
#define NOP59 NOP48 NOP11
#define NOP60 NOP48 NOP12
#define NOP61 NOP48 NOP13
#define NOP62 NOP48 NOP14
#define NOP63 NOP48 NOP15
#define NOP64 NOP48 NOP16
#define NOP65 NOP64 NOP1
#define NOP66 NOP64 NOP2
#define NOP67 NOP64 NOP3
#define NOP68 NOP64 NOP4
#define NOP69 NOP64 NOP5
#define NOP70 NOP64 NOP6
#define NOP71 NOP64 NOP7
#define NOP72 NOP64 NOP8
#define NOP73 NOP64 NOP9
#define NOP74 NOP64 NOP10
#define NOP75 NOP64 NOP11
#define NOP76 NOP64 NOP12
#define NOP77 NOP64 NOP13
#define NOP78 NOP64 NOP14
#define NOP79 NOP64 NOP15
#define NOP80 NOP64 NOP16
#define NOP81 NOP80 NOP1
#define NOP82 NOP80 NOP2
#define NOP83 NOP80 NOP3
#define NOP84 NOP80 NOP4
#define NOP85 NOP80 NOP5
#define NOP86 NOP80 NOP6
#define NOP87 NOP80 NOP7
#define NOP88 NOP80 NOP8
#define NOP89 NOP80 NOP9
#define NOP90 NOP80 NOP10
#define NOP91 NOP80 NOP11
#define NOP92 NOP80 NOP12
#define NOP93 NOP80 NOP13
#define NOP94 NOP80 NOP14
#define NOP95 NOP80 NOP15
#define NOP96 NOP80 NOP16
#define NOP97 NOP96 NOP1
#define NOP98 NOP96 NOP2
#define NOP99 NOP96 NOP3
#define NOP100 NOP96 NOP4
#define NOP101 NOP100 NOP1
#define NOP102 NOP100 NOP2
#define NOP103 NOP100 NOP3
#define NOP104 NOP100 NOP4
#define NOP105 NOP100 NOP5
#define NOP106 NOP100 NOP6
#define NOP107 NOP100 NOP7
#define NOP108 NOP100 NOP8
#define NOP109 NOP100 NOP9
#define NOP110 NOP100 NOP10
#define NOP111 NOP100 NOP11
#define NOP112 NOP100 NOP12
#define NOP113 NOP100 NOP13
#define NOP114 NOP100 NOP14
#define NOP115 NOP100 NOP15
#define NOP116 NOP100 NOP16
#define NOP117 NOP116 NOP1
#define NOP118 NOP116 NOP2
#define NOP119 NOP116 NOP3
#define NOP120 NOP116 NOP4
#define NOP121 NOP116 NOP5
#define NOP122 NOP116 NOP6
#define NOP123 NOP116 NOP7
#define NOP124 NOP116 NOP8
#define NOP125 NOP116 NOP9
#define NOP126 NOP116 NOP10
#define NOP127 NOP116 NOP11
#define NOP128 NOP116 NOP12
#define NOP129 NOP128 NOP1
#define NOP130 NOP128 NOP2
#define NOP131 NOP128 NOP3
#define NOP132 NOP128 NOP4
#define NOP133 NOP128 NOP5
#define NOP134 NOP128 NOP6
#define NOP135 NOP128 NOP7
#define NOP136 NOP128 NOP8
#define NOP137 NOP128 NOP9
#define NOP138 NOP128 NOP10
#define NOP139 NOP128 NOP11
#define NOP140 NOP128 NOP12
#define NOP141 NOP128 NOP13
#define NOP142 NOP128 NOP14
#define NOP143 NOP128 NOP15
#define NOP144 NOP128 NOP16
#define NOP145 NOP144 NOP1
#define NOP146 NOP144 NOP2
#define NOP147 NOP144 NOP3
#define NOP148 NOP144 NOP4
#define NOP149 NOP144 NOP5
#define NOP150 NOP144 NOP6
#define NOP151 NOP144 NOP7
#define NOP152 NOP144 NOP8
#define NOP153 NOP144 NOP9
#define NOP154 NOP144 NOP10
#define NOP155 NOP144 NOP11
#define NOP156 NOP144 NOP12
#define NOP157 NOP144 NOP13
#define NOP158 NOP144 NOP14
#define NOP159 NOP144 NOP15
#define NOP160 NOP144 NOP16
#define NOP161 NOP160 NOP1
#define NOP162 NOP160 NOP2
#define NOP163 NOP160 NOP3
#define NOP164 NOP160 NOP4
#define NOP165 NOP160 NOP5
#define NOP166 NOP160 NOP6
#define NOP167 NOP160 NOP7
#define NOP168 NOP160 NOP8
#define NOP169 NOP160 NOP9
#define NOP170 NOP160 NOP10
#define NOP171 NOP160 NOP11
#define NOP172 NOP160 NOP12
#define NOP173 NOP160 NOP13
#define NOP174 NOP160 NOP14
#define NOP175 NOP160 NOP15
#define NOP176 NOP160 NOP16
#define NOP177 NOP176 NOP1
#define NOP178 NOP176 NOP2
#define NOP179 NOP176 NOP3
#define NOP180 NOP176 NOP4
#define NOP181 NOP176 NOP5
#define NOP182 NOP176 NOP6
#define NOP183 NOP176 NOP7
#define NOP184 NOP176 NOP8
#define NOP185 NOP176 NOP9
#define NOP186 NOP176 NOP10
#define NOP187 NOP176 NOP11
#define NOP188 NOP176 NOP12
#define NOP189 NOP176 NOP13
#define NOP190 NOP176 NOP14
#define NOP191 NOP176 NOP15
#define NOP192 NOP176 NOP16
#define NOP193 NOP192 NOP1
#define NOP194 NOP192 NOP2
#define NOP195 NOP192 NOP3
#define NOP196 NOP192 NOP4
#define NOP197 NOP192 NOP5
#define NOP198 NOP192 NOP6
#define NOP199 NOP192 NOP7
#define NOP200 NOP192 NOP8
#define _NOP_COUNT(n) NOP##n
#define NOP_COUNT(n) _NOP_COUNT(n)
void __no_inline_not_in_flash_func(Adafruit_TestBed_Brains::setColor)(
uint32_t color) {
static uint32_t end_us = 0;
static uint32_t last_color = 0x123456;
if (last_color == color) {
// no need to update
return;
}
last_color = color;
uint8_t r = (uint8_t)(color >> 16); // red
uint8_t g = (uint8_t)(color >> 8); // green
uint8_t b = (uint8_t)color; // blue
// 1s = 1.000.000 us --> 120.000.000 nop
// 1 us -> 120 nop
// full frame, 1.25 us -> 150 nop
// - T1H 0,76 us -> 91 nop
// - T0H 0,36 us -> 43 nop
void Adafruit_TestBed_Brains::setColor(uint32_t color) {
uint8_t r = (uint8_t)(color >> 16), g = (uint8_t)(color >> 8),
b = (uint8_t)color;
uint8_t buf[3] = {r, g, b};
uint8_t *ptr, *end, p, bitMask;
@ -743,107 +663,65 @@ void __no_inline_not_in_flash_func(Adafruit_TestBed_Brains::setColor)(
p = *ptr++;
bitMask = 0x80;
// wait for previous frame to finish
enum { FRAME_TIME_US = 300 };
uint32_t now = end_us;
while (now - end_us < FRAME_TIME_US) {
now = micros();
if (now < end_us) {
// micros() overflow
end_us = now;
}
}
uint32_t const isr_context = save_and_disable_interrupts();
/* Neopixel is 800 KHz, 1T = 1.25 us = 150 nop (120Mhz), 300 nop (240Mhz)
- T1H = 0.8 us, T1L = 0.45 us
- T0H = 0.4 us, T0L = 0.85 us
If F_CPU is 120 MHz: 120 nop = 1us -> 1 nop = 8.33 ns
- T1H = 0.8 us = 96 nop, T1L = 0.45 us = 54 nop
- T0H = 0.4 us = 48 nop, T0L = 0.85 us = 102 nop
If F_CPU is 240 MHz: 240 nop = 1us -> 1 nop = 4.17 ns
- T1H = 0.8 us = 192 nop, T1L = 0.45 us = 108 nop
- T0H = 0.4 us = 96 nop, T0L = 0.85 us = 204 nop
Due to overhead the number of NOP is actually smaller, also M33 run faster
(higher IPC) therefore these are hand tuned,
*/
#if defined(ARDUINO_RASPBERRY_PI_PICO)
// value for rp2040 at 120MHz
#define T1H_CYCLE 90
#define T1L_CYCLE 39
#define T0H_CYCLE 42
#define T0L_CYCLE 84
#define LOOP_OVERHEAD_CYCLE 10 // overhead for if/else and loop
#elif defined(ARDUINO_RASPBERRY_PI_PICO_2)
// value for rp2350 at 120MHz
#define T1H_CYCLE 190
#define T1L_CYCLE 90
#define T0H_CYCLE 88
#define T0L_CYCLE 180
#define LOOP_OVERHEAD_CYCLE 5
#endif
while (1) {
// 800 KHz
for (;;) {
if (p & bitMask) {
// T1H 0.8 us = 96 nop (without overhead)
// T1H 0,76 us -> 91 nop
sio_hw->gpio_set = pinMask;
NOP_COUNT(T1H_CYCLE);
#if F_CPU == 240000000L
NOP_COUNT(T1H_CYCLE);
#endif
asm("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop;");
// T1L 0.45 = 54 - 10 (ifelse) - 5 (overhead) = 44 nop
// 150 - 91 = 59 nop
sio_hw->gpio_clr = pinMask;
NOP_COUNT(T1L_CYCLE);
#if F_CPU == 240000000L
NOP_COUNT(T1L_CYCLE);
#endif
asm("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop;");
} else {
// T0H 0.4 us = 48 cycles
// T0H 0,36 us -> 43 nop
sio_hw->gpio_set = pinMask;
NOP_COUNT(T0H_CYCLE);
#if F_CPU == 240000000L
NOP_COUNT(T0H_CYCLE);
#endif
asm("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop;");
// T0L 0.85 us = 102 - 10 (ifelse) - 5 (overhead) = 87 nop
// 150 - 43 = 107 nop
sio_hw->gpio_clr = pinMask;
NOP_COUNT(T0L_CYCLE);
#if F_CPU == 240000000L
NOP_COUNT(T0L_CYCLE);
#endif
asm("nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop; nop; nop; nop;");
}
if (bitMask >>= 1) {
// not full byte, shift to next bit
NOP_COUNT(LOOP_OVERHEAD_CYCLE);
} else {
// probably take 10 nops
// if a full byte is sent, next to another byte
if (ptr >= end) {
if (0 == (bitMask >>= 1)) {
if (ptr >= end)
break;
}
p = *ptr++;
bitMask = 0x80;
}
#if F_CPU == 240000000L
NOP_COUNT(LOOP_OVERHEAD_CYCLE);
#endif
}
restore_interrupts(isr_context);
end_us = micros();
}
void Adafruit_TestBed_Brains::lcd_write(uint8_t linenum, char linebuf[17]) {
// wait for semaphore to release
while (LCD_semaphore)
yield();
LCD_semaphore = true;
// fill the rest with spaces
memset(linebuf + strlen(linebuf), ' ', 16 - strlen(linebuf));
linebuf[16] = 0;
@ -855,7 +733,6 @@ void Adafruit_TestBed_Brains::lcd_write(uint8_t linenum, char linebuf[17]) {
Serial.flush();
_lcd_line = 1 - linenum;
LCD_semaphore = false;
}
#define _LCD_PRINTF(_line, _format) \
@ -913,14 +790,15 @@ void Adafruit_TestBed_Brains::usbh_setVBus(bool en) {
bool Adafruit_TestBed_Brains::usbh_begin(void) {
// Check for CPU frequency, must be multiple of 120Mhz for bit-banging USB
uint32_t cpu_hz = clock_get_hz(clk_sys);
if (cpu_hz % 12000000UL) {
if (cpu_hz != 120000000UL && cpu_hz != 240000000UL) {
while (!Serial) {
delay(10); // wait for native usb
}
Serial.printf("Error: CPU Clock = %lu, PIO USB require CPU clock must be "
"multiple of 12 Mhz\r\n",
"multiple of 120 Mhz\r\n",
cpu_hz);
Serial.println("Change your CPU Clock to 12*n Mhz in Menu->CPU Speed");
Serial.printf("Change your CPU Clock to either 120 or 240 Mhz in Menu->CPU "
"Speed \r\n");
while (1) {
delay(1);
}

View file

@ -1,16 +1,26 @@
#ifndef ADAFRUIT_TESTBED_BRAINS_H
#define ADAFRUIT_TESTBED_BRAINS_H
#ifdef ARDUINO_ARCH_RP2040
#include "SdFat_Adafruit_Fork.h"
#ifdef ARDUINO_RASPBERRY_PI_PICO
#include "Adafruit_TestBed.h"
#include "SdFat.h"
#include <LiquidCrystal.h>
#include "Adafruit_DAP.h"
#include "Adafruit_TinyUSB.h"
#include "ESP32BootROM.h"
#include "MD5Builder.h"
typedef struct {
const char *name;
const uint8_t *data;
const uint32_t compressed_len;
const uint32_t uncompressed_len;
const uint8_t md5[16];
} esp32_zipfile_t;
/**************************************************************************/
/*!
@brief A helper class for making RP2040 "Tester Brains"
@ -49,31 +59,24 @@ public:
bool usbh_mountFS(uint8_t dev_addr);
bool usbh_umountFS(uint8_t dev_addr);
//--------------------------------------------------------------------+1
// RP2 (rp2040 and rp2350) Target
// Target
void targetReset(uint32_t reset_ms = 20);
//--------------------------------------------------------------------+
// reset rp2 target to Boot ROM
void rp2_targetResetBootRom(int bootsel_pin = 28, uint32_t reset_ms = 20);
// RP2040 Target
//--------------------------------------------------------------------+
// reset rp2040 target to Boot ROM
void rp2040_targetResetBootRom(int bootsel_pin = 28, uint32_t reset_ms = 20);
// 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
// program rp2040 target by copying UF2 file from SDCard
// return number of copied bytes (typically uf2 file size)
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); }
size_t rp2040_programUF2(const char *fpath);
//--------------------------------------------------------------------+
// DAP (samd21/51, nrf5x, stm32f4 etc..) Target
//--------------------------------------------------------------------+
bool dap_begin(Adafruit_DAP *dp);
bool dap_connect(uint32_t swj_clock = 50);
bool dap_connect(void);
void dap_disconnect(void);
bool dap_unprotectBoot(void);
@ -83,12 +86,21 @@ public:
// program dap target with file from SDCard
// return number of programmed bytes
// Note: if do_crc32 is false, we will verify each write by reading back
size_t dap_programFlash(const char *fpath, uint32_t addr,
bool do_verify = true, bool do_crc32 = true);
size_t dap_programFlash(const char *fpath, uint32_t addr);
// read dap target flash to file on SDCard
size_t dap_readFlash(const char *fpath, uint32_t addr, size_t size);
//--------------------------------------------------------------------+
// ESP32 Target
//--------------------------------------------------------------------+
bool esp32_begin(ESP32BootROMClass *bootrom, uint32_t baudrate);
void esp32_end(bool reset_esp = false);
// program esp32 target with file from SDCard
// return number of programmed bytes
size_t esp32_programFlash(const char *fpath, uint32_t addr);
// program flash with compressed using zipfile struct
size_t esp32_programFlashDefl(const esp32_zipfile_t *zfile, uint32_t addr);
//--------------------------------------------------------------------+
// Public Variables
@ -108,6 +120,9 @@ public:
// Dap
Adafruit_DAP *dap;
// ESP32 ROM
ESP32BootROMClass *esp32boot;
private:
bool _inited;
uint8_t _lcd_line;
@ -117,9 +132,12 @@ private:
int _vbus_en_pin;
int _usbh_dp_pin;
int _target_rst;
int _target_swdio;
int _target_swdclk;
bool _esp32_flash_defl;
void lcd_write(uint8_t linenum, char buf[17]);
};

View file

@ -19,18 +19,10 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// https://docs.espressif.com/projects/esptool/en/latest/esp32/advanced-topics/serial-protocol.html
#if defined(ARDUINO_ARCH_RP2040) || defined(__SAMD51__) || \
defined(TARGET_RP2040) || defined(ARDUINO_ARCH_ESP32) || \
(defined(ARDUINO_ARCH_SAMD) && defined(ARM_MATH_CM0PLUS))
#ifdef ARDUINO_RASPBERRY_PI_PICO
#include "ESP32BootROM.h"
#include "stub_esp.h"
#ifdef USE_TINYUSB
#include "Adafruit_TinyUSB.h"
#endif
#include "stub_esp32.h"
#define DEBUG 0
@ -72,8 +64,8 @@ enum {
ESP_WRITE_REG = 0x09,
ESP_READ_REG = 0x0A,
// Some commands supported by ESP32 and later chips ROM bootloader (or -8266
// with stub)
// Some comands supported by ESP32 and later chips ROM bootloader (or -8266 w/
// stub)
ESP_SPI_SET_PARAMS = 0x0B,
ESP_SPI_ATTACH = 0x0D,
ESP_READ_FLASH_SLOW = 0x0E, // ROM only, much slower than the stub flash read
@ -152,132 +144,109 @@ enum {
USB_JTAG_SERIAL_PID = 0x1001
};
enum {
CHIP_DETECT_MAGIC_ESP32 = 0x00F01D83,
CHIP_DETECT_MAGIC_ESP32S2 = 0x000007C6,
CHIP_DETECT_MAGIC_ESP32S3 = 0x9,
};
static inline uint32_t div_ceil(uint32_t v, uint32_t d) {
return (v + d - 1) / d;
}
void ESP32BootROMClass::init() {
_gpio0Pin = -1;
_resetnPin = -1;
_supports_encrypted_flash = true;
_stub_running = false;
_rom_8266_running = false;
_chip_detect = 0;
_flashSequenceNumber = 0;
}
ESP32BootROMClass::ESP32BootROMClass(HardwareSerial &serial, int gpio0Pin,
int resetnPin)
: _serial(&serial) {
init();
_gpio0Pin = gpio0Pin;
_resetnPin = resetnPin;
_supports_encrypted_flash = true;
_stub_running = false;
_flashSequenceNumber = 0;
}
void ESP32BootROMClass::resetBootloader(void) {
if (_gpio0Pin >= 0 && _resetnPin >= 0) {
// IO0 and Resetn pins are available
int ESP32BootROMClass::begin(unsigned long baudrate) {
_serial->begin(ESP_ROM_BAUD);
pinMode(_gpio0Pin, OUTPUT);
pinMode(_resetnPin, OUTPUT);
// Reset Low (ESP32 in reset)
digitalWrite(_gpio0Pin, LOW);
digitalWrite(_resetnPin, LOW);
delay(100);
// IO0 Low, Reset HIGH (ESP32 out of reset)
digitalWrite(_resetnPin, HIGH);
// Wait for serial, needed if using with SerialHost
// Wait for serial, needed if using with SerialHost (host cdc)
while (!_serial) {
delay(10);
}
delay(100); // additional delay for SerialHost connected
// IO0 high: done
delay(50); // additional delay for SerialHost connected
digitalWrite(_gpio0Pin, HIGH);
}
#if defined(USE_TINYUSB) && defined(ARDUINO_ARCH_RP2040)
else {
// Serial Host using setDtrRts()
// - DTR -> IO0
// - RTS -> Reset
// DTR & RTS are active low signals, ie True = pin @ 0V, False = pin @ VCC.
Adafruit_USBH_CDC *serial_host = (Adafruit_USBH_CDC *)_serial;
// Wait for serial host
while (!serial_host) {
delay(10);
}
int synced = 0;
// IO0 High, Reset Low (ESP32 in reset)
serial_host->setDtrRts(false, true);
delay(100);
// IO0 Low, Reset High (ESP32 out of reset)
serial_host->setDtrRts(true, false);
delay(100);
// IO0 high, Reset High: done
serial_host->setDtrRts(false, false);
}
#endif
}
uint32_t ESP32BootROMClass::begin(unsigned long baudrate) {
_serial->begin(ESP_ROM_BAUD);
resetBootloader();
bool synced = false;
for (int retries = 0; !synced && (retries < 5); retries++) {
for (int retries = 0; !synced && (retries < 10); retries++) {
Serial.println("Trying to sync");
synced = sync();
if (synced) {
break;
}
delay(10);
}
if (!synced) {
return 0;
}
Serial.println("Synced!");
// Serial.printf("After %u ms\r\n", millis());
//------------- Chip Detect -------------//
_chip_detect = read_chip_detect();
if (!_chip_detect) {
uint32_t chip_detect = read_chip_detect();
if (!chip_detect) {
return 0;
}
Serial.printf("Chip Detect: 0x%08lX\r\n", _chip_detect);
const esp32_stub_loader_t *stub = NULL;
for (uint32_t i = 0; i < ESP_STUB_COUNT; i++) {
if (stub_esp_arr[i]->chip_detect == _chip_detect) {
stub = stub_esp_arr[i];
switch (chip_detect) {
case CHIP_DETECT_MAGIC_ESP32:
// only ESP32 have SUPPORTS_ENCRYPTED_FLASH = false
stub = &stub_esp32;
_supports_encrypted_flash = false;
Serial.println("Found ESP32");
break;
case CHIP_DETECT_MAGIC_ESP32S2:
stub = &stub_esp32s2;
Serial.println("Found ESP32-S2");
break;
case CHIP_DETECT_MAGIC_ESP32S3:
stub = &stub_esp32s3;
Serial.println("Found ESP32-S3");
break;
default:
Serial.println("Found unknown ESP");
break;
}
}
#if 0
uint8_t mac[6];
read_MAC(mac);
Serial.printf("MAC addr: %02X:%02X:%02X:%02X:%02X:%02X\n\r",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
#endif
if (stub) {
Serial.printf("Found %s\r\n", stub->chip_name);
VERIFY(uploadStub(stub));
VERIFY(syncStub(3000));
} else {
Serial.println("Found unknown ESP chip");
}
if (baudrate != ESP_ROM_BAUD) {
if (!changeBaudrate(baudrate)) {
Serial.println("Failed to change baudrate");
Serial.print("Failed to change baudrate");
return 0;
}
// _serial->end();
delay(100);
Serial.printf("Updating local Serial baudrate to %lu\r\n", baudrate);
Serial.println("Updating local Serial baudrate");
_serial->begin(baudrate);
}
@ -289,26 +258,16 @@ uint32_t ESP32BootROMClass::begin(unsigned long baudrate) {
}
}
return _chip_detect;
return 1;
}
void ESP32BootROMClass::end() {
if (_gpio0Pin >= 0 && _resetnPin >= 0) {
digitalWrite(_gpio0Pin, HIGH);
digitalWrite(_resetnPin, HIGH);
} else {
// #ifdef USE_TINYUSB
// Maybe we should reset using RTS
// Adafruit_USBH_CDC* serial_host = (Adafruit_USBH_CDC*)_serial;
// serial_host->setDtrRts(false, true);
// delay(20);
// serial_host->setDtrRts(false, false);
// #endif
}
//_serial->end();
}
bool ESP32BootROMClass::sync() {
int ESP32BootROMClass::sync() {
const uint8_t data[] = {0x07, 0x07, 0x12, 0x20, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
@ -325,7 +284,7 @@ bool ESP32BootROMClass::sync() {
return (results[0] == 0);
}
bool ESP32BootROMClass::changeBaudrate(uint32_t baudrate) {
int ESP32BootROMClass::changeBaudrate(uint32_t baudrate) {
// Two 32-bit words:
// - new baud rate, and
// - 0 if we are talking to the ROM loader or the current/old baud rate if we
@ -336,17 +295,16 @@ bool ESP32BootROMClass::changeBaudrate(uint32_t baudrate) {
data[1] = ESP_ROM_BAUD; // we only changed from 115200 to higher baud
}
DBG_PRINTF("Changing baudrate to %u\r\n", baudrate);
return sendCommandGetResponse(ESP_CHANGE_BAUDRATE, (uint8_t *)data,
sizeof(data), NULL, 0, 3000);
command(ESP_CHANGE_BAUDRATE, data, sizeof(data));
return (response(ESP_CHANGE_BAUDRATE, 3000) == 0);
}
bool ESP32BootROMClass::spiAttach() {
int ESP32BootROMClass::spiAttach() {
const uint8_t data[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
return sendCommandGetResponse(ESP_SPI_ATTACH, data, sizeof(data), NULL, 0,
3000);
command(ESP_SPI_ATTACH, data, sizeof(data));
return (response(ESP_SPI_ATTACH, 3000) == 0);
}
bool ESP32BootROMClass::isRunningStub(void) { return _stub_running; }
@ -358,32 +316,39 @@ uint32_t ESP32BootROMClass::getFlashWriteSize(void) {
//--------------------------------------------------------------------+
// Uncompressed Flashing
//--------------------------------------------------------------------+
bool ESP32BootROMClass::beginFlash(uint32_t offset, uint32_t size,
int ESP32BootROMClass::beginFlash(uint32_t offset, uint32_t size,
uint32_t chunkSize) {
const uint32_t data[5] = {size, div_ceil(size, chunkSize), chunkSize, offset,
0};
uint16_t const len = (_supports_encrypted_flash && !_stub_running) ? 20 : 16;
command(ESP_FLASH_BEGIN, data, len);
_flashSequenceNumber = 0;
return sendCommandGetResponse(ESP_FLASH_BEGIN, data, len, NULL, 0, 120000);
return (response(ESP_FLASH_BEGIN, 120000) == 0);
}
bool ESP32BootROMClass::dataFlash(const void *data, uint32_t length) {
int ESP32BootROMClass::dataFlash(const void *data, uint32_t length) {
uint32_t header[4];
header[0] = length;
header[1] = _flashSequenceNumber++;
header[2] = 0;
header[3] = 0;
return sendCommandGetResponse(ESP_FLASH_DATA, header, sizeof(header), data,
length, 3000);
command(ESP_FLASH_DATA, header, sizeof(header), data, length);
return (response(ESP_FLASH_DATA, 3000) == 0);
}
bool ESP32BootROMClass::endFlash(uint32_t reboot) {
int ESP32BootROMClass::endFlash(uint32_t reboot) {
const uint32_t data[1] = {reboot};
return sendCommandGetResponse(ESP_FLASH_END, data, sizeof(data), NULL, 0,
3000);
command(ESP_FLASH_END, data, sizeof(data));
return (response(ESP_FLASH_END, 3000) == 0);
}
//--------------------------------------------------------------------+
@ -405,35 +370,42 @@ bool ESP32BootROMClass::beginFlashDefl(uint32_t offset, uint32_t size,
uint16_t const len = (_supports_encrypted_flash && !_stub_running) ? 20 : 16;
command(ESP_FLASH_DEFL_BEGIN, data, len);
_flashSequenceNumber = 0;
return sendCommandGetResponse(ESP_FLASH_DEFL_BEGIN, data, len, NULL, 0, 3000);
return (response(ESP_FLASH_DEFL_BEGIN, 3000) == 0);
}
bool ESP32BootROMClass::dataFlashDefl(const void *data, uint32_t len) {
uint32_t header[4];
header[0] = len;
header[1] = _flashSequenceNumber++;
header[2] = 0;
header[3] = 0;
return sendCommandGetResponse(ESP_FLASH_DEFL_DATA, header, sizeof(header),
data, len, 3000);
command(ESP_FLASH_DEFL_DATA, header, sizeof(header), data, len);
return (response(ESP_FLASH_DEFL_DATA, 3000) == 0);
}
bool ESP32BootROMClass::endFlashDefl(uint32_t reboot) {
const uint32_t data[1] = {reboot};
return sendCommandGetResponse(ESP_FLASH_DEFL_END, data, sizeof(data), NULL, 0,
3000);
command(ESP_FLASH_DEFL_END, data, sizeof(data));
return (response(ESP_FLASH_DEFL_END, 3000) == 0);
}
bool ESP32BootROMClass::md5Flash(uint32_t offset, uint32_t size,
uint8_t *result) {
const uint32_t data[4] = {offset, size, 0, 0};
uint8_t resp[32];
VERIFY(sendCommandGetResponse(ESP_SPI_FLASH_MD5, data, sizeof(data), NULL, 0,
6000, resp));
command(ESP_SPI_FLASH_MD5, data, sizeof(data));
uint8_t resp[32];
VERIFY(0 == response(ESP_SPI_FLASH_MD5, 6000, resp));
// Note that the ESP32 ROM loader returns the md5sum as 32 hex encoded ASCII
// bytes, whereas the stub loader returns the md5sum as 16 raw data bytes of
@ -460,8 +432,13 @@ bool ESP32BootROMClass::md5Flash(uint32_t offset, uint32_t size,
bool ESP32BootROMClass::read_reg(uint32_t addr, uint32_t *val,
uint32_t timeout_ms) {
return sendCommandGetResponse(ESP_READ_REG, &addr, 4, NULL, 0, timeout_ms,
val);
command(ESP_READ_REG, &addr, 4);
if (0 == response(ESP_READ_REG, timeout_ms, val)) {
return true;
} else {
return false;
}
}
uint32_t ESP32BootROMClass::read_chip_detect(void) {
@ -503,9 +480,11 @@ bool ESP32BootROMClass::beginMem(uint32_t offset, uint32_t size,
uint32_t chunkSize) {
const uint32_t data[] = {size, div_ceil(size, chunkSize), chunkSize, offset};
uint16_t const len = 16;
command(ESP_MEM_BEGIN, data, len);
_flashSequenceNumber = 0;
return sendCommandGetResponse(ESP_MEM_BEGIN, data, len, NULL, 0, 3000);
return (response(ESP_MEM_BEGIN, 120000) == 0);
}
bool ESP32BootROMClass::dataMem(const void *data, uint32_t length) {
@ -515,8 +494,9 @@ bool ESP32BootROMClass::dataMem(const void *data, uint32_t length) {
header[2] = 0;
header[3] = 0;
return sendCommandGetResponse(ESP_MEM_DATA, header, sizeof(header), data,
length, 3000);
command(ESP_MEM_DATA, header, sizeof(header), data, length);
return (response(ESP_MEM_DATA, 3000) == 0);
}
bool ESP32BootROMClass::endMem(uint32_t entry) {
@ -524,7 +504,9 @@ bool ESP32BootROMClass::endMem(uint32_t entry) {
data[0] = (entry == 0);
data[1] = entry;
return sendCommandGetResponse(ESP_MEM_END, data, sizeof(data), NULL, 0, 3000);
command(ESP_MEM_END, data, sizeof(data));
return (response(ESP_MEM_END, 3000) == 0);
}
bool ESP32BootROMClass::syncStub(uint32_t timeout_ms) {
@ -596,7 +578,6 @@ bool ESP32BootROMClass::uploadStub(const esp32_stub_loader_t *stub) {
VERIFY(endMem(stub->entry));
_stub_running = true;
_rom_8266_running = false;
return true;
}
@ -605,46 +586,19 @@ bool ESP32BootROMClass::uploadStub(const esp32_stub_loader_t *stub) {
// Command & Response
//--------------------------------------------------------------------+
bool ESP32BootROMClass::sendCommandGetResponse(uint8_t opcode, const void *data,
uint16_t length,
const void *data2, uint16_t len2,
uint32_t timeout_ms,
void *body) {
for (uint8_t retry = 0; retry < 3; retry++) {
command(opcode, data, length, data2, len2);
if (response(opcode, timeout_ms, body) == 0) {
return true;
}
Serial.printf("Command 0x%02x failed, retrying %u/3...\r\n", opcode,
retry + 1);
delay(5);
}
return false;
}
void ESP32BootROMClass::command(uint8_t opcode, const void *data, uint16_t len,
const void *data2, uint16_t len2) {
uint32_t checksum = 0;
// ESP8266 ROM bootloader is slow to ready receiving commands. Need
// to wait a bit before sending new command
if (_rom_8266_running || (_chip_detect == CHIP_DETECT_MAGIC_ESP8266)) {
delay(5);
}
// for FLASH_DATA and MEM_DATA: data is header, data2 is actual payloada
// for FLASH_DATA and MEM_DATA: data is header, data2 is actual payload
if (opcode == ESP_FLASH_DATA || opcode == ESP_MEM_DATA ||
opcode == ESP_FLASH_DEFL_DATA) {
checksum = ESP_CHECKSUM_MAGIC; // seed
if (data2) {
for (uint16_t i = 0; i < len2; i++) {
checksum ^= ((const uint8_t *)data2)[i];
}
}
}
uint16_t const total_len = len + len2;
@ -658,7 +612,7 @@ void ESP32BootROMClass::command(uint8_t opcode, const void *data, uint16_t len,
writeEscapedBytes((uint8_t *)&checksum, sizeof(checksum));
writeEscapedBytes((uint8_t *)data, len);
if (data2 && len2) {
writeEscapedBytes((uint8_t const *)data2, len2);
writeEscapedBytes((uint8_t *)data2, len2);
}
_serial->write(0xc0);
@ -667,126 +621,6 @@ void ESP32BootROMClass::command(uint8_t opcode, const void *data, uint16_t len,
DBG_PRINTF("c0\r\n");
}
// return response status if success, -1 if failed
int ESP32BootROMClass::response(uint8_t opcode, uint32_t timeout_ms,
void *body) {
// Response Packet is composed of
// - 1B: slip start
// - 8B: fixed response ( struct below )
// - nB: variable response payload ( if any )
// - 2B: status, error
// - 2B: reserved // ROM only, not stub
// - 1B: slip end
struct __packed_aligned {
uint8_t dir; // 0x01 for response
uint8_t opcode;
uint16_t length; // at least 2 (or 4) for status bytes
uint32_t reg_value; // READ_REG response. zero otherwise
} fixed_resp;
uint8_t status[4] = {0};
uint32_t end_ms = millis() + timeout_ms;
if (!readSLIP(timeout_ms)) {
Serial.printf("line %d: timeout reading SLIP\r\n", __LINE__);
return -1;
}
// read fixed response first
if (8 != readBytes(&fixed_resp, 8, end_ms - millis())) {
Serial.printf("line %d\r\n", __LINE__);
return -1; // probably timeout
}
// Status byte are 2 or 4 bytes as follows:
// - ESP32 Boot ROM: 2 bytes
// - ESP8266 ROM and Stub (all chips): 4 bytes
uint8_t status_len = ((_stub_running || _rom_8266_running) ? 2 : 4);
// ESP8266 ROM only has 2 bytes status which will be larger than length
// response in sync() message this is condition is an indicator that ESP8266
// ROM is used
if ((opcode == ESP_SYNC) && (fixed_resp.length < status_len)) {
_rom_8266_running = true;
status_len = 2;
}
// read variable payload if any
// status len can be miscalculated for ESP8266 ROM (2 bytes instead of 4)
uint16_t const payload_len = fixed_resp.length - status_len;
uint8_t data[payload_len];
if (payload_len) {
uint16_t rd_len = readBytes(data, payload_len, end_ms - millis());
if (payload_len != rd_len) {
Serial.printf("Fixed Response: dir = %02x, opcode = %02x, length = %04x, "
"reg_value = %08lx\r\n",
fixed_resp.dir, fixed_resp.opcode, fixed_resp.length,
fixed_resp.reg_value);
Serial.printf(
"line %d: payload_len = %u, rd_len = %u, status_len = %u\r\n",
__LINE__, payload_len, rd_len, status_len);
if (rd_len) {
DBG_PRINT_BUF(data, rd_len);
}
return -1; // probably timeout
}
}
if (body) {
if (opcode == ESP_READ_REG) {
memcpy(body, &fixed_resp.reg_value, 4);
} else {
memcpy(body, data, payload_len);
}
}
// read status
if (status_len != readBytes(status, status_len, end_ms - millis())) {
Serial.printf("line %d\r\n", __LINE__);
return -1; // probably timeout
}
if (!readSLIP(end_ms - millis())) {
Serial.printf("line %d\r\n", __LINE__);
return -1;
}
#if DEBUG
Serial.printf("<= c0 %02x %02x %04x %08x ", fixed_resp.dir, fixed_resp.opcode,
fixed_resp.length, fixed_resp.reg_value);
if (payload_len) {
DBG_PRINT_BUF(data, payload_len);
}
DBG_PRINT_BUF(status, status_len);
Serial.println("c0");
#endif
// check direction, opcode and status
if (fixed_resp.dir == 0x01 && fixed_resp.opcode == opcode &&
status[0] == 0x00 && status[1] == 0x00) {
return 0; // status[0];
}
const char *mess_arr[0x0b + 1] = {
NULL, NULL, NULL, NULL, NULL, "Received message is invalid",
"Failed to act on received message", "Invalid CRC in message",
"Flash write error", // after writing a block of data to flash, the ROM
// loader reads the value back and the 8-bit CRC is
// compared to the data read from flash. If they
// dont match, this error is returned.
"Flash read error", "Flash read length error", "Deflate error"};
const char *mess =
(status[1] <= 0x0b) ? mess_arr[status[1]] : "Unknown Error";
Serial.printf("response failed: status = %02x %02x, %s\r\n", status[0],
status[1], mess);
return -1;
}
// read until we found SLIP (0xC0) byte
bool ESP32BootROMClass::readSLIP(uint32_t timeout_ms) {
uint32_t const end_ms = millis() + timeout_ms;
@ -837,6 +671,104 @@ uint16_t ESP32BootROMClass::readBytes(void *buf, uint16_t length,
return count;
}
// return response status if success, -1 if failed
int ESP32BootROMClass::response(uint8_t opcode, uint32_t timeout_ms,
void *body) {
// Response Packet is composed of
// - 1B: slip start
// - 8B: fixed response ( struct below )
// - nB: variable response payload ( if any )
// - 2B: status, error
// - 2B: reserved // ROM only, not stub
// - 1B: slip end
struct __packed_aligned {
uint8_t dir; // 0x01 for response
uint8_t opcode;
uint16_t length; // at least 2 (or 4) for status bytes
uint32_t reg_value; // READ_REG response. zero otherwise
} fixed_resp;
uint8_t status[4] = {0};
uint8_t const status_len = (_stub_running ? 2 : 4);
uint32_t end_ms = millis() + timeout_ms;
if (!readSLIP(timeout_ms)) {
return -1;
}
// read fixed response first
if (8 != readBytes(&fixed_resp, 8, end_ms - millis())) {
Serial.printf("line %d\r\n", __LINE__);
return -1; // probably timeout
}
// read variable payload if any
uint16_t const payload_len = fixed_resp.length - status_len;
uint8_t data[payload_len];
if (payload_len) {
uint16_t rd_len = readBytes(data, payload_len, end_ms - millis());
if (payload_len != rd_len) {
Serial.printf("line %d: payload_len = %u, rd_len = %u\r\n", __LINE__,
payload_len, rd_len);
if (rd_len) {
DBG_PRINT_BUF(data, rd_len);
}
return -1; // probably timeout
}
}
if (body) {
if (opcode == ESP_READ_REG) {
memcpy(body, &fixed_resp.reg_value, 4);
} else {
memcpy(body, data, payload_len);
}
}
// read status
if (status_len != readBytes(status, status_len, end_ms - millis())) {
Serial.printf("line %d\r\n", __LINE__);
return -1; // probably timeout
}
if (!readSLIP(end_ms - millis())) {
Serial.printf("line %d\r\n", __LINE__);
return -1;
}
#if DEBUG
Serial.printf("<= c0 %02x %02x %04x %08x ", fixed_resp.dir, fixed_resp.opcode,
fixed_resp.length, fixed_resp.reg_value);
DBG_PRINT_BUF(data, payload_len);
DBG_PRINT_BUF(status, status_len);
Serial.println("c0");
#endif
// check direction, opcode and status
if (fixed_resp.dir == 0x01 && fixed_resp.opcode == opcode &&
status[0] == 0x00 && status[1] == 0x00) {
return 0; // status[0];
}
const char *mess_arr[0x0b + 1] = {
NULL, NULL, NULL, NULL, NULL, "Received message is invalid",
"Failed to act on received message", "Invalid CRC in message",
"Flash write error", // after writing a block of data to flash, the ROM
// loader reads the value back and the 8-bit CRC is
// compared to the data read from flash. If they
// dont match, this error is returned.
"Flash read error", "Flash read length error", "Deflate error"};
const char *mess =
(status[1] <= 0x0b) ? mess_arr[status[1]] : "Unknown Error";
Serial.printf("response failed: status = %02x %02x, %s\r\n", status[0],
status[1], mess);
return -1;
}
void ESP32BootROMClass::writeEscapedBytes(const uint8_t *data,
uint16_t length) {
// skip flashing data since it is a lot to print

View file

@ -25,16 +25,7 @@
#define ESP32_DEFAULT_TIMEOUT 3000
enum {
CHIP_DETECT_MAGIC_ESP32 = 0x00F01D83,
CHIP_DETECT_MAGIC_ESP32S2 = 0x000007C6,
CHIP_DETECT_MAGIC_ESP32S3 = 0x9,
CHIP_DETECT_MAGIC_ESP8266 = 0xFFF0C101,
CHIP_DETECT_MAGIC_ESP32C6 = 0x2CE0806F,
};
typedef struct {
uint32_t chip_detect;
uint32_t entry;
uint32_t text_start;
uint32_t text_length;
@ -42,31 +33,27 @@ typedef struct {
uint32_t data_start;
uint32_t data_length;
const uint8_t *data;
const char *chip_name;
} esp32_stub_loader_t;
class ESP32BootROMClass {
public:
ESP32BootROMClass(HardwareSerial &hwSerial, int gpio0Pin = -1,
int resetnPin = -1);
ESP32BootROMClass(HardwareSerial &hwSerial, int gpio0Pin, int resetnPin);
// return chip detect magic if success, otherwise 0
uint32_t begin(unsigned long baudrate);
int begin(unsigned long baudrate);
void end();
bool isRunningStub(void);
uint32_t getFlashWriteSize(void);
// High Level commands
bool read_reg(uint32_t regAddr, uint32_t *regValue,
uint32_t timeout_ms = ESP32_DEFAULT_TIMEOUT);
bool read_MAC(uint8_t mac[6]);
uint32_t read_chip_detect(void);
bool isRunningStub(void);
uint32_t getFlashWriteSize(void);
// uncompressed
bool beginFlash(uint32_t offset, uint32_t size, uint32_t chunkSize);
bool dataFlash(const void *data, uint32_t length);
bool endFlash(uint32_t reboot);
int beginFlash(uint32_t offset, uint32_t size, uint32_t chunkSize);
int dataFlash(const void *data, uint32_t length);
int endFlash(uint32_t reboot);
// compressed
bool beginFlashDefl(uint32_t offset, uint32_t size, uint32_t zip_size);
@ -76,43 +63,32 @@ public:
bool md5Flash(uint32_t offset, uint32_t size, uint8_t *result);
private:
void init();
void resetBootloader(void);
bool sync();
bool uploadStub(const esp32_stub_loader_t *stub);
bool syncStub(uint32_t timeout_ms);
int sync();
int changeBaudrate(uint32_t baudrate);
int spiAttach();
// Command and Response
void command(uint8_t opcode, const void *data, uint16_t length,
const void *data2 = NULL, uint16_t len2 = 0);
int response(uint8_t opcode, uint32_t timeout_ms, void *body = NULL);
bool sendCommandGetResponse(uint8_t opcode, const void *data, uint16_t length,
const void *data2 = NULL, uint16_t len2 = 0,
uint32_t timeout_ms = ESP32_DEFAULT_TIMEOUT,
void *body = NULL);
// High Level commands
bool changeBaudrate(uint32_t baudrate);
bool spiAttach();
uint16_t readBytes(void *buf, uint16_t length, uint32_t timeout_ms);
bool readSLIP(uint32_t timeout_ms);
void writeEscapedBytes(const uint8_t *data, uint16_t length);
bool beginMem(uint32_t offset, uint32_t size, uint32_t chunkSize);
bool dataMem(const void *data, uint32_t length);
bool endMem(uint32_t entry);
// read and write packets
uint16_t readBytes(void *buf, uint16_t length, uint32_t timeout_ms);
bool readSLIP(uint32_t timeout_ms);
void writeEscapedBytes(const uint8_t *data, uint16_t length);
// only needed for ESP32
bool uploadStub(const esp32_stub_loader_t *stub);
bool syncStub(uint32_t timeout_ms);
private:
HardwareSerial *_serial;
int _gpio0Pin;
int _resetnPin;
bool _supports_encrypted_flash;
bool _stub_running;
bool _rom_8266_running;
uint32_t _chip_detect;
uint32_t _flashSequenceNumber;
};

File diff suppressed because it is too large Load diff

1100
src/stub_esp32.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,21 @@
import sys
import zlib
import hashlib
from pathlib import Path
import click
import os.path
output_header = 'esp_binaries.h'
# Argument is path to folder containing .bin files
# This script will create .bin.gz file with the same name to the folder
# and also print out C array of the gz along with MD5 checksum
dir = ''
if len(sys.argv) == 1:
print("No [DIRS] arguments, use current directory as default")
dir = Path('./')
else:
# only take 1 argument
dir = Path(sys.argv[1])
def print_carray(f, payload):
while len(payload) > 0:
@ -11,31 +25,19 @@ def print_carray(f, payload):
payload = payload[16:]
f.write('\n')
@click.command()
@click.argument('dpath', type=click.Path(exists=True), default='.')
@click.option('--sd', is_flag=True, default=False, help='Generate header for using with SDCard')
def main(dpath, sd):
"""
This script takes a directory path (default is current directory) and
create compressed .bin.gz file along 'esp_binaries.h' containing metadata in esp32_zipfile_t struct.
Which can be used to program ESP32 with TestBed or Brain.
If '--sd' option is specified, it will skip generating C array data for gz file.
"""
output_header = 'esp_binaries.h'
with open(output_header, 'w') as fc:
# print typedef struct
fc.write('// Generated by tools/esp_compress.py\n')
file_list = sorted(Path(dpath).glob('*.bin'))
fc.write(f'#define ESP_BINARIES_COUNT ({len(file_list)})\n\n')
file_list = sorted(dir.glob('*.bin'))
fc.write('#define ESP_BINARIES_COUNT ({})\n\n'.format(len(file_list)))
# print list of struct first
for fname in file_list:
var = fname.stem
var = var.replace('.', '_')
var = var.replace('-', '_')
fc.write(f'// const esp32_zipfile_t {var}\n')
fc.write('\n')
fc.write('// const esp32_zipfile_t {}\n'.format(var))
fc.write('\n'.format(var))
for fname in file_list:
with open(fname, 'rb') as fi:
@ -54,28 +56,19 @@ def main(dpath, sd):
var = var.replace('-', '_')
# bin gz contents
if not sd:
fc.write(f'const uint8_t _{var}_gz[{len(zimage)}] = {{')
fc.write('const uint8_t _{}_gz[{}] = {{'.format(var, len(zimage)))
print_carray(fc, zimage)
fc.write('};\n\n')
fc.write(f'const esp32_zipfile_t {var} = {{\n')
fc.write(f' .name = "{fzname}",\n')
if sd:
fc.write(f' .data = NULL,\n')
else:
fc.write(f' .data = _{var}_gz,\n')
fc.write(f' .compressed_len = {len(zimage)},\n')
fc.write(f' .uncompressed_len = {len(image)},\n')
fc.write('const esp32_zipfile_t {} = {{\n'.format(var))
fc.write(' .name = "{}",\n'.format(var))
fc.write(' .data = _{}_gz,\n'.format(var))
fc.write(' .compressed_len = {},\n'.format(len(zimage)))
fc.write(' .uncompressed_len = {},\n'.format(len(image)))
fc.write(' .md5 = {')
print_carray(fc, md5.digest())
fc.write(' },\n')
fc.write('};\n')
fc.write('\n')
deflation = 100*(1-len(zimage)/len(image))
print(f"Compressed {var}: {len(image)} to {len(zimage)} bytes, deflation: {deflation:.2f}%")
if __name__ == '__main__':
main()
print("Compressed {}: {} to {} bytes, deflation: {:.2f}%".format(var, len(image), len(zimage), 100*(1-len(zimage)/len(image))))

File diff suppressed because one or more lines are too long

View file

@ -1,45 +0,0 @@
#!/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())