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 <zephyr/sys/reboot.h>
15#include <zephyr/usb/usb_device.h>
16#include <memory>
17
18// 空包类型,用于表示不需要发送或接收任何包的情况
20{
21};
22
23
24template <>
25struct RPL::Meta::PacketTraits<EmptyPacket> : PacketTraitsBase<PacketTraits<EmptyPacket>>
26{
27 static constexpr uint16_t cmd = 0xF0FF;
28 static constexpr size_t size = sizeof(EmptyPacket);
29};
30
31namespace OF
32{
33 template <typename TxPackets, typename RxPackets>
35
36 template <typename... TxPackets, typename... RxPackets>
37 class CommBridge<std::tuple<TxPackets...>, std::tuple<RxPackets...>>
38 {
39 public:
43 static std::unique_ptr<CommBridge> create(const device* uart_dev)
44 {
45 return std::unique_ptr<CommBridge>(new CommBridge(uart_dev));
46 }
47
49 {
51 }
52
53 CommBridge(const CommBridge&) = delete;
54 CommBridge& operator=(const CommBridge&) = delete;
57
62 {
63 LOG_MODULE_DECLARE(CommBridge, CONFIG_COMM_BRIDGE_LOG_LEVEL);
64
65 if (m_RxEnabled)
66 {
67 LOG_WRN("Receive already enabled");
68 return;
69 }
70
71 uart_irq_callback_user_data_set(m_UartDev, uart_rx_callback, this);
72 uart_irq_rx_enable(m_UartDev);
73 m_RxEnabled = true;
74
75 LOG_INF("UART RX interrupt enabled");
76 }
77
82 {
83 if (!m_RxEnabled)
84 {
85 return;
86 }
87
88 uart_irq_rx_disable(m_UartDev);
89 m_RxEnabled = false;
90 LOG_MODULE_DECLARE(CommBridge, CONFIG_COMM_BRIDGE_LOG_LEVEL);
91 LOG_INF("UART RX interrupt disabled");
92 }
93
97 template <typename... Packets>
98 requires(sizeof...(Packets) == 0 || (RPL::Serializable<Packets, TxPackets...> && ...))
99 void send(const Packets&... packets)
100 {
101 LOG_MODULE_DECLARE(CommBridge, CONFIG_COMM_BRIDGE_LOG_LEVEL);
102
103 // 如果没有发送包,则直接返回
104 if constexpr (sizeof...(Packets) == 0)
105 {
106 return;
107 }
108
109 k_sem_take(&m_TxDoneSem, K_FOREVER);
110
111 auto res = m_Serializer.serialize(m_TxBuffer, TxBufferSize, packets...);
112 if (!res)
113 {
114 LOG_ERR("Serialize failed");
115 k_sem_give(&m_TxDoneSem);
116 return;
117 }
118
119 m_TxSize = res.value();
120
121 // 启动看门狗定时器,50ms 触发一次
122 k_timer_start(&m_TxWatchdog, K_MSEC(50), K_MSEC(50));
123
124 for (size_t i = 0; i < m_TxSize; ++i)
125 {
126 uart_poll_out(m_UartDev, m_TxBuffer[i]);
127 }
128
129 // 发送成功,停止看门狗并清零计数
130 k_timer_stop(&m_TxWatchdog);
131 m_BusyCount = 0;
132
133 k_sem_give(&m_TxDoneSem);
134 }
135
139 template <typename T>
140 requires(sizeof...(RxPackets) == 0 ? false : RPL::Deserializable<T, RxPackets...>)
141 T get() noexcept
142 {
143 return m_Deserializer.template get<T>();
144 }
145
146 private:
147 explicit CommBridge(const device* uart_dev) :
148 m_UartDev(uart_dev),
149 m_Deserializer(),
150 m_Parser(m_Deserializer)
151 {
152 LOG_MODULE_DECLARE(CommBridge, CONFIG_COMM_BRIDGE_LOG_LEVEL);
153 LOG_INF("Creating CommBridge");
154 if (!device_is_ready(m_UartDev))
155 {
156 LOG_ERR("UART not ready");
157 k_oops();
158 }
159
160 k_sem_init(&m_TxDoneSem, 1, 1);
161
162 k_timer_init(&m_TxWatchdog, tx_watchdog_expiry, nullptr);
163 k_timer_user_data_set(&m_TxWatchdog, this);
164
165 LOG_INF("CommBridge initialized, UART device: %s", m_UartDev->name);
166 }
167
168 // 如果 TxPackets 为空,则 TxBufferSize 为 0,否则计算实际大小
169 static constexpr size_t calculateTxBufferSize()
170 {
171 if constexpr (sizeof...(TxPackets) == 0)
172 {
173 return 0; // 没有发送包时,不需要发送缓冲区
174 }
175 else
176 {
177 return (RPL::Serializer<TxPackets...>::template frame_size<TxPackets>() + ...);
178 }
179 }
180
181 static constexpr size_t TxBufferSize = calculateTxBufferSize();
182 static constexpr size_t RxBufferSize = CONFIG_COMM_BRIDGE_MAX_RX_SIZE;
183
184 const device* m_UartDev;
185
186 RPL::Serializer<TxPackets...> m_Serializer{};
187 uint8_t m_TxBuffer[TxBufferSize > 0 ? TxBufferSize : 1]{}; // 至少1个字节以避免零长度数组
188 k_sem m_TxDoneSem{};
189 size_t m_TxSize{0};
190
191 RPL::Deserializer<RxPackets...> m_Deserializer{};
192 RPL::Parser<RxPackets...> m_Parser;
193 uint8_t m_RxBuffer[RxBufferSize]{};
194
195 bool m_RxEnabled{false};
196
197 k_timer m_TxWatchdog{};
198 uint32_t m_BusyCount{0};
199
200 static void tx_watchdog_expiry(k_timer* timer)
201 {
202 auto* bridge = static_cast<CommBridge*>(k_timer_user_data_get(timer));
203 bridge->m_BusyCount++;
204
205 if (bridge->m_BusyCount >= 5)
206 {
207 // 如果连续 5 次(250ms)阻塞在 uart_poll_out,判定为 USB 卡死,触发软复位
208 // sys_reboot(SYS_REBOOT_WARM);
209 }
210 }
211
215 static void uart_rx_callback(const device* dev, void* user_data)
216 {
217 LOG_MODULE_DECLARE(CommBridge, CONFIG_COMM_BRIDGE_LOG_LEVEL);
218 auto* bridge = static_cast<CommBridge*>(user_data);
219
220 if (!uart_irq_update(dev))
221 {
222 return;
223 }
224
225 if (uart_irq_rx_ready(dev))
226 {
227 uint8_t buffer[64];
228 int len = uart_fifo_read(dev, buffer, sizeof(buffer));
229 if (len > 0)
230 {
231 bridge->m_Parser.push_data(buffer, len);
232 }
233 }
234 }
235 };
236
237 // 便捷别名,用于创建只接收不发送的 CommBridge
238 template <typename... RxPackets>
239 using RxOnlyCommBridge = CommBridge<std::tuple<EmptyPacket>, std::tuple<RxPackets...>>;
240
241 // 便捷别名,用于创建只发送不接收的 CommBridge
242 template <typename... TxPackets>
243 using TxOnlyCommBridge = CommBridge<std::tuple<TxPackets...>, std::tuple<EmptyPacket>>;
244}
245
246#endif //OF_LIB_COMMBRIDGE_MANAGER_HPP
void start_receive()
启动中断驱动接收
定义 CommBridge.hpp:61
T get() noexcept
获取接收到的数据包
定义 CommBridge.hpp:141
void send(const Packets &... packets)
发送数据包
定义 CommBridge.hpp:99
static std::unique_ptr< CommBridge > create(const device *uart_dev)
工厂函数,创建 CommBridge 对象
定义 CommBridge.hpp:43
定义 CommBridge.hpp:34
定义 JointSetpointGenerator.hpp:9
CommBridge< std::tuple< EmptyPacket >, std::tuple< RxPackets... > > RxOnlyCommBridge
定义 CommBridge.hpp:239
CommBridge< std::tuple< TxPackets... >, std::tuple< EmptyPacket > > TxOnlyCommBridge
定义 CommBridge.hpp:243
定义 CommBridge.hpp:20
static constexpr uint16_t cmd
定义 CommBridge.hpp:27
static constexpr size_t size
定义 CommBridge.hpp:28