1#![no_std]
2
3mod consts;
4
5#[cfg(feature = "bbq")]
6mod bbq;
7#[cfg(feature = "bbq")]
8pub use bbq::{init, Consumer, DefmtConsumer, Error as BBQError, GrantR, SplitGrantR};
9
10#[cfg(feature = "rtt")]
11mod rtt;
12#[cfg(feature = "rtt")]
13use rtt::handle;
14
15#[cfg(feature = "async-await")]
16mod csec_waker;
17
18use core::sync::atomic::{AtomicBool, Ordering};
19
20#[cfg(not(any(feature = "rtt", feature = "bbq")))]
21compile_error!("You must select at least one of the `rtt` or `bbq` features (or both).");
22
23#[defmt::global_logger]
24struct Logger;
25
26static TAKEN: AtomicBool = AtomicBool::new(false);
28static mut CS_RESTORE: critical_section::RestoreState = critical_section::RestoreState::invalid();
29static mut ENCODER: defmt::Encoder = defmt::Encoder::new();
30
31fn combined_write(_data: &[u8]) {
32 #[cfg(feature = "rtt")]
33 rtt::do_write(_data);
34 #[cfg(feature = "bbq")]
35 bbq::do_write(_data);
36}
37
38unsafe impl defmt::Logger for Logger {
39 fn acquire() {
40 let restore = unsafe { critical_section::acquire() };
42
43 if TAKEN.load(Ordering::Relaxed) {
45 panic!("defmt logger taken reentrantly")
46 }
47
48 #[cfg(feature = "bbq")]
49 if bbq::should_bail() {
50 unsafe { critical_section::release(restore) };
53 return;
54 }
55
56 TAKEN.store(true, Ordering::Relaxed);
58
59 unsafe { CS_RESTORE = restore };
61
62 unsafe { ENCODER.start_frame(combined_write) }
64 }
65
66 unsafe fn flush() {
67 #[cfg(feature = "rtt")]
68 handle().flush();
70 }
71
72 unsafe fn release() {
73 ENCODER.end_frame(combined_write);
75
76 #[cfg(feature = "bbq")]
77 bbq::commit_w_grant();
78
79 TAKEN.store(false, Ordering::Relaxed);
81
82 let restore = CS_RESTORE;
84
85 critical_section::release(restore);
87
88 #[cfg(feature = "async-await")]
90 bbq::DefmtConsumer::waker().wake();
91 }
92
93 unsafe fn write(bytes: &[u8]) {
94 #[cfg(all(feature = "bbq", not(feature = "rtt")))]
95 if bbq::check_latch(Ordering::Relaxed).is_err() {
97 return;
98 }
99
100 ENCODER.write(bytes, combined_write);
102 }
103}