Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support different crystal frequencies bootloader #553

Merged
merged 3 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Added reset strategies (#487)
- Read esp-println generated defmt messages (#466)
- Add --target-app-partition argument to flash command (#461)
- Add --confirm-port argument to flash command (#455)
- Add --chip argument for flash and write-bin commands (#514)
- Add --partition-table-offset argument for specifying the partition table offset (#516)
- Read `esp-println` generated `defmt` messages (#466)
- Add `--target-app-partition` argument to flash command (#461)
- Add `--confirm-port` argument to flash command (#455)
- Add `--chip argument` for flash and write-bin commands (#514)
- Add `--partition-table-offset` argument for specifying the partition table offset (#516)
- Add `Serialize` and `Deserialize` to `FlashFrequency`, `FlashMode` and `FlashSize`. (#528)
- Add `checksum-md5` command (#536)
- Add verify and skipping of unchanged flash regions - add `--no-verify` and `--no-skip` (#538)
- Add --min-chip-rev argument to specify minimum chip revision (#252)
- Add `--min-chip-rev` argument to specify minimum chip revision (#525)
- Add `serialport` feature. (#535)
- Add support for 26 MHz bootloader for ESP32 and ESP32-C2 (#553)

### Fixed

Expand Down
24 changes: 16 additions & 8 deletions cargo-espflash/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use espflash::{
flasher::{FlashData, FlashSettings},
image_format::ImageFormatKind,
logging::initialize_logger,
targets::Chip,
targets::{Chip, XtalFrequency},
update::check_for_update,
};
use log::{debug, info, LevelFilter};
Expand Down Expand Up @@ -339,19 +339,21 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> {
)?;
}

flash_elf_image(&mut flasher, &elf_data, flash_data)?;
flash_elf_image(&mut flasher, &elf_data, flash_data, target_xtal_freq)?;
}

if args.flash_args.monitor {
let pid = flasher.get_usb_pid()?;

// The 26MHz ESP32-C2's need to be treated as a special case.
let default_baud =
if chip == Chip::Esp32c2 && args.connect_args.no_stub && target_xtal_freq == 26 {
74_880
} else {
115_200
};
let default_baud = if chip == Chip::Esp32c2
&& args.connect_args.no_stub
&& target_xtal_freq == XtalFrequency::_26Mhz
{
74_880
} else {
115_200
};

monitor(
flasher.into_interface(),
Expand Down Expand Up @@ -580,13 +582,19 @@ fn save_image(args: SaveImageArgs) -> Result<()> {
args.save_image_args.min_chip_rev,
)?;

let xtal_freq = args
.save_image_args
.xtal_freq
.unwrap_or(XtalFrequency::default(args.save_image_args.chip));

save_elf_as_image(
&elf_data,
args.save_image_args.chip,
args.save_image_args.file,
flash_data,
args.save_image_args.merge,
args.save_image_args.skip_padding,
xtal_freq,
)?;

Ok(())
Expand Down
Binary file not shown.
Binary file not shown.
24 changes: 16 additions & 8 deletions espflash/src/bin/espflash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use espflash::{
flasher::{FlashData, FlashSettings},
image_format::ImageFormatKind,
logging::initialize_logger,
targets::Chip,
targets::{Chip, XtalFrequency},
update::check_for_update,
};
use log::{debug, info, LevelFilter};
Expand Down Expand Up @@ -263,19 +263,21 @@ fn flash(args: FlashArgs, config: &Config) -> Result<()> {
)?;
}

flash_elf_image(&mut flasher, &elf_data, flash_data)?;
flash_elf_image(&mut flasher, &elf_data, flash_data, target_xtal_freq)?;
}

if args.flash_args.monitor {
let pid = flasher.get_usb_pid()?;

// The 26MHz ESP32-C2's need to be treated as a special case.
let default_baud =
if chip == Chip::Esp32c2 && args.connect_args.no_stub && target_xtal_freq == 26 {
74_880
} else {
115_200
};
let default_baud = if chip == Chip::Esp32c2
&& args.connect_args.no_stub
&& target_xtal_freq == XtalFrequency::_26Mhz
{
74_880
} else {
115_200
};

monitor(
flasher.into_interface(),
Expand Down Expand Up @@ -325,13 +327,19 @@ fn save_image(args: SaveImageArgs) -> Result<()> {
args.save_image_args.min_chip_rev,
)?;

let xtal_freq = args
.save_image_args
.xtal_freq
.unwrap_or(XtalFrequency::default(args.save_image_args.chip));

save_elf_as_image(
&elf_data,
args.save_image_args.chip,
args.save_image_args.file,
flash_data,
args.save_image_args.merge,
args.save_image_args.skip_padding,
xtal_freq,
)?;

Ok(())
Expand Down
26 changes: 18 additions & 8 deletions espflash/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use crate::{
flasher::{FlashData, FlashFrequency, FlashMode, FlashSize, Flasher, ProgressCallbacks},
image_format::ImageFormatKind,
interface::Interface,
targets::Chip,
targets::{Chip, XtalFrequency},
};

pub mod config;
Expand Down Expand Up @@ -220,6 +220,9 @@ pub struct SaveImageArgs {
/// Don't pad the image to the flash size
#[arg(long, short = 'P', requires = "merge")]
pub skip_padding: bool,
/// Cristal frequency of the target
#[arg(long, short = 'x')]
pub xtal_freq: Option<XtalFrequency>,
}

/// Open the serial monitor without flashing
Expand Down Expand Up @@ -372,7 +375,7 @@ pub fn print_board_info(flasher: &mut Flasher) -> Result<()> {
} else {
println!();
}
println!("Crystal frequency: {}MHz", info.crystal_frequency);
println!("Crystal frequency: {}", info.crystal_frequency);
println!("Flash size: {}", info.flash_size);
println!("Features: {}", info.features.join(", "));
println!("MAC address: {}", info.mac_address);
Expand Down Expand Up @@ -400,7 +403,7 @@ pub fn serial_monitor(args: MonitorArgs, config: &Config) -> Result<()> {
// The 26MHz ESP32-C2's need to be treated as a special case.
let default_baud = if chip == Chip::Esp32c2
&& args.connect_args.no_stub
&& target.crystal_freq(flasher.connection())? == 26
&& target.crystal_freq(flasher.connection())? == XtalFrequency::_26Mhz
{
74_880
} else {
Expand All @@ -424,15 +427,16 @@ pub fn save_elf_as_image(
flash_data: FlashData,
merge: bool,
skip_padding: bool,
xtal_freq: XtalFrequency,
) -> Result<()> {
let image = ElfFirmwareImage::try_from(elf_data)?;

if merge {
// To get a chip revision, the connection is needed
// For simplicity, the revision None is used
let image = chip
.into_target()
.get_flash_image(&image, flash_data.clone(), None)?;
let image =
chip.into_target()
.get_flash_image(&image, flash_data.clone(), None, xtal_freq)?;

display_image_size(image.app_size(), image.part_size());

Expand Down Expand Up @@ -466,7 +470,7 @@ pub fn save_elf_as_image(
} else {
let image = chip
.into_target()
.get_flash_image(&image, flash_data, None)?;
.get_flash_image(&image, flash_data, None, xtal_freq)?;

display_image_size(image.app_size(), image.part_size());

Expand Down Expand Up @@ -573,10 +577,16 @@ pub fn flash_elf_image(
flasher: &mut Flasher,
elf_data: &[u8],
flash_data: FlashData,
xtal_freq: XtalFrequency,
) -> Result<()> {
// Load the ELF data, optionally using the provider bootloader/partition
// table/image format, to the device's flash memory.
flasher.load_elf_to_flash(elf_data, flash_data, Some(&mut EspflashProgress::default()))?;
flasher.load_elf_to_flash(
elf_data,
flash_data,
Some(&mut EspflashProgress::default()),
xtal_freq,
)?;
info!("Flashing has completed!");

Ok(())
Expand Down
17 changes: 10 additions & 7 deletions espflash/src/flasher/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use crate::{
error::{ConnectionError, Error, ResultExt},
image_format::ImageFormatKind,
interface::Interface,
targets::Chip,
targets::{Chip, XtalFrequency},
};

mod stubs;
Expand Down Expand Up @@ -461,7 +461,7 @@ pub struct DeviceInfo {
/// The revision of the chip
pub revision: Option<(u32, u32)>,
/// The crystal frequency of the chip
pub crystal_frequency: u32,
pub crystal_frequency: XtalFrequency,
/// The total available flash size
pub flash_size: FlashSize,
/// Device features
Expand Down Expand Up @@ -894,6 +894,7 @@ impl Flasher {
elf_data: &[u8],
flash_data: FlashData,
mut progress: Option<&mut dyn ProgressCallbacks>,
xtal_freq: XtalFrequency,
) -> Result<(), Error> {
let image = ElfFirmwareImage::try_from(elf_data)?;

Expand All @@ -914,10 +915,12 @@ impl Flasher {
None
};

let image = self
.chip
.into_target()
.get_flash_image(&image, flash_data, chip_revision)?;
let image = self.chip.into_target().get_flash_image(
&image,
flash_data,
chip_revision,
xtal_freq,
)?;

// When the `cli` feature is enabled, display the image size information.
#[cfg(feature = "cli")]
Expand Down Expand Up @@ -995,7 +998,7 @@ impl Flasher {
// The ROM code thinks it uses a 40 MHz XTAL. Recompute the baud rate in order
// to trick the ROM code to set the correct baud rate for a 26 MHz XTAL.
let mut new_baud = speed;
if self.chip == Chip::Esp32c2 && !self.use_stub && xtal_freq == 26 {
if self.chip == Chip::Esp32c2 && !self.use_stub && xtal_freq == XtalFrequency::_26Mhz {
new_baud = new_baud * 40 / 26;
}

Expand Down
48 changes: 35 additions & 13 deletions espflash/src/targets/esp32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ use crate::{
error::{Error, UnsupportedImageFormatError},
flasher::{FlashData, FlashFrequency},
image_format::{IdfBootloaderFormat, ImageFormat, ImageFormatKind},
targets::{bytes_to_mac_addr, Chip, Esp32Params, ReadEFuse, SpiRegisters, Target},
targets::{
bytes_to_mac_addr, Chip, Esp32Params, ReadEFuse, SpiRegisters, Target, XtalFrequency,
},
};

const CHIP_DETECT_MAGIC_VALUES: &[u32] = &[0x00f0_1d83];
Expand All @@ -16,15 +18,6 @@ const FLASH_RANGES: &[Range<u32>] = &[
0x3f40_0000..0x3f80_0000, // DROM
];

const PARAMS: Esp32Params = Esp32Params::new(
0x1000,
0x1_0000,
0x3f_0000,
0,
FlashFrequency::_40Mhz,
include_bytes!("../../resources/bootloaders/esp32-bootloader.bin"),
);

const UART_CLKDIV_REG: u32 = 0x3ff4_0014;
const UART_CLKDIV_MASK: u32 = 0xfffff;

Expand Down Expand Up @@ -140,10 +133,14 @@ impl Target for Esp32 {
Ok((self.read_efuse(connection, 5)? >> 24) & 0x3)
}

fn crystal_freq(&self, connection: &mut Connection) -> Result<u32, Error> {
fn crystal_freq(&self, connection: &mut Connection) -> Result<XtalFrequency, Error> {
let uart_div = connection.read_reg(UART_CLKDIV_REG)? & UART_CLKDIV_MASK;
let est_xtal = (connection.get_baud()? * uart_div) / 1_000_000 / XTAL_CLK_DIVIDER;
let norm_xtal = if est_xtal > 33 { 40 } else { 26 };
let norm_xtal = if est_xtal > 33 {
XtalFrequency::_40Mhz
} else {
XtalFrequency::_26Mhz
};

Ok(norm_xtal)
}
Expand All @@ -153,17 +150,42 @@ impl Target for Esp32 {
image: &'a dyn FirmwareImage<'a>,
flash_data: FlashData,
_chip_revision: Option<(u32, u32)>,
xtal_freq: XtalFrequency,
) -> Result<Box<dyn ImageFormat<'a> + 'a>, Error> {
let image_format = flash_data
.image_format
.unwrap_or(ImageFormatKind::EspBootloader);

let booloader: &'static [u8] = match xtal_freq {
XtalFrequency::_40Mhz => {
include_bytes!("../../resources/bootloaders/esp32-bootloader.bin")
}
XtalFrequency::_26Mhz => {
include_bytes!("../../resources/bootloaders/esp32_26-bootloader.bin")
}
_ => {
return Err(Error::UnsupportedFeature {
chip: Chip::Esp32,
feature: "the selected crystal frequency".into(),
})
}
};

let params = Esp32Params::new(
0x1000,
0x1_0000,
0x3f_0000,
0,
FlashFrequency::_40Mhz,
booloader,
);

match image_format {
ImageFormatKind::EspBootloader => Ok(Box::new(IdfBootloaderFormat::new(
image,
Chip::Esp32,
flash_data.min_chip_rev,
PARAMS,
params,
flash_data.partition_table,
flash_data.partition_table_offset,
flash_data.target_app_partition,
Expand Down
Loading