use std::ops::Range;
use postcard_rpc::header::VarHeader;
use postcard_schema::Schema;
use probe_rs::Target;
use serde::{Deserialize, Serialize};
use crate::rpc::functions::{NoResponse, RpcContext, RpcResult};
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Schema)]
pub struct JEP106Code {
pub id: u8,
pub cc: u8,
}
impl From<jep106::JEP106Code> for JEP106Code {
fn from(value: jep106::JEP106Code) -> Self {
Self {
id: value.id,
cc: value.cc,
}
}
}
impl From<JEP106Code> for jep106::JEP106Code {
fn from(value: JEP106Code) -> Self {
Self {
id: value.id,
cc: value.cc,
}
}
}
#[derive(Serialize, Deserialize, Clone, Schema)]
pub struct ChipFamily {
pub name: String,
pub manufacturer: Option<JEP106Code>,
pub variants: Vec<Chip>,
}
impl From<&probe_rs_target::ChipFamily> for ChipFamily {
fn from(value: &probe_rs_target::ChipFamily) -> Self {
Self {
name: value.name.clone(),
manufacturer: value.manufacturer.map(|m| m.into()),
variants: value.variants.iter().map(|v| v.into()).collect(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Schema)]
#[serde(deny_unknown_fields)]
pub struct Chip {
pub name: String,
}
impl From<&probe_rs_target::Chip> for Chip {
fn from(value: &probe_rs_target::Chip) -> Self {
Self {
name: value.name.clone(),
}
}
}
pub type ListFamiliesResponse = RpcResult<Vec<ChipFamily>>;
pub async fn list_families(
ctx: &mut RpcContext,
_header: VarHeader,
_req: (),
) -> ListFamiliesResponse {
Ok(ctx
.registry()
.await
.families()
.iter()
.map(|f| f.into())
.collect())
}
#[derive(Serialize, Deserialize, Schema)]
pub struct ChipInfoRequest {
pub name: String,
}
#[derive(Serialize, Deserialize, Clone, Schema)]
pub struct ChipData {
pub cores: Vec<Core>,
pub memory_map: Vec<MemoryRegion>,
}
impl From<Target> for ChipData {
fn from(value: Target) -> Self {
Self {
cores: value.cores.into_iter().map(|core| core.into()).collect(),
memory_map: value
.memory_map
.into_iter()
.map(|mmap| mmap.into())
.collect(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Schema)]
pub struct Core {
pub name: String,
pub core_type: CoreType,
}
impl From<probe_rs_target::Core> for Core {
fn from(value: probe_rs_target::Core) -> Self {
Self {
name: value.name,
core_type: value.core_type.into(),
}
}
}
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, Schema)]
pub enum CoreType {
Armv6m,
Armv7a,
Armv7m,
Armv7em,
Armv8a,
Armv8m,
Riscv,
Xtensa,
}
impl From<probe_rs_target::CoreType> for CoreType {
fn from(value: probe_rs_target::CoreType) -> Self {
match value {
probe_rs_target::CoreType::Armv6m => CoreType::Armv6m,
probe_rs_target::CoreType::Armv7a => CoreType::Armv7a,
probe_rs_target::CoreType::Armv7m => CoreType::Armv7m,
probe_rs_target::CoreType::Armv7em => CoreType::Armv7em,
probe_rs_target::CoreType::Armv8a => CoreType::Armv8a,
probe_rs_target::CoreType::Armv8m => CoreType::Armv8m,
probe_rs_target::CoreType::Riscv => CoreType::Riscv,
probe_rs_target::CoreType::Xtensa => CoreType::Xtensa,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Schema)]
pub enum MemoryRegion {
Ram(RamRegion),
Generic(GenericRegion),
Nvm(NvmRegion),
}
impl From<probe_rs_target::MemoryRegion> for MemoryRegion {
fn from(value: probe_rs_target::MemoryRegion) -> Self {
match value {
probe_rs_target::MemoryRegion::Ram(rr) => MemoryRegion::Ram(rr.into()),
probe_rs_target::MemoryRegion::Generic(gr) => MemoryRegion::Generic(gr.into()),
probe_rs_target::MemoryRegion::Nvm(nr) => MemoryRegion::Nvm(nr.into()),
}
}
}
impl MemoryRegion {
pub fn address_range(&self) -> Range<u64> {
let (start, end) = match self {
MemoryRegion::Ram(rr) => rr.range,
MemoryRegion::Generic(gr) => gr.range,
MemoryRegion::Nvm(nr) => nr.range,
};
start..end
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Schema)]
pub struct NvmRegion {
pub name: Option<String>,
pub range: (u64, u64),
pub cores: Vec<String>,
pub is_alias: bool,
pub access: Option<MemoryAccess>,
}
impl From<probe_rs_target::NvmRegion> for NvmRegion {
fn from(value: probe_rs_target::NvmRegion) -> Self {
Self {
name: value.name,
range: (value.range.start, value.range.end),
cores: value.cores,
is_alias: value.is_alias,
access: value.access.map(|a| a.into()),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Schema)]
pub struct RamRegion {
pub name: Option<String>,
pub range: (u64, u64),
pub cores: Vec<String>,
#[serde(default)]
pub access: Option<MemoryAccess>,
}
impl From<probe_rs_target::RamRegion> for RamRegion {
fn from(value: probe_rs_target::RamRegion) -> Self {
Self {
name: value.name,
range: (value.range.start, value.range.end),
cores: value.cores,
access: value.access.map(|a| a.into()),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Schema)]
pub struct GenericRegion {
pub name: Option<String>,
pub range: (u64, u64),
pub cores: Vec<String>,
pub access: Option<MemoryAccess>,
}
impl From<probe_rs_target::GenericRegion> for GenericRegion {
fn from(value: probe_rs_target::GenericRegion) -> Self {
Self {
name: value.name,
range: (value.range.start, value.range.end),
cores: value.cores,
access: value.access.map(|a| a.into()),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Schema)]
pub struct MemoryAccess {
pub read: bool,
pub write: bool,
pub execute: bool,
pub boot: bool,
}
impl From<probe_rs_target::MemoryAccess> for MemoryAccess {
fn from(value: probe_rs_target::MemoryAccess) -> Self {
Self {
read: value.read,
write: value.write,
execute: value.execute,
boot: value.boot,
}
}
}
impl Default for MemoryAccess {
fn default() -> Self {
MemoryAccess {
read: true,
write: true,
execute: true,
boot: false,
}
}
}
pub type ChipInfoResponse = RpcResult<ChipData>;
pub async fn chip_info(
ctx: &mut RpcContext,
_header: VarHeader,
request: ChipInfoRequest,
) -> ChipInfoResponse {
Ok(ctx
.registry()
.await
.get_target_by_name(request.name)?
.into())
}
#[derive(Serialize, Deserialize, Schema)]
pub struct LoadChipFamilyRequest {
pub families_yaml: String,
}
pub async fn load_chip_family(
ctx: &mut RpcContext,
_header: VarHeader,
request: LoadChipFamilyRequest,
) -> NoResponse {
ctx.registry()
.await
.add_target_family_from_yaml(&request.families_yaml)?;
Ok(())
}