-
Notifications
You must be signed in to change notification settings - Fork 13
feat(i2c): Improve I2C reliability, DMA throughput, and board support #42
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
Changes from all commits
df5cc1b
44ff397
12bce2b
20ea882
9e7d481
c561efe
13b60a8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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::kI2c0: success = co_await process_i2c_field(id); break; | ||||||||||||||||||||||||||||||||||
| default: break; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| if (!success) | ||||||||||||||||||||||||||||||||||
|
|
@@ -289,4 +290,88 @@ coroutine::LifoTask<bool> Deserializer::process_imu_field(FieldId) { | |||||||||||||||||||||||||||||||||
| co_return true; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| coroutine::LifoTask<bool> Deserializer::process_i2c_field(FieldId field_id) { | ||||||||||||||||||||||||||||||||||
| I2cHeader::PayloadEnum payload_type; | ||||||||||||||||||||||||||||||||||
| uint8_t slave_address = 0; | ||||||||||||||||||||||||||||||||||
| uint16_t data_length = 0; | ||||||||||||||||||||||||||||||||||
| bool has_register = false; | ||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||
| const auto* header_bytes = co_await peek_bytes(sizeof(I2cHeader)); | ||||||||||||||||||||||||||||||||||
| if (!header_bytes) [[unlikely]] | ||||||||||||||||||||||||||||||||||
| co_return false; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| auto header = I2cHeader::CRef{header_bytes}; | ||||||||||||||||||||||||||||||||||
| payload_type = header.get<I2cHeader::PayloadType>(); | ||||||||||||||||||||||||||||||||||
| has_register = header.get<I2cHeader::HasRegister>(); | ||||||||||||||||||||||||||||||||||
| slave_address = header.get<I2cHeader::SlaveAddress>(); | ||||||||||||||||||||||||||||||||||
| data_length = header.get<I2cHeader::DataLength>(); | ||||||||||||||||||||||||||||||||||
| consume_peeked(); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if (slave_address > 0x7F) [[unlikely]] | ||||||||||||||||||||||||||||||||||
| co_return false; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| switch (payload_type) { | ||||||||||||||||||||||||||||||||||
| case I2cHeader::PayloadEnum::kWrite: | ||||||||||||||||||||||||||||||||||
| case I2cHeader::PayloadEnum::kReadResult: { | ||||||||||||||||||||||||||||||||||
| data::I2cDataView data_view{}; | ||||||||||||||||||||||||||||||||||
| data_view.slave_address = slave_address; | ||||||||||||||||||||||||||||||||||
| data_view.has_register = has_register; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if (has_register) { | ||||||||||||||||||||||||||||||||||
| const auto* register_bytes = co_await peek_bytes(1); | ||||||||||||||||||||||||||||||||||
| if (!register_bytes) [[unlikely]] | ||||||||||||||||||||||||||||||||||
| co_return false; | ||||||||||||||||||||||||||||||||||
| data_view.reg_address = std::to_integer<uint8_t>(register_bytes[0]); | ||||||||||||||||||||||||||||||||||
| consume_peeked(); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if (data_length) { | ||||||||||||||||||||||||||||||||||
| const auto* payload_bytes = co_await peek_bytes(data_length); | ||||||||||||||||||||||||||||||||||
| if (!payload_bytes) [[unlikely]] | ||||||||||||||||||||||||||||||||||
| co_return false; | ||||||||||||||||||||||||||||||||||
| data_view.payload = std::span<const std::byte>{payload_bytes, data_length}; | ||||||||||||||||||||||||||||||||||
| consume_peeked(); | ||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||
| data_view.payload = std::span<const std::byte>{}; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if (payload_type == I2cHeader::PayloadEnum::kWrite) { | ||||||||||||||||||||||||||||||||||
| callback_.i2c_write_deserialized_callback(field_id, data_view); | ||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||
| callback_.i2c_read_result_deserialized_callback(field_id, data_view); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| case I2cHeader::PayloadEnum::kReadRequest: { | ||||||||||||||||||||||||||||||||||
| data::I2cReadConfigView data_view{}; | ||||||||||||||||||||||||||||||||||
| data_view.slave_address = slave_address; | ||||||||||||||||||||||||||||||||||
| data_view.read_length = data_length; | ||||||||||||||||||||||||||||||||||
| data_view.has_register = has_register; | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if (has_register) { | ||||||||||||||||||||||||||||||||||
| const auto* register_bytes = co_await peek_bytes(1); | ||||||||||||||||||||||||||||||||||
| if (!register_bytes) [[unlikely]] | ||||||||||||||||||||||||||||||||||
| co_return false; | ||||||||||||||||||||||||||||||||||
| data_view.reg_address = std::to_integer<uint8_t>(register_bytes[0]); | ||||||||||||||||||||||||||||||||||
| consume_peeked(); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| callback_.i2c_read_config_deserialized_callback(field_id, data_view); | ||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| case I2cHeader::PayloadEnum::kError: { | ||||||||||||||||||||||||||||||||||
| data::I2cDataView data_view{}; | ||||||||||||||||||||||||||||||||||
| data_view.slave_address = slave_address; | ||||||||||||||||||||||||||||||||||
| data_view.payload = std::span<const std::byte>{}; | ||||||||||||||||||||||||||||||||||
| data_view.has_register = false; | ||||||||||||||||||||||||||||||||||
| callback_.i2c_error_deserialized_callback(field_id, data_view); | ||||||||||||||||||||||||||||||||||
| break; | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+363
to
+369
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
当报文头里 🔧 建议修改 case I2cHeader::PayloadEnum::kError: {
+ if (has_register || data_length != 0) [[unlikely]]
+ co_return false;
data::I2cDataView data_view{};
data_view.slave_address = slave_address;
data_view.payload = std::span<const std::byte>{};
data_view.has_register = false;
callback_.i2c_error_deserialized_callback(field_id, data_view);
break;
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| default: co_return false; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| co_return true; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| } // namespace librmcs::core::protocol | ||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
缺少 I2C
data_length上界校验。data_length直接用于peek_bytes,但未像 UART 分支那样限制到内部缓冲能力;超大长度输入会把错误处理路径推迟到更深处,增加边界风险。🔧 建议修改
data_length = header.get<I2cHeader::DataLength>(); consume_peeked(); } if (slave_address > 0x7F) [[unlikely]] co_return false; + +if (data_length > sizeof(pending_bytes_buffer_)) [[unlikely]] + co_return false;Also applies to: 329-334, 349-360
🤖 Prompt for AI Agents