diff --git a/firmware/c_board/app/src/can/can.hpp b/firmware/c_board/app/src/can/can.hpp index e12f4c7..cbe8e4e 100644 --- a/firmware/c_board/app/src/can/can.hpp +++ b/firmware/c_board/app/src/can/can.hpp @@ -55,43 +55,46 @@ class Can : private core::utility::Immovable { } void handle_uplink(data::DataId field_id, core::protocol::Serializer& serializer) { - auto hal_can_state = hal_can_handle_->State; - auto* hal_can_instance = hal_can_handle_->Instance; - - core::utility::assert_always( - (hal_can_state == HAL_CAN_STATE_READY) || (hal_can_state == HAL_CAN_STATE_LISTENING)); - core::utility::assert_always((hal_can_instance->RF0R & CAN_RF0R_FMP0) != 0U); - - const auto rir = hal_can_instance->sFIFOMailBox[CAN_RX_FIFO0].RIR; - const auto rdtr = hal_can_instance->sFIFOMailBox[CAN_RX_FIFO0].RDTR; - - data::CanDataView data{}; - data.is_fdcan = false; - data.is_extended_can_id = static_cast(CAN_RI0R_IDE & rir); - data.is_remote_transmission = static_cast(CAN_RI0R_RTR & rir); - - if (data.is_extended_can_id) { - data.can_id = ((CAN_RI0R_EXID | CAN_RI0R_STID) & rir) >> CAN_RI0R_EXID_Pos; - } else { - data.can_id = (CAN_RI0R_STID & rir) >> CAN_TI0R_STID_Pos; + while ((hal_can_handle_->Instance->RF0R & CAN_RF0R_FMP0) != 0U) { + auto hal_can_state = hal_can_handle_->State; + auto* hal_can_instance = hal_can_handle_->Instance; + + core::utility::assert_always( + (hal_can_state == HAL_CAN_STATE_READY) + || (hal_can_state == HAL_CAN_STATE_LISTENING)); + core::utility::assert_always((hal_can_instance->RF0R & CAN_RF0R_FMP0) != 0U); + + const auto rir = hal_can_instance->sFIFOMailBox[CAN_RX_FIFO0].RIR; + const auto rdtr = hal_can_instance->sFIFOMailBox[CAN_RX_FIFO0].RDTR; + + data::CanDataView data{}; + data.is_fdcan = false; + data.is_extended_can_id = static_cast(CAN_RI0R_IDE & rir); + data.is_remote_transmission = static_cast(CAN_RI0R_RTR & rir); + + if (data.is_extended_can_id) { + data.can_id = ((CAN_RI0R_EXID | CAN_RI0R_STID) & rir) >> CAN_RI0R_EXID_Pos; + } else { + data.can_id = (CAN_RI0R_STID & rir) >> CAN_TI0R_STID_Pos; + } + + size_t can_data_length = (CAN_RDT0R_DLC & rdtr) >> CAN_RDT0R_DLC_Pos; + if (data.is_remote_transmission) + can_data_length = 0; + + alignas(uint32_t) std::array can_data{}; + const uint32_t rdlr = hal_can_instance->sFIFOMailBox[CAN_RX_FIFO0].RDLR; + const uint32_t rdhr = hal_can_instance->sFIFOMailBox[CAN_RX_FIFO0].RDHR; + std::memcpy(can_data.data(), &rdlr, sizeof(uint32_t)); + std::memcpy(can_data.data() + 4, &rdhr, sizeof(uint32_t)); + data.can_data = {can_data.data(), can_data_length}; + + core::utility::assert_always( + serializer.write_can(field_id, data) + != core::protocol::Serializer::SerializeResult::kInvalidArgument); + + hal_can_instance->RF0R |= CAN_RF0R_RFOM0; } - - size_t can_data_length = (CAN_RDT0R_DLC & rdtr) >> CAN_RDT0R_DLC_Pos; - if (data.is_remote_transmission) - can_data_length = 0; - - alignas(uint32_t) std::array can_data{}; - const uint32_t rdlr = hal_can_instance->sFIFOMailBox[CAN_RX_FIFO0].RDLR; - const uint32_t rdhr = hal_can_instance->sFIFOMailBox[CAN_RX_FIFO0].RDHR; - std::memcpy(can_data.data(), &rdlr, sizeof(uint32_t)); - std::memcpy(can_data.data() + 4, &rdhr, sizeof(uint32_t)); - data.can_data = {can_data.data(), can_data_length}; - - core::utility::assert_always( - serializer.write_can(field_id, data) - != core::protocol::Serializer::SerializeResult::kInvalidArgument); - - hal_can_instance->RF0R |= CAN_RF0R_RFOM0; } bool try_transmit() { diff --git a/firmware/rmcs_board/app/src/can/can.hpp b/firmware/rmcs_board/app/src/can/can.hpp index 3ee8b7f..1e20349 100644 --- a/firmware/rmcs_board/app/src/can/can.hpp +++ b/firmware/rmcs_board/app/src/can/can.hpp @@ -86,20 +86,25 @@ class Can : private core::utility::Immovable { } void handle_uplink(core::protocol::FieldId field_id, core::protocol::Serializer& serializer) { - mcan_rx_message_t rx; - core::utility::assert_always(mcan_read_rxfifo(can_base_, 0, &rx) == status_success); - - data::CanDataView data; - const size_t data_length = rx.dlc; - data.is_fdcan = false; - data.is_extended_can_id = rx.use_ext_id; - data.is_remote_transmission = rx.rtr; - data.can_id = data.is_extended_can_id ? rx.ext_id : rx.std_id; - data.can_data = {reinterpret_cast(rx.data_8), data_length}; - - core::utility::assert_always( - serializer.write_can(field_id, data) - != core::protocol::Serializer::SerializeResult::kInvalidArgument); + while (true) { + mcan_rx_message_t rx; + const hpm_stat_t status = mcan_read_rxfifo(can_base_, 0, &rx); + if (status == status_mcan_rxfifo_empty) + return; + core::utility::assert_always(status == status_success); + + data::CanDataView data; + const size_t data_length = rx.dlc; + data.is_fdcan = false; + data.is_extended_can_id = rx.use_ext_id; + data.is_remote_transmission = rx.rtr; + data.can_id = data.is_extended_can_id ? rx.ext_id : rx.std_id; + data.can_data = {reinterpret_cast(rx.data_8), data_length}; + + core::utility::assert_always( + serializer.write_can(field_id, data) + != core::protocol::Serializer::SerializeResult::kInvalidArgument); + } } void irq_handler() { @@ -108,10 +113,18 @@ class Can : private core::utility::Immovable { if (!flags) [[unlikely]] return; - if (flags & MCAN_INT_RXFIFO0_NEW_MSG) [[likely]] - handle_uplink(data_id_, usb::get_serializer()); + uint32_t remaining_flags = flags; + if (flags & MCAN_INT_RXFIFO0_NEW_MSG) [[likely]] { + mcan_clear_interrupt_flags(can_base_, MCAN_INT_RXFIFO0_NEW_MSG); + + auto& serializer = usb::get_serializer(); + handle_uplink(data_id_, serializer); + + remaining_flags &= ~MCAN_INT_RXFIFO0_NEW_MSG; + } - mcan_clear_interrupt_flags(can_base_, flags); + if (remaining_flags != 0U) + mcan_clear_interrupt_flags(can_base_, remaining_flags); } private: