diff --git a/lasercan-bootloader/Cargo.lock b/lasercan-bootloader/Cargo.lock index ae1d86e..704fb36 100644 --- a/lasercan-bootloader/Cargo.lock +++ b/lasercan-bootloader/Cargo.lock @@ -2,6 +2,12 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "anyhow" +version = "1.0.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59d2a3357dde987206219e78ecfbbb6e8dad06cbb65292758d3270e6254f7355" + [[package]] name = "atomic-polyfill" version = "1.0.3" @@ -34,18 +40,19 @@ checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" [[package]] name = "binmarshal" -version = "0.1.12" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0a69dafda4da53e405937badae1a435d66b4a0181c905beef285dff0f1ef2f" +checksum = "ef52819335fe738d04a0941a49ccd3b54c12660611456e2919a6bbb86787bc7a" dependencies = [ + "anyhow", "binmarshal-macros", ] [[package]] name = "binmarshal-macros" -version = "0.1.10" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5099242cef81968a7571f5bc689604eeeb31650385060ac18650b5ed8fc55029" +checksum = "a28cee2e730b6ddc4ea2afe66696682e79957e6f687f28a440d9124a532d4ddb" dependencies = [ "darling", "proc-macro2", @@ -247,9 +254,11 @@ checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" [[package]] name = "grapple-frc-msgs" -version = "0.1.3" -source = "git+https://github.com/GrappleRobotics/frc-msgs#4f27eca1ff51de8fae41e9a152a727afb56a5f4b" +version = "2024.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0255bc7532ea01eb1d10406bf34e998f4f4ec4c4da13985f424b2450f8d05" dependencies = [ + "anyhow", "binmarshal", "smallvec", "strum_macros", @@ -307,7 +316,7 @@ dependencies = [ [[package]] name = "lasercan-bootloader" -version = "0.2.0" +version = "0.3.0" dependencies = [ "bxcan", "cortex-m", diff --git a/lasercan-bootloader/Cargo.toml b/lasercan-bootloader/Cargo.toml index 672c927..753ff0c 100644 --- a/lasercan-bootloader/Cargo.toml +++ b/lasercan-bootloader/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lasercan-bootloader" -version = "0.2.0" +version = "0.3.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -12,7 +12,7 @@ cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.1" panic-halt = "0.2.0" stm32f1xx-hal = { version = "0.10.0", features = ["rt", "stm32f103", "medium"] } -grapple-frc-msgs = { git = "https://github.com/GrappleRobotics/frc-msgs", default-features = false } +grapple-frc-msgs = { version = "~2024.0.5", default-features = false } bxcan = "0.7.0" embedded-alloc = "0.5.1" lasercan-common = { path = "../lasercan-common" } diff --git a/lasercan-bootloader/src/main.rs b/lasercan-bootloader/src/main.rs index 43ac1e0..ffdd8b2 100644 --- a/lasercan-bootloader/src/main.rs +++ b/lasercan-bootloader/src/main.rs @@ -38,7 +38,7 @@ mod app { use bxcan::{ExtendedId, filter::Mask32, Interrupts, Rx0, Tx}; use core::ops::Deref; use cortex_m::peripheral::SCB; - use grapple_frc_msgs::{can::{CANId, CANMessage, FragmentReassembler, UnparsedCANMessage}, DEVICE_TYPE_FIRMWARE_UPGRADE, grapple::{MANUFACTURER_GRAPPLE, GrappleBroadcastMessage, device_info::GrappleDeviceInfo, GrappleDeviceMessage, firmware::GrappleFirmwareMessage}, DEVICE_ID_BROADCAST, DEVICE_TYPE_BROADCAST, binmarshal::BinMarshal, ManufacturerMessage, Message}; + use grapple_frc_msgs::{DEVICE_TYPE_FIRMWARE_UPGRADE, binmarshal::{BinMarshal, rw::BitView}, grapple::{MANUFACTURER_GRAPPLE, GrappleBroadcastMessage, device_info::GrappleDeviceInfo, GrappleDeviceMessage, firmware::GrappleFirmwareMessage, TaggedGrappleMessage, fragments::FragmentReassembler}, DEVICE_ID_BROADCAST, DEVICE_TYPE_BROADCAST, ManufacturerMessage, Message, MessageId}; use lasercan_common::bootutil::{is_firmware_update_in_progress, is_user_code_present, FLASH_USER, FLASH_META_FIRMWARE_RESET_LOC}; use stm32f1xx_hal::{prelude::*, watchdog::IndependentWatchdog, can::Can, pac::{CAN1, Interrupt}, gpio::{ErasedPin, Output}, flash::{self, FLASH_START}}; use tiny_rng::Rand; @@ -122,12 +122,12 @@ mod app { unsafe { can_bus.modify_filters() .enable_bank(0, bxcan::Fifo::Fifo0, Mask32::frames_with_ext_id( - ExtendedId::new_unchecked(CANId { device_type: DEVICE_TYPE_FIRMWARE_UPGRADE, manufacturer: MANUFACTURER_GRAPPLE, api_class: 0x00, api_index: 0x00, device_id: 0x00 }.into()), - ExtendedId::new_unchecked(CANId { device_type: 0xFF, manufacturer: 0xFF, api_class: 0x00, api_index: 0x00, device_id: 0x00 }.into()), + ExtendedId::new_unchecked(MessageId { device_type: DEVICE_TYPE_FIRMWARE_UPGRADE, manufacturer: MANUFACTURER_GRAPPLE, api_class: 0x00, api_index: 0x00, device_id: 0x00 }.into()), + ExtendedId::new_unchecked(MessageId { device_type: 0xFF, manufacturer: 0xFF, api_class: 0x00, api_index: 0x00, device_id: 0x00 }.into()), )) .enable_bank(1, bxcan::Fifo::Fifo0, Mask32::frames_with_ext_id( - ExtendedId::new_unchecked(CANId { device_type: DEVICE_TYPE_BROADCAST, manufacturer: MANUFACTURER_GRAPPLE, api_class: 0x00, api_index: 0x00, device_id: 0x00 }.into()), - ExtendedId::new_unchecked(CANId { device_type: 0xFF, manufacturer: 0xFF, api_class: 0x00, api_index: 0x00, device_id: 0x00 }.into()), + ExtendedId::new_unchecked(MessageId { device_type: DEVICE_TYPE_BROADCAST, manufacturer: MANUFACTURER_GRAPPLE, api_class: 0x00, api_index: 0x00, device_id: 0x00 }.into()), + ExtendedId::new_unchecked(MessageId { device_type: 0xFF, manufacturer: 0xFF, api_class: 0x00, api_index: 0x00, device_id: 0x00 }.into()), )); } @@ -145,12 +145,12 @@ mod app { // Perform arbitration let mut queue = VecDeque::with_capacity(16); - enqueue(CANMessage::Message(Message::new( + enqueue(TaggedGrappleMessage::new( 0, - ManufacturerMessage::Grapple(GrappleDeviceMessage::Broadcast( + GrappleDeviceMessage::Broadcast( GrappleBroadcastMessage::DeviceInfo(GrappleDeviceInfo::ArbitrationRequest) - )) - )), &mut queue); + ) + ), &mut queue); ( SharedResources { @@ -209,104 +209,99 @@ mod app { match ctx.local.can_rx.receive() { Ok(frame) => match (frame.id(), frame.data()) { (bxcan::Id::Extended(ext), data) => { - let d = data.map(|x| x.deref()).unwrap_or(&[]); - let unparsed = UnparsedCANMessage::new(ext.as_raw(), d); - if unparsed.id.device_id == DEVICE_ID_BROADCAST || unparsed.id.device_id == my_id { - let msg = CANMessage::from(unparsed); - let reassembled = ctx.local.reassemble.process(0 as i64, d.len() as u8, msg); - match reassembled { - Some((_, msg)) => match msg { - CANMessage::Message(msg) => { - match msg.msg { - ManufacturerMessage::Grapple(GrappleDeviceMessage::Broadcast(bmsg)) => match bmsg { - GrappleBroadcastMessage::DeviceInfo(di) => match di { - GrappleDeviceInfo::ArbitrationRequest if msg.device_id == my_id => { - // Reply to the arbitration request with a rejection, since this ID belongs to us. - let msg = Message::new( - my_id, - ManufacturerMessage::Grapple(GrappleDeviceMessage::Broadcast( - GrappleBroadcastMessage::DeviceInfo(GrappleDeviceInfo::ArbitrationReject) - )) - ); - ctx.shared.can_tx_queue.lock(|q| enqueue(CANMessage::Message(msg), q)); - }, - GrappleDeviceInfo::ArbitrationReject if msg.device_id == my_id => { - // Retry Arbitration. - let msg = ctx.shared.device_id.lock(|did| { - *did = ctx.local.rng.rand_u8() & 0b11111; - Message::new( - *did, - ManufacturerMessage::Grapple(GrappleDeviceMessage::Broadcast( - GrappleBroadcastMessage::DeviceInfo(GrappleDeviceInfo::ArbitrationRequest) - )) + let id = MessageId::from(ext.as_raw()); + // Only process messages bound for us + if id.device_id == DEVICE_ID_BROADCAST || id.device_id == my_id { + let d = data.map(|x| x.deref()).unwrap_or(&[]); + match ManufacturerMessage::read(&mut BitView::new(d), id.clone()) { + Some(ManufacturerMessage::Grapple(grpl_msg)) => { + match ctx.local.reassemble.defragment(0 as i64, &id, grpl_msg) { + Some(GrappleDeviceMessage::Broadcast(bmsg)) => match bmsg { + GrappleBroadcastMessage::DeviceInfo(di) => match di { + GrappleDeviceInfo::ArbitrationRequest if id.device_id == my_id => { + // Reply to the arbitration request with a rejection, since this ID belongs to us. + let msg = TaggedGrappleMessage::new( + my_id, + GrappleDeviceMessage::Broadcast( + GrappleBroadcastMessage::DeviceInfo(GrappleDeviceInfo::ArbitrationReject) + ) + ); + ctx.shared.can_tx_queue.lock(|q| enqueue(msg, q)); + }, + GrappleDeviceInfo::ArbitrationReject if id.device_id == my_id => { + // Retry Arbitration. + let msg = ctx.shared.device_id.lock(|did| { + *did = ctx.local.rng.rand_u8() & 0b11111; + TaggedGrappleMessage::new( + *did, + GrappleDeviceMessage::Broadcast( + GrappleBroadcastMessage::DeviceInfo(GrappleDeviceInfo::ArbitrationRequest) ) - }); - - ctx.shared.can_tx_queue.lock(|q| enqueue(CANMessage::Message(msg), q)); - }, - GrappleDeviceInfo::EnumerateRequest => { - let new_msg = Message::new( - my_id, - ManufacturerMessage::Grapple(GrappleDeviceMessage::Broadcast( - GrappleBroadcastMessage::DeviceInfo(GrappleDeviceInfo::EnumerateResponse { - model_id: META_MODEL_ID.clone(), - serial: my_serial, - is_dfu: true, - is_dfu_in_progress: *ctx.local.offset != 0, - version: META_BOOTLOADER_VERSION.to_owned(), - name: "".to_owned() - }) ) - )); - ctx.shared.can_tx_queue.lock(|q| enqueue(CANMessage::Message(new_msg), q)); - }, - _ => () + }); + + ctx.shared.can_tx_queue.lock(|q| enqueue(msg, q)); }, - }, - ManufacturerMessage::Grapple(GrappleDeviceMessage::FirmwareUpdate(fwupdate)) => match fwupdate { - GrappleFirmwareMessage::StartFieldUpgrade { .. } => (), - GrappleFirmwareMessage::UpdatePart(data) => { - ctx.shared.status_led.lock(|led| led.toggle()); - - let mut flash_writer = ctx.local.flash.writer(flash::SectorSize::Sz1K, flash::FlashSize::Sz64K); - let user_code_offset = FLASH_USER as usize - FLASH_START as usize; - - // Erase the sector if required. Obviously, this requires our data step size to be a factor of 1024. - if (user_code_offset + *ctx.local.offset) as u32 % 1024 == 0 { - // Erase the flash region - flash_writer.erase((user_code_offset + *ctx.local.offset) as u32, 1024).unwrap(); - } - - // Write the flash data (must be aligned to 16 bits) - flash_writer.write((user_code_offset + *ctx.local.offset) as u32, &data[..]).unwrap(); - - *ctx.local.offset += data.len() as usize; - - // Reply with an ACK - let new_msg = Message::new( + GrappleDeviceInfo::EnumerateRequest => { + let new_msg = TaggedGrappleMessage::new( my_id, - ManufacturerMessage::Grapple(GrappleDeviceMessage::FirmwareUpdate( - GrappleFirmwareMessage::UpdatePartAck - )) + GrappleDeviceMessage::Broadcast( + GrappleBroadcastMessage::DeviceInfo(GrappleDeviceInfo::EnumerateResponse { + model_id: META_MODEL_ID.clone(), + serial: my_serial, + is_dfu: true, + is_dfu_in_progress: *ctx.local.offset != 0, + version: META_BOOTLOADER_VERSION.to_owned(), + name: "".to_owned() + }) + ) ); - ctx.shared.can_tx_queue.lock(|q| enqueue(CANMessage::Message(new_msg), q)); - // send_can_message(&mut can_bus, CANMessage::Message(new_msg)); + ctx.shared.can_tx_queue.lock(|q| enqueue(new_msg, q)); }, - GrappleFirmwareMessage::UpdateDone => { - let mut flash_writer = ctx.local.flash.writer(flash::SectorSize::Sz1K, flash::FlashSize::Sz64K); - ctx.shared.status_led.lock(|led| led.set_high()); + _ => () + }, + }, + Some(GrappleDeviceMessage::FirmwareUpdate(fwupdate)) => match fwupdate { + GrappleFirmwareMessage::StartFieldUpgrade { .. } => (), + GrappleFirmwareMessage::UpdatePart(data) => { + ctx.shared.status_led.lock(|led| led.toggle()); + + let mut flash_writer = ctx.local.flash.writer(flash::SectorSize::Sz1K, flash::FlashSize::Sz64K); + let user_code_offset = FLASH_USER as usize - FLASH_START as usize; + + // Erase the sector if required. Obviously, this requires our data step size to be a factor of 1024. + if (user_code_offset + *ctx.local.offset) as u32 % 1024 == 0 { + // Erase the flash region + flash_writer.erase((user_code_offset + *ctx.local.offset) as u32, 1024).unwrap(); + } + + // Write the flash data (must be aligned to 16 bits) + flash_writer.write((user_code_offset + *ctx.local.offset) as u32, &data[..]).unwrap(); + + *ctx.local.offset += data.len() as usize; + + // Reply with an ACK + let new_msg = TaggedGrappleMessage::new( + my_id, + GrappleDeviceMessage::FirmwareUpdate( + GrappleFirmwareMessage::UpdatePartAck + ) + ); + ctx.shared.can_tx_queue.lock(|q| enqueue(new_msg, q)); + }, + GrappleFirmwareMessage::UpdateDone => { + let mut flash_writer = ctx.local.flash.writer(flash::SectorSize::Sz1K, flash::FlashSize::Sz64K); + ctx.shared.status_led.lock(|led| led.set_high()); - // /* Mark the firmware as good to go */ - flash_writer.write(FLASH_META_FIRMWARE_RESET_LOC as u32 - FLASH_START, &[0xDE, 0xAD, 0xBE, 0xEF]).unwrap(); + // /* Mark the firmware as good to go */ + flash_writer.write(FLASH_META_FIRMWARE_RESET_LOC as u32 - FLASH_START, &[0xDE, 0xAD, 0xBE, 0xEF]).unwrap(); - cortex_m::peripheral::SCB::sys_reset(); - }, - _ => () + cortex_m::peripheral::SCB::sys_reset(); }, _ => () - } - }, - _ => () + }, + _ => () + } }, _ => () } @@ -332,30 +327,20 @@ mod app { }; } - fn enqueue(mut msg: CANMessage, q: &mut VecDeque) { + fn enqueue(mut msg: TaggedGrappleMessage, q: &mut VecDeque) { static FRAG_ID: core::sync::atomic::AtomicU8 = core::sync::atomic::AtomicU8::new(0); - msg.update(()); - - match msg { - CANMessage::Message(msg) => { - let frag_id = FRAG_ID.load(core::sync::atomic::Ordering::Relaxed); - let msgs = grapple_frc_msgs::can::FragmentReassembler::maybe_split(msg, frag_id).unwrap(); - - for msg in msgs { - let frame = unsafe { - bxcan::Frame::new_data( - ExtendedId::new_unchecked(Into::::into(msg.id.clone())), - bxcan::Data::new(&msg.payload[0..msg.len as usize]).unwrap() - ) - }; - - q.push_back(frame); - } - rtic::pend(Interrupt::USB_HP_CAN_TX); - FRAG_ID.store(frag_id.wrapping_add(1), core::sync::atomic::Ordering::Relaxed); - }, - _ => panic!("Can't send fragments or generics directly - use the FragmentReasssembler.") - } + let frag_id = FRAG_ID.load(core::sync::atomic::Ordering::Relaxed); + FragmentReassembler::maybe_fragment(msg.device_id, msg.msg, frag_id, &mut |id, buf| { + let frame = unsafe { + bxcan::Frame::new_data( + ExtendedId::new_unchecked(Into::::into(id.clone())), + bxcan::Data::new(buf).unwrap() + ) + }; + q.push_back(frame); + }); + rtic::pend(Interrupt::USB_HP_CAN_TX); + FRAG_ID.store(frag_id.wrapping_add(1), core::sync::atomic::Ordering::Relaxed); } } \ No newline at end of file diff --git a/lasercan-firmware/Cargo.lock b/lasercan-firmware/Cargo.lock index 765eb3e..22e41ac 100644 --- a/lasercan-firmware/Cargo.lock +++ b/lasercan-firmware/Cargo.lock @@ -277,9 +277,9 @@ dependencies = [ [[package]] name = "grapple-frc-msgs" -version = "2024.0.4" +version = "2024.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27e76fc8d413a8a60ff7050f6ac659d4f32123e7ff6ef71dca4b3609374e70e2" +checksum = "96b0255bc7532ea01eb1d10406bf34e998f4f4ec4c4da13985f424b2450f8d05" dependencies = [ "anyhow", "binmarshal", @@ -356,7 +356,7 @@ dependencies = [ [[package]] name = "lasercan-firmware" -version = "2024.0.0" +version = "2024.0.1" dependencies = [ "bxcan", "cortex-m", diff --git a/lasercan-firmware/Cargo.toml b/lasercan-firmware/Cargo.toml index b50ad2e..ad25fce 100644 --- a/lasercan-firmware/Cargo.toml +++ b/lasercan-firmware/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lasercan-firmware" -version = "2024.0.0" +version = "2024.0.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -12,7 +12,7 @@ cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } cortex-m-rt = "0.7.1" panic-halt = "0.2.0" stm32f1xx-hal = { version = "0.10.0", features = ["rt", "stm32f103", "medium"] } -grapple-frc-msgs = { version = "~2024.0.0", default-features = false, features = ["lasercan_nop_patch"] } +grapple-frc-msgs = { version = "~2024.0.5", default-features = false, features = ["lasercan_nop_patch", "grapple_lasercan"] } bxcan = "0.7.0" embedded-alloc = "0.5.1" lasercan-common = { path = "../lasercan-common" } diff --git a/lasercan-firmware/src/main.rs b/lasercan-firmware/src/main.rs index b7f4e83..df1da6e 100644 --- a/lasercan-firmware/src/main.rs +++ b/lasercan-firmware/src/main.rs @@ -361,13 +361,12 @@ mod app { let my_serial = lasercan_common::get_serial_hash(); - unsafe { asm!("nop") } - ctx.shared.config.lock(|cfg| { loop { match ctx.local.can_rx.receive() { Ok(frame) => match (frame.id(), frame.data()) { (bxcan::Id::Extended(ext), data) => { + unsafe { asm!("nop") } let id = MessageId::from(ext.as_raw()); // Only process messages bound for us