Use custom partition table to prevent firmware getting overwritten
This commit is contained in:
parent
40b9b5d278
commit
b1625cdf7c
38
firmware/.vscode/launch.json
vendored
38
firmware/.vscode/launch.json
vendored
|
|
@ -10,6 +10,14 @@
|
||||||
"coreConfigs": [
|
"coreConfigs": [
|
||||||
{
|
{
|
||||||
"programBinary": "target/xtensa-esp32s3-none-elf/debug/acid-firmware",
|
"programBinary": "target/xtensa-esp32s3-none-elf/debug/acid-firmware",
|
||||||
|
"rttEnabled": true,
|
||||||
|
"rttChannelFormats": [
|
||||||
|
{
|
||||||
|
"channelNumber": 0,
|
||||||
|
"dataFormat": "String",
|
||||||
|
"mode": "BlockIfFull"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -22,6 +30,14 @@
|
||||||
"coreConfigs": [
|
"coreConfigs": [
|
||||||
{
|
{
|
||||||
"programBinary": "target/xtensa-esp32s3-none-elf/release/acid-firmware",
|
"programBinary": "target/xtensa-esp32s3-none-elf/release/acid-firmware",
|
||||||
|
"rttEnabled": true,
|
||||||
|
"rttChannelFormats": [
|
||||||
|
{
|
||||||
|
"channelNumber": 0,
|
||||||
|
"dataFormat": "String",
|
||||||
|
"mode": "BlockIfFull"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -32,12 +48,23 @@
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"flashingConfig": {
|
"flashingConfig": {
|
||||||
"flashingEnabled": true,
|
"flashingEnabled": true,
|
||||||
|
"formatOptions": {
|
||||||
|
"idf_partition_table": "partition-table.csv"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"probe": "303a:1001",
|
"probe": "303a:1001",
|
||||||
"chip": "esp32s3",
|
"chip": "esp32s3",
|
||||||
"coreConfigs": [
|
"coreConfigs": [
|
||||||
{
|
{
|
||||||
"programBinary": "target/xtensa-esp32s3-none-elf/debug/acid-firmware",
|
"programBinary": "target/xtensa-esp32s3-none-elf/debug/acid-firmware",
|
||||||
|
"rttEnabled": true,
|
||||||
|
"rttChannelFormats": [
|
||||||
|
{
|
||||||
|
"channelNumber": 0,
|
||||||
|
"dataFormat": "String",
|
||||||
|
"mode": "BlockIfFull"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -48,12 +75,23 @@
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"flashingConfig": {
|
"flashingConfig": {
|
||||||
"flashingEnabled": true,
|
"flashingEnabled": true,
|
||||||
|
"formatOptions": {
|
||||||
|
"idf_partition_table": "partition-table.csv"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"probe": "303a:1001",
|
"probe": "303a:1001",
|
||||||
"chip": "esp32s3",
|
"chip": "esp32s3",
|
||||||
"coreConfigs": [
|
"coreConfigs": [
|
||||||
{
|
{
|
||||||
"programBinary": "target/xtensa-esp32s3-none-elf/release/acid-firmware",
|
"programBinary": "target/xtensa-esp32s3-none-elf/release/acid-firmware",
|
||||||
|
"rttEnabled": true,
|
||||||
|
"rttChannelFormats": [
|
||||||
|
{
|
||||||
|
"channelNumber": 0,
|
||||||
|
"dataFormat": "String",
|
||||||
|
"mode": "BlockIfFull"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
10
firmware/.vscode/tasks.json
vendored
10
firmware/.vscode/tasks.json
vendored
|
|
@ -5,7 +5,10 @@
|
||||||
"label": "rust: cargo build",
|
"label": "rust: cargo build",
|
||||||
"type": "cargo",
|
"type": "cargo",
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}/acid-firmware"
|
"cwd": "${workspaceFolder}/acid-firmware",
|
||||||
|
"env": {
|
||||||
|
"ESP_LOG": "info"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"command": "build",
|
"command": "build",
|
||||||
"args": [
|
"args": [
|
||||||
|
|
@ -23,7 +26,10 @@
|
||||||
"label": "rust: cargo build --release",
|
"label": "rust: cargo build --release",
|
||||||
"type": "cargo",
|
"type": "cargo",
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "${workspaceFolder}/acid-firmware"
|
"cwd": "${workspaceFolder}/acid-firmware",
|
||||||
|
"env": {
|
||||||
|
"ESP_LOG": "info"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"command": "build",
|
"command": "build",
|
||||||
"args": [
|
"args": [
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
[target.'cfg(all(any(target_arch = "riscv32", target_arch = "xtensa"), target_os = "none"))']
|
[target.'cfg(all(any(target_arch = "riscv32", target_arch = "xtensa"), target_os = "none"))']
|
||||||
runner = "espflash flash --monitor"
|
runner = "espflash flash --partition-table partition-table.csv --monitor"
|
||||||
# runner = "probe-rs run --chip esp32s3 --preverify"
|
# runner = "probe-rs run --chip esp32s3 --preverify"
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
|
|
|
||||||
|
|
@ -87,6 +87,7 @@ chrono = { version = "0.4.43", default-features = false, features = ["alloc", "s
|
||||||
tinyvec = { version = "1.10.0", default-features = false, features = ["alloc"] }
|
tinyvec = { version = "1.10.0", default-features = false, features = ["alloc"] }
|
||||||
esp-metadata-generated = { version = "0.3.0", features = ["esp32s3"] }
|
esp-metadata-generated = { version = "0.3.0", features = ["esp32s3"] }
|
||||||
hex = { version = "0.4.3", default-features = false, features = ["alloc"] }
|
hex = { version = "0.4.3", default-features = false, features = ["alloc"] }
|
||||||
|
indoc = "2.0.7"
|
||||||
|
|
||||||
# A fork of slint with patches for `allocator_api` support.
|
# A fork of slint with patches for `allocator_api` support.
|
||||||
# Don't forget to change `slint-build` in build dependencies, if this is changed.
|
# Don't forget to change `slint-build` in build dependencies, if this is changed.
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,15 @@ extern crate alloc;
|
||||||
|
|
||||||
use core::alloc::Layout;
|
use core::alloc::Layout;
|
||||||
use core::cell::RefCell;
|
use core::cell::RefCell;
|
||||||
|
use core::fmt::Write;
|
||||||
use core::sync::atomic::{AtomicBool, Ordering};
|
use core::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::collections::vec_deque::VecDeque;
|
use alloc::collections::vec_deque::VecDeque;
|
||||||
|
use alloc::string::String;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
|
use alloc::vec::Vec;
|
||||||
use embassy_embedded_hal::adapter::BlockingAsync;
|
use embassy_embedded_hal::adapter::BlockingAsync;
|
||||||
use embassy_embedded_hal::flash::partition::Partition;
|
use embassy_embedded_hal::flash::partition::Partition;
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
|
|
@ -33,6 +36,7 @@ use embassy_sync::mutex::Mutex;
|
||||||
use embassy_sync::signal::Signal;
|
use embassy_sync::signal::Signal;
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use esp_alloc::{HeapRegion, MemoryCapability};
|
use esp_alloc::{HeapRegion, MemoryCapability};
|
||||||
|
use esp_bootloader_esp_idf::partitions::PartitionTable;
|
||||||
use esp_hal::Blocking;
|
use esp_hal::Blocking;
|
||||||
use esp_hal::clock::CpuClock;
|
use esp_hal::clock::CpuClock;
|
||||||
use esp_hal::dma::{BurstConfig, DmaDescriptor, DmaTxBuf, ExternalBurstConfig};
|
use esp_hal::dma::{BurstConfig, DmaDescriptor, DmaTxBuf, ExternalBurstConfig};
|
||||||
|
|
@ -50,6 +54,7 @@ use esp_hal::system::Stack;
|
||||||
use esp_hal::timer::timg::TimerGroup;
|
use esp_hal::timer::timg::TimerGroup;
|
||||||
use esp_rtos::embassy::Executor;
|
use esp_rtos::embassy::Executor;
|
||||||
use esp_storage::FlashStorage;
|
use esp_storage::FlashStorage;
|
||||||
|
use indoc::writedoc;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use rmk::channel::{CONTROLLER_CHANNEL, ControllerSub};
|
use rmk::channel::{CONTROLLER_CHANNEL, ControllerSub};
|
||||||
use rmk::config::{BehaviorConfig, PositionalConfig, RmkConfig, StorageConfig, VialConfig};
|
use rmk::config::{BehaviorConfig, PositionalConfig, RmkConfig, StorageConfig, VialConfig};
|
||||||
|
|
@ -242,10 +247,20 @@ async fn main(_spawner: Spawner) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize the flash
|
// Initialize the flash
|
||||||
static FLASH: StaticCell<Mutex<CriticalSectionRawMutex, BlockingAsync<FlashStorage>>> =
|
static PARTITION_TABLE_BUFFER: StaticCell<Vec<u8, &'static esp_alloc::EspHeap>> =
|
||||||
StaticCell::new();
|
StaticCell::new();
|
||||||
let flash = FLASH.init_with(|| {
|
let partition_table_buffer = PARTITION_TABLE_BUFFER.init_with(|| {
|
||||||
let flash = FlashStorage::new(peripherals.FLASH)
|
let mut buffer = Vec::<u8, _>::new_in(&PSRAM_ALLOCATOR);
|
||||||
|
buffer.resize(1024, 0_u8);
|
||||||
|
buffer
|
||||||
|
});
|
||||||
|
|
||||||
|
static FLASH: StaticCell<(
|
||||||
|
Mutex<CriticalSectionRawMutex, BlockingAsync<FlashStorage>>,
|
||||||
|
PartitionTable<'static>,
|
||||||
|
)> = StaticCell::new();
|
||||||
|
let (flash, partition_table) = FLASH.init_with(|| {
|
||||||
|
let mut flash = FlashStorage::new(peripherals.FLASH)
|
||||||
// Flash memory may not be written to while another core is executing from it.
|
// Flash memory may not be written to while another core is executing from it.
|
||||||
// By default, `FlashStorage` is configured to abort the operation and log an error message.
|
// By default, `FlashStorage` is configured to abort the operation and log an error message.
|
||||||
// However, it can also be configured to auto-park the other core, such that writing to
|
// However, it can also be configured to auto-park the other core, such that writing to
|
||||||
|
|
@ -254,19 +269,68 @@ async fn main(_spawner: Spawner) {
|
||||||
// to avoid having to park the other core, which could result in better performance.
|
// to avoid having to park the other core, which could result in better performance.
|
||||||
// Invalid configuration would then present itself as freezing/UB.
|
// Invalid configuration would then present itself as freezing/UB.
|
||||||
.multicore_auto_park();
|
.multicore_auto_park();
|
||||||
|
let partition_table = {
|
||||||
|
esp_bootloader_esp_idf::partitions::read_partition_table(
|
||||||
|
&mut flash,
|
||||||
|
partition_table_buffer,
|
||||||
|
)
|
||||||
|
.expect("Failed to read the partition table.")
|
||||||
|
};
|
||||||
|
|
||||||
Mutex::<CriticalSectionRawMutex, _>::new(async_flash_wrapper(flash))
|
(
|
||||||
|
Mutex::<CriticalSectionRawMutex, _>::new(async_flash_wrapper(flash)),
|
||||||
|
partition_table,
|
||||||
|
)
|
||||||
});
|
});
|
||||||
const FLASH_SIZE_TOTAL: u32 = 16 * 1024 * 1024;
|
|
||||||
const FLASH_PART_FIRMWARE_OFFSET: u32 = 0;
|
{
|
||||||
const FLASH_PART_FIRMWARE_SIZE: u32 = 0x3f0000;
|
let mut buffer = String::new();
|
||||||
const FLASH_PART_RMK_OFFSET: u32 = FLASH_PART_FIRMWARE_OFFSET + FLASH_PART_FIRMWARE_SIZE;
|
|
||||||
const FLASH_PART_RMK_SIZE_IN_SECTORS: u32 = 16;
|
writeln!(buffer, "Partition table:").unwrap();
|
||||||
const FLASH_PART_RMK_SIZE: u32 = FLASH_PART_RMK_SIZE_IN_SECTORS * FlashStorage::SECTOR_SIZE;
|
|
||||||
const FLASH_PART_ACID_OFFSET: u32 = FLASH_PART_RMK_OFFSET + FLASH_PART_RMK_SIZE;
|
for (index, partition) in partition_table.iter().enumerate() {
|
||||||
const FLASH_PART_ACID_SIZE: u32 = FLASH_SIZE_TOTAL - FLASH_PART_ACID_OFFSET;
|
writedoc!(
|
||||||
let flash_part_rmk = Partition::new(flash, FLASH_PART_RMK_OFFSET, FLASH_PART_RMK_SIZE);
|
buffer,
|
||||||
let flash_part_acid = Partition::new(flash, FLASH_PART_ACID_OFFSET, FLASH_PART_ACID_SIZE);
|
"
|
||||||
|
Partition #{index} {label:?}:
|
||||||
|
offset: 0x{offset:x}
|
||||||
|
length: 0x{len:x}
|
||||||
|
type: 0x{type:?}
|
||||||
|
read only: {read_only}
|
||||||
|
encrypted: {encrypted}
|
||||||
|
magic: {magic}
|
||||||
|
",
|
||||||
|
label = partition.label_as_str(),
|
||||||
|
offset = partition.offset(),
|
||||||
|
len = partition.len(),
|
||||||
|
type = partition.partition_type(),
|
||||||
|
read_only = partition.is_read_only(),
|
||||||
|
encrypted = partition.is_encrypted(),
|
||||||
|
magic = partition.magic(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("{}", buffer);
|
||||||
|
}
|
||||||
|
let flash_part_info_rmk = partition_table
|
||||||
|
.iter()
|
||||||
|
.find(|partition| partition.label_as_str() == "rmk")
|
||||||
|
.expect("No \"rmk\" partition found. Make sure to use the custom partition-table.csv when flashing.");
|
||||||
|
let flash_part_info_acid = partition_table
|
||||||
|
.iter()
|
||||||
|
.find(|partition| partition.label_as_str() == "acid")
|
||||||
|
.expect("No \"acid\" partition found. Make sure to use the custom partition-table.csv when flashing.");
|
||||||
|
let flash_part_rmk = Partition::new(
|
||||||
|
flash,
|
||||||
|
flash_part_info_rmk.offset(),
|
||||||
|
flash_part_info_rmk.len(),
|
||||||
|
);
|
||||||
|
let flash_part_acid = Partition::new(
|
||||||
|
flash,
|
||||||
|
flash_part_info_acid.offset(),
|
||||||
|
flash_part_info_acid.len(),
|
||||||
|
);
|
||||||
|
|
||||||
info!("Flash memory configured!");
|
info!("Flash memory configured!");
|
||||||
|
|
||||||
|
|
@ -313,7 +377,15 @@ async fn main(_spawner: Spawner) {
|
||||||
let vial_config = VialConfig::new(VIAL_KEYBOARD_ID, VIAL_KEYBOARD_DEF, &[(0, 0), (1, 1)]);
|
let vial_config = VialConfig::new(VIAL_KEYBOARD_ID, VIAL_KEYBOARD_DEF, &[(0, 0), (1, 1)]);
|
||||||
let storage_config = StorageConfig {
|
let storage_config = StorageConfig {
|
||||||
start_addr: 0,
|
start_addr: 0,
|
||||||
num_sectors: FLASH_PART_RMK_SIZE_IN_SECTORS as u8,
|
num_sectors: {
|
||||||
|
assert!(
|
||||||
|
flash_part_info_rmk.len() as u32 % FlashStorage::SECTOR_SIZE == 0,
|
||||||
|
"The size of the RMK partition must be a multiple of {} bytes. Current size: {}",
|
||||||
|
FlashStorage::SECTOR_SIZE,
|
||||||
|
flash_part_info_rmk.len()
|
||||||
|
);
|
||||||
|
(flash_part_info_rmk.len() as u32 / FlashStorage::SECTOR_SIZE) as u8
|
||||||
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let rmk_config = RmkConfig {
|
let rmk_config = RmkConfig {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue