One Framework 0.1.0
RoboMaster嵌入式框架“一键”解决方案,为你的“创意”服务。
载入中...
搜索中...
未找到
CommBridge.hpp
浏览该文件的文档.
1// Copyright (c) 2025. MoonFeather
2// SPDX-License-Identifier: BSD-3-Clause
3
4#ifndef OF_LIB_COMMBRIDGE_MANAGER_HPP
5#define OF_LIB_COMMBRIDGE_MANAGER_HPP
6
7#include <RPL/Serializer.hpp>
8#include <RPL/Deserializer.hpp>
9#include <RPL/Parser.hpp>
10#include <zephyr/device.h>
11#include <zephyr/drivers/uart.h>
12#include <zephyr/kernel.h>
13#include <zephyr/logging/log.h>
14#include <memory>
15
16// 空包类型,用于表示不需要发送或接收任何包的情况
18{
19};
20
21
22template <>
23struct RPL::Meta::PacketTraits<EmptyPacket> : PacketTraitsBase<PacketTraits<EmptyPacket>>
24{
25 static constexpr uint16_t cmd = 0xF0FF;
26 static constexpr size_t size = sizeof(EmptyPacket);
27};
28
29namespace OF
30{
31 template <typename TxPackets, typename RxPackets>
33
34 template <typename... TxPackets, typename... RxPackets>
35 class CommBridge<std::tuple<TxPackets...>, std::tuple<RxPackets...>>
36 {
37 public:
41 static std::unique_ptr<CommBridge> create(const device* uart_dev)
42 {
43 return std::unique_ptr<CommBridge>(new CommBridge(uart_dev));
44 }
45
47 {
49 }
50
51 CommBridge(const CommBridge&) = delete;
52 CommBridge& operator=(const CommBridge&) = delete;
55
60 {
61 LOG_MODULE_DECLARE(CommBridge, CONFIG_COMM_BRIDGE_LOG_LEVEL);
62
63 if (m_RxEnabled)
64 {
65 LOG_WRN("Receive already enabled");
66 return;
67 }
68
69 uart_irq_callback_user_data_set(m_UartDev, uart_rx_callback, this);
70 uart_irq_rx_enable(m_UartDev);
71 m_RxEnabled = true;
72
73 LOG_INF("UART RX interrupt enabled");
74 }
75
80 {
81 if (!m_RxEnabled)
82 {
83 return;
84 }
85
86 uart_irq_rx_disable(m_UartDev);
87 m_RxEnabled = false;
88 LOG_MODULE_DECLARE(CommBridge, CONFIG_COMM_BRIDGE_LOG_LEVEL);
89 LOG_INF("UART RX interrupt disabled");
90 }
91
95 template <typename... Packets>
96 requires(sizeof...(Packets) == 0 || (RPL::Serializable<Packets, TxPackets...> && ...))
97 void send(const Packets&... packets)
98 {
99 LOG_MODULE_DECLARE(CommBridge, CONFIG_COMM_BRIDGE_LOG_LEVEL);
100
101 // 如果没有发送包,则直接返回
102 if constexpr (sizeof...(Packets) == 0)
103 {
104 return;
105 }
106
107 k_sem_take(&m_TxDoneSem, K_FOREVER);
108
109 auto res = m_Serializer.serialize(m_TxBuffer, TxBufferSize, packets...);
110 if (!res)
111 {
112 LOG_ERR("Serialize failed");
113 k_sem_give(&m_TxDoneSem);
114 return;
115 }
116
117 m_TxSize = res.value();
118
119 for (size_t i = 0; i < m_TxSize; ++i)
120 {
121 uart_poll_out(m_UartDev, m_TxBuffer[i]);
122 }
123
124 k_sem_give(&m_TxDoneSem);
125 }
126
130 template <typename T>
131 requires(sizeof...(RxPackets) == 0 ? false : RPL::Deserializable<T, RxPackets...>)
132 T get() noexcept
133 {
134 return m_Deserializer.template get<T>();
135 }
136
137 private:
138 explicit CommBridge(const device* uart_dev) :
139 m_UartDev(uart_dev),
140 m_Deserializer(),
141 m_Parser(m_Deserializer)
142 {
143 LOG_MODULE_DECLARE(CommBridge, CONFIG_COMM_BRIDGE_LOG_LEVEL);
144 LOG_INF("Creating CommBridge");
145 if (!device_is_ready(m_UartDev))
146 {
147 LOG_ERR("UART not ready");
148 k_oops();
149 }
150
151 k_sem_init(&m_TxDoneSem, 1, 1);
152
153 LOG_INF("CommBridge initialized, UART device: %s", m_UartDev->name);
154 }
155
156 // 如果 TxPackets 为空,则 TxBufferSize 为 0,否则计算实际大小
157 static constexpr size_t calculateTxBufferSize()
158 {
159 if constexpr (sizeof...(TxPackets) == 0)
160 {
161 return 0; // 没有发送包时,不需要发送缓冲区
162 }
163 else
164 {
165 return (RPL::Serializer<TxPackets...>::template frame_size<TxPackets>() + ...);
166 }
167 }
168
169 static constexpr size_t TxBufferSize = calculateTxBufferSize();
170 static constexpr size_t RxBufferSize = CONFIG_COMM_BRIDGE_MAX_RX_SIZE;
171
172 const device* m_UartDev;
173
174 RPL::Serializer<TxPackets...> m_Serializer{};
175 uint8_t m_TxBuffer[TxBufferSize > 0 ? TxBufferSize : 1]{}; // 至少1个字节以避免零长度数组
176 k_sem m_TxDoneSem{};
177 size_t m_TxSize{0};
178
179 RPL::Deserializer<RxPackets...> m_Deserializer{};
180 RPL::Parser<RxPackets...> m_Parser;
181 uint8_t m_RxBuffer[RxBufferSize]{};
182
183 bool m_RxEnabled{false};
184
188 static void uart_rx_callback(const device* dev, void* user_data)
189 {
190 LOG_MODULE_DECLARE(CommBridge, CONFIG_COMM_BRIDGE_LOG_LEVEL);
191 auto* bridge = static_cast<CommBridge*>(user_data);
192
193 if (!uart_irq_update(dev))
194 {
195 return;
196 }
197
198 if (uart_irq_rx_ready(dev))
199 {
200 uint8_t buffer[64];
201 int len = uart_fifo_read(dev, buffer, sizeof(buffer));
202 if (len > 0)
203 {
204 bridge->m_Parser.push_data(buffer, len);
205 }
206 }
207 }
208 };
209
210 // 便捷别名,用于创建只接收不发送的 CommBridge
211 template <typename... RxPackets>
212 using RxOnlyCommBridge = CommBridge<std::tuple<EmptyPacket>, std::tuple<RxPackets...>>;
213
214 // 便捷别名,用于创建只发送不接收的 CommBridge
215 template <typename... TxPackets>
216 using TxOnlyCommBridge = CommBridge<std::tuple<TxPackets...>, std::tuple<EmptyPacket>>;
217}
218
219#endif //OF_LIB_COMMBRIDGE_MANAGER_HPP
void start_receive()
启动中断驱动接收
定义 CommBridge.hpp:59
T get() noexcept
获取接收到的数据包
定义 CommBridge.hpp:132
void send(const Packets &... packets)
发送数据包
定义 CommBridge.hpp:97
static std::unique_ptr< CommBridge > create(const device *uart_dev)
工厂函数,创建 CommBridge 对象
定义 CommBridge.hpp:41
定义 CommBridge.hpp:32
定义 Mecanum.hpp:6
CommBridge< std::tuple< EmptyPacket >, std::tuple< RxPackets... > > RxOnlyCommBridge
定义 CommBridge.hpp:212
CommBridge< std::tuple< TxPackets... >, std::tuple< EmptyPacket > > TxOnlyCommBridge
定义 CommBridge.hpp:216
定义 CommBridge.hpp:18
static constexpr uint16_t cmd
定义 CommBridge.hpp:25
static constexpr size_t size
定义 CommBridge.hpp:26