1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#![no_std]
use core::sync::atomic::{AtomicBool, Ordering};
mod ring_buffer;
pub use ring_buffer::{RingBuf, RingBuffer};
#[defmt::global_logger]
struct Logger;
static TAKEN: AtomicBool = AtomicBool::new(false);
static mut CS_RESTORE: critical_section::RestoreState = critical_section::RestoreState::invalid();
static mut ENCODER: defmt::Encoder = defmt::Encoder::new();
static mut RING_BUFFER: Option<&'static mut dyn RingBuf> = None;
static mut LOG_AVAILABLE: fn() = || ();
unsafe impl defmt::Logger for Logger {
fn acquire() {
let restore = unsafe { critical_section::acquire() };
if TAKEN.load(Ordering::Relaxed) {
panic!("defmt logger taken reentrantly")
}
TAKEN.store(true, Ordering::Relaxed);
unsafe { CS_RESTORE = restore };
unsafe { ENCODER.start_frame(do_write) }
}
unsafe fn flush() {
}
unsafe fn release() {
ENCODER.end_frame(do_write);
TAKEN.store(false, Ordering::Relaxed);
let restore = CS_RESTORE;
critical_section::release(restore);
}
unsafe fn write(bytes: &[u8]) {
ENCODER.write(bytes, do_write);
}
}
fn do_write(data: &[u8]) {
unsafe {
if let Some(buffer) = RING_BUFFER.as_mut() {
buffer.write(data);
LOG_AVAILABLE();
}
}
}
pub unsafe fn init<const SIZE: usize>(ring_buffer: &'static mut RingBuffer<SIZE>, log_available: fn()) {
defmt::assert!(RING_BUFFER.is_none());
RING_BUFFER = Some(ring_buffer as &mut dyn RingBuf);
LOG_AVAILABLE = log_available;
}
pub fn read(data: &mut [u8]) -> (usize, bool) {
unsafe {
critical_section::with(|_cs| {
if let Some(buffer) = RING_BUFFER.as_mut() {
buffer.read(data)
} else {
(0, false)
}
})
}
}