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

orb-mcu-util: add --can-fd option #277

Merged
merged 1 commit into from
Oct 25, 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
9 changes: 4 additions & 5 deletions mcu-util/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ static BUILD_INFO: BuildInfo = make_build_info!();
struct Args {
#[clap(subcommand)]
subcmd: SubCommand,
#[clap(short, long, default_value = "false")]
can_fd: bool,
}

#[derive(Parser, Debug)]
Expand Down Expand Up @@ -96,9 +98,6 @@ pub struct McuUpdate {
/// Path to binary file
#[clap(short, long)]
path: String,
/// Use CAN-FD to send the image
#[clap(short, long, default_value = "false")]
can_fd: bool,
}

/// Stress tests options
Expand Down Expand Up @@ -132,7 +131,7 @@ enum SecureElement {
}

async fn execute(args: Args) -> Result<()> {
let (mut orb, orb_tasks) = Orb::new().await?;
let (mut orb, orb_tasks) = Orb::new(args.can_fd).await?;

match args.subcmd {
SubCommand::Info => {
Expand Down Expand Up @@ -160,7 +159,7 @@ async fn execute(args: Args) -> Result<()> {
}
SubCommand::Image(Image::Update(opts)) => {
orb.borrow_mut_mcu(opts.mcu)
.update_firmware(&opts.path, opts.can_fd)
.update_firmware(&opts.path)
.await?
}
SubCommand::HardwareRevision { filename } => {
Expand Down
98 changes: 42 additions & 56 deletions mcu-util/src/orb/main_board.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub struct MainBoard {
canfd_iface: CanRawMessaging,
isotp_iface: CanIsoTpMessaging,
message_queue_rx: mpsc::UnboundedReceiver<McuPayload>,
canfd: bool,
}

pub struct MainBoardBuilder {
Expand All @@ -41,8 +42,8 @@ impl MainBoardBuilder {
}
}

pub async fn build(self) -> Result<(MainBoard, BoardTaskHandles)> {
let (mut canfd_iface, raw_can_task_handle) = CanRawMessaging::new(
pub async fn build(self, canfd: bool) -> Result<(MainBoard, BoardTaskHandles)> {
let (canfd_iface, raw_can_task_handle) = CanRawMessaging::new(
String::from("can0"),
Device::Main,
self.message_queue_tx.clone(),
Expand All @@ -57,34 +58,12 @@ impl MainBoardBuilder {
)
.wrap_err("Failed to create CanIsoTpMessaging for MainBoard")?;

// Send a heartbeat to the main mcu to ensure it is alive
// & "subscribe" to the main mcu messages: messages to the Jetson
// are going to be sent after the heartbeat
let ack_result = canfd_iface
.send(McuPayload::ToMain(
main_messaging::jetson_to_mcu::Payload::Heartbeat(
main_messaging::Heartbeat {
timeout_seconds: 0_u32,
},
),
))
.await
.map(|c| {
if let CommonAckError::Success = c {
Ok(())
} else {
Err(eyre!("ack error: {c}"))
}
});
if let Err(e) = ack_result {
error!("Failed to send heartbeat to main mcu: {:#?}", e);
}

Ok((
MainBoard {
canfd_iface,
isotp_iface,
message_queue_rx: self.message_queue_rx,
canfd,
},
BoardTaskHandles {
raw: raw_can_task_handle,
Expand All @@ -98,19 +77,38 @@ impl MainBoard {
pub fn builder() -> MainBoardBuilder {
MainBoardBuilder::new()
}

/// Send a message to the security board with preferred interface
pub async fn send(&mut self, payload: McuPayload) -> Result<CommonAckError> {
if matches!(payload, McuPayload::ToMain(_)) {
tracing::trace!(
"sending to main mcu over {}: {:?}",
if self.canfd { "can-fd" } else { "iso-tp" },
payload
);
if self.canfd {
self.canfd_iface.send(payload).await
} else {
self.isotp_iface.send(payload).await
}
} else {
Err(eyre!(
"Message not targeted to security board: {:?}",
payload
))
}
}
}

#[async_trait]
impl Board for MainBoard {
async fn reboot(&mut self, delay: Option<u32>) -> Result<()> {
let delay = delay.unwrap_or(REBOOT_DELAY);
self.isotp_iface
.send(McuPayload::ToMain(
main_messaging::jetson_to_mcu::Payload::Reboot(
main_messaging::RebootWithDelay { delay },
),
))
.await?;
let reboot_msg =
McuPayload::ToMain(main_messaging::jetson_to_mcu::Payload::Reboot(
main_messaging::RebootWithDelay { delay },
));
self.send(reboot_msg).await?;
info!("🚦 Rebooting main microcontroller in {} seconds", delay);
Ok(())
}
Expand Down Expand Up @@ -161,7 +159,7 @@ impl Board for MainBoard {
Ok(())
}

async fn update_firmware(&mut self, path: &str, canfd: bool) -> Result<()> {
async fn update_firmware(&mut self, path: &str) -> Result<()> {
let buffer = dfu::load_binary_file(path)?;
debug!("Sending file {} ({} bytes)", path, buffer.len());
let mut block_iter =
Expand All @@ -170,24 +168,12 @@ impl Board for MainBoard {
);

while let Some(payload) = block_iter.next() {
if canfd {
while self
.canfd_iface
.send(McuPayload::ToMain(payload.clone()))
.await
.is_err()
{
tokio::time::sleep(Duration::from_millis(100)).await;
}
} else {
while self
.isotp_iface
.send(McuPayload::ToMain(payload.clone()))
.await
.is_err()
{
tokio::time::sleep(Duration::from_millis(100)).await;
}
while self
.send(McuPayload::ToMain(payload.clone()))
.await
.is_err()
{
tokio::time::sleep(Duration::from_millis(100)).await;
}
dfu::print_progress(block_iter.progress_percentage());
}
Expand All @@ -200,7 +186,8 @@ impl Board for MainBoard {
McuPayload::ToMain(main_messaging::jetson_to_mcu::Payload::FwImageCheck(
main_messaging::FirmwareImageCheck { crc32: crc },
));
if let Ok(ack) = self.isotp_iface.send(payload).await {

if let Ok(ack) = self.send(payload).await {
if !matches!(ack, CommonAckError::Success) {
return Err(eyre!(
"Unable to check image integrity: ack error: {}",
Expand Down Expand Up @@ -240,7 +227,7 @@ impl Board for MainBoard {
},
),
);
if let Ok(ack) = self.isotp_iface.send(payload).await {
if let Ok(ack) = self.send(payload).await {
if !matches!(ack, CommonAckError::Success) {
return Err(eyre!(
"Unable to activate image: ack error: {}",
Expand Down Expand Up @@ -349,8 +336,8 @@ impl MainBoardInfo {
/// on timeout, returns the info that was fetched so far
async fn build(mut self, main_board: &mut MainBoard) -> Result<Self, Self> {
let mut is_err = false;

if let Err(e) = main_board
.isotp_iface
.send(McuPayload::ToMain(
main_messaging::jetson_to_mcu::Payload::ValueGet(
main_messaging::ValueGet {
Expand All @@ -366,7 +353,6 @@ impl MainBoardInfo {
}

if let Err(e) = main_board
.isotp_iface
.send(McuPayload::ToMain(
main_messaging::jetson_to_mcu::Payload::ValueGet(
main_messaging::ValueGet {
Expand All @@ -382,7 +368,6 @@ impl MainBoardInfo {
}

if let Err(e) = main_board
.isotp_iface
.send(McuPayload::ToMain(
main_messaging::jetson_to_mcu::Payload::ValueGet(
main_messaging::ValueGet {
Expand Down Expand Up @@ -437,6 +422,7 @@ impl MainBoardInfo {
unreachable!("should always be a message from the main board")
};

tracing::trace!("rx message from main-mcu: {:?}", main_mcu_payload);
match main_mcu_payload {
main_messaging::mcu_to_jetson::Payload::Versions(v) => {
self.fw_versions = Some(v);
Expand Down
9 changes: 5 additions & 4 deletions mcu-util/src/orb/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub trait Board {
/// This operation will also switch the board, and in case
/// of the security microcontroller, it will reboot the board
/// to perform the update.
async fn update_firmware(&mut self, path: &str, canfd: bool) -> Result<()>;
async fn update_firmware(&mut self, path: &str) -> Result<()>;

/// Switch the firmware images on the board, from secondary to primary
/// Images are checked for validity before the switch: if the images are
Expand All @@ -59,9 +59,10 @@ pub struct Orb {
}

impl Orb {
pub async fn new() -> Result<(Self, OrbTaskHandles)> {
let (main_board, main_task_handle) = MainBoard::builder().build().await?;
let (sec_board, sec_task_handle) = SecurityBoard::builder().build().await?;
pub async fn new(can_fd: bool) -> Result<(Self, OrbTaskHandles)> {
let (main_board, main_task_handle) = MainBoard::builder().build(can_fd).await?;
let (sec_board, sec_task_handle) =
SecurityBoard::builder().build(can_fd).await?;
let info = OrbInfo::default();

Ok((
Expand Down
Loading
Loading