Skip to main content

rustmeter_beacon_core/protocol/
raw_writers.rs

1use crate::{time_delta::TimeDelta, tracing::write_tracing_data};
2use arbitrary_int::{traits::Integer, u3};
3
4pub mod event_ids {
5    pub const EMBASSY_TASK_READY: u8 = 1;
6    pub const EMBASSY_TASK_EXEC_BEGIN: u8 = 2;
7    pub const EMBASSY_TASK_EXEC_END: u8 = 3;
8    pub const EMBASSY_EXECUTOR_POLL_START: u8 = 4;
9    pub const EMBASSY_EXECUTOR_IDLE: u8 = 5;
10    pub const MONITOR_START: u8 = 6;
11    pub const MONITOR_END: u8 = 7;
12    pub const MONITOR_VALUE: u8 = 8;
13    pub const TYPE_DEFINITION: u8 = 9;
14    pub const DATA_LOSS_EVENT: u8 = 10;
15    pub const DEFMT_DATA_EVENT: u8 = 11;
16}
17
18#[inline(always)]
19pub fn write_embassy_task_ready(task_id: u16, executor_id: u3) {
20    // Add payload
21    let mut buffer = [0u8; 8];
22    buffer[0] = (event_ids::EMBASSY_TASK_READY << 3) | executor_id.as_u8();
23    buffer[1..3].copy_from_slice(&task_id.to_le_bytes());
24
25    // Write to global buffer
26    let timestamp = TimeDelta::from_now();
27    let pos = timestamp.write_bytes_mut(&mut buffer[3..]);
28    unsafe { write_tracing_data(&buffer[..3 + pos]) };
29}
30
31#[inline(always)]
32pub fn write_embassy_task_exec_begin(task_id: u16, executor_id: u3) {
33    // Add payload
34    let mut buffer = [0u8; 8];
35    buffer[0] = (event_ids::EMBASSY_TASK_EXEC_BEGIN << 3) | executor_id.as_u8();
36    buffer[1..3].copy_from_slice(&task_id.to_le_bytes());
37
38    // Write to global buffer
39    let timestamp = TimeDelta::from_now();
40    let pos = timestamp.write_bytes_mut(&mut buffer[3..]);
41    unsafe { write_tracing_data(&buffer[..3 + pos]) };
42}
43
44#[inline(always)]
45pub fn write_embassy_task_exec_end(executor_id: u3) {
46    // Add payload
47    let mut buffer = [0u8; 8];
48    buffer[0] = (event_ids::EMBASSY_TASK_EXEC_END << 3) | executor_id.as_u8();
49
50    // Write to global buffer
51    let timestamp = TimeDelta::from_now();
52    let pos = timestamp.write_bytes_mut(&mut buffer[1..]);
53    unsafe { write_tracing_data(&buffer[..1 + pos]) };
54}
55
56#[inline(always)]
57pub fn write_embassy_executor_poll_start(executor_id: u3) {
58    // Add payload
59    let mut buffer = [0u8; 8];
60    buffer[0] = (event_ids::EMBASSY_EXECUTOR_POLL_START << 3) | executor_id.as_u8();
61
62    // Write to global buffer
63    let timestamp = TimeDelta::from_now();
64    let pos = timestamp.write_bytes_mut(&mut buffer[1..]);
65    unsafe { write_tracing_data(&buffer[..1 + pos]) };
66}
67
68#[inline(always)]
69pub fn write_embassy_executor_idle(executor_id: u3) {
70    // Add payload
71    let mut buffer = [0u8; 8];
72    buffer[0] = (event_ids::EMBASSY_EXECUTOR_IDLE << 3) | executor_id.as_u8();
73
74    // Write to global buffer
75    let timestamp = TimeDelta::from_now();
76    let pos = timestamp.write_bytes_mut(&mut buffer[1..]);
77    unsafe { write_tracing_data(&buffer[..1 + pos]) };
78}
79
80#[inline(always)]
81pub fn write_monitor_start(monitor_id: u8) {
82    // Add payload
83    let mut buffer = [0u8; 8];
84    buffer[0] = event_ids::MONITOR_START << 3;
85    buffer[1] = monitor_id;
86
87    // Write to global buffer
88    let timestamp = TimeDelta::from_now();
89    let pos = timestamp.write_bytes_mut(&mut buffer[2..]);
90    unsafe { write_tracing_data(&buffer[..2 + pos]) };
91}
92
93#[inline(always)]
94pub fn write_monitor_end() {
95    // Add payload
96    let mut buffer = [0u8; 8];
97    buffer[0] = event_ids::MONITOR_END << 3;
98
99    // Write to global buffer
100    let timestamp = TimeDelta::from_now();
101    let pos = timestamp.write_bytes_mut(&mut buffer[1..]);
102    unsafe { write_tracing_data(&buffer[..1 + pos]) };
103}
104
105#[inline(always)]
106pub fn write_defmt_data(data: &[u8]) {
107    // TODO: Create chunked writes if data is too large
108    // Create header
109    let mut buffer = [0u8; 20]; // 2 header + 2 timestamp + 16 data
110    buffer[0] = event_ids::DEFMT_DATA_EVENT << 3;
111
112    // Send in chunks
113    let mut start = 0;
114    while start < data.len() {
115        let chunk_size = core::cmp::min(16, data.len() - start);
116        buffer[1] = chunk_size as u8;
117
118        // Copy payload data
119        buffer[2..2 + chunk_size].copy_from_slice(&data[start..start + chunk_size]);
120        let next_pos = 2 + chunk_size;
121
122        // Write to global buffer with timestamp
123        let timestamp = TimeDelta::from_now();
124        let pos = timestamp.write_bytes_mut(&mut buffer[next_pos..]);
125        unsafe { write_tracing_data(&buffer[..next_pos + pos]) };
126
127        start += chunk_size;
128    }
129
130    // buffer[1] = data.len() as u8;
131
132    // // Copy payload data
133    // buffer[2..2 + data.len()].copy_from_slice(data);
134    // let next_pos = 2 + data.len();
135
136    // // Write to global buffer with timestamp
137    // let timestamp = TimeDelta::from_now();
138    // let pos = timestamp.write_bytes_mut(&mut buffer[next_pos..]);
139    // unsafe { write_tracing_data(&buffer[..next_pos + pos]) };
140}
141
142// TODO: Implement monitor value!
143
144#[cfg(test)]
145pub mod tests {
146    use super::*;
147    use crate::{
148        mocks::test_mocks::{mock_time_provider, mock_trace_writer, with_mocks},
149        protocol::EventPayload,
150    };
151    use arbitrary_int::u3;
152
153    #[test]
154    fn test_write_embassy_task_ready() {
155        with_mocks(
156            mock_trace_writer(EventPayload::EmbassyTaskReady {
157                task_id: 12345,
158                executor_id: u3::new(5),
159            }),
160            mock_time_provider,
161            || 0,
162            || {
163                write_embassy_task_ready(12345, u3::new(5));
164            },
165        );
166    }
167
168    #[test]
169    fn test_write_embassy_task_exec_begin() {
170        with_mocks(
171            mock_trace_writer(EventPayload::EmbassyTaskExecBegin {
172                task_id: 54321,
173                executor_id: u3::new(2),
174            }),
175            mock_time_provider,
176            || 0,
177            || {
178                write_embassy_task_exec_begin(54321, u3::new(2));
179            },
180        );
181    }
182
183    #[test]
184    fn test_write_embassy_task_exec_end() {
185        with_mocks(
186            mock_trace_writer(EventPayload::EmbassyTaskExecEnd {
187                executor_id: u3::new(3),
188            }),
189            mock_time_provider,
190            || 0,
191            || {
192                write_embassy_task_exec_end(u3::new(3));
193            },
194        );
195    }
196
197    #[test]
198    fn test_write_embassy_executor_poll_start() {
199        with_mocks(
200            mock_trace_writer(EventPayload::EmbassyExecutorPollStart {
201                executor_id: u3::new(1),
202            }),
203            mock_time_provider,
204            || 0,
205            || {
206                write_embassy_executor_poll_start(u3::new(1));
207            },
208        );
209    }
210
211    #[test]
212    fn test_write_embassy_executor_idle() {
213        with_mocks(
214            mock_trace_writer(EventPayload::EmbassyExecutorIdle {
215                executor_id: u3::new(4),
216            }),
217            mock_time_provider,
218            || 0,
219            || {
220                write_embassy_executor_idle(u3::new(4));
221            },
222        );
223    }
224
225    #[test]
226    pub fn test_write_monitor_start() {
227        with_mocks(
228            mock_trace_writer(EventPayload::MonitorStart { monitor_id: 10 }),
229            mock_time_provider,
230            || 0,
231            || {
232                write_monitor_start(10);
233            },
234        );
235    }
236
237    #[test]
238    pub fn test_write_monitor_end() {
239        with_mocks(
240            mock_trace_writer(EventPayload::MonitorEnd),
241            mock_time_provider,
242            || 0,
243            || {
244                write_monitor_end();
245            },
246        );
247    }
248}