use crate::error::Result;
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum ChipFamily {
#[default]
Ws63,
Bs2x,
Bs25,
Ws53,
Sw39,
Generic,
}
impl ChipFamily {
#[must_use]
pub fn default_baud(&self) -> u32 {
115200
}
#[must_use]
pub fn high_speed_baud(&self) -> u32 {
match self {
Self::Bs2x | Self::Bs25 => 2_000_000,
_ => 921_600,
}
}
#[must_use]
pub fn supported_bauds(&self) -> &'static [u32] {
match self {
Self::Bs2x | Self::Bs25 => &[115_200, 230_400, 460_800, 921_600, 2_000_000],
_ => &[115_200, 230_400, 460_800, 921_600],
}
}
pub fn supports_usb_dfu(&self) -> bool {
matches!(self, Self::Bs2x | Self::Bs25)
}
pub fn supports_efuse(&self) -> bool {
true }
pub fn requires_signed_firmware(&self) -> bool {
matches!(self, Self::Ws63 | Self::Bs2x | Self::Bs25)
}
pub fn from_name(name: &str) -> Option<Self> {
match name.to_lowercase().as_str() {
"ws63" => Some(Self::Ws63),
"bs2x" | "bs21" => Some(Self::Bs2x),
"bs25" => Some(Self::Bs25),
"ws53" => Some(Self::Ws53),
"sw39" => Some(Self::Sw39),
"generic" | "auto" => Some(Self::Generic),
_ => None,
}
}
}
impl fmt::Display for ChipFamily {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Ws63 => write!(f, "WS63"),
Self::Bs2x => write!(f, "BS2X"),
Self::Bs25 => write!(f, "BS25"),
Self::Ws53 => write!(f, "WS53"),
Self::Sw39 => write!(f, "SW39"),
Self::Generic => write!(f, "Generic"),
}
}
}
#[derive(Debug, Clone)]
pub struct ChipConfig {
pub family: ChipFamily,
pub init_baud: u32,
pub target_baud: u32,
pub late_baud_switch: bool,
pub handshake_timeout_secs: u32,
pub transfer_timeout_secs: u32,
}
impl ChipConfig {
pub fn new(family: ChipFamily) -> Self {
Self {
family,
init_baud: family.default_baud(),
target_baud: family.high_speed_baud(),
late_baud_switch: false,
handshake_timeout_secs: 30,
transfer_timeout_secs: 60,
}
}
#[must_use]
pub fn with_baud(mut self, baud: u32) -> Self {
self.target_baud = baud;
self
}
#[must_use]
pub fn with_late_baud(mut self, late: bool) -> Self {
self.late_baud_switch = late;
self
}
#[must_use]
pub fn with_handshake_timeout(mut self, secs: u32) -> Self {
self.handshake_timeout_secs = secs;
self
}
}
impl Default for ChipConfig {
fn default() -> Self {
Self::new(ChipFamily::default())
}
}
pub trait ChipOps {
fn family(&self) -> ChipFamily;
fn config(&self) -> &ChipConfig;
fn prepare_binary(&self, data: &[u8], _addr: u32) -> Result<Vec<u8>> {
Ok(data.to_vec())
}
fn needs_signing(&self, _addr: u32) -> bool {
false
}
fn flash_base(&self) -> u32 {
0x00000000
}
fn flash_size(&self) -> u32 {
0x00800000 }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_chip_family_from_name() {
assert_eq!(ChipFamily::from_name("ws63"), Some(ChipFamily::Ws63));
assert_eq!(ChipFamily::from_name("BS2X"), Some(ChipFamily::Bs2x));
assert_eq!(ChipFamily::from_name("unknown"), None);
}
#[test]
fn test_chip_config_defaults() {
let config = ChipConfig::new(ChipFamily::Ws63);
assert_eq!(config.init_baud, 115200);
assert_eq!(config.target_baud, 921600);
}
}