Skip to content

Commit 5ca0aca

Browse files
committed
[pin_remap 3/3]: add Arduino Nano ESP32 board
1 parent b785adf commit 5ca0aca

16 files changed

+767
-2
lines changed

Diff for: boards.txt

+69
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ menu.MemoryType=Memory Type
1818
menu.EraseFlash=Erase All Flash Before Sketch Upload
1919
menu.JTAGAdapter=JTAG Adapter
2020
menu.ZigbeeMode=Zigbee Mode
21+
menu.PinNumbers=Pin Numbering
2122

2223
# Custom options
2324
menu.Revision=Board Revision
@@ -28335,3 +28336,71 @@ atd147_s3.menu.EraseFlash.all=Enabled
2833528336
atd147_s3.menu.EraseFlash.all.upload.erase_cmd=-e
2833628337

2833728338
##############################################################
28339+
28340+
nano_nora.name=Arduino Nano ESP32
28341+
nano_nora.vid.0=0x2341
28342+
nano_nora.pid.0=0x0070
28343+
nano_nora.upload_port.0.vid=0x2341
28344+
nano_nora.upload_port.0.pid=0x0070
28345+
28346+
nano_nora.bootloader.tool=esptool_py
28347+
nano_nora.bootloader.tool.default=esptool_py
28348+
28349+
nano_nora.upload.tool=dfu-util
28350+
nano_nora.upload.tool.default=dfu-util
28351+
nano_nora.upload.tool.network=esp_ota
28352+
nano_nora.upload.protocol=serial
28353+
nano_nora.upload.maximum_size=3145728
28354+
nano_nora.upload.maximum_data_size=327680
28355+
nano_nora.upload.use_1200bps_touch=false
28356+
nano_nora.upload.wait_for_upload_port=false
28357+
28358+
nano_nora.serial.disableDTR=false
28359+
nano_nora.serial.disableRTS=false
28360+
28361+
nano_nora.build.tarch=xtensa
28362+
nano_nora.build.bootloader_addr=0x0
28363+
nano_nora.build.target=esp32s3
28364+
nano_nora.build.mcu=esp32s3
28365+
nano_nora.build.core=esp32
28366+
nano_nora.build.variant=arduino_nano_nora
28367+
nano_nora.build.board=NANO_ESP32
28368+
nano_nora.build.code_debug=0
28369+
28370+
nano_nora.build.usb_mode=0
28371+
nano_nora.build.cdc_on_boot=1
28372+
nano_nora.build.msc_on_boot=0
28373+
nano_nora.build.dfu_on_boot=1
28374+
nano_nora.build.f_cpu=240000000L
28375+
nano_nora.build.flash_size=16MB
28376+
nano_nora.build.flash_freq=80m
28377+
nano_nora.build.flash_mode=dio
28378+
nano_nora.build.boot=qio
28379+
nano_nora.build.boot_freq=80m
28380+
nano_nora.build.partitions=app3M_fat9M_fact512k_16MB
28381+
nano_nora.build.defines=-DBOARD_HAS_PIN_REMAP {build.disable_pin_remap} -DBOARD_HAS_PSRAM '-DUSB_MANUFACTURER="Arduino"' '-DUSB_PRODUCT="Nano ESP32"'
28382+
nano_nora.build.loop_core=-DARDUINO_RUNNING_CORE=1
28383+
nano_nora.build.event_core=-DARDUINO_EVENT_RUNNING_CORE=1
28384+
nano_nora.build.psram_type=opi
28385+
nano_nora.build.memory_type={build.boot}_{build.psram_type}
28386+
nano_nora.build.disable_pin_remap=
28387+
28388+
nano_nora.tools.esptool_py.program.pattern_args=--chip {build.mcu} --port "{serial.port}" --before default_reset --after hard_reset write_flash -z --flash_mode {build.flash_mode} --flash_freq {build.flash_freq} --flash_size {build.flash_size} {build.bootloader_addr} "{build.path}/{build.project_name}.bootloader.bin" 0x8000 "{build.path}/{build.project_name}.partitions.bin" 0xe000 "{runtime.platform.path}/tools/partitions/boot_app0.bin" 0xf70000 "{build.variant.path}/extra/nora_recovery/nora_recovery.ino.bin" 0x10000 "{build.path}/{build.project_name}.bin"
28389+
nano_nora.tools.esptool_py.erase.pattern_args=--chip {build.mcu} --port "{serial.port}" --before default_reset --after hard_reset erase_flash
28390+
28391+
nano_nora.menu.PartitionScheme.default=With FAT partition (default)
28392+
nano_nora.menu.PartitionScheme.spiffs=With SPIFFS partition (advanced)
28393+
nano_nora.menu.PartitionScheme.spiffs.build.partitions=app3M_spiffs9M_fact512k_16MB
28394+
28395+
nano_nora.menu.PinNumbers.default=By Arduino pin (default)
28396+
nano_nora.menu.PinNumbers.byGPIONumber=By GPIO number (legacy)
28397+
nano_nora.menu.PinNumbers.byGPIONumber.build.disable_pin_remap=-DBOARD_USES_HW_GPIO_NUMBERS
28398+
28399+
nano_nora.menu.USBMode.default=Normal mode (TinyUSB)
28400+
nano_nora.menu.USBMode.hwcdc=Debug mode (Hardware CDC)
28401+
nano_nora.menu.USBMode.hwcdc.build.usb_mode=1
28402+
nano_nora.menu.USBMode.hwcdc.build.copy_jtag_files=1
28403+
nano_nora.menu.USBMode.hwcdc.build.openocdscript=esp32s3-builtin.cfg
28404+
nano_nora.menu.USBMode.hwcdc.build.debugconfig=esp32s3-arduino.json
28405+
28406+
##############################################################

Diff for: cores/esp32/USB.cpp

+11-2
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@
5151
#define USB_WEBUSB_URL "https://espressif.github.io/arduino-esp32/webusb.html"
5252
#endif
5353

54-
#if CFG_TUD_DFU_RUNTIME
54+
#if CFG_TUD_DFU
55+
__attribute__((weak)) uint16_t load_dfu_ota_descriptor(uint8_t * dst, uint8_t * itf) {
56+
return 0;
57+
}
58+
#elif CFG_TUD_DFU_RUNTIME
5559
static uint16_t load_dfu_descriptor(uint8_t * dst, uint8_t * itf)
5660
{
5761
#define DFU_ATTRS (DFU_ATTR_CAN_DOWNLOAD | DFU_ATTR_CAN_UPLOAD | DFU_ATTR_MANIFESTATION_TOLERANT)
@@ -65,6 +69,9 @@ static uint16_t load_dfu_descriptor(uint8_t * dst, uint8_t * itf)
6569
memcpy(dst, descriptor, TUD_DFU_RT_DESC_LEN);
6670
return TUD_DFU_RT_DESC_LEN;
6771
}
72+
#endif /* CFG_TUD_DFU_RUNTIME */
73+
74+
#if CFG_TUD_DFU_RUNTIME
6875
// Invoked on DFU_DETACH request to reboot to the bootloader
6976
void tud_dfu_runtime_reboot_to_dfu_cb(void)
7077
{
@@ -207,7 +214,9 @@ ESPUSB::operator bool() const
207214
}
208215

209216
bool ESPUSB::enableDFU(){
210-
#if CFG_TUD_DFU_RUNTIME
217+
#if CFG_TUD_DFU
218+
return tinyusb_enable_interface(USB_INTERFACE_DFU, TUD_DFU_DESC_LEN(1), load_dfu_ota_descriptor) == ESP_OK;
219+
#elif CFG_TUD_DFU_RUNTIME
211220
return tinyusb_enable_interface(USB_INTERFACE_DFU, TUD_DFU_RT_DESC_LEN, load_dfu_descriptor) == ESP_OK;
212221
#endif /* CFG_TUD_DFU_RUNTIME */
213222
return false;

Diff for: package/package_esp32_index.template.json

+8
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
},
3434
{
3535
"name": "ESP32-C3 Dev Board"
36+
},
37+
{
38+
"name": "Arduino Nano ESP32"
3639
}
3740
],
3841
"toolsDependencies": [
@@ -90,6 +93,11 @@
9093
"packager": "esp32",
9194
"name": "mklittlefs",
9295
"version": "3.0.0-gnu12-dc7f933"
96+
},
97+
{
98+
"packager": "arduino",
99+
"name": "dfu-util",
100+
"version": "0.11.0-arduino5"
93101
}
94102
]
95103
}

Diff for: platform.txt

+8
Original file line numberDiff line numberDiff line change
@@ -277,3 +277,11 @@ tools.esp_ota.upload.protocol=network
277277
tools.esp_ota.upload.field.password=Password
278278
tools.esp_ota.upload.field.password.secret=true
279279
tools.esp_ota.upload.pattern={cmd} -i {upload.port.address} -p {upload.port.properties.port} --auth={upload.field.password} -f "{build.path}/{build.project_name}.bin"
280+
281+
## Upload Sketch Through DFU OTA
282+
## -------------------------------------------
283+
tools.dfu-util.path={runtime.tools.dfu-util-0.11.0-arduino5.path}
284+
tools.dfu-util.cmd=dfu-util
285+
tools.dfu-util.upload.params.verbose=-d
286+
tools.dfu-util.upload.params.quiet=
287+
tools.dfu-util.upload.pattern="{path}/{cmd}" --device {vid.0}:{pid.0} -D "{build.path}/{build.project_name}.bin" -Q

Diff for: tools/ide-debug/esp32s3-arduino.json

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name":"Arduino on ESP32-S3",
3+
"toolchainPrefix":"xtensa-esp32s3-elf",
4+
"svdFile":"debug.svd",
5+
"request":"attach",
6+
"overrideAttachCommands":[
7+
"set remote hardware-watchpoint-limit 2",
8+
"monitor reset halt",
9+
"monitor gdb_sync",
10+
"thb setup",
11+
"interrupt"
12+
],
13+
"overrideRestartCommands":[
14+
"monitor reset halt",
15+
"monitor gdb_sync",
16+
"interrupt"
17+
]
18+
}

Diff for: tools/partitions/app3M_fat9M_fact512k_16MB.csv

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Name, Type, SubType, Offset, Size, Flags
2+
nvs, data, nvs, 0x9000, 0x5000,
3+
otadata, data, ota, 0xe000, 0x2000,
4+
app0, app, ota_0, 0x10000, 0x300000,
5+
app1, app, ota_1, 0x310000, 0x300000,
6+
ffat, data, fat, 0x610000, 0x960000,
7+
factory, app, factory, 0xF70000, 0x80000,
8+
coredump, data, coredump, 0xFF0000, 0x10000,
9+
# to create/use ffat, see https://github.com/marcmerlin/esp32_fatfsimage

Diff for: tools/partitions/app3M_spiffs9M_fact512k_16MB.csv

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Name, Type, SubType, Offset, Size, Flags
2+
nvs, data, nvs, 0x9000, 0x5000,
3+
otadata, data, ota, 0xe000, 0x2000,
4+
app0, app, ota_0, 0x10000, 0x300000,
5+
app1, app, ota_1, 0x310000, 0x300000,
6+
spiffs, data, spiffs, 0x610000, 0x960000,
7+
factory, app, factory, 0xF70000, 0x80000,
8+
coredump, data, coredump, 0xFF0000, 0x10000,

Diff for: variants/arduino_nano_nora/dfu_callbacks.cpp

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
#include "Arduino.h"
2+
3+
#include <esp32-hal-tinyusb.h>
4+
#include <esp_system.h>
5+
6+
// defines an "Update" object accessed only by this translation unit
7+
// (also, the object requires MD5Builder internally)
8+
namespace {
9+
// ignore '{anonymous}::MD5Builder::...() defined but not used' warnings
10+
#pragma GCC diagnostic push
11+
#pragma GCC diagnostic ignored "-Wunused-function"
12+
#include "../../libraries/Update/src/Updater.cpp"
13+
#include "../../cores/esp32/MD5Builder.cpp"
14+
#pragma GCC diagnostic pop
15+
}
16+
17+
#define ALT_COUNT 1
18+
19+
//--------------------------------------------------------------------+
20+
// DFU callbacks
21+
// Note: alt is used as the partition number, in order to support multiple partitions like FLASH, EEPROM, etc.
22+
//--------------------------------------------------------------------+
23+
24+
uint16_t load_dfu_ota_descriptor(uint8_t * dst, uint8_t * itf)
25+
{
26+
#define DFU_ATTRS (DFU_ATTR_CAN_DOWNLOAD | DFU_ATTR_CAN_UPLOAD | DFU_ATTR_MANIFESTATION_TOLERANT)
27+
28+
uint8_t str_index = tinyusb_add_string_descriptor("Arduino DFU");
29+
uint8_t descriptor[TUD_DFU_DESC_LEN(ALT_COUNT)] = {
30+
// Interface number, string index, attributes, detach timeout, transfer size */
31+
TUD_DFU_DESCRIPTOR(*itf, ALT_COUNT, str_index, DFU_ATTRS, 100, CFG_TUD_DFU_XFER_BUFSIZE),
32+
};
33+
*itf+=1;
34+
memcpy(dst, descriptor, TUD_DFU_DESC_LEN(ALT_COUNT));
35+
return TUD_DFU_DESC_LEN(ALT_COUNT);
36+
}
37+
38+
// Invoked right before tud_dfu_download_cb() (state=DFU_DNBUSY) or tud_dfu_manifest_cb() (state=DFU_MANIFEST)
39+
// Application return timeout in milliseconds (bwPollTimeout) for the next download/manifest operation.
40+
// During this period, USB host won't try to communicate with us.
41+
uint32_t tud_dfu_get_timeout_cb(uint8_t alt, uint8_t state)
42+
{
43+
if ( state == DFU_DNBUSY )
44+
{
45+
// longest delay for Flash writing
46+
return 10;
47+
}
48+
else if (state == DFU_MANIFEST)
49+
{
50+
// time for esp32_ota_set_boot_partition to check final image
51+
return 100;
52+
}
53+
54+
return 0;
55+
}
56+
57+
// Invoked when received DFU_DNLOAD (wLength>0) following by DFU_GETSTATUS (state=DFU_DNBUSY) requests
58+
// This callback could be returned before flashing op is complete (async).
59+
// Once finished flashing, application must call tud_dfu_finish_flashing()
60+
void tud_dfu_download_cb(uint8_t alt, uint16_t block_num, uint8_t const* data, uint16_t length)
61+
{
62+
if (!Update.isRunning())
63+
{
64+
// this is the first data block, start update if possible
65+
if (!Update.begin())
66+
{
67+
tud_dfu_finish_flashing(DFU_STATUS_ERR_TARGET);
68+
return;
69+
}
70+
}
71+
72+
// write a block of data to Flash
73+
// XXX: Update API is needlessly non-const
74+
size_t written = Update.write(const_cast<uint8_t*>(data), length);
75+
tud_dfu_finish_flashing((written == length) ? DFU_STATUS_OK : DFU_STATUS_ERR_WRITE);
76+
}
77+
78+
// Invoked when download process is complete, received DFU_DNLOAD (wLength=0) following by DFU_GETSTATUS (state=Manifest)
79+
// Application can do checksum, or actual flashing if buffered entire image previously.
80+
// Once finished flashing, application must call tud_dfu_finish_flashing()
81+
void tud_dfu_manifest_cb(uint8_t alt)
82+
{
83+
(void) alt;
84+
bool ok = Update.end(true);
85+
86+
// flashing op for manifest is complete
87+
tud_dfu_finish_flashing(ok? DFU_STATUS_OK : DFU_STATUS_ERR_VERIFY);
88+
}
89+
90+
// Invoked when received DFU_UPLOAD request
91+
// Application must populate data with up to length bytes and
92+
// Return the number of written bytes
93+
uint16_t tud_dfu_upload_cb(uint8_t alt, uint16_t block_num, uint8_t* data, uint16_t length)
94+
{
95+
(void) alt;
96+
(void) block_num;
97+
(void) data;
98+
(void) length;
99+
100+
// not implemented
101+
return 0;
102+
}
103+
104+
// Invoked when the Host has terminated a download or upload transfer
105+
void tud_dfu_abort_cb(uint8_t alt)
106+
{
107+
(void) alt;
108+
// ignore
109+
}
110+
111+
// Invoked when a DFU_DETACH request is received
112+
void tud_dfu_detach_cb(void)
113+
{
114+
// done, reboot
115+
esp_restart();
116+
}

Diff for: variants/arduino_nano_nora/double_tap.c

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include <string.h>
2+
3+
#include <esp_system.h>
4+
#include <esp32s3/rom/cache.h>
5+
#include <esp_heap_caps.h>
6+
7+
#include "double_tap.h"
8+
9+
#define NUM_TOKENS 3
10+
static const uint32_t MAGIC_TOKENS[NUM_TOKENS] = {
11+
0xf01681de, 0xbd729b29, 0xd359be7a,
12+
};
13+
14+
static void *magic_area;
15+
static uint32_t backup_area[NUM_TOKENS];
16+
17+
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
18+
// Current IDF does not map external RAM to a fixed address.
19+
// The actual VMA depends on other enabled devices, so the precise
20+
// location must be discovered.
21+
#include <esp_psram.h>
22+
#include <esp_private/esp_psram_extram.h>
23+
static uintptr_t get_extram_data_high(void) {
24+
// get a pointer into SRAM area (only the address is useful)
25+
void *psram_ptr = heap_caps_malloc(16, MALLOC_CAP_SPIRAM);
26+
heap_caps_free(psram_ptr);
27+
28+
// keep moving backwards until leaving PSRAM area
29+
uintptr_t psram_base_addr = (uintptr_t) psram_ptr;
30+
psram_base_addr &= ~(CONFIG_MMU_PAGE_SIZE - 1); // align to start of page
31+
while (esp_psram_check_ptr_addr((void *) psram_base_addr)) {
32+
psram_base_addr -= CONFIG_MMU_PAGE_SIZE;
33+
}
34+
35+
// offset is one page from start of PSRAM
36+
return psram_base_addr + CONFIG_MMU_PAGE_SIZE + esp_psram_get_size();
37+
}
38+
#else
39+
#include <soc/soc.h>
40+
#define get_extram_data_high() ((uintptr_t) SOC_EXTRAM_DATA_HIGH)
41+
#endif
42+
43+
44+
void double_tap_init(void) {
45+
// magic location block ends 0x20 bytes from end of PSRAM
46+
magic_area = (void *) (get_extram_data_high() - 0x20 - sizeof(MAGIC_TOKENS));
47+
}
48+
49+
void double_tap_mark() {
50+
memcpy(backup_area, magic_area, sizeof(MAGIC_TOKENS));
51+
memcpy(magic_area, MAGIC_TOKENS, sizeof(MAGIC_TOKENS));
52+
Cache_WriteBack_Addr((uintptr_t) magic_area, sizeof(MAGIC_TOKENS));
53+
}
54+
55+
void double_tap_invalidate() {
56+
if (memcmp(backup_area, MAGIC_TOKENS, sizeof(MAGIC_TOKENS))) {
57+
// different contents: restore backup
58+
memcpy(magic_area, backup_area, sizeof(MAGIC_TOKENS));
59+
} else {
60+
// clear memory
61+
memset(magic_area, 0, sizeof(MAGIC_TOKENS));
62+
}
63+
Cache_WriteBack_Addr((uintptr_t) magic_area, sizeof(MAGIC_TOKENS));
64+
}
65+
66+
bool double_tap_check_match() {
67+
return (memcmp(magic_area, MAGIC_TOKENS, sizeof(MAGIC_TOKENS)) == 0);
68+
}

Diff for: variants/arduino_nano_nora/double_tap.h

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#ifndef __DOUBLE_TAP_H__
2+
#define __DOUBLE_TAP_H__
3+
4+
#include <stdint.h>
5+
#include <stdbool.h>
6+
7+
#ifdef __cplusplus
8+
extern "C" {
9+
#endif
10+
11+
void double_tap_init(void);
12+
void double_tap_mark(void);
13+
void double_tap_invalidate(void);
14+
bool double_tap_check_match(void);
15+
16+
#ifdef __cplusplus
17+
}
18+
#endif
19+
20+
#endif /* __DOUBLE_TAP_H__ */

0 commit comments

Comments
 (0)