Skip to content
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
14 changes: 14 additions & 0 deletions core/include/librmcs/data/datas.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ enum class DataId : uint8_t {
kUart3 = 14,

kImu = 15,

kSession = 16,
};

enum class SessionType : uint8_t {
kStart = 0,
kStartAck = 1,
kKeepalive = 2,
kKeepaliveAck = 3,
};

struct SessionControlView {
SessionType type;
uint32_t nonce;
};

struct CanDataView {
Expand Down
17 changes: 17 additions & 0 deletions core/src/protocol/deserializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ coroutine::LifoTask<void> Deserializer::process_stream() {
case FieldId::kUart3: success = co_await process_uart_field(id); break;
case FieldId::kGpio: success = co_await process_gpio_field(id); break;
case FieldId::kImu: success = co_await process_imu_field(id); break;
case FieldId::kSession: success = co_await process_session_field(id); break;
default: break;
}
if (!success)
Expand Down Expand Up @@ -317,4 +318,20 @@ coroutine::LifoTask<bool> Deserializer::process_imu_field(FieldId) {
co_return true;
}

coroutine::LifoTask<bool> Deserializer::process_session_field(FieldId) {
const auto* header_bytes = co_await peek_bytes(sizeof(SessionHeader));
if (!header_bytes) [[unlikely]]
co_return false;

auto header = SessionHeader::CRef{header_bytes};
data::SessionControlView data_view{};
data_view.type = header.get<SessionHeader::Type>();
data_view.nonce = header.get<SessionHeader::Nonce>();
consume_peeked();

callback_.session_control_deserialized_callback(data_view);

co_return true;
}

} // namespace librmcs::core::protocol
4 changes: 4 additions & 0 deletions core/src/protocol/deserializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class DeserializeCallback {

virtual void temperature_deserialized_callback(const data::TemperatureDataView& data) = 0;

virtual void session_control_deserialized_callback(const data::SessionControlView& data) = 0;

virtual void error_callback() = 0;
};

Expand Down Expand Up @@ -120,6 +122,8 @@ class Deserializer : private coroutine::InlineLifoContext<1024> {

coroutine::LifoTask<bool> process_imu_field(FieldId field_id);

coroutine::LifoTask<bool> process_session_field(FieldId field_id);

// Await until at least `size` contiguous bytes are available at the current read position.
// Returns a pointer to a contiguous region of at least `size` bytes.
// (from input buffer or pending cache)
Expand Down
9 changes: 9 additions & 0 deletions core/src/protocol/protocol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ struct UartHeaderExtendedLayout {
using DataLengthExtended = BitfieldMember<6, 10>;
};

struct SessionHeaderLayout {
using Type = BitfieldMember<4, 4, data::SessionType>;
using Nonce = BitfieldMember<8, 32, uint32_t>;
};

} // namespace layouts

struct FieldHeader
Expand Down Expand Up @@ -82,6 +87,10 @@ struct UartHeaderExtended
, layouts::UartHeaderLayout
, layouts::UartHeaderExtendedLayout {};

struct SessionHeader
: utility::Bitfield<5>
, layouts::SessionHeaderLayout {};

struct GpioHeader : utility::Bitfield<2> {
enum class PayloadEnum : uint8_t {
kDigitalWriteLow = 0b0000,
Expand Down
26 changes: 26 additions & 0 deletions core/src/protocol/serializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,25 @@ class Serializer {
return SerializeResult::kSuccess;
}

SerializeResult write_session_control(const data::SessionControlView& view) noexcept {
const std::size_t required = required_session_size();

auto dst = buffer_.allocate(required);
LIBRMCS_VERIFY_LIKELY(!dst.empty(), SerializeResult::kBadAlloc);
utility::assert_debug(dst.size() == required);
std::byte* cursor = dst.data();

write_field_header(cursor, FieldId::kSession);

auto header = SessionHeader::Ref(cursor);
cursor += sizeof(SessionHeader);
header.set<SessionHeader::Type>(view.type);
header.set<SessionHeader::Nonce>(view.nonce);

utility::assert_debug(cursor == dst.data() + dst.size());
return SerializeResult::kSuccess;
}

private:
static constexpr bool use_extended_field_header(FieldId field_id) {
utility::assert_debug(field_id != FieldId::kExtend);
Expand Down Expand Up @@ -489,6 +508,13 @@ class Serializer {
return total;
}

static constexpr std::size_t required_session_size() {
constexpr std::size_t total = required_field_header_size(FieldId::kSession)
+ sizeof(SessionHeader) - sizeof(FieldHeader);
utility::assert_debug(total <= kProtocolBufferSize);
return total;
}

SerializeBuffer& buffer_;
};

Expand Down
38 changes: 15 additions & 23 deletions firmware/c_board/app/src/usb/interrupt_safe_buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ class InterruptSafeBuffer final

std::span<std::byte> allocate(size_t size) noexcept override {
core::utility::assert_debug(size <= core::protocol::kProtocolBufferSize);
if (is_locked_.test(std::memory_order::relaxed))
if (is_locked_.test(std::memory_order::relaxed)) {
return {};
}

auto out = out_.load(std::memory_order::relaxed);

Expand Down Expand Up @@ -102,36 +103,27 @@ class InterruptSafeBuffer final
}

void clear() {
const bool was_locked = is_locked_.test_and_set(std::memory_order::relaxed);
core::utility::assert_debug(!was_locked);

auto in = in_.load(std::memory_order::relaxed);
auto out = out_.load(std::memory_order::relaxed);

auto readable = in - out;
if (!readable)
return;
if (readable) {
auto offset = out & kMask;
auto slice = std::min(readable, kBatchCount - offset);

auto offset = out & kMask;
auto slice = std::min(readable, kBatchCount - offset);
for (size_t i = 0; i < slice; i++)
batches_[offset + i].reset();
for (size_t i = 0; i < readable - slice; i++)
batches_[i].reset();

for (size_t i = 0; i < slice; i++)
batches_[offset + i].reset();
for (size_t i = 0; i < readable - slice; i++)
batches_[i].reset();

std::atomic_signal_fence(std::memory_order::release);
out_.store(in, std::memory_order::relaxed);
}

bool try_lock() { return !is_locked_.test_and_set(std::memory_order::relaxed); }

bool try_unlock_and_clear() {
if (!is_locked_.test(std::memory_order::relaxed))
return false;
std::atomic_signal_fence(std::memory_order::release);
out_.store(in, std::memory_order::relaxed);
}

// Unlocking drops stale queued batches from the last not-ready cycle before
// new ISR writes are accepted.
clear();
is_locked_.clear(std::memory_order::relaxed);
return true;
}

private:
Expand Down
11 changes: 9 additions & 2 deletions firmware/c_board/app/src/usb/vendor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,20 @@ void tud_dfu_runtime_reboot_to_dfu_cb() {
NVIC_SystemReset();
}

void tud_suspend_cb(bool remote_wakeup_en) { (void)remote_wakeup_en; }
void tud_suspend_cb(bool remote_wakeup_en) {
(void)remote_wakeup_en;
usb::vendor->deactivate_session();
usb::vendor->finish_downlink_transfer();
}

void tud_resume_cb() {}

void tud_mount_cb() {}

void tud_umount_cb() {}
void tud_umount_cb() {
usb::vendor->deactivate_session();
usb::vendor->finish_downlink_transfer();
}

} // extern "C"

Expand Down
Loading
Loading